[meta.reflection] (original) (raw)

21 Metaprogramming library [meta]


21.4.1 Header synopsis [meta.syn]

21.4.2 Checking string literals [meta.string.literal]

21.4.3 Promoting to static storage [meta.define.static]

21.4.4 Class exception [meta.reflection.exception]

21.4.5 Operator representations [meta.reflection.operators]

21.4.6 Reflection names and locations [meta.reflection.names]

21.4.7 Reflection queries [meta.reflection.queries]

21.4.8 Access control context [meta.reflection.access.context]

21.4.9 Member accessibility queries [meta.reflection.access.queries]

21.4.10 Reflection member queries [meta.reflection.member.queries]

21.4.11 Reflection layout queries [meta.reflection.layout]

21.4.12 Annotation reflection [meta.reflection.annotation]

21.4.13 Value extraction [meta.reflection.extract]

21.4.14 Reflection substitution [meta.reflection.substitute]

21.4.15 Expression result reflection [meta.reflection.result]

21.4.16 Reflection class definition generation [meta.reflection.define.aggregate]

21.4.17 Reflection type traits [meta.reflection.traits]


21.4.1 Header synopsis [meta.syn]

21.4.2 Checking string literals [meta.string.literal]

consteval bool is_string_literal(const char* p);consteval bool is_string_literal(const wchar_t* p);consteval bool is_string_literal(const char8_t* p);consteval bool is_string_literal(const char16_t* p);consteval bool is_string_literal(const char32_t* p);

21.4.3 Promoting to static storage [meta.define.static]

