13 KiB
[expr.reflect]
7 Expressions [expr]
7.6 Compound expressions [expr.compound]
7.6.2 Unary expressions [expr.unary]
7.6.2.10 The reflection operator [expr.reflect]
reflect-expression:
^^ ::
^^ reflection-name
^^ type-id
^^ id-expression
reflection-name:
nested-name-specifieropt identifier
nested-name-specifier template identifier
The unary ^^ operator, called the reflection operator, yields a prvalue of type std::meta::info ([basic.fundamental]).
[Note 1:
This document places no restriction on representing, by reflections, constructs not described by this document or using the names of such constructs as operands of reflect-expressions.
â end note]
The component names of a reflection-name are those of its nested-name-specifier (if any) and its identifier.
The terminal name of a reflection-name of the formnested-name-specifier template identifier shall denote a template.
A reflect-expression is parsed as the longest possible sequence of tokens that could syntactically form a reflect-expression.
An unparenthesized reflect-expression that represents a template shall not be followed by <.
[Example 1: static_assert(std::meta::is_type(^^int())); // ^^ applies to the type-id int()template struct X {};consteval bool operator<(std::meta::info, X) { return false; }consteval void g(std::meta::info r, X 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 < xv; // OK} â end example]
A reflect-expression of the form ^^:: represents the global namespace.
If a reflect-expression R matches the form ^^reflection-name, it is interpreted as such; the identifier is looked up and the representation of R is determined as follows:
-
If lookup finds a declaration that replaced a using-declarator during a single search ([basic.lookup.general], [namespace.udecl]),R is ill-formed. [Example 2: struct A { struct S {}; };struct B : A { using A::S; };constexpr std::meta::info r1 = ^^B::S; // error: A::S found through using-declaratorstruct C : virtual B { struct S {}; };struct D : virtual B, C {}; D::S s; // OK, names C::S per [class.member.lookup]constexpr std::meta::info r2 = ^^D::S; // OK, result C::S not found through using-declarator â end example]
-
Otherwise, if lookup finds a namespace alias ([namespace.alias]),R represents that namespace alias. For any other namespace-name,R represents the denoted namespace.
-
Otherwise, if lookup finds a namespace ([basic.namespace]),R represents that namespace.
-
Otherwise, if lookup finds a concept ([temp.concept]),R represents the denoted concept.
-
Otherwise, if lookup finds a template ([temp.names]), the representation of R is determined as follows:
-
If lookup finds an injected-class-name ([class.pre]), then: + (5.5.1.1) If the reflection-name is of the formnested-name-specifier template identifier, then R represents the class template named by the injected-class-name.
-
[(5.5.1.2)](#5.5.1.2) Otherwise, the injected-class-name shall be unambiguous
-
-
when considered as a type-name andR represents the class template specialization so named.
-
Otherwise, if lookup finds an overload set, that overload set shall contain only declarations of a unique function template F;R represents F.
-
Otherwise, if lookup finds a class template, variable template, or alias template,R represents that template. [Note 2: Lookup never finds a partial or explicit specialization. â end note]
-
Otherwise, if lookup finds a type alias A,R represents the underlying entity of A if A was introduced by the declaration of a template parameter; otherwise, R represents A.
-
Otherwise, if lookup finds a class or an enumeration,R represents the denoted type.
-
Otherwise, if lookup finds a class member of an anonymous union ([class.union.anon]), R represents that class member.
-
Otherwise, the reflection-name shall be an id-expression I and R is ^^I (see below).
A reflect-expression R of the form^^type-id represents an entity determined as follows:
-
If the type-id designates a placeholder type ([dcl.spec.auto.general]),R is ill-formed.
-
Otherwise, if the type-id names a type alias that is a specialization of an alias template ([temp.alias]),R represents that type alias.
A reflect-expression R of the form^^id-expression represents an entity determined as follows:
-
If the id-expression denotes
a variable declared by an init-capture ([expr.prim.lambda.capture]),
a function-local predefined variable ([dcl.fct.def.general]),
a local parameter introduced by a requires-expression ([expr.prim.req]), or
a local entity E ([basic.pre]) for which a lambda scope intervenes between the point at which E was introduced and R,
then R is ill-formed.
-
Otherwise, if the id-expression denotes an overload set S, overload resolution for the expression &S with no target shall select a unique function ([over.over]);R represents that function.
-
Otherwise, if the id-expression denotes a variable, structured binding, enumerator, or non-static data member,R represents that entity.
-
Otherwise, R is ill-formed. [Note 3: This includes unqualified-ids that name a constant template parameter andpack-index-expressions. â end note]
The id-expression of a reflect-expression is an unevaluated operand ([expr.context]).
[Example 3: template void fn() requires (^^T != ^^int);template void fn() requires (^^T == ^^int);template void fn() requires (sizeof(T) == sizeof(int));
constexpr std::meta::info a = ^^fn; // OKconstexpr std::meta::info b = ^^fn; // error: ambiguousconstexpr std::meta::info c = ^^std::vector; // OKtemplatestruct S {static constexpr std::meta::info r = ^^T; using type = T;};static_assert(S::r == ^^int);static_assert(^^S::type != ^^int);
typedef struct X {} Y;typedef struct Z {} Z;constexpr std::meta::info e = ^^Y; // OK, represents the type alias Yconstexpr std::meta::info f = ^^Z; // OK, represents the type alias Z, not the type ([basic.lookup.general]) â end example]