This commit is contained in:
2025-10-25 03:02:53 +03:00
commit 043225d523
3416 changed files with 681196 additions and 0 deletions

219
cppdraft/expr/reflect.md Normal file
View File

@@ -0,0 +1,219 @@
[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.10The reflection operator[expr.reflect]")
^^ ::
^^ [*reflection-name*](#nt:reflection-name "7.6.2.10The reflection operator[expr.reflect]")
^^ [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]")
^^ [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]")
[reflection-name:](#nt:reflection-name "7.6.2.10The reflection operator[expr.reflect]")
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]")opt [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") template [*identifier*](lex.name#nt:identifier "5.11Identifiers[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.10The reflection operator[expr.reflect]"),
yields a prvalue of type std::meta::info ([[basic.fundamental]](basic.fundamental "6.9.2Fundamental 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.10The 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.10The reflection operator[expr.reflect]") are those of its [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") (if any) and
its [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")[.](#2.sentence-1)
The terminal name of a [*reflection-name*](#nt:reflection-name "7.6.2.10The reflection operator[expr.reflect]") of the form[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") template [*identifier*](lex.name#nt:identifier "5.11Identifiers[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.10The 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.10The reflection operator[expr.reflect]")[.](#3.sentence-1)
An unparenthesized [*reflect-expression*](#nt:reflect-expression "7.6.2.10The 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.2Type 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.2Type names[dcl.name]")^^X < xv; // error: [*reflect-expression*](#nt:reflect-expression "7.6.2.10The 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.10The 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.10The reflection operator[expr.reflect]") R matches
the form ^^[*reflection-name*](#nt:reflection-name "7.6.2.10The reflection operator[expr.reflect]"),
it is interpreted as such;
the [*identifier*](lex.name#nt:identifier "5.11Identifiers[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.10The using declaration[namespace.udecl]") during a single search ([[basic.lookup.general]](basic.lookup.general "6.5.1General"), [[namespace.udecl]](namespace.udecl "9.10The 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.10The 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.2Member name lookup")constexpr std::meta::info r2 = ^^D::S; // OK, result C::S not found through [*using-declarator*](namespace.udecl#nt:using-declarator "9.10The using declaration[namespace.udecl]") — *end example*]
- [(5.2)](#5.2)
Otherwise, if lookup finds a namespace alias ([[namespace.alias]](namespace.alias "9.9.3Namespace alias")),R represents that namespace alias[.](#5.2.sentence-1)
For any other [*namespace-name*](namespace.def.general#nt:namespace-name "9.9.2.1General[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.9Namespaces")),R represents that namespace[.](#5.3.sentence-1)
- [(5.4)](#5.4)
Otherwise, if lookup finds a concept ([[temp.concept]](temp.concept "13.7.9Concept 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.3Names 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.1Preamble")), then:
+
[(5.5.1.1)](#5.5.1.1)
If the [*reflection-name*](#nt:reflection-name "7.6.2.10The reflection operator[expr.reflect]") is of the form[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") template [*identifier*](lex.name#nt:identifier "5.11Identifiers[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.3Simple 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.2Anonymous unions")), R represents that class member[.](#5.8.sentence-1)
- [(5.9)](#5.9)
Otherwise,
the [*reflection-name*](#nt:reflection-name "7.6.2.10The reflection operator[expr.reflect]") shall be an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[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.10The reflection operator[expr.reflect]") R of the form^^[*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") represents an entity determined as follows:
- [(6.1)](#6.1)
If the [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") designates
a placeholder type ([[dcl.spec.auto.general]](dcl.spec.auto.general "9.2.9.7.1General")),R is ill-formed[.](#6.1.sentence-1)
- [(6.2)](#6.2)
Otherwise, if the [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") names a type alias
that is a specialization of an alias template ([[temp.alias]](temp.alias "13.7.8Alias 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.2Type 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.10The reflection operator[expr.reflect]") R of the form^^[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[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.1General[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.3Captures[expr.prim.lambda.capture]") ([[expr.prim.lambda.capture]](expr.prim.lambda.capture "7.5.6.3Captures")),
* [(7.1.2)](#7.1.2)
a function-local predefined variable ([[dcl.fct.def.general]](dcl.fct.def.general "9.6.1General")),
* [(7.1.3)](#7.1.3)
a local parameter introduced by
a [*requires-expression*](expr.prim.req.general#nt:requires-expression "7.5.8.1General[expr.prim.req.general]") ([[expr.prim.req]](expr.prim.req "7.5.8Requires expressions")), or
* [(7.1.4)](#7.1.4)
a local entity E ([[basic.pre]](basic.pre "6.1Preamble")) 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.1General[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.3Address 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.1General[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.2Unqualified 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.4Pack 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.1General[expr.prim.id.general]") of
a [*reflect-expression*](#nt:reflect-expression "7.6.2.10The reflection operator[expr.reflect]") is an unevaluated operand ([[expr.context]](expr.context "7.2.3Context 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.1General")) — *end example*]