Files
cppdraft_translate/cppdraft/expr/reflect.md
2025-10-25 03:02:53 +03:00

220 lines
13 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[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*]