[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<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*](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<true> < 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<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>; // OKconstexpr std::meta::info b = ^^fn<int>; // error: ambiguousconstexpr std::meta::info c = ^^std::vector; // OKtemplate<typename T>struct S {static constexpr std::meta::info r = ^^T; using type = T;};static_assert(S<int>::r == ^^int);static_assert(^^S<int>::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*]
