On Sat, Nov 29, 2025 at 03:18:14PM -0500, Eczbek wrote:
> From 21240d2a1d4c99fb85ceb9b39c95eb18f8e61c1d Mon Sep 17 00:00:00 2001
> From: Eczbek <[email protected]>
> Date: Wed, 26 Nov 2025 21:58:28 -0500
> Subject: [PATCH] c++: Make std::meta::operator_of() accept operator function
> templates [PR122771]
>
> eval_operator_of() checks if a reflection does not
> represent an operator function, but it should also check that
> the reflection does not represent an operator function template.
Thanks for the patch, it looks good.
Since Reflection isn't merged yet, we can either wait for that to happen,
or I could include the patch in my devel reflection branch, but I think
we'd need a Signed-off-by.
> PR c++/122771
Please assign that PR to yourself (if you're able to).
Thanks!
> gcc/cp/ChangeLog:
>
> * reflect.cc (eval_operator_of): Add check for operator function
> templates and improve error message.
>
> gcc/testsuite/ChangeLog:
>
> * g++.dg/reflect/operator_of1.C: Add tests for operator function
> templates.
> ---
> gcc/cp/reflect.cc | 6 +-
> gcc/testsuite/g++.dg/reflect/operator_of1.C | 107 +++++++++++++++++++-
> 2 files changed, 110 insertions(+), 3 deletions(-)
>
> diff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc
> index 38188920cea..6e84c6c40c1 100644
> --- a/gcc/cp/reflect.cc
> +++ b/gcc/cp/reflect.cc
> @@ -2332,10 +2332,12 @@ eval_operator_of (location_t loc, const
> constexpr_ctx *ctx, tree r,
> bool *non_constant_p, tree *jump_target, tree ret_type,
> tree fun)
> {
> - if (eval_is_operator_function (r) == boolean_false_node)
> + if (eval_is_operator_function (r) == boolean_false_node
> + && eval_is_operator_function_template (r) == boolean_false_node)
> return throw_exception (loc, ctx,
> "reflection does not represent an operator "
> - "function", fun, non_constant_p, jump_target);
> + "function or operator function template",
> + fun, non_constant_p, jump_target);
> r = maybe_get_reflection_fndecl (r);
> r = STRIP_TEMPLATE (r);
> maybe_init_meta_operators (loc);
> diff --git a/gcc/testsuite/g++.dg/reflect/operator_of1.C
> b/gcc/testsuite/g++.dg/reflect/operator_of1.C
> index 25e73713bb9..e950b1a1b90 100644
> --- a/gcc/testsuite/g++.dg/reflect/operator_of1.C
> +++ b/gcc/testsuite/g++.dg/reflect/operator_of1.C
> @@ -164,11 +164,68 @@ struct S
> struct T
> {
> T &operator ++ (int);
> - T &operator -- (int);
> + T &operator -- (int);
> T &operator + ();
> T &operator - ();
> };
>
> +struct U
> +{
> + using size_t = decltype (sizeof 0);
> + template<int> void *operator new (size_t, void *);
> + template<int> void *operator new[] (size_t, void *);
> + template<int> void operator delete (void *, U);
> + template<int> void operator delete[] (void *, U);
> + template<int> U &operator () (const U &);
> + template<int> U &operator [] (const U &);
> + template<int> U &operator = (const U &);
> + template<int> U &operator << (int);
> + template<int> U &operator >> (int);
> + template<int> U &operator ++ ();
> + template<int> U &operator -- ();
> + template<int> U &operator ~ ();
> + template<int> U &operator ! ();
> + template<int> U &operator + (const U &);
> + template<int> U &operator - (const U &);
> + template<int> U &operator * (const U &);
> + template<int> U &operator / (const U &);
> + template<int> U &operator % (const U &);
> + template<int> U &operator ^ (const U &);
> + template<int> U &operator & (const U &);
> + template<int> U &operator | (const U &);
> + template<int> U &operator += (const U &);
> + template<int> U &operator -= (const U &);
> + template<int> U &operator *= (const U &);
> + template<int> U &operator /= (const U &);
> + template<int> U &operator %= (const U &);
> + template<int> U &operator ^= (const U &);
> + template<int> U &operator &= (const U &);
> + template<int> U &operator |= (const U &);
> + template<int> U &operator <<= (int);
> + template<int> U &operator >>= (int);
> + template<int> bool operator == (const U &);
> + template<int> bool operator != (const U &);
> + template<int> bool operator < (const U &);
> + template<int> bool operator > (const U &);
> + template<int> bool operator <= (const U &);
> + template<int> bool operator >= (const U &);
> + template<int> int operator <=> (const U &);
> + template<int> bool operator && (const U &);
> + template<int> bool operator || (const U &);
> + template<int> U &operator , (const U &);
> + template<int> U *operator -> ();
> + template<int> U &operator ->* (const U &);
> + template<int> U &operator co_await ();
> +};
> +
> +struct V
> +{
> + template<int> V &operator ++ (int);
> + template<int> V &operator -- (int);
> + template<int> V &operator + ();
> + template<int> V &operator - ();
> +};
> +
> static_assert (operator_of (^^S::operator new) == op_new);
> static_assert (operator_of (^^S::operator delete) ==
> std::meta::op_delete);
> static_assert (operator_of (^^S::operator new[]) ==
> std::meta::operators::op_array_new);
> @@ -217,3 +274,51 @@ static_assert (operator_of (^^T::operator +) ==
> op_plus);
> static_assert (operator_of (^^T::operator -) == op_minus);
> static_assert (operator_of (^^T::operator ++) == op_plus_plus);
> static_assert (operator_of (^^T::operator --) == op_minus_minus);
> +static_assert (operator_of (^^U::operator new) == op_new);
> +static_assert (operator_of (^^U::operator delete) == std::meta::op_delete);
> +static_assert (operator_of (^^U::operator new[]) ==
> std::meta::operators::op_array_new);
> +static_assert (operator_of (^^U::operator delete[]) == op_array_delete);
> +static_assert (operator_of (^^U::operator co_await) == op_co_await);
> +static_assert (operator_of (^^U::operator ()) == op_parentheses);
> +static_assert (operator_of (^^U::operator []) == op_square_brackets);
> +static_assert (operator_of (^^U::operator ->) == op_arrow);
> +static_assert (operator_of (^^U::operator ->*) == op_arrow_star);
> +static_assert (operator_of (^^U::operator ~) == op_tilde);
> +static_assert (operator_of (^^U::operator !) == op_exclamation);
> +static_assert (operator_of (^^U::operator +) == op_plus);
> +static_assert (operator_of (^^U::operator -) == op_minus);
> +static_assert (operator_of (^^U::operator *) == op_star);
> +static_assert (operator_of (^^U::operator /) == op_slash);
> +static_assert (operator_of (^^U::operator %) == op_percent);
> +static_assert (operator_of (^^U::operator ^) == op_caret);
> +static_assert (operator_of (^^U::operator &) == op_ampersand);
> +static_assert (operator_of (template_of (^^U::operator =<0>)) ==
> op_equals);
> +static_assert (operator_of (^^U::operator |) == op_pipe);
> +static_assert (operator_of (^^U::operator +=) == op_plus_equals);
> +static_assert (operator_of (^^U::operator -=) == op_minus_equals);
> +static_assert (operator_of (^^U::operator *=) == op_star_equals);
> +static_assert (operator_of (^^U::operator /=) == op_slash_equals);
> +static_assert (operator_of (^^U::operator %=) == op_percent_equals);
> +static_assert (operator_of (^^U::operator ^=) == op_caret_equals);
> +static_assert (operator_of (^^U::operator &=) == op_ampersand_equals);
> +static_assert (operator_of (^^U::operator |=) == op_pipe_equals);
> +static_assert (operator_of (^^U::operator ==) == op_equals_equals);
> +static_assert (operator_of (^^U::operator !=) == op_exclamation_equals);
> +static_assert (operator_of (^^U::operator <) == op_less);
> +static_assert (operator_of (^^U::operator >) == op_greater);
> +static_assert (operator_of (^^U::operator <=) == op_less_equals);
> +static_assert (operator_of (^^U::operator >=) == op_greater_equals);
> +static_assert (operator_of (^^U::operator <=>) == op_spaceship);
> +static_assert (operator_of (^^U::operator &&) == op_ampersand_ampersand);
> +static_assert (operator_of (^^U::operator ||) == op_pipe_pipe);
> +static_assert (operator_of (^^U::operator <<) == op_less_less);
> +static_assert (operator_of (^^U::operator >>) == op_greater_greater);
> +static_assert (operator_of (^^U::operator <<=) == op_less_less_equals);
> +static_assert (operator_of (^^U::operator >>=) ==
> op_greater_greater_equals);
> +static_assert (operator_of (^^U::operator ++) == op_plus_plus);
> +static_assert (operator_of (^^U::operator --) == op_minus_minus);
> +static_assert (operator_of (^^U::operator ,) == op_comma);
> +static_assert (operator_of (^^V::operator +) == op_plus);
> +static_assert (operator_of (^^V::operator -) == op_minus);
> +static_assert (operator_of (^^V::operator ++) == op_plus_plus);
> +static_assert (operator_of (^^V::operator --) == op_minus_minus);
> --
> 2.52.0
>
Marek