template<ranges::[input_range](range.refinements#concept:input%5Frange "25.4.6 Other range refinements [range.refinements]") R> consteval info reflect_constant_string(R&& r);

template<ranges::[input_range](range.refinements#concept:input%5Frange "25.4.6 Other range refinements [range.refinements]") R> consteval info reflect_constant_array(R&& r);

template<ranges::[input_range](range.refinements#concept:input%5Frange "25.4.6 Other range refinements [range.refinements]") R> consteval const ranges::range_value_t<R>* define_static_string(R&& r);

template<ranges::[input_range](range.refinements#concept:input%5Frange "25.4.6 Other range refinements [range.refinements]") R> consteval span<const ranges::range_value_t<R>> define_static_array(R&& r);

template<class T> consteval const remove_cvref_t<T>* define_static_object(T&& t);

21.4.4 Class exception [meta.reflection.exception]

namespace std::meta { class exception : public std::exception { private: optional<string> what_; u8string u8what_; info from_; source_location where_; public: consteval exception(u8string_view what, info from, source_location where = source_location::current()) noexcept;consteval exception(string_view what, info from, source_location where = source_location::current()) noexcept; exception(const exception&) = default; exception(exception&&) = default; exception& operator=(const exception&) = default; exception& operator=(exception&&) = default;constexpr const char* what() const noexcept override;consteval u8string_view u8what() const noexcept;consteval info from() const noexcept;consteval source_location where() const noexcept;};}

Reflection functions throw exceptions of type meta​::​exceptionto signal an error.

meta​::​exception is a consteval-only type.

consteval exception(u8string_view what, info from, source_location where = source_location::current()) noexcept;

Effects: Initializes_u8what__ with what,from_ with from, and_where__ with where.

If what can be represented in the ordinary literal encoding, initializes what_ with what, transcoded from UTF-8 to the ordinary literal encoding.

Otherwise, what_ is value-initialized.

consteval exception(string_view what, info from, source_location where = source_location::current()) noexcept;

Constant When: what designates a sequence of characters that can be encoded in UTF-8.

Effects: Initializes_what__ with what,u8what_ with whattranscoded from the ordinary literal encoding to UTF-8,from_ with from and_where__ with where.

constexpr const char* what() const noexcept override;

Constant When: what_.has_value() is true.

consteval u8string_view u8what() const noexcept;

consteval info from() const noexcept;

consteval source_location where() const noexcept;

21.4.5 Operator representations [meta.reflection.operators]

enum class [operators](#lib:operators "21.4.5 Operator representations [meta.reflection.operators]") { _see below_;};using enum operators;

The enumeration type operators specifies constants used to identify operators that can be overloaded, with the meanings listed in Table 63.

The values of the constants are distinct.

consteval operators operator_of(info r);

Returns: The value of the enumerator from operatorswhose corresponding operator-function-idis the unqualified name of the entity represented by r.

Throws: meta​::​exception unlessr represents an operator function or operator function template.

consteval string_view symbol_of(operators op);consteval u8string_view u8symbol_of(operators op);

Returns: A string_view or u8string_viewcontaining the characters of the operator symbol name corresponding to op, respectively encoded with the ordinary literal encoding or with UTF-8.

Throws: meta​::​exception unless the value of op corresponds to one of the enumerators in operators.

21.4.6 Reflection names and locations [meta.reflection.names]

consteval bool has_identifier(info r);

Returns:

consteval string_view identifier_of(info r);consteval u8string_view u8identifier_of(info r);

Let E be UTF-8 for u8identifier_of, and otherwise the ordinary literal encoding.

Returns: An ntmbs, encoded with E, determined as follows:

Throws: meta​::​exception unlesshas_identifier(r) is trueand the identifier that would be returned (see above) is representable by E.

consteval string_view display_string_of(info r);consteval u8string_view u8display_string_of(info r);

Returns: Animplementation-definedstring_view or u8string_view, respectively.

Recommended practice: Where possible, implementations should return a string suitable for identifying the represented construct.

consteval source_location source_location_of(info r);

Returns: If r represents a value, a type other than a class type or an enumeration type, the global namespace, or a data member description, then source_location{}.

Otherwise, animplementation-definedsource_location value.

Recommended practice: If r represents an entity with a definition that is reachable from the evaluation context, a value corresponding to a definition should be returned.

21.4.7 Reflection queries [meta.reflection.queries]

consteval bool _has-type_(info r); // _exposition only_

Returns: true if r represents a value, annotation, object, variable, function whose type does not contain an undeduced placeholder type and that is not a constructor or destructor, enumerator, non-static data member, unnamed bit-field, direct base class relationship, data member description, or function parameter.

Otherwise, false.

consteval info type_of(info r);

Returns:

Throws: meta​::​exception unless_has-type_(r) is true.

consteval info object_of(info r);

Returns:

Throws: meta​::​exception unlessr is a reflection representing either

[Example 1: int x;int& y = x;static_assert(^^x != ^^y); static_assert(object_of(^^x) == object_of(^^y)); — _end example_]

consteval info constant_of(info r);

Let R be a constant expression of type infosuch that R == r is true.

If r represents an annotation, then let C be its underlying constant.

Effects: Equivalent to:if constexpr (is_annotation(R)) { return C;} else if constexpr (is_array_type(type_of(R))) { return reflect_constant_array([: R :]);} else if constexpr (is_function_type(type_of(R))) { return reflect_function([: R :]);} else { return reflect_constant([: R :]);}

[Example 2: constexpr int x = 0;constexpr int y = 0;static_assert(^^x != ^^y); static_assert(constant_of(^^x) == constant_of(^^y)); static_assert(constant_of(^^x) == reflect_constant(0)); struct S { int m; };constexpr S s {42};static_assert(is_object(constant_of(^^s)) && is_object(reflect_object(s)));static_assert(constant_of(^^s) != reflect_object(s)); static_assert(constant_of(^^s) == constant_of(reflect_object(s))); consteval info fn() { constexpr int x = 42;return ^^x;} constexpr info r = constant_of(fn()); — _end example_]

consteval bool is_public(info r);consteval bool is_protected(info r);consteval bool is_private(info r);

Returns: true if r represents either

Otherwise, false.

consteval bool is_virtual(info r);

Returns: true if r represents either a virtual member function or a direct base class relationship for which B is a virtual base class of D.

Otherwise, false.

consteval bool is_pure_virtual(info r);consteval bool is_override(info r);

Returns: true if r represents a member function that is pure virtual or overrides another member function, respectively.

Otherwise, false.

consteval bool is_final(info r);

Returns: true if r represents a final class or a final member function.

Otherwise, false.

consteval bool is_deleted(info r);consteval bool is_defaulted(info r);

consteval bool is_user_provided(info r);consteval bool is_user_declared(info r);

Returns: true if r represents a function that is user-provided or user-declared ([dcl.fct.def.default]), respectively.

Otherwise, false.

consteval bool is_explicit(info r);

Returns: true if r represents a member function that is declared explicit.

Otherwise, false.

[Note 1:

If r represents a member function template that is declared explicit,is_explicit(r) is still falsebecause in general, such queries for templates cannot be answered.

— _end note_]

consteval bool is_noexcept(info r);

Returns: true if r represents a noexcept function type or a function with a non-throwing exception specification ([except.spec]).

Otherwise, false.

[Note 2:

If r represents a function template that is declared noexcept,is_noexcept(r) is still falsebecause in general, such queries for templates cannot be answered.

— _end note_]

consteval bool is_bit_field(info r);

Returns: true if r represents a bit-field, or if r represents a data member description ([class.mem.general]) for which W is not ⊥.

Otherwise, false.

consteval bool is_enumerator(info r);consteval bool is_annotation(info r);

Returns: true if r represents an enumerator or annotation, respectively.

Otherwise, false.

consteval bool is_const(info r);consteval bool is_volatile(info r);

Let T be type_of(r) if has-type(r) is true.

Otherwise, let T be dealias(r).

Returns: true if T represents a const or volatile type, respectively, or a const- or volatile-qualified function type, respectively.

Otherwise, false.

consteval bool is_mutable_member(info r);

Returns: true if r represents a mutable non-static data member.

Otherwise, false.

consteval bool is_lvalue_reference_qualified(info r);consteval bool is_rvalue_reference_qualified(info r);

Let T be type_of(r) if has-type(r) is true.

Otherwise, let T be dealias(r).

Returns: true if T represents an lvalue- or rvalue-qualified function type, respectively.

Otherwise, false.

consteval bool has_static_storage_duration(info r);consteval bool has_thread_storage_duration(info r);consteval bool has_automatic_storage_duration(info r);

Returns: true if r represents an object or variable that has static, thread, or automatic storage duration, respectively ([basic.stc]).

Otherwise, false.

[Note 3:

It is not possible to have a reflection representing an object or variable having dynamic storage duration.

— _end note_]

consteval bool has_internal_linkage(info r);consteval bool has_module_linkage(info r);consteval bool has_external_linkage(info r);consteval bool has_linkage(info r);

Returns: true if r represents a variable, function, type, template, or namespace whose name has internal linkage, module linkage, external linkage, or any linkage, respectively ([basic.link]).

Otherwise, false.

consteval bool has_c_language_linkage(info r);

Returns: true if r represents a variable, function, or function type with C language linkage.

Otherwise, false.

consteval bool is_complete_type(info r);

Returns: true if is_type(r) is trueand there is some point in the evaluation context from which the type represented by dealias(r)is not an incomplete type ([basic.types]).

Otherwise, false.

consteval bool is_enumerable_type(info r);

A type T is enumerable from a point P if either

Returns: true if dealias(r) represents a type that is enumerable from some point in the evaluation context.

Otherwise, false.

[Example 3: class S;enum class E;static_assert(!is_enumerable_type(^^S));static_assert(!is_enumerable_type(^^E));class S { void mfn() { static_assert(is_enumerable_type(^^S));} static_assert(!is_enumerable_type(^^S));};static_assert(is_enumerable_type(^^S));enum class E { A = is_enumerable_type(^^E) ? 1 : 2 };static_assert(is_enumerable_type(^^E));static_assert(static_cast<int>(E::A) == 2); — _end example_]

consteval bool is_variable(info r);

Returns: true if r represents a variable.

Otherwise, false.

consteval bool is_type(info r);consteval bool is_namespace(info r);

Returns: true if r represents an entity whose underlying entity is a type or namespace, respectively.

Otherwise, false.

consteval bool is_type_alias(info r);consteval bool is_namespace_alias(info r);

Returns: true if r represents a type alias or namespace alias, respectively.

Otherwise, false.

[Note 4:

A specialization of an alias template is a type alias.

— _end note_]

consteval bool is_function(info r);

Returns: true if r represents a function.

Otherwise, false.

consteval bool is_conversion_function(info r);consteval bool is_operator_function(info r);consteval bool is_literal_operator(info r);

consteval bool is_special_member_function(info r);consteval bool is_constructor(info r);consteval bool is_default_constructor(info r);consteval bool is_copy_constructor(info r);consteval bool is_move_constructor(info r);consteval bool is_assignment(info r);consteval bool is_copy_assignment(info r);consteval bool is_move_assignment(info r);consteval bool is_destructor(info r);

Returns: true if r represents a function that is a special member function ([special]), a constructor, a default constructor, a copy constructor, a move constructor, an assignment operator, a copy assignment operator, a move assignment operator, or a destructor, respectively.

Otherwise, false.

consteval bool is_function_parameter(info r);

Returns: true if r represents a function parameter.

Otherwise, false.

consteval bool is_explicit_object_parameter(info r);

Returns: true if r represents a function parameter that is an explicit object parameter ([dcl.fct]).

Otherwise, false.

consteval bool has_default_argument(info r);

Returns: If r represents a parameter P of a function F, then:

Otherwise, false.

consteval bool has_ellipsis_parameter(info r);

Returns: true if r represents a function or function type that has an ellipsis in its parameter-type-list ([dcl.fct]).

Otherwise, false.

consteval bool is_template(info r);

Returns: true if r represents a function template, class template, variable template, alias template, or concept.

Otherwise, false.

[Note 5:

A template specialization is not a template.

For example,is_template(​^^std​::​vector) is truebut is_template(​^^std​::​vector<int>) is false.

— _end note_]

consteval bool is_function_template(info r);consteval bool is_variable_template(info r);consteval bool is_class_template(info r);consteval bool is_alias_template(info r);consteval bool is_conversion_function_template(info r);consteval bool is_operator_function_template(info r);consteval bool is_literal_operator_template(info r);consteval bool is_constructor_template(info r);consteval bool is_concept(info r);

Returns: true if r represents a function template, variable template, class template, alias template, conversion function template, operator function template, literal operator template, constructor template, or concept, respectively.

Otherwise, false.

consteval bool is_value(info r);consteval bool is_object(info r);

Returns: true if r represents a value or object, respectively.

Otherwise, false.

consteval bool is_structured_binding(info r);

Returns: true if r represents a structured binding.

Otherwise, false.

consteval bool is_class_member(info r);consteval bool is_namespace_member(info r);consteval bool is_nonstatic_data_member(info r);consteval bool is_static_member(info r);consteval bool is_base(info r);

Returns: true if r represents a class member, namespace member, non-static data member, static member, or direct base class relationship, respectively.

Otherwise, false.

consteval bool has_default_member_initializer(info r);

Returns: true if r represents a non-static data member that has a default member initializer.

Otherwise, false.

consteval bool has_parent(info r);

Returns:

consteval info parent_of(info r);

Returns:

Throws: meta​::​exception unlesshas_parent(r) is true.

[Example 4: struct I { };struct F : I { union { int o;};enum N { A};};constexpr auto ctx = std::meta::access_context::current();static_assert(parent_of(^^F) == ^^::);static_assert(parent_of(bases_of(^^F, ctx)[0]) == ^^F);static_assert(is_union_type(parent_of(^^F::o)));static_assert(parent_of(^^F::N) == ^^F);static_assert(parent_of(^^F::A) == ^^F::N); — _end example_]

consteval info dealias(info r);

Returns: If r represents an entity, then a reflection representing the underlying entity of what r represents.

Otherwise, r.

[Example 5: using X = int;using Y = X;static_assert(dealias(^^int) == ^^int);static_assert(dealias(^^X) == ^^int);static_assert(dealias(^^Y) == ^^int); — _end example_]

consteval bool has_template_arguments(info r);

Returns: true if r represents a specialization of a function template, variable template, class template, or an alias template.

Otherwise, false.

consteval info template_of(info r);

Returns: A reflection of the template of the specialization represented by r.

Throws: meta​::​exception unlesshas_template_arguments(r) is true.

consteval vector<info> template_arguments_of(info r);

Returns: A vector containing reflections of the template arguments of the template specialization represented by r, in the order in which they appear in the corresponding template argument list.

For a given template argument A, its corresponding reflection R is determined as follows:

Throws: meta​::​exception unlesshas_template_arguments(r) is true.

[Example 6: template<class T, class U = T> struct Pair { };template<class T> struct Pair<char, T> { };template<class T> using PairPtr = Pair<T*>;static_assert(template_of(^^Pair<int>) == ^^Pair);static_assert(template_of(^^Pair<char, char>) == ^^Pair);static_assert(template_arguments_of(^^Pair<int>).size() == 2);static_assert(template_arguments_of(^^Pair<int>)[0] == ^^int);static_assert(template_of(^^PairPtr<int>) == ^^PairPtr);static_assert(template_arguments_of(^^PairPtr<int>).size() == 1);struct S { };int i;template<int, int&, S, template<class> class> struct X { };constexpr auto T = ^^X<1, i, S{}, PairPtr>;static_assert(is_value(template_arguments_of(T)[0]));static_assert(is_object(template_arguments_of(T)[1]));static_assert(is_object(template_arguments_of(T)[2]));static_assert(template_arguments_of(T)[3] == ^^PairPtr); — _end example_]

consteval vector<info> parameters_of(info r);

Returns:

Throws: meta​::​exception unlessr represents a function or a function type.

consteval info variable_of(info r);

Returns: The reflection of the parameter variable corresponding to r.

Throws: meta​::​exception unless

consteval info return_type_of(info r);

Returns: The reflection of the return type of the function or function type represented by r.

Throws: meta​::​exception unless either r represents a function and has-type(r) is trueor r represents a function type.

21.4.8 Access control context [meta.reflection.access.context]

The class access_contextrepresents a namespace, class, or function from which queries pertaining to access rules may be performed, as well as the designating class ([class.access.base]), if any.

An access_context has an associated scope and designating class.

namespace std::meta { struct access_context { access_context() = delete;consteval info scope() const;consteval info designating_class() const;static consteval access_context current() noexcept;static consteval access_context unprivileged() noexcept;static consteval access_context unchecked() noexcept;consteval access_context via(info cls) const;};}

The type access_context is a structural, consteval-only, non-aggregate type.

Two values ac1 and ac2 of type access_contextare template-argument-equivalent ([temp.type]) if ac1.scope() and ac2.scope() are template-argument-equivalent and ac1.designating_class() and ac2.designating_class()are template-argument-equivalent.

consteval info [scope](#lib:access%5Fcontext,scope "21.4.8 Access control context [meta.reflection.access.context]")() const;consteval info [designating_class](#lib:access%5Fcontext,designating%5Fclass "21.4.8 Access control context [meta.reflection.access.context]")() const;

Returns: The access_context's associated scope and designating class, respectively.

static consteval access_context [current](#lib:access%5Fcontext,current "21.4.8 Access control context [meta.reflection.access.context]")() noexcept;

Given a program point P, let eval-point(P) be the following program point:

Given a scope S, let ctx-scope(S) be the following scope:

Returns: An access_context whose designating class is the null reflection and whose scope represents the function, class, or namespace whose corresponding function parameter scope, class scope, or namespace scope, respectively, is ctx-scope(S), where S is the immediate scope of eval-point(P)and P is the point at which the invocation of current lexically appears.

Remarks: current is not an addressable function ([namespace.std]).

An invocation of current that appears at a program point Pis value-dependent ([temp.dep.constexpr]) if _eval-point_​(​P) is enclosed by a scope corresponding to a templated entity.

[Example 1: struct A { int a = 0;consteval A(int p) : a(p) {} };struct B : A { using A::A;consteval B(int p, int q) : A(p * q) {} info s = access_context::current().scope();};struct C : B { using B::B; };struct Agg { consteval bool eq(info rhs = access_context::current().scope()) { return s == rhs;} info s = access_context::current().scope();};namespace NS { static_assert(Agg{}.s == access_context::current().scope()); static_assert(Agg{}.eq()); static_assert(B(1).s == ^^B); static_assert(is_constructor(B{1, 2}.s) && parent_of(B{1, 2}.s) == ^^B); static_assert(is_constructor(C{1, 2}.s) && parent_of(C{1, 2}.s) == ^^B); auto fn() -> [:is_namespace(access_context::current().scope()) ? ^^int : ^^bool:];static_assert(type_of(^^fn) == ^^auto()->int); template<auto R> struct TCls { consteval bool fn() requires (is_type(access_context::current().scope())) { return true; } };static_assert(TCls<0>{}.fn()); } — _end example_]

static consteval access_context [unprivileged](#lib:access%5Fcontext,unprivileged "21.4.8 Access control context [meta.reflection.access.context]")() noexcept;

Returns: An access_context whose designating class is the null reflection and whose scope is the global namespace.

static consteval access_context [unchecked](#lib:access%5Fcontext,unchecked "21.4.8 Access control context [meta.reflection.access.context]")() noexcept;

Returns: An access_context whose designating class and scope are both the null reflection.

consteval access_context [via](#lib:access%5Fcontext,via "21.4.8 Access control context [meta.reflection.access.context]")(info cls) const;

Returns: An access_context whose scope is this->scope()and whose designating class is cls.

Throws: meta​::​exception unlesscls is either the null reflection or a reflection of a complete class type.

21.4.9 Member accessibility queries [meta.reflection.access.queries]

consteval bool is_accessible(info r, access_context ctx);

Let PARENT-CLS(r) be:

Let DESIGNATING-CLS(r, ctx) be:

Returns:

[Note 2:

The definitions of when a class member or base class is accessible from a point Pdo not consider whether a declaration of that entity is reachable from P.

— _end note_]

Throws: meta​::​exception ifr represents a class member for which PARENT-CLS(r) is an incomplete class.

[Example 1: consteval access_context fn() { return access_context::current();} class Cls { int mem;friend consteval access_context fn();public: static constexpr auto r = ^^mem;};static_assert(is_accessible(Cls::r, fn())); static_assert(!is_accessible(Cls::r, access_context::current())); static_assert(is_accessible(Cls::r, access_context::unchecked())); — _end example_]

consteval bool has_inaccessible_nonstatic_data_members(info r, access_context ctx);

Returns: true if is_accessible(R, ctx) is falsefor any R in nonstatic_data_members_of(​r, access_context​​::​unchecked()).

Otherwise, false.

Throws: meta​::​exception if

consteval bool has_inaccessible_bases(info r, access_context ctx);

Returns: true if is_accessible(R, ctx) is falsefor any R in bases_of(​r, access_context​::​​unchecked()).

Otherwise, false.

Throws: meta​::​exception if the evaluation ofbases_of(r, access_context​::​unchecked())would exit via an exception.

consteval bool has_inaccessible_subobjects(info r, access_context ctx);

Effects: Equivalent to:return has_inaccessible_bases(r, ctx) || has_inaccessible_nonstatic_data_members(r, ctx);

21.4.10 Reflection member queries [meta.reflection.member.queries]

consteval vector<info> members_of(info r, access_context ctx);

A declaration D members-of-precedes a point Pif D precedes either Por the point immediately following the class-specifierof the outermost class for which P is in a complete-class context.

A declaration D of a member M of a class or namespace Q isQ-members-of-eligible if

It is implementation-defined whether declarations of other members of a closure type Qare Q-members-of-eligible.

A member M of a class or namespace Q isQ-members-of-representable from a point Pif a Q-members-of-eligible declaration of M members-of-precedes P, and M is

Returns: A vector containing reflections of all members Mof the entity Q represented by dealias(r) for which

If dealias(r) represents a class C, then the vector also contains reflections representing all unnamed bit-fields Bwhose declarations inhabit the class scope corresponding to Cfor which is_accessible(^^B, ctx) is true.

Reflections of class members and unnamed bit-fields that are declared appear in the order in which they are declared.

[Note 2:

Base classes are not members.

Implicitly-declared special members appear after any user-declared members ([special]).

— _end note_]

Throws: meta​::​exception unlessdealias(r) is a reflection representing either a class type that is complete from some point in the evaluation context or a namespace.

[Example 1: export module M;namespace NS { export int m;static int l;} static_assert(members_of(^^NS, access_context::current()).size() == 2);import M;static_assert( members_of(^^NS, access_context::current()).size() == 1); class B {};struct S : B { private: class I;public: int m;};static_assert( members_of(^^S, access_context::current()).size() == 7); static_assert( members_of(^^S, access_context::unchecked()).size() == 8); — _end example_]

consteval vector<info> bases_of(info type, access_context ctx);

Returns: Let C be the class represented by dealias(type).

A vector containing the reflections of all the direct base class relationships B, if any, of C such that is_accessible(^^B, ctx) is true.

The direct base class relationships appear in the order in which the corresponding base classes appear in the base-specifier-list of C.

Throws: meta​::​exception unlessdealias(type) represents a class type that is complete from some point in the evaluation context.

consteval vector<info> static_data_members_of(info type, access_context ctx);

Returns: A vector containing each element e of members_of(type, ctx)such that is_variable(e) is true, preserving their order.

Throws: meta​::​exception unlessdealias(type) represents a class type that is complete from some point in the evaluation context.

consteval vector<info> nonstatic_data_members_of(info type, access_context ctx);

Returns: A vector containing each element e of members_of(type, ctx)such that is_nonstatic_data_member(e) is true, preserving their order.

Throws: meta​::​exception unlessdealias(type) represents a class type that is complete from some point in the evaluation context.

consteval vector<info> subobjects_of(info type, access_context ctx);

Returns: A vector containing each element of bases_of(type, ctx)followed by each element of nonstatic_data_members_of(​type,​ ctx), preserving their order.

Throws: meta​::​exception unlessdealias(type) represents a class type that is complete from some point in the evaluation context.

consteval vector<info> enumerators_of(info type_enum);

Returns: A vector containing the reflections of each enumerator of the enumeration represented by dealias(type_enum), in the order in which they are declared.

Throws: meta​::​exception unlessdealias(type_enum) represents an enumeration type, and is_enumerable_type(​type_enum) is true.

21.4.11 Reflection layout queries [meta.reflection.layout]

struct member_offset { ptrdiff_t bytes; ptrdiff_t bits;constexpr ptrdiff_t total_bits() const;auto operator<=>(const member_offset&) const = default;};constexpr ptrdiff_t member_offset::total_bits() const;

Returns: bytes * CHAR_BIT + bits.

consteval member_offset offset_of(info r);

Let V be the offset in bits from the beginning of a complete object of the type represented by parent_of(r)to the subobject associated with the construct represented by r.

Returns: {V / CHAR_BIT, V % CHAR_BIT}.

Throws: meta​::​exception unlessr represents a non-static data member, unnamed bit-field, or direct base class relationship for which either B is not a virtual base class or D is not an abstract class.

consteval size_t size_of(info r);

Returns: If

then sizeof(T) if T is not a reference type and size_of(add_pointer(​^^T)) otherwise.

Otherwise, size_of(type_of(r)).

[Note 1:

It is possible that while sizeof(char)​ == size_of(^^char)is true, that sizeof(char&)​ == size_of(​^^char&)is false.

If b represents a direct base class relationship of an empty base class, then size_of(b) > 0 is true.

— _end note_]

Throws: meta​::​exception unless all of the following conditions are met:

consteval size_t alignment_of(info r);

Returns:

Throws: meta​::​exception unless all of the following conditions are met:

consteval size_t bit_size_of(info r);

Returns:

Throws: meta​::​exception unless all of the following conditions are met:

21.4.12 Annotation reflection [meta.reflection.annotation]

consteval vector<info> annotations_of(info item);

Let E be

Returns: A vector containing all of the reflections Rrepresenting each annotation applying to each declaration of E that precedes either some point in the evaluation context ([expr.const]) or a point immediately following the class-specifierof the outermost class for which such a point is in a complete-class context.

For any two reflections and in the returned vector, if the annotation represented by precedes the annotation represented by , then appears before .

If and represent annotations from the same translation unit T, any element in the returned vector between and represents an annotation from T.

[Note 1:

The order in which two annotations appear is otherwise unspecified.

— _end note_]

Throws: meta​::​exception unlessitem represents a type, type alias, variable, function, namespace, enumerator, direct base class relationship, or non-static data member.

[Example 1: [[=1]] void f();[[=2, =3]] void g();void g [[=4]] ();static_assert(annotations_of(^^f).size() == 1);static_assert(annotations_of(^^g).size() == 3);static_assert([: constant_of(annotations_of(^^g)[0]) :] == 2);static_assert(extract<int>(annotations_of(^^g)[1]) == 3);static_assert(extract<int>(annotations_of(^^g)[2]) == 4);struct Option { bool value; };struct C { [[=Option{true}]] int a;[[=Option{false}]] int b;};static_assert(extract<Option>(annotations_of(^^C::a)[0]).value);static_assert(!extract<Option>(annotations_of(^^C::b)[0]).value);template<class T> struct [[=42]] D { };constexpr std::meta::info a1 = annotations_of(^^D<int>)[0];constexpr std::meta::info a2 = annotations_of(^^D<char>)[0];static_assert(a1 != a2);static_assert(constant_of(a1) == constant_of(a2));[[=1]] int x, y;static_assert(annotations_of(^^x)[0] == annotations_of(^^y)[0]); — _end example_]

consteval vector<info> annotations_of_with_type(info item, info type);

Returns: A vector containing each element e of annotations_of(item)whereremove_const(type_of(e)) == remove_const(type) is true, preserving their order.

Throws: meta​::​exception unless

21.4.14 Reflection substitution [meta.reflection.substitute]

Let TARG-SPLICE(x) be:

template<class R> concept [reflection_range](#concept:reflection%5Frange "21.4.14 Reflection substitution [meta.reflection.substitute]") = ranges::[input_range](range.refinements#concept:input%5Frange "25.4.6 Other range refinements [range.refinements]")<R> && [same_as](concept.same#concept:same%5Fas "18.4.2 Concept same_­as [concept.same]")<ranges::range_value_t<R>, info> && [same_as](concept.same#concept:same%5Fas "18.4.2 Concept same_­as [concept.same]")<remove_cvref_t<ranges::range_reference_t<R>>, info>;template<[reflection_range](#concept:reflection%5Frange "21.4.14 Reflection substitution [meta.reflection.substitute]") R = initializer_list<info>> consteval bool [can_substitute](#lib:can%5Fsubstitute "21.4.14 Reflection substitution [meta.reflection.substitute]")(info templ, R&& arguments);

Let Z be the template represented by templand let Args... be a sequence of prvalue constant expressions that compute the reflections held by the elements of arguments, in order.

Returns: true if Z<_TARG-SPLICE_(Args)...> is a valid template-id ([temp.names]) that does not name a function whose type contains an undeduced placeholder type.

Otherwise, false.

Throws: meta​::​exception unlesstempl represents a template, and every reflection in arguments represents a construct usable as a template argument ([temp.arg]).

[Note 1:

If forming Z<_TARG-SPLICE_(Args)...> leads to a failure outside of the immediate context, the program is ill-formed.

— _end note_]

template<[reflection_range](#concept:reflection%5Frange "21.4.14 Reflection substitution [meta.reflection.substitute]") R = initializer_list<info>> consteval info substitute(info templ, R&& arguments);

Let Z be the template represented by templand let Args... be a sequence of prvalue constant expressions that compute the reflections held by the elements of arguments, in order.

Returns: ^^Z<_TARG-SPLICE_(Args)...>.

Throws: meta​::​exception unlesscan_substitute(templ, arguments) is true.

[Note 2:

If forming Z<_TARG-SPLICE_(Args)...> leads to a failure outside of the immediate context, the program is ill-formed.

— _end note_]

[Example 1: template<class T> auto fn1();static_assert(!can_substitute(^^fn1, {^^int})); constexpr info r1 = substitute(^^fn1, {^^int}); template<class T> auto fn2() { static_assert(^^T != ^^int); return 0;} constexpr bool r2 = can_substitute(^^fn2, {^^int}); — _end example_]

[Example 2: consteval info to_integral_constant(unsigned i) { return substitute(^^integral_constant, {^^unsigned, reflect_constant(i)});} constexpr info r = to_integral_constant(2); — _end example_]

21.4.15 Expression result reflection [meta.reflection.result]

template<class T> consteval info reflect_constant(T expr);

Mandates: is_copy_constructible_v<T> is trueand T is a cv-unqualified structural type ([temp.param]) that is not a reference type.

Let V be:

Let TCls be the invented template:template<T P> struct TCls;

Returns: template_arguments_of(^^TCls<V>)[0].

[Note 1:

This is a reflection of an object for class types, and a reflection of a value otherwise.

— _end note_]

Throws: meta​::​exception unless the template-id TCls<V> would be valid.

[Example 1: template<auto D> struct A { };struct N { int x; };struct K { char const* p; };constexpr info r1 = reflect_constant(42);static_assert(is_value(r1));static_assert(r1 == template_arguments_of(^^A<42>)[0]);constexpr info r2 = reflect_constant(N{42});static_assert(is_object(r2));static_assert(r2 == template_arguments_of(^^A<N{42}>)[0]);constexpr info r3 = reflect_constant(K{nullptr}); constexpr info r4 = reflect_constant(K{"ebab"}); — _end example_]

template<class T> consteval info reflect_object(T& expr);

Mandates: T is an object type.

Returns: A reflection of the object designated by expr.

Throws: meta​::​exception ifE is not suitable for use as a constant template argument for a constant template parameter of type T& ([temp.arg.nontype]), where E is an lvalue constant expression that computes the object that expr refers to.

template<class T> consteval info reflect_function(T& fn);

Mandates: T is a function type.

Returns: A reflection of the function designated by fn.

Throws: meta​::​exception ifF is not suitable for use as a constant template argument for a constant template parameter of type T& ([temp.arg.nontype]), where F is an lvalue constant expression that computes the function that fn refers to.

21.4.16 Reflection class definition generation [meta.reflection.define.aggregate]

namespace std::meta { struct data_member_options { struct name-type { template<class T> requires constructible_from<u8string, T> consteval name-type(T&&);template<class T> requires constructible_from<string, T> consteval name-type(T&&);private: variant<u8string, string> contents; }; optional<_name-type_> name; optional<int> alignment; optional<int> bit_width;bool no_unique_address = false;};}

template<class T> requires [constructible_from](concept.constructible#concept:constructible%5Ffrom "18.4.11 Concept constructible_­from [concept.constructible]")<u8string, T> consteval _name-type_(T&& value);

Effects: Initializes _contents_with u8string(std​::​forward<T>(value)).

Effects: Initializes _contents_with string(std​::​forward<T>(value)).

[Note 1:

The class name-type allows the function data_member_spec to accept an ordinary string literal (or string_view, string, etc.)

or a UTF-8 string literal (or u8string_view, u8string, etc.)

equally well.

[Example 1: consteval void fn() { data_member_options o1 = {.name = "ordinary_literal_encoding"}; data_member_options o2 = {.name = u8"utf8_encoding"};} — _end example_]

— _end note_]

consteval info data_member_spec(info type, data_member_options options);

Returns: A reflection of a data member description ([class.mem.general]) where

[Note 2:

The returned reflection value is primarily useful in conjunction with define_aggregate; it can also be queried by certain other functions in std​::​meta(e.g., type_of, identifier_of).

— _end note_]

Throws: meta​::​exception unless the following conditions are met:

consteval bool is_data_member_spec(info r);

Returns: true if r represents a data member description.

Otherwise, false.

template<[reflection_range](#concept:reflection%5Frange "21.4.14 Reflection substitution [meta.reflection.substitute]") R = initializer_list<info>> consteval info define_aggregate(info class_type, R&& mdescrs);

Let C be the type represented by class_typeand be the reflection value in mdescrs.

For every in mdescrs, let be the corresponding data member description represented by .

Constant When:

Effects: Produces an injected declaration D ([expr.const]) that defines C and has properties as follows:

Remarks: If C is a specialization of a templated class and it has not been instantiated,C is treated as an explicit specialization.

21.4.17 Reflection type traits [meta.reflection.traits]

This subclause specifies consteval functions to query the properties of types ([meta.unary]), query the relationships between types ([meta.rel]), or transform types ([meta.trans]), during program translation.

Each consteval function declared in this class has an associated class template declared elsewhere in this document.

Every function and function template declared in this subclause throws an exception of type meta​::​exceptionunless the following conditions are met:

consteval bool is_void_type(info type);consteval bool is_null_pointer_type(info type);consteval bool is_integral_type(info type);consteval bool is_floating_point_type(info type);consteval bool is_array_type(info type);consteval bool is_pointer_type(info type);consteval bool is_lvalue_reference_type(info type);consteval bool is_rvalue_reference_type(info type);consteval bool is_member_object_pointer_type(info type);consteval bool is_member_function_pointer_type(info type);consteval bool is_enum_type(info type);consteval bool is_union_type(info type);consteval bool is_class_type(info type);consteval bool is_function_type(info type);consteval bool is_reflection_type(info type);consteval bool is_reference_type(info type);consteval bool is_arithmetic_type(info type);consteval bool is_fundamental_type(info type);consteval bool is_object_type(info type);consteval bool is_scalar_type(info type);consteval bool is_compound_type(info type);consteval bool is_member_pointer_type(info type);consteval bool is_const_type(info type);consteval bool is_volatile_type(info type);consteval bool is_trivially_copyable_type(info type);consteval bool is_standard_layout_type(info type);consteval bool is_empty_type(info type);consteval bool is_polymorphic_type(info type);consteval bool is_abstract_type(info type);consteval bool is_final_type(info type);consteval bool is_aggregate_type(info type);consteval bool is_consteval_only_type(info type);consteval bool is_signed_type(info type);consteval bool is_unsigned_type(info type);consteval bool is_bounded_array_type(info type);consteval bool is_unbounded_array_type(info type);consteval bool is_scoped_enum_type(info type);template<reflection_range R = initializer_list<info>> consteval bool is_constructible_type(info type, R&& type_args);consteval bool is_default_constructible_type(info type);consteval bool is_copy_constructible_type(info type);consteval bool is_move_constructible_type(info type);consteval bool is_assignable_type(info type_dst, info type_src);consteval bool is_copy_assignable_type(info type);consteval bool is_move_assignable_type(info type);consteval bool is_swappable_with_type(info type1, info type2);consteval bool is_swappable_type(info type);consteval bool is_destructible_type(info type);template<reflection_range R = initializer_list<info>> consteval bool is_trivially_constructible_type(info type, R&& type_args);consteval bool is_trivially_default_constructible_type(info type);consteval bool is_trivially_copy_constructible_type(info type);consteval bool is_trivially_move_constructible_type(info type);consteval bool is_trivially_assignable_type(info type_dst, info type_src);consteval bool is_trivially_copy_assignable_type(info type);consteval bool is_trivially_move_assignable_type(info type);consteval bool is_trivially_destructible_type(info type);template<reflection_range R = initializer_list<info>> consteval bool is_nothrow_constructible_type(info type, R&& type_args);consteval bool is_nothrow_default_constructible_type(info type);consteval bool is_nothrow_copy_constructible_type(info type);consteval bool is_nothrow_move_constructible_type(info type);consteval bool is_nothrow_assignable_type(info type_dst, info type_src);consteval bool is_nothrow_copy_assignable_type(info type);consteval bool is_nothrow_move_assignable_type(info type);consteval bool is_nothrow_swappable_with_type(info type1, info type2);consteval bool is_nothrow_swappable_type(info type);consteval bool is_nothrow_destructible_type(info type);consteval bool is_implicit_lifetime_type(info type);consteval bool has_virtual_destructor(info type);consteval bool has_unique_object_representations(info type);consteval bool reference_constructs_from_temporary(info type_dst, info type_src);consteval bool reference_converts_from_temporary(info type_dst, info type_src);consteval bool is_same_type(info type1, info type2);consteval bool is_base_of_type(info type_base, info type_derived);consteval bool is_virtual_base_of_type(info type_base, info type_derived);consteval bool is_convertible_type(info type_src, info type_dst);consteval bool is_nothrow_convertible_type(info type_src, info type_dst);consteval bool is_layout_compatible_type(info type1, info type2);consteval bool is_pointer_interconvertible_base_of_type(info type_base, info type_derived);template<reflection_range R = initializer_list<info>> consteval bool is_invocable_type(info type, R&& type_args);template<reflection_range R = initializer_list<info>> consteval bool is_invocable_r_type(info type_result, info type, R&& type_args);template<reflection_range R = initializer_list<info>> consteval bool is_nothrow_invocable_type(info type, R&& type_args);template<reflection_range R = initializer_list<info>> consteval bool is_nothrow_invocable_r_type(info type_result, info type, R&& type_args);consteval info remove_const(info type);consteval info remove_volatile(info type);consteval info remove_cv(info type);consteval info add_const(info type);consteval info add_volatile(info type);consteval info add_cv(info type);consteval info remove_reference(info type);consteval info add_lvalue_reference(info type);consteval info add_rvalue_reference(info type);consteval info make_signed(info type);consteval info make_unsigned(info type);consteval info remove_extent(info type);consteval info remove_all_extents(info type);consteval info remove_pointer(info type);consteval info add_pointer(info type);consteval info remove_cvref(info type);consteval info decay(info type);template<reflection_range R = initializer_list<info>> consteval info common_type(R&& type_args);template<reflection_range R = initializer_list<info>> consteval info common_reference(R&& type_args);consteval info underlying_type(info type);template<reflection_range R = initializer_list<info>> consteval info invoke_result(info type, R&& type_args);consteval info unwrap_reference(info type);consteval info unwrap_ref_decay(info type);

For a function or function template F defined in this subclause, let C be its associated class template.

For the evaluation of a call to F, let S be the specialization of C in terms of which the call is specified.

Each function or function template declared above has the following behavior based on the signature and return type of that function or function template.

[Note 2:

The associated class template need not be instantiated.

— _end note_]

[Note 3:

For those functions or function templates which return a reflection, that reflection always represents a type and never a type alias.

— _end note_]

[Note 4:

If t is a reflection of the type intand u is a reflection of an alias to the type int, then t == u is falsebut is_same_type(t, u) is true.

Also, t == dealias(u) is true.

— _end note_]

consteval size_t rank(info type);

Returns: std​::​rank<T>​::​value, where T is the type represented by dealias(type).

consteval size_t extent(info type, unsigned i = 0);

Returns: std​::​extent<T, I>​::​value, where T is the type represented by dealias(type)and I is a constant equal to i.

consteval size_t tuple_size(info type);

Returns: std​::​tuple_size<T>​::​value, where T is the type represented by dealias(type).

consteval info tuple_element(size_t index, info type);

Returns: A reflection representing the type denoted by std​::​tuple_element<I, T>​::​type, where T is the type represented by dealias(type)and I is a constant equal to index.

consteval size_t variant_size(info type);

Returns: std​::​variant_size<T>​::​value, where T is the type represented by dealias(type).

consteval info variant_alternative(size_t index, info type);

Returns: A reflection representing the type denoted bystd​::​variant_alternative<I, T>​::​type, where T is the type represented by dealias(type)and I is a constant equal to index.

consteval strong_ordering type_order(info t1, info t2);

Returns: std​::​type_order<, >​::​value, where and are the types represented by dealias(​t1) and dealias(t2), respectively.