reflection operator (since C++26) - cppreference.com
From cppreference.com
The unary ^^ operator, called the reflection operator, yields the reflection of the given language construct, of type std::meta::info.
Syntax
^^ ::
|
(1) | ||||||||
^^ reflection-name
|
(2) | ||||||||
^^ type-id
|
(3) | ||||||||
^^ id-expression
|
(4) | ||||||||
The longest sequence of tokens that could syntactically form the operand of ^^ is parsed. If the result represents a template, the expression must not be directly followed by <.
static_assert(std::meta::is_type(^^int())); // ^^int() represents the type int() // not a function call to ^^int template<bool> struct X {}; consteval bool operator<(std::meta::info, X<false>) { return false; } consteval void g(std::meta::info r, X<false> xv) { r == ^^int && true; // error: ^^ applies to the type-id int&& r == ^^int & true; // error: ^^ applies to the type-id int& r == (^^int) && true; // OK r == ^^int &&&& true; // error: int &&&& is not a valid type-id ^^X < xv; // error: reflect-expression that represents a template is followed by < (^^X) < xv; // OK ^^X<true> < xv; // OK }
Explanation
1) The expression ^^:: represents the global namespace.
2) In ^^reflection-name, the reflection-name is looked up, and the representation is determined as follows:
- If lookup finds a declaration that replaced a using-declarator, the expression is invalid.
- Otherwise, if lookup finds a namespace alias, namespace, or concept, the result represents that entity.
- Otherwise, if lookup finds a template:
- If lookup finds a injected-class-name:
- If the template disambiguator is present, the result represents the class template named by the injected-class-name.
- Otherwise, the injected-class-name must be unambiguous when considered as a type-name (otherwise the expression is invalid). The result represents the type so named.
- Otherwise, if lookup finds an overload set, that overload set must contain only declarations of a unique function template. The result represents that function template.
- Otherwise, if lookup finds a class template, variable template, or alias template, the result represents that template.
- Otherwise, if lookup finds a type template parameter, the result represents the type of the corresponding argument.
- Otherwise, if lookup finds a typedef name or type alias, the result represents that type alias.
template<typename T> struct S { static constexpr std::meta::info r = ^^T; using type = T; }; static_assert(S<int>::r == ^^int); // OK static_assert(^^S<int>::type != ^^int); // OK typedef struct X {} Y; typedef struct Z {} Z; constexpr std::meta::info e = ^^Y; // OK, represents the type alias Y constexpr std::meta::info f = ^^Z; // OK, represents the type alias Z, not the type
- Otherwise, if lookup finds a class type or an enumeration type, the result represents that type.
- Otherwise, if lookup finds a class member of an anonymous union, the result represents that member.
- Otherwise, the reflection-name is considered an id-expression (see form (4) below).
3) The expression ^^type-id represents an entity determined as follows:
- If the type-id designates a placeholder type (e.g.
auto), the expression is invalid. - Otherwise, if the type-id names an alias template with a template argument list, the result represents the type alias so named. (Other form of type alias names would be treated as a reflection-name, and the result would also represent the type alias.)
- Otherwise, the result represents the type denoted by the type-id.
4) The expression ^^id-expression represents an entity determined as follows:
- If the id-expression denotes:
- a variable declared by a lambda's init-capture,
- a function-local predefined variable (
__func__), - a local parameter declared by a
requiresexpression, or - a local entity for which a lambda scope intervenes between the point at which it is introduced and the reflect expression (whether the entity is captured or not),
- the expression is invalid.
- Otherwise, if the id-expression denotes an overload set, overload resolution must select a unique function. The result represents that function.
template<typename T> void fn() requires (^^T != ^^int); template<typename T> void fn() requires (^^T == ^^int); template<typename T> void fn() requires (sizeof(T) == sizeof(int)); constexpr std::meta::info a = ^^fn<char>; // OK constexpr std::meta::info b = ^^fn<int>; // error: ambiguous
- Otherwise, if the id-expression denotes a variable, structured binding, enumerator, or non-static data member, the result represents that entity.
- Otherwise (e.g. the id-expression denotes a non-type template parameter or a pack indexing expression), the expression is invalid.
The operand is an unevaluated operand.
Notes
A reflection value can also be produced by std::meta::reflect_constant, std::meta::reflect_object, std::meta::reflect_function, or default-initializing std::meta::info. In addition, a reflection value can be obtained by calling <meta> functions with existing std::meta::info objects.
If a type alias appears as part of a type-id, the reflection operator does not preserve the type alias.
using T = int; static_assert(^^T != ^^int); static_assert(^^T& == ^^int&); static_assert(^^T const == ^^const int);
Example
int arr[] = {1, 2, 3}; auto [a1, a2, a3] = arr; [[=1]] void fn(int n); enum Enum { A }; using Alias = int; struct S { int mem; }; template<auto> struct TCls {}; template<auto> void TFn(); template<auto> int TVar; template<auto N> using TAlias = TCls<N>; template<auto> concept Concept = true; namespace NS {} namespace NSAlias = NS; constexpr auto r_arr = ^^arr; // represents a variable constexpr auto r_sb = ^^a3; // represents a structured binding constexpr auto r_fn = ^^fn; // represents a function constexpr auto r_enum = ^^Enum::A; // represents an enumerator constexpr auto r_alias = ^^Alias; // represents a type alias constexpr auto r_type = ^^S; // represents a type constexpr auto r_mem = ^^S::mem; // represents a class member constexpr auto r_tcls = ^^TCls; // represents a class template constexpr auto r_tfn = ^^TFn; // represents a function template constexpr auto r_tvar = ^^TVar; // represents a variable template constexpr auto r_ttype = ^^TAlias; // represents an alias template constexpr auto r_cncpt = ^^Concept; // represents a concept constexpr auto r_ns = ^^NS; // represents a namespace constexpr auto r_ns2 = ^^NSAlias; // represents a namespace alias int main() {}
See also
| returns a reflection representing a value or template parameter object, suitable for use as a constant template argument (function template) [edit] | |
| returns a reflection representing an object, suitable for use as a constant template argument (function template) [edit] | |
| returns a reflection representing a function, suitable for use as a constant template argument (function template) [edit] |