[meta.reflection]

# 21 Metaprogramming library [[meta]](./#meta)

## 21.4 Reflection [meta.reflection]

### [21.4.1](#meta.syn) Header <meta> synopsis [[meta.syn]](meta.syn)

[ð](#header:%3cmeta%3e)

#include <initializer_list> // see [[initializer.list.syn]](initializer.list.syn "17.11.2 Header <initializer_­list> synopsis")namespace std {// [[meta.string.literal]](#meta.string.literal "21.4.2 Checking string literals"), checking string literalsconsteval 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); // [[meta.define.static]](#meta.define.static "21.4.3 Promoting to static storage strings"), promoting to static storage stringstemplate<ranges::[input_range](range.refinements#concept:input_range "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_range "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&& r);}namespace std::meta {using info = decltype(^^::); // [[meta.reflection.exception]](#exception "21.4.4 Class exception"), class exceptionclass exception; // [[meta.reflection.operators]](#operators "21.4.5 Operator representations"), operator representationsenum class operators {*see below*; }; using enum operators; consteval operators operator_of(info r); consteval string_view symbol_of(operators op); consteval u8string_view u8symbol_of(operators op); // [[meta.reflection.names]](#names "21.4.6 Reflection names and locations"), reflection names and locationsconsteval bool has_identifier(info r); consteval string_view identifier_of(info r); consteval u8string_view u8identifier_of(info r); consteval string_view display_string_of(info r); consteval u8string_view u8display_string_of(info r); consteval source_location source_location_of(info r); // [[meta.reflection.queries]](#queries "21.4.7 Reflection queries"), reflection queriesconsteval info type_of(info r); consteval info object_of(info r); consteval info constant_of(info r); consteval bool is_public(info r); consteval bool is_protected(info r); consteval bool is_private(info r); consteval bool is_virtual(info r); consteval bool is_pure_virtual(info r); consteval bool is_override(info r); consteval bool is_final(info r); 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); consteval bool is_explicit(info r); consteval bool is_noexcept(info r); consteval bool is_bit_field(info r); consteval bool is_enumerator(info r); consteval bool is_annotation(info r); consteval bool is_const(info r); consteval bool is_volatile(info r); consteval bool is_mutable_member(info r); consteval bool is_lvalue_reference_qualified(info r); consteval bool is_rvalue_reference_qualified(info r); consteval bool has_static_storage_duration(info r); consteval bool has_thread_storage_duration(info r); consteval bool has_automatic_storage_duration(info r); consteval bool has_internal_linkage(info r); consteval bool has_module_linkage(info r); consteval bool has_external_linkage(info r); consteval bool has_c_language_linkage(info r); consteval bool has_linkage(info r); consteval bool is_complete_type(info r); consteval bool is_enumerable_type(info r); consteval bool is_variable(info r); consteval bool is_type(info r); consteval bool is_namespace(info r); consteval bool is_type_alias(info r); consteval bool is_namespace_alias(info r); consteval bool is_function(info r); 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); consteval bool is_function_parameter(info r); consteval bool is_explicit_object_parameter(info r); consteval bool has_default_argument(info r); consteval bool has_ellipsis_parameter(info r); consteval bool is_template(info r); 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); consteval bool is_value(info r); consteval bool is_object(info r); consteval bool is_structured_binding(info r); 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); consteval bool has_default_member_initializer(info r); consteval bool has_parent(info r); consteval info parent_of(info r); consteval info dealias(info r); consteval bool has_template_arguments(info r); consteval info template_of(info r); consteval vector<info> template_arguments_of(info r); consteval vector<info> parameters_of(info r); consteval info variable_of(info r); consteval info return_type_of(info r); // [[meta.reflection.access.context]](#access.context "21.4.8 Access control context"), access control contextstruct access_context; // [[meta.reflection.access.queries]](#access.queries "21.4.9 Member accessibility queries"), member accessibility queriesconsteval bool is_accessible(info r, access_context ctx); consteval bool has_inaccessible_nonstatic_data_members(info r, access_context ctx); consteval bool has_inaccessible_bases(info r, access_context ctx); consteval bool has_inaccessible_subobjects(info r, access_context ctx); // [[meta.reflection.member.queries]](#member.queries "21.4.10 Reflection member queries"), reflection member queriesconsteval vector<info> members_of(info r, access_context ctx); consteval vector<info> bases_of(info type, access_context ctx); consteval vector<info> static_data_members_of(info type, access_context ctx); consteval vector<info> nonstatic_data_members_of(info type, access_context ctx); consteval vector<info> subobjects_of(info type, access_context ctx); consteval vector<info> enumerators_of(info type_enum); // [[meta.reflection.layout]](#layout "21.4.11 Reflection layout queries"), reflection layout queriesstruct member_offset; consteval member_offset offset_of(info r); consteval size_t size_of(info r); consteval size_t alignment_of(info r); consteval size_t bit_size_of(info r); // [[meta.reflection.extract]](#extract "21.4.12 Value extraction"), value extractiontemplate<class T>consteval T extract(info); // [[meta.reflection.substitute]](#substitute "21.4.13 Reflection substitution"), reflection substitutiontemplate<class R>concept reflection_range = *see below*; template<[reflection_range](#concept:reflection_range "21.4.13 Reflection substitution [meta.reflection.substitute]") R = initializer_list<info>>consteval bool can_substitute(info templ, R&& arguments); template<[reflection_range](#concept:reflection_range "21.4.13 Reflection substitution [meta.reflection.substitute]") R = initializer_list<info>>consteval info substitute(info templ, R&& arguments); // [[meta.reflection.result]](#result "21.4.14 Expression result reflection"), expression result reflectiontemplate<class T>consteval info reflect_constant(const T& value); template<class T>consteval info reflect_object(T& object); template<class T>consteval info reflect_function(T& fn); // [[meta.reflection.array]](#array "21.4.15 Promoting to static storage arrays"), promoting to static storage arraystemplate<ranges::[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") R>consteval info reflect_constant_string(R&& r); template<ranges::[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") R>consteval info reflect_constant_array(R&& r); // [[meta.reflection.define.aggregate]](#define.aggregate "21.4.16 Reflection class definition generation"), class definition generationstruct data_member_options; consteval info data_member_spec(info type, data_member_options options); consteval bool is_data_member_spec(info r); template<[reflection_range](#concept:reflection_range "21.4.13 Reflection substitution [meta.reflection.substitute]") R = initializer_list<info>>consteval info define_aggregate(info type_class, R&&); // associated with [[meta.unary.cat]](meta.unary.cat "21.3.6.2 Primary type categories"), primary type categoriesconsteval 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); // associated with [[meta.unary.comp]](meta.unary.comp "21.3.6.3 Composite type traits"), composite type categoriesconsteval 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); // associated with [[meta.unary.prop]](meta.unary.prop "21.3.6.4 Type properties"), type propertiesconsteval bool is_const_type(info type); consteval bool is_volatile_type(info type); consteval bool is_trivially_copyable_type(info type); consteval bool is_trivially_relocatable_type(info type); consteval bool is_replaceable_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](#concept:reflection_range "21.4.13 Reflection substitution [meta.reflection.substitute]") 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](#concept:reflection_range "21.4.13 Reflection substitution [meta.reflection.substitute]") 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](#concept:reflection_range "21.4.13 Reflection substitution [meta.reflection.substitute]") 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_nothrow_relocatable_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); // associated with [[meta.unary.prop.query]](meta.unary.prop.query "21.3.7 Type property queries"), type property queriesconsteval size_t rank(info type); consteval size_t extent(info type, unsigned i = 0); // associated with [[meta.rel]](meta.rel "21.3.8 Relationships between types"), type relationsconsteval 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](#concept:reflection_range "21.4.13 Reflection substitution [meta.reflection.substitute]") R = initializer_list<info>>consteval bool is_invocable_type(info type, R&& type_args); template<[reflection_range](#concept:reflection_range "21.4.13 Reflection substitution [meta.reflection.substitute]") R = initializer_list<info>>consteval bool is_invocable_r_type(info type_result, info type, R&& type_args); template<[reflection_range](#concept:reflection_range "21.4.13 Reflection substitution [meta.reflection.substitute]") R = initializer_list<info>>consteval bool is_nothrow_invocable_type(info type, R&& type_args); template<[reflection_range](#concept:reflection_range "21.4.13 Reflection substitution [meta.reflection.substitute]") R = initializer_list<info>>consteval bool is_nothrow_invocable_r_type(info type_result, info type, R&& type_args); // associated with [[meta.trans.cv]](meta.trans.cv "21.3.9.2 Const-volatile modifications"), const-volatile modificationsconsteval 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); // associated with [[meta.trans.ref]](meta.trans.ref "21.3.9.3 Reference modifications"), reference modificationsconsteval info remove_reference(info type); consteval info add_lvalue_reference(info type); consteval info add_rvalue_reference(info type); // associated with [[meta.trans.sign]](meta.trans.sign "21.3.9.4 Sign modifications"), sign modificationsconsteval info make_signed(info type); consteval info make_unsigned(info type); // associated with [[meta.trans.arr]](meta.trans.arr "21.3.9.5 Array modifications"), array modificationsconsteval info remove_extent(info type); consteval info remove_all_extents(info type); // associated with [[meta.trans.ptr]](meta.trans.ptr "21.3.9.6 Pointer modifications"), pointer modificationsconsteval info remove_pointer(info type); consteval info add_pointer(info type); // associated with [[meta.trans.other]](meta.trans.other "21.3.9.7 Other transformations"), other transformationsconsteval info remove_cvref(info type); consteval info decay(info type); template<[reflection_range](#concept:reflection_range "21.4.13 Reflection substitution [meta.reflection.substitute]") R = initializer_list<info>>consteval info common_type(R&& type_args); template<[reflection_range](#concept:reflection_range "21.4.13 Reflection substitution [meta.reflection.substitute]") R = initializer_list<info>>consteval info common_reference(R&& type_args); consteval info underlying_type(info type); template<[reflection_range](#concept:reflection_range "21.4.13 Reflection substitution [meta.reflection.substitute]") 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); consteval size_t tuple_size(info type); consteval info tuple_element(size_t index, info type); consteval size_t variant_size(info type); consteval info variant_alternative(size_t index, info type); consteval strong_ordering type_order(info type_a, info type_b); // [[meta.reflection.annotation]](#annotation "21.4.18 Annotation reflection"), annotation reflectionconsteval vector<info> annotations_of(info item); consteval vector<info> annotations_of_with_type(info item, info type);}

[1](#meta.syn-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3281)

Unless otherwise specified,
each function, and each specialization of any function template,
specified in this header
is a designated addressable function ([[namespace.std]](namespace.std "16.4.5.2.1 Namespace std"))[.](#meta.syn-1.sentence-1)

[2](#meta.syn-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3287)

The behavior of any function specified in namespace std​::​meta isimplementation-defined
when a reflection of a construct not otherwise specified by this document
is provided as an argument[.](#meta.syn-2.sentence-1)

[*Note [1](#meta.syn-note-1)*:

Values of type std​::​meta​::​info can represent implementation-specific constructs ([[basic.fundamental]](basic.fundamental "6.9.2 Fundamental types"))[.](#meta.syn-2.sentence-2)

â *end note*]

[*Note [2](#meta.syn-note-2)*:

Many of the functions specified in namespace std​::​meta have semantics that can be affected by
the completeness of class types represented by reflection values[.](#meta.syn-2.sentence-3)

For such functions,
for any reflection r such that dealias(r) represents a specialization of a templated class with a reachable definition,
the specialization is implicitly instantiated ([[temp.inst]](temp.inst "13.9.2 Implicit instantiation"))[.](#meta.syn-2.sentence-4)

[*Example [1](#meta.syn-example-1)*: template<class T>struct X { T mem;};

static_assert(size_of(^^X<int>) == sizeof(int)); // instantiates X<int> â *end example*]

â *end note*]

[3](#meta.syn-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3317)

Any function in namespace std​::​meta whose return type is string_view or u8string_view returns an object *V* such that*V*.data()[*V*.size()] equals '\0'[.](#meta.syn-3.sentence-1)

[*Example [2](#meta.syn-example-2)*: struct C { };

constexpr string_view sv = identifier_of(^^C);static_assert(sv == "C");static_assert(sv.data()[0] == 'C');static_assert(sv.data()[1] == '\0'); â *end example*]

[4](#meta.syn-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3333)

For the purpose of exposition,
throughout this clause ^^*E* is used
to indicate a reflection representing source construct *E*[.](#meta.syn-4.sentence-1)

### [21.4.2](#meta.string.literal) Checking string literals [[meta.string.literal]](meta.string.literal)

[ð](#lib:is_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);
`

[1](#meta.string.literal-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3350)

*Returns*: 

- [(1.1)](#meta.string.literal-1.1)

  If p points to an unspecified object ([[expr.const]](expr.const "7.7 Constant expressions")), false[.](#meta.string.literal-1.1.sentence-1)

- [(1.2)](#meta.string.literal-1.2)

  Otherwise, if p points to a subobject
 of a string literal object ([[lex.string]](lex.string "5.13.5 String literals")), true[.](#meta.string.literal-1.2.sentence-1)

- [(1.3)](#meta.string.literal-1.3)

  Otherwise, false[.](#meta.string.literal-1.3.sentence-1)

### [21.4.3](#meta.define.static) Promoting to static storage strings [[meta.define.static]](meta.define.static)

[1](#meta.define.static-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3367)

The functions in this subclause promote compile-time storage into static storage[.](#meta.define.static-1.sentence-1)

[ð](#lib:define_static_string)

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

[2](#meta.define.static-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3377)

*Effects*: Equivalent to:return extract<const ranges::range_value_t<R>*>(meta::reflect_constant_string(r));

[ð](#lib:define_static_array)

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

[3](#meta.define.static-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3392)

*Effects*: Equivalent to:using T = ranges::range_value_t<R>;
meta::info array = meta::reflect_constant_array(r);if (is_array_type(type_of(array))) {return span<const T>(extract<const T*>(array), extent(type_of(array)));} else {return span<const T>();}

[ð](#lib:define_static_object)

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

[4](#meta.define.static-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3413)

*Effects*: Equivalent to:using U = remove_cvref_t<T>;if constexpr (is_class_type(^^U)) {return addressof(extract<const U&>(meta::reflect_constant(std::forward<T>(t))));} else {return define_static_array(span(addressof(t), 1)).data();}

[5](#meta.define.static-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3425)

[*Note [1](#meta.define.static-note-1)*:

For class types,define_static_object provides
the address of the template parameter object ([[temp.param]](temp.param "13.2 Template parameters"))
that is template-argument equivalent to t[.](#meta.define.static-5.sentence-1)

â *end note*]

### [21.4.4](#exception) Class exception [[meta.reflection.exception]](meta.reflection.exception)

[ð](#lib:exception)

namespace std::meta {class exception : public std::exception {private: optional<string> *what_*; // *exposition only* u8string *u8what_*; // *exposition only* info *from_*; // *exposition only* source_location *where_*; // *exposition only*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; };}

[1](#exception-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3467)

Reflection functions throw exceptions of type meta​::​exception to signal an error[.](#exception-1.sentence-1)

meta​::​exception is a consteval-only type[.](#exception-1.sentence-2)

[ð](#lib:exception,constructor)

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

[2](#exception-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3478)

*Effects*: Initializes*u8what_* with what,*from_* with from, and*where_* with where[.](#exception-2.sentence-1)

If what can be represented in the ordinary literal encoding,
initializes *what_* with what,
transcoded from UTF-8 to the ordinary literal encoding[.](#exception-2.sentence-2)

Otherwise, *what_* is value-initialized[.](#exception-2.sentence-3)

[ð](#lib:exception,constructor_)

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

[3](#exception-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3496)

*Constant When*: what designates a sequence of characters
that can be encoded in UTF-8[.](#exception-3.sentence-1)

[4](#exception-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3501)

*Effects*: Initializes*what_* with what,*u8what_* with what transcoded from the ordinary literal encoding to UTF-8,*from_* with from and*where_* with where[.](#exception-4.sentence-1)

[ð](#lib:what,exception)

`constexpr const char* what() const noexcept override;
`

[5](#exception-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3517)

*Constant When*: *what_*.has_value() is true[.](#exception-5.sentence-1)

[6](#exception-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3521)

*Returns*: *what_*->c_str()[.](#exception-6.sentence-1)

[ð](#lib:u8what,exception)

`consteval u8string_view u8what() const noexcept;
`

[7](#exception-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3531)

*Returns*: *u8what_*[.](#exception-7.sentence-1)

[ð](#lib:from,exception)

`consteval info from() const noexcept;
`

[8](#exception-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3541)

*Returns*: *from_*[.](#exception-8.sentence-1)

[ð](#lib:where,exception)

`consteval source_location where() const noexcept;
`

[9](#exception-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3551)

*Returns*: *where_*[.](#exception-9.sentence-1)

### [21.4.5](#operators) Operator representations [[meta.reflection.operators]](meta.reflection.operators)

[ð](#operators-itemdecl:1)

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

[1](#operators-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3566)

The enumeration type operators specifies
constants used to identify operators that can be overloaded,
with the meanings listed in Table [63](#tab:meta.reflection.operators "Table 63: Enum class operators")[.](#operators-1.sentence-1)

The values of the constants are distinct[.](#operators-1.sentence-2)

Table [63](#tab:meta.reflection.operators) — Enum class operators [[tab:meta.reflection.operators]](./tab:meta.reflection.operators)  

| [ð](#tab:meta.reflection.operators-row-1)<br>**Constant** | **Corresponding [*operator-function-id*](over.oper.general#nt:operator-function-id "12.4.1 General [over.oper.general]")** | **Operator symbol name** |
| --- | --- | --- |
| [ð](#tab:meta.reflection.operators-row-2)<br>op_new | operator new | new |
| [ð](#tab:meta.reflection.operators-row-3)<br>op_delete | operator delete | delete |
| [ð](#tab:meta.reflection.operators-row-4)<br>op_array_new | operator new[] | new[] |
| [ð](#tab:meta.reflection.operators-row-5)<br>op_array_delete | operator delete[] | delete[] |
| [ð](#tab:meta.reflection.operators-row-6)<br>op_co_await | operator co_await | co_await |
| [ð](#tab:meta.reflection.operators-row-7)<br>op_parentheses | operator() | () |
| [ð](#tab:meta.reflection.operators-row-8)<br>op_square_brackets | operator[] | [] |
| [ð](#tab:meta.reflection.operators-row-9)<br>op_arrow | operator-> | -> |
| [ð](#tab:meta.reflection.operators-row-10)<br>op_arrow_star | operator->* | ->* |
| [ð](#tab:meta.reflection.operators-row-11)<br>op_tilde | operator~ | ~ |
| [ð](#tab:meta.reflection.operators-row-12)<br>op_exclamation | operator! | ! |
| [ð](#tab:meta.reflection.operators-row-13)<br>op_plus | operator+ | + |
| [ð](#tab:meta.reflection.operators-row-14)<br>op_minus | operator- | - |
| [ð](#tab:meta.reflection.operators-row-15)<br>op_star | operator* | * |
| [ð](#tab:meta.reflection.operators-row-16)<br>op_slash | operator/ | / |
| [ð](#tab:meta.reflection.operators-row-17)<br>op_percent | operator% | % |
| [ð](#tab:meta.reflection.operators-row-18)<br>op_caret | operator^ | ^ |
| [ð](#tab:meta.reflection.operators-row-19)<br>op_ampersand | operator& | & |
| [ð](#tab:meta.reflection.operators-row-20)<br>op_equals | operator= | = |
| [ð](#tab:meta.reflection.operators-row-21)<br>op_pipe | operator| | | |
| [ð](#tab:meta.reflection.operators-row-22)<br>op_plus_equals | operator+= | += |
| [ð](#tab:meta.reflection.operators-row-23)<br>op_minus_equals | operator-= | -= |
| [ð](#tab:meta.reflection.operators-row-24)<br>op_star_equals | operator*= | *= |
| [ð](#tab:meta.reflection.operators-row-25)<br>op_slash_equals | operator/= | /= |
| [ð](#tab:meta.reflection.operators-row-26)<br>op_percent_equals | operator%= | %= |
| [ð](#tab:meta.reflection.operators-row-27)<br>op_caret_equals | operator^= | ^= |
| [ð](#tab:meta.reflection.operators-row-28)<br>op_ampersand_equals | operator&= | &= |
| [ð](#tab:meta.reflection.operators-row-29)<br>op_pipe_equals | operator|= | |= |
| [ð](#tab:meta.reflection.operators-row-30)<br>op_equals_equals | operator== | == |
| [ð](#tab:meta.reflection.operators-row-31)<br>op_exclamation_equals | operator!= | != |
| [ð](#tab:meta.reflection.operators-row-32)<br>op_less | operator< | < |
| [ð](#tab:meta.reflection.operators-row-33)<br>op_greater | operator> | > |
| [ð](#tab:meta.reflection.operators-row-34)<br>op_less_equals | operator<= | <= |
| [ð](#tab:meta.reflection.operators-row-35)<br>op_greater_equals | operator>= | >= |
| [ð](#tab:meta.reflection.operators-row-36)<br>op_spaceship | operator<=> | <=> |
| [ð](#tab:meta.reflection.operators-row-37)<br>op_ampersand_ampersand | operator&& | && |
| [ð](#tab:meta.reflection.operators-row-38)<br>op_pipe_pipe | operator|| | || |
| [ð](#tab:meta.reflection.operators-row-39)<br>op_less_less | operator<< | << |
| [ð](#tab:meta.reflection.operators-row-40)<br>op_greater_greater | operator>> | >> |
| [ð](#tab:meta.reflection.operators-row-41)<br>op_less_less_equals | operator<<= | <<= |
| [ð](#tab:meta.reflection.operators-row-42)<br>op_greater_greater_equals | operator>>= | >>= |
| [ð](#tab:meta.reflection.operators-row-43)<br>op_plus_plus | operator++ | ++ |
| [ð](#tab:meta.reflection.operators-row-44)<br>op_minus_minus | operator-- | -- |
| [ð](#tab:meta.reflection.operators-row-45)<br>op_comma | operator, | , |

[ð](#lib:operator_of)

`consteval operators operator_of(info r);
`

[2](#operators-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3633)

*Returns*: The value of the enumerator from operators whose corresponding [*operator-function-id*](over.oper.general#nt:operator-function-id "12.4.1 General [over.oper.general]") is the unqualified name of the entity represented by r[.](#operators-2.sentence-1)

[3](#operators-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3639)

*Throws*: meta​::​exception unlessr represents an operator function or operator function template[.](#operators-3.sentence-1)

[ð](#lib:symbol_of)

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

[4](#operators-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3653)

*Returns*: A string_view or u8string_view containing the characters of the operator symbol name corresponding to op,
respectively encoded with the ordinary literal encoding or with UTF-8[.](#operators-4.sentence-1)

[5](#operators-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3659)

*Throws*: meta​::​exception unless
the value of op corresponds to one of the enumerators in operators[.](#operators-5.sentence-1)

### [21.4.6](#names) Reflection names and locations [[meta.reflection.names]](meta.reflection.names)

[ð](#lib:has_identifier)

`consteval bool has_identifier(info r);
`

[1](#names-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3673)

*Returns*: 

- [(1.1)](#names-1.1)

  If r represents an entity
 that has a typedef name for linkage purposes ([[dcl.typedef]](dcl.typedef "9.2.4 The typedef specifier")),
 then true[.](#names-1.1.sentence-1)

- [(1.2)](#names-1.2)

  Otherwise, if r represents an unnamed entity,
 then false[.](#names-1.2.sentence-1)

- [(1.3)](#names-1.3)

  Otherwise, if r represents a class type,
 then !has_template_arguments(r)[.](#names-1.3.sentence-1)

- [(1.4)](#names-1.4)

  Otherwise, if r represents a function,
 then true if has_template_arguments(r) is false and the function is not a
 constructor,
 destructor,
 operator function, or
 conversion function[.](#names-1.4.sentence-1)
  Otherwise, false[.](#names-1.4.sentence-2)

- [(1.5)](#names-1.5)

  Otherwise, if r represents a template,
 then true if r does not represent a
 constructor template,
 operator function template,
 or conversion function template[.](#names-1.5.sentence-1)
  Otherwise, false[.](#names-1.5.sentence-2)

- [(1.6)](#names-1.6)

  Otherwise, if r represents the ith parameter of a function F that is an (implicit or explicit) specialization of a templated function T and the ith parameter of the instantiated declaration of T whose template arguments are those of F would be instantiated from a pack,
 then false[.](#names-1.6.sentence-1)

- [(1.7)](#names-1.7)

  Otherwise, if r represents the parameter P of a function F,
 then let S be the set of declarations,
 ignoring any explicit instantiations,
 that precede some point in the evaluation context
 and that declare either F or a templated function
 of which F is a specialization; true if
  * [(1.7.1)](#names-1.7.1)

there is a declaration D in S that introduces a name N for either P or the parameter corresponding to P in the templated function that D declares and

  * [(1.7.2)](#names-1.7.2)

no declaration in S does so using any name other than N[.](#names-1.7.sentence-1)

   Otherwise, false[.](#names-1.7.sentence-2)
  [*Example [1](#names-example-1)*: void fun(int);constexpr std::meta::info r = parameters_of(^^fun)[0];static_assert(!has_identifier(r));

    void fun(int x);static_assert(has_identifier(r));

    void fun(int x);static_assert(has_identifier(r));

    void poison() {void fun(int y);}static_assert(!has_identifier(r)); â *end example*]

- [(1.8)](#names-1.8)

  Otherwise, if r represents a variable,
 then false if the declaration of that variable
 was instantiated from a function parameter pack[.](#names-1.8.sentence-1)
  Otherwise, !has_template_arguments(r)[.](#names-1.8.sentence-2)

- [(1.9)](#names-1.9)

  Otherwise, if r represents a structured binding,
 then false if the declaration of that structured binding
 was instantiated from a structured binding pack[.](#names-1.9.sentence-1)
  Otherwise, true[.](#names-1.9.sentence-2)

- [(1.10)](#names-1.10)

  Otherwise, if r represents a type alias,
 then !has_template_arguments(r)[.](#names-1.10.sentence-1)

- [(1.11)](#names-1.11)

  Otherwise, if r represents an
 enumerator,
 non-static-data member,
 namespace, or
 namespace alias,
 then true[.](#names-1.11.sentence-1)

- [(1.12)](#names-1.12)

  Otherwise, if r represents a direct base class relationship,
 then has_identifier(type_of(r))[.](#names-1.12.sentence-1)

- [(1.13)](#names-1.13)

  Otherwise, r represents a data member description (T,N,A,W,NUA) ([[class.mem.general]](class.mem.general "11.4.1 General")); true if N is not â¥[.](#names-1.13.sentence-1)
  Otherwise, false[.](#names-1.13.sentence-2)

[ð](#lib:identifier_of)

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

[2](#names-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3782)

Let E be UTF-8 for u8identifier_of,
and otherwise the ordinary literal encoding[.](#names-2.sentence-1)

[3](#names-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3786)

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

- [(3.1)](#names-3.1)

  If r represents an entity with a typedef name for linkage purposes,
 then that name[.](#names-3.1.sentence-1)

- [(3.2)](#names-3.2)

  Otherwise, if r represents a literal operator or literal operator template,
 then the [*ud-suffix*](lex.ext#nt:ud-suffix "5.13.9 User-defined literals [lex.ext]") of the operator or operator template[.](#names-3.2.sentence-1)

- [(3.3)](#names-3.3)

  Otherwise, if r represents the parameter P of a function F,
 then let S be the set of declarations,
 ignoring any explicit instantiations,
 that precede some point in the evaluation context
 and that declare either F or a templated function of which F is a specialization;
 the name that was introduced by a declaration in S for the parameter corresponding to P[.](#names-3.3.sentence-1)

- [(3.4)](#names-3.4)

  Otherwise, if r represents an entity,
 then the identifier introduced by the declaration of that entity[.](#names-3.4.sentence-1)

- [(3.5)](#names-3.5)

  Otherwise, if r represents a direct base class relationship,
 then identifier_of(type_of(r)) or u8identifier_of(type_of(r)),
 respectively[.](#names-3.5.sentence-1)

- [(3.6)](#names-3.6)

  Otherwise, r represents a data member description (T,N,A,W,NUA) ([[class.mem.general]](class.mem.general "11.4.1 General"));
 a string_view or u8string_view, respectively,
 containing the identifier N[.](#names-3.6.sentence-1)

[4](#names-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3820)

*Throws*: meta​::​exception unlesshas_identifier(r) is true and the identifier that would be returned (see above)
is representable by E[.](#names-4.sentence-1)

[ð](#lib:display_string_of)

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

[5](#names-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3836)

*Returns*: Animplementation-definedstring_view or u8string_view, respectively[.](#names-5.sentence-1)

[6](#names-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3842)

*Recommended practice*: Where possible,
implementations should return a string
suitable for identifying the represented construct[.](#names-6.sentence-1)

[ð](#lib:source_location_of)

`consteval source_location source_location_of(info r);
`

[7](#names-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3855)

*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{}[.](#names-7.sentence-1)

Otherwise, animplementation-definedsource_location value[.](#names-7.sentence-2)

[8](#names-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3867)

*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[.](#names-8.sentence-1)

### [21.4.7](#queries) Reflection queries [[meta.reflection.queries]](meta.reflection.queries)

[ð](#queries-itemdecl:1)

`consteval bool has-type(info r);  // exposition only
`

[1](#queries-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3881)

*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[.](#queries-1.sentence-1)

Otherwise, false[.](#queries-1.sentence-2)

[ð](#lib:type_of)

`consteval info type_of(info r);
`

[2](#queries-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3905)

*Returns*: 

- [(2.1)](#queries-2.1)

  If r represents the ith parameter of a function F,
 then the ith type
 in the parameter-type-list of F ([[dcl.fct]](dcl.fct "9.3.4.6 Functions"))[.](#queries-2.1.sentence-1)

- [(2.2)](#queries-2.2)

  Otherwise, if r represents a
 value,
 object,
 variable,
 function,
 non-static data member, or
 unnamed bit-field,
 then the type of what is represented by r[.](#queries-2.2.sentence-1)

- [(2.3)](#queries-2.3)

  Otherwise, if r represents an annotation,
 then type_of(constant_of(r))[.](#queries-2.3.sentence-1)

- [(2.4)](#queries-2.4)

  Otherwise, if r represents
 an enumerator N of an enumeration E, then:
  * [(2.4.1)](#queries-2.4.1)

      If E is defined by a declaration D that precedes a point P in the evaluation context
 and P does not occur within an [*enum-specifier*](dcl.enum#nt:enum-specifier "9.8.1 Enumeration declarations [dcl.enum]") of D,
 then a reflection of E[.](#queries-2.4.1.sentence-1)

  * [(2.4.2)](#queries-2.4.2)

      Otherwise, a reflection of the type of N prior to the closing brace of the [*enum-specifier*](dcl.enum#nt:enum-specifier "9.8.1 Enumeration declarations [dcl.enum]") as specified in [[dcl.enum]](dcl.enum "9.8.1 Enumeration declarations")[.](#queries-2.4.2.sentence-1)

- [(2.5)](#queries-2.5)

  Otherwise, if r represents
 a direct base class relationship (D,B),
 then a reflection of B[.](#queries-2.5.sentence-1)

- [(2.6)](#queries-2.6)

  Otherwise, for a data member description (T,N,A,W,NUA) ([[class.mem.general]](class.mem.general "11.4.1 General")),
 a reflection of the type T[.](#queries-2.6.sentence-1)

[3](#queries-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3947)

*Throws*: meta​::​exception unless*has-type*(r) is true[.](#queries-3.sentence-1)

[ð](#lib:object_of)

`consteval info object_of(info r);
`

[4](#queries-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3959)

*Returns*: 

- [(4.1)](#queries-4.1)

  If r represents an object,
 then r[.](#queries-4.1.sentence-1)

- [(4.2)](#queries-4.2)

  Otherwise, if r represents a reference,
 then a reflection of the object referred to by that reference[.](#queries-4.2.sentence-1)

- [(4.3)](#queries-4.3)

  Otherwise, r represents a variable;
 a reflection of the object declared by that variable[.](#queries-4.3.sentence-1)

[*Example [1](#queries-example-1)*: int x;int& y = x;

static_assert(^^x != ^^y); // OK, r and y are different variables so their// reflections compare differentstatic_assert(object_of(^^x) == object_of(^^y)); // OK, because y is a reference// to x, their underlying objects are the same â *end example*]

[5](#queries-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L3984)

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

- [(5.1)](#queries-5.1)

an object with static storage duration ([[basic.stc.general]](basic.stc.general "6.8.6.1 General")), or

- [(5.2)](#queries-5.2)

a variable that either declares or refers to such an object,
 and if that variable is a reference R, then either
  * [(5.2.1)](#queries-5.2.1)

R is usable in constant expressions ([[expr.const]](expr.const "7.7 Constant expressions")), or

  * [(5.2.2)](#queries-5.2.2)

the lifetime of R began within the core constant expression
 currently under evaluation[.](#queries-5.sentence-1)

[ð](#lib:constant_of)

`consteval info constant_of(info r);
`

[6](#queries-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4010)

Let R be a constant expression of type info such that R == r is true[.](#queries-6.sentence-1)

If r represents an annotation,
then let C be its underlying constant[.](#queries-6.sentence-2)

[7](#queries-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4016)

*Effects*: Equivalent to:if constexpr (is_annotation(R)) {return C;} else {return reflect_constant([: R :]);}

[*Example [2](#queries-example-2)*: constexpr int x = 0;constexpr int y = 0;

static_assert(^^x != ^^y); // OK, x and y are different variables,// so their reflections compare differentstatic_assert(constant_of(^^x) == constant_of(^^y)); // OK, both constant_of(^^x) and// constant_of(^^y) represent the value 0static_assert(constant_of(^^x) == reflect_constant(0)); // OK, likewisestruct S { int m; };constexpr S s {42};static_assert(is_object(constant_of(^^s)) && is_object(reflect_object(s)));static_assert(constant_of(^^s) != // OK, template parameter object that is template-argument- reflect_object(s)); // equivalent to s is a different object than sstatic_assert(constant_of(^^s) == constant_of(reflect_object(s))); // OKconsteval info fn() {constexpr int x = 42; return ^^x;}constexpr info r = constant_of(fn()); // error: x is outside its lifetime â *end example*]

[8](#queries-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4056)

*Throws*: meta​::​exception unless
either r represents an annotation or[: R :] is a valid[*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9 Expression splicing [expr.prim.splice]") ([[expr.prim.splice]](expr.prim.splice "7.5.9 Expression splicing"))[.](#queries-8.sentence-1)

[ð](#lib:is_public)

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

[9](#queries-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4074)

*Returns*: true if r represents either

- [(9.1)](#queries-9.1)

a class member or unnamed bit-field
 that is public, protected, or private, respectively, or

- [(9.2)](#queries-9.2)

a direct base class relationship (D,B) for which B is, respectively,
 a public, protected, or private base class of D[.](#queries-9.sentence-1)

Otherwise, false[.](#queries-9.sentence-2)

[ð](#lib:is_virtual)

`consteval bool is_virtual(info r);
`

[10](#queries-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4094)

*Returns*: true if r represents either a virtual member function
or a direct base class relationship (D,B) for which B is a virtual base class of D[.](#queries-10.sentence-1)

Otherwise, false[.](#queries-10.sentence-2)

[ð](#lib:is_pure_virtual)

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

[11](#queries-11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4110)

*Returns*: true if r represents a member function that is pure virtual
or overrides another member function, respectively[.](#queries-11.sentence-1)

Otherwise, false[.](#queries-11.sentence-2)

[ð](#lib:is_final)

`consteval bool is_final(info r);
`

[12](#queries-12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4123)

*Returns*: true if r represents a final class or a final member function[.](#queries-12.sentence-1)

Otherwise, false[.](#queries-12.sentence-2)

[ð](#lib:is_deleted)

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

[13](#queries-13)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4137)

*Returns*: true if r represents a function that is
a deleted function ([[dcl.fct.def.delete]](dcl.fct.def.delete "9.6.3 Deleted definitions"))
or defaulted function ([[dcl.fct.def.default]](dcl.fct.def.default "9.6.2 Explicitly-defaulted functions")), respectively[.](#queries-13.sentence-1)

Otherwise, false[.](#queries-13.sentence-2)

[ð](#lib:is_user_provided)

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

[14](#queries-14)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4153)

*Returns*: true if r represents a function that is
user-provided or user-declared ([[dcl.fct.def.default]](dcl.fct.def.default "9.6.2 Explicitly-defaulted functions")), respectively[.](#queries-14.sentence-1)

Otherwise, false[.](#queries-14.sentence-2)

[ð](#lib:is_explicit)

`consteval bool is_explicit(info r);
`

[15](#queries-15)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4166)

*Returns*: true if r represents a member function that is declared explicit[.](#queries-15.sentence-1)

Otherwise, false[.](#queries-15.sentence-2)

[*Note [1](#queries-note-1)*:

If r represents a member function template that is declared explicit,is_explicit(r) is still false because in general,
such queries for templates cannot be answered[.](#queries-15.sentence-3)

â *end note*]

[ð](#lib:is_noexcept)

`consteval bool is_noexcept(info r);
`

[16](#queries-16)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4184)

*Returns*: true if r represents a noexcept function type
or a function with a non-throwing exception specification ([[except.spec]](except.spec "14.5 Exception specifications"))[.](#queries-16.sentence-1)

Otherwise, false[.](#queries-16.sentence-2)

[*Note [2](#queries-note-2)*:

If r represents a function template that is declared noexcept,is_noexcept(r) is still false because in general,
such queries for templates cannot be answered[.](#queries-16.sentence-3)

â *end note*]

[ð](#lib:is_bit_field)

`consteval bool is_bit_field(info r);
`

[17](#queries-17)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4203)

*Returns*: true if r represents a bit-field,
or if r represents a data member description(T,N,A,W,NUA) ([[class.mem.general]](class.mem.general "11.4.1 General"))
for which W is not â¥[.](#queries-17.sentence-1)

Otherwise, false[.](#queries-17.sentence-2)

[ð](#lib:is_enumerator)

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

[18](#queries-18)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4220)

*Returns*: true if r represents an enumerator or annotation, respectively[.](#queries-18.sentence-1)

Otherwise, false[.](#queries-18.sentence-2)

[ð](#lib:is_const)

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

[19](#queries-19)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4234)

Let T be type_of(r) if *has-type*(r) is true[.](#queries-19.sentence-1)

Otherwise, let T be dealias(r)[.](#queries-19.sentence-2)

[20](#queries-20)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4238)

*Returns*: true if T represents a const or volatile type, respectively,
or a const- or volatile-qualified function type, respectively[.](#queries-20.sentence-1)

Otherwise, false[.](#queries-20.sentence-2)

[ð](#lib:is_mutable_member)

`consteval bool is_mutable_member(info r);
`

[21](#queries-21)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4251)

*Returns*: true if r represents a mutable non-static data member[.](#queries-21.sentence-1)

Otherwise, false[.](#queries-21.sentence-2)

[ð](#lib:is_lvalue_reference_qualified)

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

[22](#queries-22)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4265)

Let T be type_of(r) if *has-type*(r) is true[.](#queries-22.sentence-1)

Otherwise, let T be dealias(r)[.](#queries-22.sentence-2)

[23](#queries-23)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4269)

*Returns*: true if T represents an
lvalue- or rvalue-qualified function type, respectively[.](#queries-23.sentence-1)

Otherwise, false[.](#queries-23.sentence-2)

[ð](#lib:has_static_storage_duration)

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

[24](#queries-24)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4286)

*Returns*: true if r represents an object or variable that has
static, thread, or automatic storage duration, respectively ([[basic.stc]](basic.stc "6.8.6 Storage duration"))[.](#queries-24.sentence-1)

Otherwise, false[.](#queries-24.sentence-2)

[*Note [3](#queries-note-3)*:

It is not possible to have a reflection
representing an object or variable having dynamic storage duration[.](#queries-24.sentence-3)

â *end note*]

[ð](#lib:has_internal_linkage)

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

[25](#queries-25)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4311)

*Returns*: true if r represents a
variable,
function,
type,
template, or
namespace
whose name has
internal linkage,
module linkage,
C language linkage, or
any linkage, respectively ([[basic.link]](basic.link "6.7 Program and linkage"))[.](#queries-25.sentence-1)

Otherwise, false[.](#queries-25.sentence-2)

[ð](#lib:is_complete_type)

`consteval bool is_complete_type(info r);
`

[26](#queries-26)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4333)

*Returns*: true if is_type(r) is true and there is some point in the evaluation context
from which the type represented by dealias(r) is not an incomplete type ([[basic.types]](basic.types "6.9 Types"))[.](#queries-26.sentence-1)

Otherwise, false[.](#queries-26.sentence-2)

[ð](#lib:is_enumerable_type)

`consteval bool is_enumerable_type(info r);
`

[27](#queries-27)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4348)

A type T is [*enumerable*](#def:enumerable) from a point P if either

- [(27.1)](#queries-27.1)

T is a class type complete at point P or

- [(27.2)](#queries-27.2)

T is an enumeration type defined by a declaration D such that D is reachable from P but P does not occur within an [*enum-specifier*](dcl.enum#nt:enum-specifier "9.8.1 Enumeration declarations [dcl.enum]") of D ([[dcl.enum]](dcl.enum "9.8.1 Enumeration declarations"))[.](#queries-27.sentence-1)

[28](#queries-28)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4359)

*Returns*: true if dealias(r) represents a type that is enumerable
from some point in the evaluation context[.](#queries-28.sentence-1)

Otherwise, false[.](#queries-28.sentence-2)

[*Example [3](#queries-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*]

[ð](#lib:is_variable)

`consteval bool is_variable(info r);
`

[29](#queries-29)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4394)

*Returns*: true if r represents a variable[.](#queries-29.sentence-1)

Otherwise, false[.](#queries-29.sentence-2)

[ð](#lib:is_type)

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

[30](#queries-30)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4408)

*Returns*: true if r represents an entity
whose underlying entity is a type or namespace, respectively[.](#queries-30.sentence-1)

Otherwise, false[.](#queries-30.sentence-2)

[ð](#lib:is_type_alias)

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

[31](#queries-31)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4423)

*Returns*: true if r represents a type alias or namespace alias, respectively[.](#queries-31.sentence-1)

Otherwise, false[.](#queries-31.sentence-2)

[*Note [4](#queries-note-4)*:

A specialization of an alias template is a type alias[.](#queries-31.sentence-3)

â *end note*]

[ð](#lib:is_function)

`consteval bool is_function(info r);
`

[32](#queries-32)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4438)

*Returns*: true if r represents a function[.](#queries-32.sentence-1)

Otherwise, false[.](#queries-32.sentence-2)

[ð](#lib:is_conversion_function)

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

[33](#queries-33)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4454)

*Returns*: true if r represents a function that is a
conversion function ([[class.conv.fct]](class.conv.fct "11.4.8.3 Conversion functions")),
operator function ([[over.oper]](over.oper "12.4 Overloaded operators")), or
literal operator ([[over.literal]](over.literal "12.6 User-defined literals")), respectively[.](#queries-33.sentence-1)

Otherwise, false[.](#queries-33.sentence-2)

[ð](#lib:is_special_member_function)

`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);
`

[34](#queries-34)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4485)

*Returns*: true if r represents a function that is a
special member function ([[special]](special "11.4.4 Special member functions")),
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[.](#queries-34.sentence-1)

Otherwise, false[.](#queries-34.sentence-2)

[ð](#lib:is_function_parameter)

`consteval bool is_function_parameter(info r);
`

[35](#queries-35)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4506)

*Returns*: true if r represents a function parameter[.](#queries-35.sentence-1)

Otherwise, false[.](#queries-35.sentence-2)

[ð](#lib:is_explicit_object_parameter)

`consteval bool is_explicit_object_parameter(info r);
`

[36](#queries-36)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4518)

*Returns*: true if r represents a function parameter
that is an explicit object parameter ([[dcl.fct]](dcl.fct "9.3.4.6 Functions"))[.](#queries-36.sentence-1)

Otherwise, false[.](#queries-36.sentence-2)

[ð](#lib:has_default_argument)

`consteval bool has_default_argument(info r);
`

[37](#queries-37)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4531)

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

- [(37.1)](#queries-37.1)

  If F is a specialization of a templated function T,
 then true if there exists a declaration D of T that precedes some point in the evaluation context
 and D specifies a default argument
 for the parameter of T corresponding to P[.](#queries-37.1.sentence-1)
  Otherwise, false[.](#queries-37.1.sentence-2)

- [(37.2)](#queries-37.2)

  Otherwise, if there exists a declaration D of F that precedes some point in the evaluation context
 and D specifies a default argument for P,
 then true[.](#queries-37.2.sentence-1)

Otherwise, false[.](#queries-37.sentence-2)

[ð](#lib:has_ellipsis_parameter)

`consteval bool has_ellipsis_parameter(info r);
`

[38](#queries-38)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4557)

*Returns*: true if r represents a function or function type
that has an ellipsis in its parameter-type-list ([[dcl.fct]](dcl.fct "9.3.4.6 Functions"))[.](#queries-38.sentence-1)

Otherwise, false[.](#queries-38.sentence-2)

[ð](#lib:is_template)

`consteval bool is_template(info r);
`

[39](#queries-39)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4570)

*Returns*: true if r represents a
function template,
class template,
variable template,
alias template, or
concept[.](#queries-39.sentence-1)

Otherwise, false[.](#queries-39.sentence-2)

[40](#queries-40)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4580)

[*Note [5](#queries-note-5)*:

A template specialization is not a template[.](#queries-40.sentence-1)

For example,is_template(​^^std​::​vector) is true but is_template(​^^std​::​vector<int>) is false[.](#queries-40.sentence-2)

â *end note*]

[ð](#lib:is_function_template)

`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);
`

[41](#queries-41)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4611)

*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[.](#queries-41.sentence-1)

Otherwise, false[.](#queries-41.sentence-2)

[ð](#lib:is_value)

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

[42](#queries-42)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4634)

*Returns*: true if r represents a value or object, respectively[.](#queries-42.sentence-1)

Otherwise, false[.](#queries-42.sentence-2)

[ð](#lib:is_structured_binding)

`consteval bool is_structured_binding(info r);
`

[43](#queries-43)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4646)

*Returns*: true if r represents a structured binding[.](#queries-43.sentence-1)

Otherwise, false[.](#queries-43.sentence-2)

[ð](#lib:is_class_member)

`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);
`

[44](#queries-44)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4666)

*Returns*: true if r represents a
class member,
namespace member,
non-static data member,
static member, or
direct base class relationship, respectively[.](#queries-44.sentence-1)

Otherwise, false[.](#queries-44.sentence-2)

[ð](#lib:has_default_member_initializer)

`consteval bool has_default_member_initializer(info r);
`

[45](#queries-45)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4683)

*Returns*: true if r represents a non-static data member
that has a default member initializer[.](#queries-45.sentence-1)

Otherwise, false[.](#queries-45.sentence-2)

[ð](#lib:has_parent)

`consteval bool has_parent(info r);
`

[46](#queries-46)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4696)

*Returns*: 

- [(46.1)](#queries-46.1)

  If r represents the global namespace,
 then false[.](#queries-46.1.sentence-1)

- [(46.2)](#queries-46.2)

  Otherwise, if r represents an entity that has C language linkage ([[dcl.link]](dcl.link "9.12 Linkage specifications")),
 then false[.](#queries-46.2.sentence-1)

- [(46.3)](#queries-46.3)

  Otherwise, if r represents an entity that has a
 language linkage other than C++ language linkage,
 then an implementation-defined
 value[.](#queries-46.3.sentence-1)

- [(46.4)](#queries-46.4)

  Otherwise, if r represents a type that is neither a class nor enumeration type,
 then false[.](#queries-46.4.sentence-1)

- [(46.5)](#queries-46.5)

  Otherwise, if r represents an entity or direct base class relationship,
 then true[.](#queries-46.5.sentence-1)

- [(46.6)](#queries-46.6)

  Otherwise, false[.](#queries-46.6.sentence-1)

[ð](#lib:parent_of)

`consteval info parent_of(info r);
`

[47](#queries-47)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4729)

*Returns*: 

- [(47.1)](#queries-47.1)

  If r represents a non-static data member
 that is a direct member of an anonymous union,
 or an unnamed bit-field declared
 within the [*member-specification*](class.mem.general#nt:member-specification "11.4.1 General [class.mem.general]") of such a union,
 then a reflection representing the innermost enclosing anonymous union[.](#queries-47.1.sentence-1)

- [(47.2)](#queries-47.2)

  Otherwise, if r represents an enumerator,
 then a reflection representing the corresponding enumeration type[.](#queries-47.2.sentence-1)

- [(47.3)](#queries-47.3)

  Otherwise, if r represents a direct base class relationship (D,B),
 then a reflection representing D[.](#queries-47.3.sentence-1)

- [(47.4)](#queries-47.4)

  Otherwise, let E be a class, function, or namespace
 whose class scope, function parameter scope, or namespace scope, respectively,
 is the innermost such scope that either is, or encloses,
 the target scope of a declaration of what is represented by r[.](#queries-47.4.sentence-1)

  * [(47.4.1)](#queries-47.4.1)

      If E is the function call operator of a closure type
 for a [*consteval-block-declaration*](dcl.pre#nt:consteval-block-declaration "9.1 Preamble [dcl.pre]") ([[dcl.pre]](dcl.pre "9.1 Preamble")),
 then parent_of(​parent_of(^^E))[.](#queries-47.4.1.sentence-1)
      [*Note [6](#queries-note-6)*:
      In this case,
 the first parent_of will be the closure type,
 so the second parent_of is necessary
 to give the parent of that closure type[.](#queries-47.4.1.sentence-2)
 â *end note*]

  * [(47.4.2)](#queries-47.4.2)

      Otherwise, ^^E[.](#queries-47.4.2.sentence-1)

[*Example [4](#queries-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*]

[48](#queries-48)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4788)

*Throws*: meta​::​exception unlesshas_parent(r) is true[.](#queries-48.sentence-1)

[ð](#lib:dealias)

`consteval info dealias(info r);
`

[49](#queries-49)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4800)

*Returns*: A reflection representing the underlying entity of what r represents[.](#queries-49.sentence-1)

[*Example [5](#queries-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*]

[50](#queries-50)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4813)

*Throws*: meta​::​exception unlessr represents an entity[.](#queries-50.sentence-1)

[ð](#lib:has_template_arguments)

`consteval bool has_template_arguments(info r);
`

[51](#queries-51)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4825)

*Returns*: true if r represents a specialization of a
function template,
variable template,
class template, or
an alias template[.](#queries-51.sentence-1)

Otherwise, false[.](#queries-51.sentence-2)

[ð](#lib:template_of)

`consteval info template_of(info r);
`

[52](#queries-52)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4841)

*Returns*: A reflection of the template of the specialization represented by r[.](#queries-52.sentence-1)

[53](#queries-53)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4845)

*Throws*: meta​::​exception unlesshas_template_arguments(r) is true[.](#queries-53.sentence-1)

[ð](#lib:template_arguments_of)

`consteval vector<info> template_arguments_of(info r);
`

[54](#queries-54)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4857)

*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[.](#queries-54.sentence-1)

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

- [(54.1)](#queries-54.1)

  If A denotes a type or type alias,
 then R is a reflection representing the underlying entity of A[.](#queries-54.1.sentence-1)
  [*Note [7](#queries-note-7)*:
  R always represents a type, never a type alias[.](#queries-54.1.sentence-2)
 â *end note*]

- [(54.2)](#queries-54.2)

  Otherwise, if A denotes a
 class template,
 variable template,
 concept, or
 alias template,
 then R is a reflection representing A[.](#queries-54.2.sentence-1)

- [(54.3)](#queries-54.3)

  Otherwise, A is a constant template argument ([[temp.arg.nontype]](temp.arg.nontype "13.4.3 Constant template arguments"))[.](#queries-54.3.sentence-1)
  Let P be the corresponding template parameter[.](#queries-54.3.sentence-2)

  * [(54.3.1)](#queries-54.3.1)

      If P has reference type,
 then R is a reflection
 representing the object or function referred to by A[.](#queries-54.3.1.sentence-1)

  * [(54.3.2)](#queries-54.3.2)

      Otherwise, if P has class type,
 then R represents the corresponding template parameter object[.](#queries-54.3.2.sentence-1)

  * [(54.3.3)](#queries-54.3.3)

      Otherwise, R is a reflection representing the value of A[.](#queries-54.3.3.sentence-1)

[*Example [6](#queries-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*]

[55](#queries-55)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4920)

*Throws*: meta​::​exception unlesshas_template_arguments(r) is true[.](#queries-55.sentence-1)

[ð](#lib:parameters_of)

`consteval vector<info> parameters_of(info r);
`

[56](#queries-56)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4932)

*Returns*: 

- [(56.1)](#queries-56.1)

  If r represents a function F,
 then a vector containing reflections of the parameters of F,
 in the order in which they appear in a declaration of F[.](#queries-56.1.sentence-1)

- [(56.2)](#queries-56.2)

  Otherwise, r represents a function type T;
 a vector containing reflections of the types
 in parameter-type-list ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")) of T,
 in the order in which they appear in the parameter-type-list[.](#queries-56.2.sentence-1)

[57](#queries-57)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4946)

*Throws*: meta​::​exception unlessr represents a function or a function type[.](#queries-57.sentence-1)

[ð](#lib:variable_of)

`consteval info variable_of(info r);
`

[58](#queries-58)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4958)

*Returns*: The reflection of the parameter variable corresponding to r[.](#queries-58.sentence-1)

[59](#queries-59)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4962)

*Throws*: meta​::​exception unless

- [(59.1)](#queries-59.1)

r represents a parameter of a function F and

- [(59.2)](#queries-59.2)

there is a point P in the evaluation context
 for which the innermost non-block scope enclosing P is the function parameter scope ([[basic.scope.param]](basic.scope.param "6.4.4 Function parameter scope"))
 associated with F[.](#queries-59.sentence-1)

[ð](#lib:return_type_of)

`consteval info return_type_of(info r);
`

[60](#queries-60)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4982)

*Returns*: The reflection of the return type
of the function or function type represented by r[.](#queries-60.sentence-1)

[61](#queries-61)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4987)

*Throws*: meta​::​exception unless
either r represents a function
and *has-type*(r) is true or r represents a function type[.](#queries-61.sentence-1)

### [21.4.8](#access.context) Access control context [[meta.reflection.access.context]](meta.reflection.access.context)

[1](#access.context-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L4997)

The access_context class is a non-aggregate type
that represents a namespace, class, or function
from which queries pertaining to access rules may be performed,
as well as the designating class ([[class.access.base]](class.access.base "11.8.3 Accessibility of base classes and base class members")), if any[.](#access.context-1.sentence-1)

[2](#access.context-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5004)

An access_context has an associated scope and designating class[.](#access.context-2.sentence-1)

[ð](#lib:access_context_)

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; };}

[3](#access.context-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5024)

access_context is a structural type[.](#access.context-3.sentence-1)

Two values ac1 and ac2 of type access_context are template-argument-equivalent ([[temp.type]](temp.type "13.6 Type equivalence"))
if ac1.scope() and ac2.scope() are template-argument-equivalent
and ac1.designating_class() and ac2.designating_class() are template-argument-equivalent[.](#access.context-3.sentence-2)

[ð](#access.context-itemdecl:1)

`consteval info [scope](#lib:access_context,scope "21.4.8 Access control context [meta.reflection.access.context]")() const;
consteval info [designating_class](#lib:access_context,designating_class "21.4.8 Access control context [meta.reflection.access.context]")() const;
`

[4](#access.context-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5039)

*Returns*: The access_context's associated scope
and designating class, respectively[.](#access.context-4.sentence-1)

[ð](#access.context-itemdecl:2)

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

[5](#access.context-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5050)

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

- [(5.1)](#access.context-5.1)

  If a potentially-evaluated subexpression ([[intro.execution]](intro.execution "6.10.1 Sequential execution"))
 of a default member initializer I for a member of class C ([[class.mem.general]](class.mem.general "11.4.1 General"))
 appears at P,
 then a point determined as follows:
  * [(5.1.1)](#access.context-5.1.1)

      If an aggregate initialization is using I, *eval-point*(Q),
 where Q is the point at which that aggregate initialization appears[.](#access.context-5.1.1.sentence-1)

  * [(5.1.2)](#access.context-5.1.2)

      Otherwise, if an initialization
 by an inherited constructor ([[class.inhctor.init]](class.inhctor.init "11.9.4 Initialization by inherited constructor")) is using I,
 a point whose immediate scope is the class scope corresponding to C[.](#access.context-5.1.2.sentence-1)

  * [(5.1.3)](#access.context-5.1.3)

      Otherwise, a point whose immediate scope
 is the function parameter scope
 corresponding to the constructor definition that is using I[.](#access.context-5.1.3.sentence-1)

- [(5.2)](#access.context-5.2)

  Otherwise, if a potentially-evaluated subexpression
 of a default argument ([[dcl.fct.default]](dcl.fct.default "9.3.4.7 Default arguments")) appears at P, *eval-point*(Q),
 where Q is the point at which the invocation of the function ([[expr.call]](expr.call "7.6.1.3 Function call"))
 using that default argument appears[.](#access.context-5.2.sentence-1)

- [(5.3)](#access.context-5.3)

  Otherwise, if the immediate scope of P is a function parameter scope introduced by a declaration D,
 and P appears either before the locus of D or within the trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") of D,
 a point whose immediate scope is the innermost scope enclosing the locus of D that is not a template parameter scope[.](#access.context-5.3.sentence-1)

- [(5.4)](#access.context-5.4)

  Otherwise, if the immediate scope of P is a function parameter scope
 introduced by a [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]") L whose [*lambda-introducer*](expr.prim.lambda.general#nt:lambda-introducer "7.5.6.1 General [expr.prim.lambda.general]") appears at point Q,
 and P appears either within the [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]") or the trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") of L, *eval-point*(Q)[.](#access.context-5.4.sentence-1)

- [(5.5)](#access.context-5.5)

  Otherwise, if the innermost non-block scope enclosing P is the function parameter scope
 introduced by a [*consteval-block-declaration*](dcl.pre#nt:consteval-block-declaration "9.1 Preamble [dcl.pre]") ([[dcl.pre]](dcl.pre "9.1 Preamble")),
 a point whose immediate scope is that inhabited
 by the outermost [*consteval-block-declaration*](dcl.pre#nt:consteval-block-declaration "9.1 Preamble [dcl.pre]") D containing P such that each scope (if any) that intervenes between P and the function parameter scope introduced by D is either
  * [(5.5.1)](#access.context-5.5.1)

a block scope or

  * [(5.5.2)](#access.context-5.5.2)

a function parameter scope or lambda scope
 introduced by a [*consteval-block-declaration*](dcl.pre#nt:consteval-block-declaration "9.1 Preamble [dcl.pre]")[.](#access.context-5.5.sentence-1)

- [(5.6)](#access.context-5.6)

  Otherwise, P[.](#access.context-5.6.sentence-1)

[6](#access.context-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5114)

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

- [(6.1)](#access.context-6.1)

  If S is a class scope or namespace scope, S[.](#access.context-6.1.sentence-1)

- [(6.2)](#access.context-6.2)

  Otherwise, if S is a function parameter scope
 introduced by the declaration of a function, S[.](#access.context-6.2.sentence-1)

- [(6.3)](#access.context-6.3)

  Otherwise, if S is a lambda scope
 introduced by a [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]") L,
 the function parameter scope
 corresponding to the call operator of the closure type of L[.](#access.context-6.3.sentence-1)

- [(6.4)](#access.context-6.4)

  Otherwise, *ctx-scope*(Sâ²),
 where Sâ² is the parent scope of S[.](#access.context-6.4.sentence-1)

[7](#access.context-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5135)

*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[.](#access.context-7.sentence-1)

[*Example [1](#access.context-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()); // OKstatic_assert(Agg{}.eq()); // OKstatic_assert(B(1).s == ^^B); // OKstatic_assert(is_constructor(B{1, 2}.s) && parent_of(B{1, 2}.s) == ^^B); // OKstatic_assert(is_constructor(C{1, 2}.s) && parent_of(C{1, 2}.s) == ^^B); // OKauto fn() -> [:is_namespace(access_context::current().scope()) ? ^^int : ^^bool:]; static_assert(type_of(^^fn) == ^^auto()->int); // OKtemplate<auto R>struct TCls {consteval bool fn()requires (is_type(access_context::current().scope())) {return true; // OK, scope is TCls<R>.}}; static_assert(TCls<0>{}.fn()); // OK} â *end example*]

[8](#access.context-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5185)

*Remarks*: current is not an addressable function ([[namespace.std]](namespace.std "16.4.5.2.1 Namespace std"))[.](#access.context-8.sentence-1)

An invocation of current that appears at a program point P is value-dependent ([[temp.dep.constexpr]](temp.dep.constexpr "13.8.3.4 Value-dependent expressions"))
if *eval-point*​(​P) is enclosed by a scope
corresponding to a templated entity[.](#access.context-8.sentence-2)

[ð](#access.context-itemdecl:3)

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

[9](#access.context-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5199)

*Returns*: An access_context whose designating class is the null reflection
and whose scope is the global namespace[.](#access.context-9.sentence-1)

[ð](#access.context-itemdecl:4)

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

[10](#access.context-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5210)

*Returns*: An access_context whose designating class and scope
are both the null reflection[.](#access.context-10.sentence-1)

[ð](#access.context-itemdecl:5)

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

[11](#access.context-11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5221)

*Returns*: An access_context whose scope is this->scope() and whose designating class is cls[.](#access.context-11.sentence-1)

[12](#access.context-12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5226)

*Throws*: meta​::​exception unlesscls is either the null reflection
or a reflection of a complete class type[.](#access.context-12.sentence-1)

### [21.4.9](#access.queries) Member accessibility queries [[meta.reflection.access.queries]](meta.reflection.access.queries)

[ð](#lib:is_accessible)

`consteval bool is_accessible(info r, access_context ctx);
`

[1](#access.queries-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5241)

Let *PARENT-CLS*(r) be:

- [(1.1)](#access.queries-1.1)

  If parent_of(r) represents a class C, then C[.](#access.queries-1.1.sentence-1)

- [(1.2)](#access.queries-1.2)

  Otherwise, *PARENT-CLS*(parent_of(r))[.](#access.queries-1.2.sentence-1)

[2](#access.queries-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5248)

Let *DESIGNATING-CLS*(r, ctx) be:

- [(2.1)](#access.queries-2.1)

  If ctx.designating_class() represents a class C, then C[.](#access.queries-2.1.sentence-1)

- [(2.2)](#access.queries-2.2)

  Otherwise, *PARENT-CLS*(r)[.](#access.queries-2.2.sentence-1)

[3](#access.queries-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5255)

*Returns*: 

- [(3.1)](#access.queries-3.1)

  If r represents an unnamed bit-field F,
 then is_accessible(rH, ctx),
 where rH represents a hypothetical non-static data member
 of the class represented by *PARENT-CLS*(r) with the same access as F[.](#access.queries-3.1.sentence-1)
  [*Note [1](#access.queries-note-1)*:
  Unnamed bit-fields are treated as class members
 for the purpose of is_accessible[.](#access.queries-3.1.sentence-2)
 â *end note*]

- [(3.2)](#access.queries-3.2)

  Otherwise, if r does not represent a class member
 or a direct base class relationship,
 then true[.](#access.queries-3.2.sentence-1)

- [(3.3)](#access.queries-3.3)

  Otherwise, if r represents
  * [(3.3.1)](#access.queries-3.3.1)

a class member that is not a (possibly indirect or variant)
 member of *DESIGNATING-CLS*(​r, ctx) or

  * [(3.3.2)](#access.queries-3.3.2)

a direct base class relationship such that parent_of(r) does not represent *DESIGNATING-CLS*(​r, ctx) or a (direct or indirect) base class thereof,

then false[.](#access.queries-3.3.sentence-1)

- [(3.4)](#access.queries-3.4)

  Otherwise, if ctx.scope() is the null reflection,
 then true[.](#access.queries-3.4.sentence-1)

- [(3.5)](#access.queries-3.5)

  Otherwise, letting P be a program point whose immediate scope is the
 function parameter scope, class scope, or namespace scope
 corresponding to the
 function, class, or namespace
 represented by ctx.scope():
  * [(3.5.1)](#access.queries-3.5.1)

      If r represents a direct base class relationship (D,B),
 then true if base class B of *DESIGNATING-CLS*(​r, ctx) is accessible at P ([[class.access.base]](class.access.base "11.8.3 Accessibility of base classes and base class members"));
 otherwise false[.](#access.queries-3.5.1.sentence-1)

  * [(3.5.2)](#access.queries-3.5.2)

      Otherwise, r represents a class member M; true if M would be accessible at P with the designating class ([[class.access.base]](class.access.base "11.8.3 Accessibility of base classes and base class members")) as *DESIGNATING-CLS*(r, ctx) if the effect of any [*using-declaration*](namespace.udecl#nt:using-declaration "9.10 The using declaration [namespace.udecl]")*s* ([[namespace.udecl]](namespace.udecl "9.10 The using declaration")) were ignored[.](#access.queries-3.5.2.sentence-1)
      Otherwise, false[.](#access.queries-3.5.2.sentence-2)

[*Note [2](#access.queries-note-2)*:

The definitions of when a class member or base class is accessible from a point P do not consider whether a declaration of that entity is reachable from P[.](#access.queries-3.sentence-2)

â *end note*]

[*Example [1](#access.queries-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())); // OKstatic_assert(!is_accessible(Cls::r, access_context::current())); // OKstatic_assert(is_accessible(Cls::r, access_context::unchecked())); // OK â *end example*]

[4](#access.queries-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5330)

*Throws*: meta​::​exception if

- [(4.1)](#access.queries-4.1)

r represents a class member
 for which *PARENT-CLS*(r) is an incomplete class or

- [(4.2)](#access.queries-4.2)

r represents a direct base class relationship (D,B) for which D is incomplete[.](#access.queries-4.sentence-1)

[ð](#lib:has_inaccessible_nonstatic_data_members)

`consteval bool has_inaccessible_nonstatic_data_members(info r, access_context ctx);
`

[5](#access.queries-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5349)

*Returns*: true if is_accessible(R, ctx) is false for any R in nonstatic_data_members_of(​r, access_context​​::​unchecked())[.](#access.queries-5.sentence-1)

Otherwise, false[.](#access.queries-5.sentence-2)

[6](#access.queries-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5355)

*Throws*: meta​::​exception unless

- [(6.1)](#access.queries-6.1)

nonstatic_data_members_of(​r, access_context​::​​unchecked()) is a constant subexpression and

- [(6.2)](#access.queries-6.2)

r does not represent a closure type[.](#access.queries-6.sentence-1)

[ð](#access.queries-itemdecl:3)

`consteval bool has_inaccessible_bases(info r, access_context ctx);
`

[7](#access.queries-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5372)

*Returns*: true if is_accessible(R, ctx) is false for any R in bases_of(​r, access_context​::​​unchecked())[.](#access.queries-7.sentence-1)

Otherwise, false[.](#access.queries-7.sentence-2)

[8](#access.queries-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5378)

*Throws*: meta​::​exception unlessbases_of(r, access_context​::​unchecked()) is a constant subexpression[.](#access.queries-8.sentence-1)

[ð](#lib:has_inaccessible_subobjects)

`consteval bool has_inaccessible_subobjects(info r, access_context ctx);
`

[9](#access.queries-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5391)

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

### [21.4.10](#member.queries) Reflection member queries [[meta.reflection.member.queries]](meta.reflection.member.queries)

[ð](#lib:members_of)

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

[1](#member.queries-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5407)

A declaration D [*members-of-precedes*](#def:members-of-precedes) a point P if D precedes either P or the point immediately following the [*class-specifier*](class.pre#nt:class-specifier "11.1 Preamble [class.pre]") of the outermost class for which P is in a complete-class context[.](#member.queries-1.sentence-1)

[2](#member.queries-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5413)

A declaration D of a member M of a class or namespace Q is[*Q-members-of-eligible*](#def:Q-members-of-eligible) if

- [(2.1)](#member.queries-2.1)

the host scope of D ([[basic.scope.scope]](basic.scope.scope "6.4.1 General"))
 is the class scope or namespace scope associated with Q,

- [(2.2)](#member.queries-2.2)

D is not a friend declaration,

- [(2.3)](#member.queries-2.3)

M is not a closure type ([[expr.prim.lambda.closure]](expr.prim.lambda.closure "7.5.6.2 Closure types")),

- [(2.4)](#member.queries-2.4)

M is not a specialization of a template ([[temp.pre]](temp.pre "13.1 Preamble")),

- [(2.5)](#member.queries-2.5)

if Q is a class that is not a closure type,
 then M is a direct member of Q ([[class.mem.general]](class.mem.general "11.4.1 General"))
 that is not a variant member of a
 nested anonymous union of Q ([[class.union.anon]](class.union.anon "11.5.2 Anonymous unions")), and

- [(2.6)](#member.queries-2.6)

if Q is a closure type,
 then M is a function call operator or function call operator template[.](#member.queries-2.sentence-1)

It is implementation-defined
whether declarations of other members of a closure type Q are Q-members-of-eligible[.](#member.queries-2.sentence-2)

[3](#member.queries-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5440)

A member M of a class or namespace Q is[*Q-members-of-representable*](#def:Q-members-of-representable) from a point P if a Q-members-of-eligible declaration of M members-of-precedes P,
and M is

- [(3.1)](#member.queries-3.1)

a class or enumeration type

- [(3.2)](#member.queries-3.2)

a type alias

- [(3.3)](#member.queries-3.3)

a class template, function template,
 variable template, alias template, or concept,

- [(3.4)](#member.queries-3.4)

a variable or reference V for which the type of V does not contain an undeduced placeholder type,

- [(3.5)](#member.queries-3.5)

a function F for which
  * [(3.5.1)](#member.queries-3.5.1)

the type of F does not contain an undeduced placeholder type,

  * [(3.5.2)](#member.queries-3.5.2)

the constraints (if any) of F are satisfied, and

  * [(3.5.3)](#member.queries-3.5.3)

if F is a prospective destructor, F is the selected destructor ([[class.dtor]](class.dtor "11.4.7 Destructors")),

- [(3.6)](#member.queries-3.6)

a non-static data member,

- [(3.7)](#member.queries-3.7)

a namespace, or

- [(3.8)](#member.queries-3.8)

a namespace alias[.](#member.queries-3.sentence-1)

[*Note [1](#member.queries-note-1)*:

Examples of direct members that are not Q-members-of-representable
for any entity Q include:
unscoped enumerators ([[enum]](enum "9.8 Enumerations")),
partial specializations of templates ([[temp.spec.partial]](temp.spec.partial "13.7.6 Partial specialization")), and
closure types ([[expr.prim.lambda.closure]](expr.prim.lambda.closure "7.5.6.2 Closure types"))[.](#member.queries-3.sentence-2)

â *end note*]

[4](#member.queries-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5482)

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

- [(4.1)](#member.queries-4.1)

M is Q-members-of-representable
 from some point in the evaluation context and

- [(4.2)](#member.queries-4.2)

is_accessible(^^M, ctx) is true[.](#member.queries-4.sentence-1)

If dealias(r) represents a class C,
then the vector also contains reflections
representing all unnamed bit-fields B whose declarations inhabit the class scope corresponding to C for which is_accessible(^^B, ctx) is true[.](#member.queries-4.sentence-2)

Reflections of class members and unnamed bit-fields that are declared
appear in the order in which they are declared[.](#member.queries-4.sentence-3)

[*Note [2](#member.queries-note-2)*:

Base classes are not members[.](#member.queries-4.sentence-4)

Implicitly-declared special members
appear after any user-declared members ([[special]](special "11.4.4 Special member functions"))[.](#member.queries-4.sentence-5)

â *end note*]

[*Example [1](#member.queries-example-1)*: // TU1export module M;namespace NS {export int m; static int l;}static_assert(members_of(^^NS, access_context::current()).size() == 2);

// TU2import M;

static_assert( // NS​::​l does not precede members_of(^^NS, access_context::current()).size() == 1); // the constant-expression ([[basic.lookup]](basic.lookup "6.5 Name lookup"))class B {};

struct S : B {private:class I;public:int m;};

static_assert( // 6 special members, members_of(^^S, access_context::current()).size() == 7); // 1 public member,// does not include basestatic_assert( // all of the above, members_of(^^S, access_context::unchecked()).size() == 8); // as well as a reflection// representing S​::​I â *end example*]

[5](#member.queries-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5540)

*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[.](#member.queries-5.sentence-1)

[ð](#lib:bases_of)

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

[6](#member.queries-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5554)

*Returns*: Let C be the class represented by dealias(type)[.](#member.queries-6.sentence-1)

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[.](#member.queries-6.sentence-2)

The direct base class relationships appear in the order in which
the corresponding base classes appear in the [*base-specifier-list*](class.derived.general#nt:base-specifier-list "11.7.1 General [class.derived.general]") of C[.](#member.queries-6.sentence-3)

[7](#member.queries-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5563)

*Throws*: meta​::​exception unlessdealias(type) represents a class type
that is complete from some point in the evaluation context[.](#member.queries-7.sentence-1)

[ð](#lib:static_data_members_of)

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

[8](#member.queries-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5576)

*Returns*: A vector containing each element e of members_of(type, ctx) such that is_variable(e) is true,
preserving their order[.](#member.queries-8.sentence-1)

[9](#member.queries-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5582)

*Throws*: meta​::​exception unlessdealias(type) represents a class type
that is complete from some point in the evaluation context[.](#member.queries-9.sentence-1)

[ð](#lib:nonstatic_data_members_of)

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

[10](#member.queries-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5596)

*Returns*: A vector containing each element e of members_of(type, ctx) such that is_nonstatic_data_member(e) is true,
preserving their order[.](#member.queries-10.sentence-1)

[11](#member.queries-11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5602)

*Throws*: meta​::​exception unlessdealias(type) represents a class type
that is complete from some point in the evaluation context[.](#member.queries-11.sentence-1)

[ð](#lib:subobjects_of)

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

[12](#member.queries-12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5615)

*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[.](#member.queries-12.sentence-1)

[13](#member.queries-13)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5621)

*Throws*: meta​::​exception unlessdealias(type) represents a class type
that is complete from some point in the evaluation context[.](#member.queries-13.sentence-1)

[ð](#lib:enumerators_of)

`consteval vector<info> enumerators_of(info type_enum);
`

[14](#member.queries-14)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5634)

*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[.](#member.queries-14.sentence-1)

[15](#member.queries-15)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5640)

*Throws*: meta​::​exception unlessdealias(type_enum) represents an enumeration type,
and is_enumerable_type(​type_enum) is true[.](#member.queries-15.sentence-1)

### [21.4.11](#layout) Reflection layout queries [[meta.reflection.layout]](meta.reflection.layout)

[ð](#lib:member_offset)

`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;
`

[1](#layout-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5663)

*Returns*: bytes * CHAR_BIT + bits[.](#layout-1.sentence-1)

[ð](#lib:offset_of)

`consteval member_offset offset_of(info r);
`

[2](#layout-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5674)

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 entity represented by r[.](#layout-2.sentence-1)

[3](#layout-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5679)

*Returns*: {V / CHAR_BIT, V % CHAR_BIT}[.](#layout-3.sentence-1)

[4](#layout-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5683)

*Throws*: meta​::​exception unlessr represents a non-static data member,
unnamed bit-field, or
direct base class relationship (D,B) for which either B is not a virtual base class
or D is not an abstract class[.](#layout-4.sentence-1)

[ð](#lib:size_of)

`consteval size_t size_of(info r);
`

[5](#layout-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5699)

*Returns*: If r represents

- [(5.1)](#layout-5.1)

a non-static data member of type T,

- [(5.2)](#layout-5.2)

a data member description (T,N,A,W,NUA), or

- [(5.3)](#layout-5.3)

dealias(r) represents a type T,

then sizeof(T) if T is not a reference type
and size_of(​add_pointer(​^^T)) otherwise[.](#layout-5.sentence-1)

Otherwise, size_of(type_of(r))[.](#layout-5.sentence-2)

[*Note [1](#layout-note-1)*:

It is possible that while sizeof(char)​ == size_of(^^char) is true,
that sizeof(char&)​ == size_of(​^^char&) is false[.](#layout-5.sentence-3)

If b represents a direct base class relationship of an empty base class,
then size_of(b) > 0 is true[.](#layout-5.sentence-4)

â *end note*]

[6](#layout-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5719)

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

- [(6.1)](#layout-6.1)

  dealias(r) is a reflection of a
type,
object,
value,
variable of non-reference type,
non-static data member that is not a bit-field,
direct base class relationship, or
data member description (T,N,A,W,NUA) ([[class.mem.general]](class.mem.general "11.4.1 General"))
where W is not â¥[.](#layout-6.1.sentence-1)

- [(6.2)](#layout-6.2)

  If dealias(r) represents a type,
then is_complete_type(r) is true[.](#layout-6.2.sentence-1)

[ð](#lib:alignment_of)

`consteval size_t alignment_of(info r);
`

[7](#layout-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5746)

*Returns*: 

- [(7.1)](#layout-7.1)

  If dealias(r) represents a type T,
 then alignment_of(add_pointer(r)) if T is a reference type
 and the alignment requirement of T otherwise[.](#layout-7.1.sentence-1)

- [(7.2)](#layout-7.2)

  Otherwise, if dealias(r) represents a variable or object,
 then the alignment requirement of the variable or object[.](#layout-7.2.sentence-1)

- [(7.3)](#layout-7.3)

  Otherwise, if r represents a direct base class relationship,
 then alignment_of(type_of(r))[.](#layout-7.3.sentence-1)

- [(7.4)](#layout-7.4)

  Otherwise, if r represents a non-static data member M of a class C,
 then the alignment of the direct member subobject
 corresponding to M of a complete object of type C[.](#layout-7.4.sentence-1)

- [(7.5)](#layout-7.5)

  Otherwise, r represents a data member description (T,N,A,W,NUA) ([[class.mem.general]](class.mem.general "11.4.1 General"))[.](#layout-7.5.sentence-1)
  If A is not â¥,
 then the value A[.](#layout-7.5.sentence-2)
  Otherwise, alignment_of(^^T)[.](#layout-7.5.sentence-3)

[8](#layout-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5771)

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

- [(8.1)](#layout-8.1)

  dealias(r) is a reflection of a
type,
object,
variable of non-reference type,
non-static data member that is not a bit-field,
direct base class relationship, or
data member description[.](#layout-8.1.sentence-1)

- [(8.2)](#layout-8.2)

  If dealias(r) represents a type,
then is_complete_type(r) is true[.](#layout-8.2.sentence-1)

[ð](#lib:bit_size_of)

`consteval size_t bit_size_of(info r);
`

[9](#layout-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5796)

*Returns*: 

- [(9.1)](#layout-9.1)

  If r represents
 an unnamed bit-field
 or a non-static data member that is a bit-field
 with width W,
 then W[.](#layout-9.1.sentence-1)

- [(9.2)](#layout-9.2)

  Otherwise, if r represents a data member description (T,N,A,W,NUA) ([[class.mem.general]](class.mem.general "11.4.1 General"))
 and W is not â¥,
 then W[.](#layout-9.2.sentence-1)

- [(9.3)](#layout-9.3)

  Otherwise, CHAR_BIT * size_of(r)[.](#layout-9.3.sentence-1)

[10](#layout-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5814)

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

- [(10.1)](#layout-10.1)

  dealias(r) is a reflection of a
type,
object,
value,
variable of non-reference type,
non-static data member,
unnamed bit-field,
direct base class relationship, or
data member description[.](#layout-10.1.sentence-1)

- [(10.2)](#layout-10.2)

  If dealias(r) represents a type T,
there is a point within the evaluation context from which T is not incomplete[.](#layout-10.2.sentence-1)

### [21.4.12](#extract) Value extraction [[meta.reflection.extract]](meta.reflection.extract)

[1](#extract-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5837)

The extract function template may be used
to extract a value out of a reflection when its type is known[.](#extract-1.sentence-1)

[2](#extract-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5841)

The following are defined for exposition only
to aid in the specification of extract[.](#extract-2.sentence-1)

[ð](#extract-itemdecl:1)

`template<class T>
  consteval T extract-ref(info r);      // exposition only
`

[3](#extract-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5851)

[*Note [1](#extract-note-1)*:

T is a reference type[.](#extract-3.sentence-1)

â *end note*]

[4](#extract-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5856)

*Returns*: If r represents an object O,
then a reference to O[.](#extract-4.sentence-1)

Otherwise, a reference to the object declared, or referred to,
by the variable represented by r[.](#extract-4.sentence-2)

[5](#extract-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5863)

*Throws*: meta​::​exception unless

- [(5.1)](#extract-5.1)

r represents a variable or object of type U,

- [(5.2)](#extract-5.2)

is_convertible_v<remove_reference_t<U>(*)[],​ remove_reference_t<​T>(​*)[]> is true,  
and
  [*Note [2](#extract-note-2)*:
  The intent is to allow only qualification conversion from U to T[.](#extract-5.2.sentence-1)
 â *end note*]

- [(5.3)](#extract-5.3)

If r represents a variable,
 then either that variable is usable in constant expressions
 or its lifetime began within the core constant expression currently under evaluation[.](#extract-5.sentence-1)

[ð](#extract-itemdecl:2)

`template<class T>
  consteval T extract-member-or-function(info r);       // exposition only
`

[6](#extract-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5888)

*Returns*: 

- [(6.1)](#extract-6.1)

  If T is a pointer type,
 then a pointer value pointing to the function represented by r[.](#extract-6.1.sentence-1)

- [(6.2)](#extract-6.2)

  Otherwise, a pointer-to-member value
 designating the non-static data member or function represented by r[.](#extract-6.2.sentence-1)

[7](#extract-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5899)

*Throws*: meta​::​exception unless

- [(7.1)](#extract-7.1)

r represents a non-static data member with type X,
 that is not a bit-field,
 that is a direct member of class C, T and X C​::​* are similar types ([[conv.qual]](conv.qual "7.3.6 Qualification conversions")), and is_convertible_v<X C​::​*, T> is true;

- [(7.2)](#extract-7.2)

r represents an implicit object member function
 with type F or F noexcept that is a direct member of a class C,
 and T is F C​::​*; or

- [(7.3)](#extract-7.3)

r represents a non-member function,
 static member function, or
 explicit object member function
 of function type F or F noexcept,
 and T is F*[.](#extract-7.sentence-1)

[ð](#extract-itemdecl:3)

`template<class T>
  consteval T extract-value(info r);    // exposition only
`

[8](#extract-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5929)

Let U be the type of the value or object that r represents[.](#extract-8.sentence-1)

[9](#extract-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5932)

*Returns*: static_cast<T>([:R:]),
where R is a constant expression of type info such that R == r is true[.](#extract-9.sentence-1)

[10](#extract-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5938)

*Throws*: meta​::​exception unless

- [(10.1)](#extract-10.1)

U is a pointer type, T and U are either similar ([[conv.qual]](conv.qual "7.3.6 Qualification conversions"))
 or both function pointer types, and is_convertible_v<U, T> is true,

- [(10.2)](#extract-10.2)

U is not a pointer type
 and the cv-unqualified types of T and U are the same,

- [(10.3)](#extract-10.3)

U is an array type, T is a pointer type, and
 the value r represents is convertible to T, or

- [(10.4)](#extract-10.4)

U is a closure type, T is a function pointer type, and
 the value that r represents is convertible to T[.](#extract-10.sentence-1)

[ð](#lib:extract)

`template<class T>
  consteval T extract(info r);
`

[11](#extract-11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5968)

Let U be remove_cv_t<T>[.](#extract-11.sentence-1)

[12](#extract-12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5971)

*Effects*: Equivalent to:if constexpr (is_reference_type(^^T)) {return *extract-ref*<T>(r);} else if constexpr (is_nonstatic_data_member(r) || is_function(r)) {return *extract-member-or-function*<U>(r);} else {return *extract-value*<U>(constant_of(r));}

### [21.4.13](#substitute) Reflection substitution [[meta.reflection.substitute]](meta.reflection.substitute)

[ð](#concept:reflection_range)

`template<class R>
concept [reflection_range](#concept:reflection_range "21.4.13 Reflection substitution [meta.reflection.substitute]") =
  ranges::[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")<R> &&
  [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")<ranges::range_value_t<R>, info> &&
  [same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")<remove_cvref_t<ranges::range_reference_t<R>>, info>;

template<[reflection_range](#concept:reflection_range "21.4.13 Reflection substitution [meta.reflection.substitute]") R = initializer_list<info>>
  consteval bool [can_substitute](#lib:can_substitute "21.4.13 Reflection substitution [meta.reflection.substitute]")(info templ, R&& arguments);
`

[1](#substitute-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L5999)

Let Z be the template represented by templ and let Args... be a sequence of prvalue constant expressions
that compute the reflections held by the elements of arguments,
in order[.](#substitute-1.sentence-1)

[2](#substitute-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6005)

*Returns*: true if Z<[:Args:]...> is a valid [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]") ([[temp.names]](temp.names "13.3 Names of template specializations"))
that does not name a function
whose type contains an undeduced placeholder type[.](#substitute-2.sentence-1)

Otherwise, false[.](#substitute-2.sentence-2)

[3](#substitute-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6012)

*Throws*: meta​::​exception unlesstempl represents a template,
and every reflection in arguments represents a construct
usable as a template argument ([[temp.arg]](temp.arg "13.4 Template arguments"))[.](#substitute-3.sentence-1)

[4](#substitute-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6019)

[*Note [1](#substitute-note-1)*:

If forming Z<[:Args:]...> leads to a failure
outside of the immediate context,
the program is ill-formed[.](#substitute-4.sentence-1)

â *end note*]

[ð](#lib:substitute)

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

[5](#substitute-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6034)

Let Z be the template represented by templ and let Args... be a sequence of prvalue constant expressions
that compute the reflections held by the elements of arguments,
in order[.](#substitute-5.sentence-1)

[6](#substitute-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6040)

*Returns*: ^^Z<[:Args:]...>[.](#substitute-6.sentence-1)

[7](#substitute-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6044)

*Throws*: meta​::​exception unlesscan_substitute(templ, arguments) is true[.](#substitute-7.sentence-1)

[8](#substitute-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6049)

[*Note [2](#substitute-note-2)*:

If forming Z<[:Args:]...> leads to a failure outside of the immediate context,
the program is ill-formed[.](#substitute-8.sentence-1)

â *end note*]

[9](#substitute-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6055)

[*Example [1](#substitute-example-1)*: template<class T>auto fn1();

static_assert(!can_substitute(^^fn1, {^^int})); // OKconstexpr info r1 = substitute(^^fn1, {^^int}); // error: fn<int> contains an undeduced// placeholder type for its return typetemplate<class T>auto fn2() {static_assert(^^T != ^^int); // static assertion failed during instantiation of fn<int>return 0; }constexpr bool r2 = can_substitute(^^fn2, {^^int}); // error: instantiation of body of fn<int>// is needed to deduce return type â *end example*]

[10](#substitute-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6076)

[*Example [2](#substitute-example-2)*: consteval info to_integral_constant(unsigned i) {return substitute(^^integral_constant, {^^unsigned, reflect_constant(i)});}constexpr info r = to_integral_constant(2); // OK, r represents the type// integral_constant<unsigned, 2> â *end example*]

### [21.4.14](#result) Expression result reflection [[meta.reflection.result]](meta.reflection.result)

[ð](#lib:reflect_constant)

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

[1](#result-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6097)

*Mandates*: is_copy_constructible_v<T> is true and T is a cv-unqualified structural type ([[temp.param]](temp.param "13.2 Template parameters"))
that is not a reference type[.](#result-1.sentence-1)

[2](#result-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6103)

Let V be:

- [(2.1)](#result-2.1)

if T is a class type,
 then an object that is template-argument-equivalent to the value of expr;

- [(2.2)](#result-2.2)

otherwise, the value of expr[.](#result-2.sentence-1)

[3](#result-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6113)

*Returns*: template_arguments_of(^^TCls<V>)[0],
with TCls as defined below[.](#result-3.sentence-1)

[*Note [1](#result-note-1)*:

This is a reflection of an object for class types,
and a reflection of a value otherwise[.](#result-3.sentence-2)

â *end note*]

[4](#result-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6122)

*Throws*: meta​::​exception unless
the [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]") TCls<V> would be valid
given the invented templatetemplate<T P> struct TCls;

[5](#result-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6131)

[*Example [1](#result-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}); // OKconstexpr info r4 = reflect_constant(K{"ebab"}); // error: constituent pointer// points to string literal â *end example*]

[ð](#lib:reflect_object)

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

[6](#result-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6162)

*Mandates*: T is an object type[.](#result-6.sentence-1)

[7](#result-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6166)

*Returns*: A reflection of the object designated by expr[.](#result-7.sentence-1)

[8](#result-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6170)

*Throws*: meta​::​exception unlessexpr is suitable for use as a constant template argument
for a constant template parameter of type T& ([[temp.arg.nontype]](temp.arg.nontype "13.4.3 Constant template arguments"))[.](#result-8.sentence-1)

[ð](#lib:reflect_function)

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

[9](#result-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6184)

*Mandates*: T is a function type[.](#result-9.sentence-1)

[10](#result-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6188)

*Returns*: A reflection of the function designated by fn[.](#result-10.sentence-1)

[11](#result-11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6192)

*Throws*: meta​::​exception unlessfn is suitable for use as a constant template argument
for a constant template parameter of type T& ([[temp.arg.nontype]](temp.arg.nontype "13.4.3 Constant template arguments"))[.](#result-11.sentence-1)

### [21.4.15](#array) Promoting to static storage arrays [[meta.reflection.array]](meta.reflection.array)

[1](#array-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6201)

The functions in this subclause promote compile-time storage into static storage[.](#array-1.sentence-1)

[ð](#lib:reflect_constant_string)

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

[2](#array-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6211)

Let CharT be ranges​::​range_value_t<R>[.](#array-2.sentence-1)

[3](#array-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6214)

*Mandates*: CharT is one ofchar,wchar_t,char8_t,char16_t,char32_t[.](#array-3.sentence-1)

[4](#array-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6223)

Let V be the pack of values of type CharT whose elements are the corresponding elements of r,
except that if r refers to a string literal object,
then V does not include the trailing null terminator of r[.](#array-4.sentence-1)

[5](#array-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6229)

Let P be the template parameter object ([[temp.param]](temp.param "13.2 Template parameters"))
of type const CharT[sizeof...(V) + 1] initialized with {V..., CharT()}[.](#array-5.sentence-1)

[6](#array-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6234)

*Returns*: ^^P[.](#array-6.sentence-1)

[7](#array-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6238)

[*Note [1](#array-note-1)*:

P is a potentially non-unique object ([[intro.object]](intro.object "6.8.2 Object model"))[.](#array-7.sentence-1)

â *end note*]

[ð](#lib:reflect_constant_array)

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

[8](#array-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6251)

Let T be ranges​::​range_value_t<R>[.](#array-8.sentence-1)

[9](#array-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6254)

*Mandates*: T is a structural type ([[temp.param]](temp.param "13.2 Template parameters")),is_constructible_v<T, ranges​::​range_reference_t<R>> is true, andis_copy_constructible_v<T> is true[.](#array-9.sentence-1)

[10](#array-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6260)

Let V be the pack of values of type info of the same size as r,
where the ith element is reflect_constant(ei),
where ei is the ith element of r[.](#array-10.sentence-1)

[11](#array-11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6266)

Let P be

- [(11.1)](#array-11.1)

  If sizeof...(V) > 0 is true,
 then the template parameter object ([[temp.param]](temp.param "13.2 Template parameters"))
 of type const T[​sizeof...(​V)] initialized with {[:V:]...}[.](#array-11.1.sentence-1)

- [(11.2)](#array-11.2)

  Otherwise, the template parameter object
 of type array<T, 0> initialized with {}[.](#array-11.2.sentence-1)

[12](#array-12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6280)

*Returns*: ^^P[.](#array-12.sentence-1)

[13](#array-13)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6284)

*Throws*: meta​::​exception unlessreflect_constant(e) is a constant subexpression
for every element e of r[.](#array-13.sentence-1)

[14](#array-14)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6290)

[*Note [2](#array-note-2)*:

P is a potentially non-unique object ([[intro.object]](intro.object "6.8.2 Object model"))[.](#array-14.sentence-1)

â *end note*]

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

[ð](#lib:data_member_options)

namespace std::meta {struct data_member_options {struct *name-type* { // *exposition only*template<class T>requires [constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")<u8string, T>consteval *name-type*(T&&); template<class T>requires [constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")<string, T>consteval *name-type*(T&&); private: variant<u8string, string> *contents*; // *exposition only*};

 optional<*name-type*> name;
 optional<int> alignment;
 optional<int> bit_width; bool no_unique_address = false; };}

[1](#define.aggregate-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6323)

The classes data_member_options and data_member_options​::​*name-type* are consteval-only types ([[basic.types.general]](basic.types.general "6.9.1 General")),
and are not structural types ([[temp.param]](temp.param "13.2 Template parameters"))[.](#define.aggregate-1.sentence-1)

[ð](#define.aggregate-itemdecl:1)

`template<class T>
  requires [constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")<u8string, T>
  consteval name-type(T&& value);
`

[2](#define.aggregate-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6336)

*Effects*: Initializes *contents* with u8string(std​::​forward<T>(value))[.](#define.aggregate-2.sentence-1)

[ð](#define.aggregate-itemdecl:2)

`template<class T>
  requires [constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_­from [concept.constructible]")<string, T>
  consteval name-type(T&& value);
`

[3](#define.aggregate-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6349)

*Effects*: Initializes *contents* with string(std​::​forward<T>(value))[.](#define.aggregate-3.sentence-1)

[*Note [1](#define.aggregate-note-1)*:

The class *name-type* allows
the function data_member_spec to accept
an ordinary string literal (or string_view, string, etc[.](#define.aggregate-3.sentence-2))

or a UTF-8 string literal (or u8string_view, u8string, etc[.](#define.aggregate-3.sentence-3))

equally well[.](#define.aggregate-3.sentence-4)

[*Example [1](#define.aggregate-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*]

[ð](#lib:data_member_spec)

`consteval info data_member_spec(info type, data_member_options options);
`

[4](#define.aggregate-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6376)

*Returns*: A reflection of a data member description(T,N,A,W,NUA) ([[class.mem.general]](class.mem.general "11.4.1 General")) where

- [(4.1)](#define.aggregate-4.1)

T is the type represented by dealias(type),

- [(4.2)](#define.aggregate-4.2)

N is either the identifier encoded by options.name or â¥ if options.name does not contain a value,

- [(4.3)](#define.aggregate-4.3)

A is either the alignment value held by options.alignment or â¥ if options.alignment does not contain a value,

- [(4.4)](#define.aggregate-4.4)

W is either the value held by options.bit_width or â¥ if options.bit_width does not contain a value, and

- [(4.5)](#define.aggregate-4.5)

NUA is the value held by options.no_unique_address[.](#define.aggregate-4.sentence-1)

[*Note [2](#define.aggregate-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)[.](#define.aggregate-4.sentence-2)

â *end note*]

[5](#define.aggregate-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6402)

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

- [(5.1)](#define.aggregate-5.1)

dealias(type) represents either an object type or a reference type;

- [(5.2)](#define.aggregate-5.2)

if options.name contains a value, then:
  * [(5.2.1)](#define.aggregate-5.2.1)

holds_alternative<u8string>(options.name->*contents*) is true and get<u8string>(​options.name->*contents*) contains a valid identifier ([[lex.name]](lex.name "5.11 Identifiers"))
 that is not a keyword ([[lex.key]](lex.key "5.12 Keywords"))
 when interpreted with UTF-8, or

  * [(5.2.2)](#define.aggregate-5.2.2)

holds_alternative<string>(options.name->*contents*) is true and get<string>(options.name->*contents*) contains a valid identifier ([[lex.name]](lex.name "5.11 Identifiers"))
 that is not a keyword ([[lex.key]](lex.key "5.12 Keywords"))
 when interpreted with the ordinary literal encoding;

  [*Note [3](#define.aggregate-note-3)*:
  The name corresponds to the spelling of an identifier token
 after phase 6 of translation ([[lex.phases]](lex.phases "5.2 Phases of translation"))[.](#define.aggregate-5.2.sentence-1)
  Lexical constructs like [*universal-character-name*](lex.universal.char#nt:universal-character-name "5.3.2 Universal character names [lex.universal.char]")*s* ([[lex.universal.char]](lex.universal.char "5.3.2 Universal character names")) are not processed
 and will cause evaluation to fail[.](#define.aggregate-5.2.sentence-2)
  For example, R"(\u03B1)" is an invalid identifier
 and is not interpreted as "Î±"[.](#define.aggregate-5.2.sentence-3)
 â *end note*]

- [(5.3)](#define.aggregate-5.3)

if options.name does not contain a value,
 then options.bit_width contains a value;

- [(5.4)](#define.aggregate-5.4)

if options.bit_width contains a value V, then
  * [(5.4.1)](#define.aggregate-5.4.1)

is_integral_type(type) || is_enum_type(type) is true,

  * [(5.4.2)](#define.aggregate-5.4.2)

options.alignment does not contain a value,

  * [(5.4.3)](#define.aggregate-5.4.3)

options.no_unique_address is false, and

  * [(5.4.4)](#define.aggregate-5.4.4)

if V equals 0,
 then options.name does not contain a value; and

- [(5.5)](#define.aggregate-5.5)

if options.alignment contains a value,
 it is an alignment value ([[basic.align]](basic.align "6.8.3 Alignment"))
 not less than alignment_of(type)[.](#define.aggregate-5.sentence-1)

[ð](#lib:is_data_member_spec)

`consteval bool is_data_member_spec(info r);
`

[6](#define.aggregate-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6462)

*Returns*: true if r represents a data member description[.](#define.aggregate-6.sentence-1)

Otherwise, false[.](#define.aggregate-6.sentence-2)

[ð](#lib:define_aggregate)

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

[7](#define.aggregate-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6475)

Let C be the class represented by class_type and rK be the Kth reflection value in mdescrs[.](#define.aggregate-7.sentence-1)

For every rK in mdescrs,
let (TK,NK,AK,WK,NUAK) be
the corresponding data member description represented by rK[.](#define.aggregate-7.sentence-2)

[8](#define.aggregate-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6482)

*Constant When*: 

- [(8.1)](#define.aggregate-8.1)

C is incomplete from every point in the evaluation context;
  [*Note [4](#define.aggregate-note-4)*:
  C can be a class template specialization
 for which there is a reachable definition of the class template[.](#define.aggregate-8.1.sentence-1)
  In this case,
 the injected declaration is an explicit specialization[.](#define.aggregate-8.1.sentence-2)
 â *end note*]

- [(8.2)](#define.aggregate-8.2)

is_data_member_spec(rK) is true for every rK;

- [(8.3)](#define.aggregate-8.3)

is_complete_type(TK) is true for every rK; and

- [(8.4)](#define.aggregate-8.4)

for every pair (rK,rL) where K<L,
 if NK is not â¥ and NL is not â¥,
 then either:
  * [(8.4.1)](#define.aggregate-8.4.1)

NK != NL is true or

  * [(8.4.2)](#define.aggregate-8.4.2)

NK == u8"_" is true[.](#define.aggregate-8.sentence-1)
      [*Note [5](#define.aggregate-note-5)*:
      Every provided identifier is unique or "_"[.](#define.aggregate-8.4.2.sentence-2)
 â *end note*]

[9](#define.aggregate-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6512)

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

- [(9.1)](#define.aggregate-9.1)

  The target scope of D is the scope to which C belongs ([[basic.scope.scope]](basic.scope.scope "6.4.1 General"))[.](#define.aggregate-9.1.sentence-1)

- [(9.2)](#define.aggregate-9.2)

  The locus of D follows immediately after the core constant expression
 currently under evaluation[.](#define.aggregate-9.2.sentence-1)

- [(9.3)](#define.aggregate-9.3)

  The characteristic sequence of D ([[expr.const]](expr.const "7.7 Constant expressions"))
 is the sequence of reflection values rK[.](#define.aggregate-9.3.sentence-1)

- [(9.4)](#define.aggregate-9.4)

  If C is a specialization of a templated class T,
 and C is not a local class,
 then D is an explicit specialization of T[.](#define.aggregate-9.4.sentence-1)

- [(9.5)](#define.aggregate-9.5)

  For each rK,
 there is a corresponding entity MK belonging to the class scope of D with the following properties:
  * [(9.5.1)](#define.aggregate-9.5.1)

      If NK is â¥, MK is an unnamed bit-field[.](#define.aggregate-9.5.1.sentence-1)
      Otherwise, MK is a non-static data member whose name is the identifier
 determined by the character sequence encoded by NK in UTF-8[.](#define.aggregate-9.5.1.sentence-2)

  * [(9.5.2)](#define.aggregate-9.5.2)

      The type of MK is TK[.](#define.aggregate-9.5.2.sentence-1)

  * [(9.5.3)](#define.aggregate-9.5.3)

      MK is declared with the attribute [[no_unique_address]] if and only if NUAK is true[.](#define.aggregate-9.5.3.sentence-1)

  * [(9.5.4)](#define.aggregate-9.5.4)

      If WK is not â¥, MK is a bit-field whose width is that value[.](#define.aggregate-9.5.4.sentence-1)
      Otherwise, MK is not a bit-field[.](#define.aggregate-9.5.4.sentence-2)

  * [(9.5.5)](#define.aggregate-9.5.5)

      If AK is not â¥, MK has the [*alignment-specifier*](dcl.attr.grammar#nt:alignment-specifier "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") alignas(AK)[.](#define.aggregate-9.5.5.sentence-1)
      Otherwise, MK has no [*alignment-specifier*](dcl.attr.grammar#nt:alignment-specifier "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")[.](#define.aggregate-9.5.5.sentence-2)

- [(9.6)](#define.aggregate-9.6)

  For every rL in mdescrs such that K<L,
 the declaration corresponding to rK precedes the declaration corresponding to rL[.](#define.aggregate-9.6.sentence-1)

[10](#define.aggregate-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6562)

*Returns*: class_type[.](#define.aggregate-10.sentence-1)

### [21.4.17](#traits) Reflection type traits [[meta.reflection.traits]](meta.reflection.traits)

[1](#traits-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6569)

This subclause specifies consteval functions to
query the properties of types ([[meta.unary]](meta.unary "21.3.6 Unary type traits")),
query the relationships between types ([[meta.rel]](meta.rel "21.3.8 Relationships between types")), or
transform types ([[meta.trans]](meta.trans "21.3.9 Transformations between types")),
during program translation[.](#traits-1.sentence-1)

Each consteval function declared in this class
has an associated class template declared elsewhere in this document[.](#traits-1.sentence-2)

[2](#traits-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6578)

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

- [(2.1)](#traits-2.1)

  For every parameter p of type info, is_type(p) is true[.](#traits-2.1.sentence-1)

- [(2.2)](#traits-2.2)

  For every parameter r whose type is constrained on [reflection_range](#concept:reflection_range "21.4.13 Reflection substitution [meta.reflection.substitute]"), ranges​::​​all_of(​r, is_type) is true[.](#traits-2.2.sentence-1)

// associated with [[meta.unary.cat]](meta.unary.cat "21.3.6.2 Primary type categories"), primary type categoriesconsteval bool [is_void_type](#lib:is_void_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_null_pointer_type](#lib:is_null_pointer_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_integral_type](#lib:is_integral_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_floating_point_type](#lib:is_floating_point_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_array_type](#lib:is_array_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_pointer_type](#lib:is_pointer_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_lvalue_reference_type](#lib:is_lvalue_reference_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_rvalue_reference_type](#lib:is_rvalue_reference_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_member_object_pointer_type](#lib:is_member_object_pointer_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_member_function_pointer_type](#lib:is_member_function_pointer_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_enum_type](#lib:is_enum_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_union_type](#lib:is_union_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_class_type](#lib:is_class_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_function_type](#lib:is_function_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_reflection_type](#lib:is_reflection_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);

// associated with [[meta.unary.comp]](meta.unary.comp "21.3.6.3 Composite type traits"), composite type categoriesconsteval bool [is_reference_type](#lib:is_reference_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_arithmetic_type](#lib:is_arithmetic_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_fundamental_type](#lib:is_fundamental_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_object_type](#lib:is_object_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_scalar_type](#lib:is_scalar_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_compound_type](#lib:is_compound_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_member_pointer_type](#lib:is_member_pointer_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);

// associated with [[meta.unary.prop]](meta.unary.prop "21.3.6.4 Type properties"), type propertiesconsteval bool [is_const_type](#lib:is_const_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_volatile_type](#lib:is_volatile_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_trivially_copyable_type](#lib:is_trivially_copyable_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_trivially_relocatable_type](#lib:is_trivially_relocatable_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_replaceable_type](#lib:is_replaceable_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_standard_layout_type](#lib:is_standard_layout_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_empty_type](#lib:is_empty_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_polymorphic_type](#lib:is_polymorphic_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_abstract_type](#lib:is_abstract_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_final_type](#lib:is_final_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_aggregate_type](#lib:is_aggregate_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_consteval_only_type](#lib:is_consteval_only_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_signed_type](#lib:is_signed_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_unsigned_type](#lib:is_unsigned_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_bounded_array_type](#lib:is_bounded_array_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_unbounded_array_type](#lib:is_unbounded_array_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_scoped_enum_type](#lib:is_scoped_enum_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);

template<[reflection_range](#concept:reflection_range "21.4.13 Reflection substitution [meta.reflection.substitute]") R = initializer_list<info>>consteval bool [is_constructible_type](#lib:is_constructible_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type, R&& type_args);consteval bool [is_default_constructible_type](#lib:is_default_constructible_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_copy_constructible_type](#lib:is_copy_constructible_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_move_constructible_type](#lib:is_move_constructible_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);

consteval bool [is_assignable_type](#lib:is_assignable_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type_dst, info type_src);consteval bool [is_copy_assignable_type](#lib:is_copy_assignable_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_move_assignable_type](#lib:is_move_assignable_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);

consteval bool [is_swappable_with_type](#lib:is_swappable_with_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type1, info type2);consteval bool [is_swappable_type](#lib:is_swappable_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);

consteval bool [is_destructible_type](#lib:is_destructible_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);

template<[reflection_range](#concept:reflection_range "21.4.13 Reflection substitution [meta.reflection.substitute]") R = initializer_list<info>>consteval bool [is_trivially_constructible_type](#lib:is_trivially_constructible_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type, R&& type_args);consteval bool [is_trivially_default_constructible_type](#lib:is_trivially_default_constructible_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_trivially_copy_constructible_type](#lib:is_trivially_copy_constructible_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_trivially_move_constructible_type](#lib:is_trivially_move_constructible_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);

consteval bool [is_trivially_assignable_type](#lib:is_trivially_assignable_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type_dst, info type_src);consteval bool [is_trivially_copy_assignable_type](#lib:is_trivially_copy_assignable_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_trivially_move_assignable_type](#lib:is_trivially_move_assignable_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_trivially_destructible_type](#lib:is_trivially_destructible_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);

template<[reflection_range](#concept:reflection_range "21.4.13 Reflection substitution [meta.reflection.substitute]") R = initializer_list<info>>consteval bool [is_nothrow_constructible_type](#lib:is_nothrow_constructible_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type, R&& type_args);consteval bool [is_nothrow_default_constructible_type](#lib:is_nothrow_default_constructible_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_nothrow_copy_constructible_type](#lib:is_nothrow_copy_constructible_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_nothrow_move_constructible_type](#lib:is_nothrow_move_constructible_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);

consteval bool [is_nothrow_assignable_type](#lib:is_nothrow_assignable_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type_dst, info type_src);consteval bool [is_nothrow_copy_assignable_type](#lib:is_nothrow_copy_assignable_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_nothrow_move_assignable_type](#lib:is_nothrow_move_assignable_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);

consteval bool [is_nothrow_swappable_with_type](#lib:is_nothrow_swappable_with_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type1, info type2);consteval bool [is_nothrow_swappable_type](#lib:is_nothrow_swappable_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);

consteval bool [is_nothrow_destructible_type](#lib:is_nothrow_destructible_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval bool [is_nothrow_relocatable_type](#lib:is_nothrow_relocatable_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);

consteval bool [is_implicit_lifetime_type](#lib:is_implicit_lifetime_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);

consteval bool [has_virtual_destructor](#lib:has_virtual_destructor "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);

consteval bool [has_unique_object_representations](#lib:has_unique_object_representations "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);

consteval bool [reference_constructs_from_temporary](#lib:reference_constructs_from_temporary "21.4.17 Reflection type traits [meta.reflection.traits]")(info type_dst, info type_src);consteval bool [reference_converts_from_temporary](#lib:reference_converts_from_temporary "21.4.17 Reflection type traits [meta.reflection.traits]")(info type_dst, info type_src);

// associated with [[meta.rel]](meta.rel "21.3.8 Relationships between types"), type relationsconsteval bool [is_same_type](#lib:is_same_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type1, info type2);consteval bool [is_base_of_type](#lib:is_base_of_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type_base, info type_derived);consteval bool [is_virtual_base_of_type](#lib:is_virtual_base_of_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type_base, info type_derived);consteval bool [is_convertible_type](#lib:is_convertible_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type_src, info type_dst);consteval bool [is_nothrow_convertible_type](#lib:is_nothrow_convertible_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type_src, info type_dst);consteval bool [is_layout_compatible_type](#lib:is_layout_compatible_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type1, info type2);consteval bool [is_pointer_interconvertible_base_of_type](#lib:is_pointer_interconvertible_base_of_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type_base, info type_derived);

template<[reflection_range](#concept:reflection_range "21.4.13 Reflection substitution [meta.reflection.substitute]") R = initializer_list<info>>consteval bool [is_invocable_type](#lib:is_invocable_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type, R&& type_args);template<[reflection_range](#concept:reflection_range "21.4.13 Reflection substitution [meta.reflection.substitute]") R = initializer_list<info>>consteval bool [is_invocable_r_type](#lib:is_invocable_r_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type_result, info type, R&& type_args);

template<[reflection_range](#concept:reflection_range "21.4.13 Reflection substitution [meta.reflection.substitute]") R = initializer_list<info>>consteval bool [is_nothrow_invocable_type](#lib:is_nothrow_invocable_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type, R&& type_args);template<[reflection_range](#concept:reflection_range "21.4.13 Reflection substitution [meta.reflection.substitute]") R = initializer_list<info>>consteval bool [is_nothrow_invocable_r_type](#lib:is_nothrow_invocable_r_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type_result, info type, R&& type_args);

// associated with [[meta.trans.cv]](meta.trans.cv "21.3.9.2 Const-volatile modifications"), const-volatile modificationsconsteval info [remove_const](#lib:remove_const "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval info [remove_volatile](#lib:remove_volatile "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval info [remove_cv](#lib:remove_cv "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval info [add_const](#lib:add_const "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval info [add_volatile](#lib:add_volatile "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval info [add_cv](#lib:add_cv "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);

// associated with [[meta.trans.ref]](meta.trans.ref "21.3.9.3 Reference modifications"), reference modificationsconsteval info [remove_reference](#lib:remove_reference "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval info [add_lvalue_reference](#lib:add_lvalue_reference "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval info [add_rvalue_reference](#lib:add_rvalue_reference "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);

// associated with [[meta.trans.sign]](meta.trans.sign "21.3.9.4 Sign modifications"), sign modificationsconsteval info [make_signed](#lib:make_signed "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval info [make_unsigned](#lib:make_unsigned "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);

// associated with [[meta.trans.arr]](meta.trans.arr "21.3.9.5 Array modifications"), array modificationsconsteval info [remove_extent](#lib:remove_extent "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval info [remove_all_extents](#lib:remove_all_extents "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);

// associated with [[meta.trans.ptr]](meta.trans.ptr "21.3.9.6 Pointer modifications"), pointer modificationsconsteval info [remove_pointer](#lib:remove_pointer "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval info [add_pointer](#lib:add_pointer "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);

// associated with [[meta.trans.other]](meta.trans.other "21.3.9.7 Other transformations"), other transformationsconsteval info [remove_cvref](#lib:remove_cvref "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval info [decay](#lib:decay "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);template<[reflection_range](#concept:reflection_range "21.4.13 Reflection substitution [meta.reflection.substitute]") R = initializer_list<info>>consteval info [common_type](time.traits.specializations#lib:common_type "30.4.3 Specializations of common_­type [time.traits.specializations]")(R&& type_args);template<[reflection_range](#concept:reflection_range "21.4.13 Reflection substitution [meta.reflection.substitute]") R = initializer_list<info>>consteval info [common_reference](#lib:common_reference "21.4.17 Reflection type traits [meta.reflection.traits]")(R&& type_args);consteval info [underlying_type](#lib:underlying_type "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);template<[reflection_range](#concept:reflection_range "21.4.13 Reflection substitution [meta.reflection.substitute]") R = initializer_list<info>>consteval info [invoke_result](#lib:invoke_result "21.4.17 Reflection type traits [meta.reflection.traits]")(info type, R&& type_args);consteval info [unwrap_reference](#lib:unwrap_reference "21.4.17 Reflection type traits [meta.reflection.traits]")(info type);consteval info [unwrap_ref_decay](functional.syn#lib:unwrap_ref_decay "22.10.2 Header <functional> synopsis [functional.syn]")(info type);

[3](#traits-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6747)

Each function or function template declared above has the following behavior
based on the signature and return type of that function or function template[.](#traits-3.sentence-1)

[*Note [1](#traits-note-1)*:

The associated class template need not be instantiated[.](#traits-3.sentence-2)

â *end note*]

Table [64](#tab:meta.reflection.traits) — Reflection type traits [[tab:meta.reflection.traits]](./tab:meta.reflection.traits)  

| [ð](#tab:meta.reflection.traits-row-1)<br>**Signature and Return Type** | ***Returns*** |
| --- | --- |
| [ð](#tab:meta.reflection.traits-row-2)<br>bool meta​::​*UNARY*(info type);   bool meta​::​*UNARY*_type(info type); | std​::​*UNARY*_v<T>, where T is the type or type alias represented by type |
| [ð](#tab:meta.reflection.traits-row-3)<br>bool meta​::​*BINARY*(info t1, info t2);   bool meta​::​*BINARY*_type(info t1, info t2); | std​::​*BINARY*_v<T1, T2>, where T1 and T2 are the types or type aliases represented by t1 and t2, respectively |
| [ð](#tab:meta.reflection.traits-row-4)<br>template<reflection_range R>   bool meta​::​*VARIADIC*_type(info type, R&& args); | std​::​*VARIADIC*_v<T, U...>, where T is the type or type alias represented by type and U... is the pack of types or type aliases whose elements are represented by the corresponding elements of args |
| [ð](#tab:meta.reflection.traits-row-5)<br>template<reflection_range R>   bool meta​::​*VARIADIC*_type(info t1, info t2, R&& args); | std​::​*VARIADIC*_v<T1, T2, U...>, where T1 and T2 are the types or type aliases represented by t1 and t2, respectively, and U... is the pack of types or type aliases whose elements are represented by the corresponding elements of args |
| [ð](#tab:meta.reflection.traits-row-6)<br>info meta​::​*UNARY*(info type); | A reflection representing the type denoted by std​::​*UNARY*_t<​T>, where T is the type or type alias represented by type |
| [ð](#tab:meta.reflection.traits-row-7)<br>template<reflection_range R>   info meta​::​*VARIADIC*(R&& args); | A reflection representing the type denoted by std​::​*VARIADIC*_t<T...>, where T... is the pack of types or type aliases whose elements are represented by the corresponding elements of args |
| [ð](#tab:meta.reflection.traits-row-8)<br>template<reflection_range R>   info meta​::​*VARIADIC*(info type, R&& args); | A reflection representing the type denoted by std​::​*VARIADIC*_t<T, U...>, where T is the type or type alias represented by type and U... is the pack of types or type aliases whose elements are represented by the corresponding elements of args |

[4](#traits-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6817)

[*Note [2](#traits-note-2)*:

For those functions or function templates which return a reflection,
that reflection always represents a type and never a type alias[.](#traits-4.sentence-1)

â *end note*]

[5](#traits-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6823)

[*Note [3](#traits-note-3)*:

If t is a reflection of the type int and u is a reflection of an alias to the type int,
then t == u is false but is_same_type(t, u) is true[.](#traits-5.sentence-1)

Also, t == dealias(u) is true[.](#traits-5.sentence-2)

â *end note*]

[ð](#lib:rank)

`consteval size_t rank(info type);
`

[6](#traits-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6838)

*Returns*: rank_v<T>,
where T is the type represented by dealias(type)[.](#traits-6.sentence-1)

[ð](#lib:extent)

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

[7](#traits-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6850)

*Returns*: extent_v<T, I>,
where T is the type represented by dealias(type) and I is a constant equal to i[.](#traits-7.sentence-1)

[ð](#lib:tuple_size)

`consteval size_t tuple_size(info type);
`

[8](#traits-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6863)

*Returns*: tuple_size_v<T>,
where T is the type represented by dealias(type)[.](#traits-8.sentence-1)

[ð](#lib:tuple_element)

`consteval info tuple_element(size_t index, info type);
`

[9](#traits-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6875)

*Returns*: A reflection representing
the type denoted by tuple_element_t<I, T>,
where T is the type represented by dealias(type) and I is a constant equal to index[.](#traits-9.sentence-1)

[ð](#lib:variant_size)

`consteval size_t variant_size(info type);
`

[10](#traits-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6889)

*Returns*: variant_size_v<T>,
where T is the type represented by dealias(type)[.](#traits-10.sentence-1)

[ð](#lib:variant_alternative)

`consteval info variant_alternative(size_t index, info type);
`

[11](#traits-11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6901)

*Returns*: A reflection representing the type denoted byvariant_alternative_t<I, T>,
where T is the type represented by dealias(type) and I is a constant equal to index[.](#traits-11.sentence-1)

[ð](#lib:type_order)

`consteval strong_ordering type_order(info t1, info t2);
`

[12](#traits-12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6915)

*Returns*: type_order_v<T1, T2>,
where T1 and T2 are the types
represented by dealias(t1) and dealias(t2), respectively[.](#traits-12.sentence-1)

### [21.4.18](#annotation) Annotation reflection [[meta.reflection.annotation]](meta.reflection.annotation)

[ð](#lib:annotations_of)

`consteval vector<info> annotations_of(info item);
`

[1](#annotation-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6930)

Let E be

- [(1.1)](#annotation-1.1)

the corresponding [*base-specifier*](class.derived.general#nt:base-specifier "11.7.1 General [class.derived.general]") if item represents a direct base class relationship,

- [(1.2)](#annotation-1.2)

otherwise, the entity represented by item[.](#annotation-1.sentence-1)

[2](#annotation-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6940)

*Returns*: A vector containing all of the reflections R representing each annotation applying to each declaration of E that precedes either
some point in the evaluation context ([[expr.const]](expr.const "7.7 Constant expressions")) or
a point immediately following the [*class-specifier*](class.pre#nt:class-specifier "11.1 Preamble [class.pre]") of the outermost class for which such a point is in a complete-class context[.](#annotation-2.sentence-1)

For any two reflections R1 and R2 in the returned vector,
if the annotation represented by R1 precedes the annotation represented by R2,
then R1 appears before R2[.](#annotation-2.sentence-2)

If R1 and R2 represent annotations from the same translation unit T,
any element in the returned vector between R1 and R2 represents an annotation from T[.](#annotation-2.sentence-3)

[*Note [1](#annotation-note-1)*:

The order in which two annotations appear is otherwise unspecified[.](#annotation-2.sentence-4)

â *end note*]

[*Example [1](#annotation-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*]

[3](#annotation-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L6991)

*Throws*: meta​::​exception unlessitem represents a
type,
type alias,
variable,
function,
namespace,
enumerator,
direct base class relationship, or
non-static data member[.](#annotation-3.sentence-1)

[ð](#lib:annotations_of_with_type)

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

[4](#annotation-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L7011)

*Returns*: A vector containing each element e of annotations_of(item) whereremove_const(type_of(e)) == remove_const(type) is true, preserving their order[.](#annotation-4.sentence-1)

[5](#annotation-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/meta.tex#L7020)

*Throws*: meta​::​exception unless

- [(5.1)](#annotation-5.1)

annotations_of(item) is a constant expression and

- [(5.2)](#annotation-5.2)

dealias(type) represents a type that is complete
 from some point in the evaluation context[.](#annotation-5.sentence-1)
