reflection operator (since C++26) - cppreference.com
Namespaces
Variants

reflection operator (since C++26)

From cppreference.com
 
 
C++ language
General topics
Flow control
Conditional execution statements
if
Iteration statements (loops)
for
range-for (C++11)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications (until C++17*)
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
explicit (C++11)
static

Special member functions
Templates
Miscellaneous
 
 

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)
reflection-name - an identifier, optionally qualified, optionally using template disambiguator. This form takes precedence over type-id and id-expression
type-id - a type-id
id-expression - an id-expression

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 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 requires expression, 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

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.

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

See also