[expr.reflect] # 7 Expressions [[expr]](./#expr) ## 7.6 Compound expressions [[expr.compound]](expr.compound#expr.reflect) ### 7.6.2 Unary expressions [[expr.unary]](expr.unary#expr.reflect) #### 7.6.2.10 The reflection operator [expr.reflect] [reflect-expression:](#nt:reflect-expression "7.6.2.10 The reflection operator [expr.reflect]") ^^ :: ^^ [*reflection-name*](#nt:reflection-name "7.6.2.10 The reflection operator [expr.reflect]") ^^ [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") ^^ [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") [reflection-name:](#nt:reflection-name "7.6.2.10 The reflection operator [expr.reflect]") [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")opt [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") template [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [1](#1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6637) The unary ^^ operator, called the [*reflection operator*](#def:operator,reflection "7.6.2.10 The reflection operator [expr.reflect]"), yields a prvalue of type std​::​meta​::​info ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types"))[.](#1.sentence-1) [*Note [1](#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-expression*](#nt:reflect-expression "7.6.2.10 The reflection operator [expr.reflect]")*s*[.](#1.sentence-2) — *end note*] [2](#2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6648) The component names of a [*reflection-name*](#nt:reflection-name "7.6.2.10 The reflection operator [expr.reflect]") are those of its [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") (if any) and its [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")[.](#2.sentence-1) The terminal name of a [*reflection-name*](#nt:reflection-name "7.6.2.10 The reflection operator [expr.reflect]") of the form[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") template [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") shall denote a template[.](#2.sentence-2) [3](#3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6656) A [*reflect-expression*](#nt:reflect-expression "7.6.2.10 The reflection operator [expr.reflect]") is parsed as the longest possible sequence of tokens that could syntactically form a [*reflect-expression*](#nt:reflect-expression "7.6.2.10 The reflection operator [expr.reflect]")[.](#3.sentence-1) An unparenthesized [*reflect-expression*](#nt:reflect-expression "7.6.2.10 The reflection operator [expr.reflect]") that represents a template shall not be followed by <[.](#3.sentence-2) [*Example [1](#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*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") 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*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]")^^X < xv; // error: [*reflect-expression*](#nt:reflect-expression "7.6.2.10 The reflection operator [expr.reflect]") that represents a template is followed by <(^^X) < xv; // OK^^X < xv; // OK} — *end example*] [4](#4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6680) A [*reflect-expression*](#nt:reflect-expression "7.6.2.10 The reflection operator [expr.reflect]") of the form ^^​::​ represents the global namespace[.](#4.sentence-1) [5](#5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6684) If a [*reflect-expression*](#nt:reflect-expression "7.6.2.10 The reflection operator [expr.reflect]") R matches the form ^^[*reflection-name*](#nt:reflection-name "7.6.2.10 The reflection operator [expr.reflect]"), it is interpreted as such; the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") is looked up and the representation of R is determined as follows: - [(5.1)](#5.1) If lookup finds a declaration that replaced a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]") during a single search ([[basic.lookup.general]](basic.lookup.general "6.5.1 General"), [[namespace.udecl]](namespace.udecl "9.10 The using declaration")),R is ill-formed[.](#5.1.sentence-1) [*Example [2](#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-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]")struct C : virtual B { struct S {}; };struct D : virtual B, C {}; D::S s; // OK, names C​::​S per [[class.member.lookup]](class.member.lookup "6.5.2 Member name lookup")constexpr std::meta::info r2 = ^^D::S; // OK, result C​::​S not found through [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]") — *end example*] - [(5.2)](#5.2) Otherwise, if lookup finds a namespace alias ([[namespace.alias]](namespace.alias "9.9.3 Namespace alias")),R represents that namespace alias[.](#5.2.sentence-1) For any other [*namespace-name*](namespace.def.general#nt:namespace-name "9.9.2.1 General [namespace.def.general]"),R represents the denoted namespace[.](#5.2.sentence-2) - [(5.3)](#5.3) Otherwise, if lookup finds a namespace ([[basic.namespace]](basic.namespace "9.9 Namespaces")),R represents that namespace[.](#5.3.sentence-1) - [(5.4)](#5.4) Otherwise, if lookup finds a concept ([[temp.concept]](temp.concept "13.7.9 Concept definitions")),R represents the denoted concept[.](#5.4.sentence-1) - [(5.5)](#5.5) Otherwise, if lookup finds a template ([[temp.names]](temp.names "13.3 Names of template specializations")), the representation of R is determined as follows: * [(5.5.1)](#5.5.1) If lookup finds an injected-class-name ([[class.pre]](class.pre "11.1 Preamble")), then: + [(5.5.1.1)](#5.5.1.1) If the [*reflection-name*](#nt:reflection-name "7.6.2.10 The reflection operator [expr.reflect]") is of the form[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") template [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]"), then R represents the class template named by the injected-class-name[.](#5.5.1.1.sentence-1) + [(5.5.1.2)](#5.5.1.2) Otherwise, the injected-class-name shall be unambiguous when considered as a [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]") andR represents the class template specialization so named[.](#5.5.1.2.sentence-1) * [(5.5.2)](#5.5.2) Otherwise, if lookup finds an overload set, that overload set shall contain only declarations of a unique function template F;R represents F[.](#5.5.2.sentence-1) * [(5.5.3)](#5.5.3) Otherwise, if lookup finds a class template, variable template, or alias template,R represents that template[.](#5.5.3.sentence-1) [*Note [2](#note-2)*: Lookup never finds a partial or explicit specialization[.](#5.5.3.sentence-2) — *end note*] - [(5.6)](#5.6) 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[.](#5.6.sentence-1) - [(5.7)](#5.7) Otherwise, if lookup finds a class or an enumeration,R represents the denoted type[.](#5.7.sentence-1) - [(5.8)](#5.8) Otherwise, if lookup finds a class member of an anonymous union ([[class.union.anon]](class.union.anon "11.5.2 Anonymous unions")), R represents that class member[.](#5.8.sentence-1) - [(5.9)](#5.9) Otherwise, the [*reflection-name*](#nt:reflection-name "7.6.2.10 The reflection operator [expr.reflect]") shall be an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") I and R is ^^I (see below)[.](#5.9.sentence-1) [6](#6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6764) A [*reflect-expression*](#nt:reflect-expression "7.6.2.10 The reflection operator [expr.reflect]") R of the form^^[*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") represents an entity determined as follows: - [(6.1)](#6.1) If the [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") designates a placeholder type ([[dcl.spec.auto.general]](dcl.spec.auto.general "9.2.9.7.1 General")),R is ill-formed[.](#6.1.sentence-1) - [(6.2)](#6.2) Otherwise, if the [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") names a type alias that is a specialization of an alias template ([[temp.alias]](temp.alias "13.7.8 Alias templates")),R represents that type alias[.](#6.2.sentence-1) - [(6.3)](#6.3) Otherwise, R represents the type denoted by the [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]")[.](#6.3.sentence-1) [7](#7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L6781) A [*reflect-expression*](#nt:reflect-expression "7.6.2.10 The reflection operator [expr.reflect]") R of the form^^[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") represents an entity determined as follows: - [(7.1)](#7.1) If the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") denotes * [(7.1.1)](#7.1.1) a variable declared by an [*init-capture*](expr.prim.lambda.capture#nt:init-capture "7.5.6.3 Captures [expr.prim.lambda.capture]") ([[expr.prim.lambda.capture]](expr.prim.lambda.capture "7.5.6.3 Captures")), * [(7.1.2)](#7.1.2) a function-local predefined variable ([[dcl.fct.def.general]](dcl.fct.def.general "9.6.1 General")), * [(7.1.3)](#7.1.3) a local parameter introduced by a [*requires-expression*](expr.prim.req.general#nt:requires-expression "7.5.8.1 General [expr.prim.req.general]") ([[expr.prim.req]](expr.prim.req "7.5.8 Requires expressions")), or * [(7.1.4)](#7.1.4) a local entity E ([[basic.pre]](basic.pre "6.1 Preamble")) for which a lambda scope intervenes between the point at which E was introduced and R, then R is ill-formed[.](#7.1.sentence-1) - [(7.2)](#7.2) Otherwise, if the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") denotes an overload set S, overload resolution for the expression &S with no target shall select a unique function ([[over.over]](over.over "12.3 Address of an overload set"));R represents that function[.](#7.2.sentence-1) - [(7.3)](#7.3) Otherwise, if the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") denotes a variable, structured binding, enumerator, or non-static data member,R represents that entity[.](#7.3.sentence-1) - [(7.4)](#7.4) Otherwise, R is ill-formed[.](#7.4.sentence-1) [*Note [3](#note-3)*: This includes [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]")*s* that name a constant template parameter and[*pack-index-expression*](expr.prim.pack.index#nt:pack-index-expression "7.5.5.4 Pack indexing expression [expr.prim.pack.index]")*s*[.](#7.4.sentence-2) — *end note*] The [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") of a [*reflect-expression*](#nt:reflect-expression "7.6.2.10 The reflection operator [expr.reflect]") is an unevaluated operand ([[expr.context]](expr.context "7.2.3 Context dependence"))[.](#7.sentence-2) [*Example [3](#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]](basic.lookup.general "6.5.1 General")) — *end example*]