21 Metaprogramming library [meta]

21.4 Reflection [meta.reflection]

21.4.6 Reflection queries [meta.reflection.queries]

consteval bool has-type(info r); // exposition only
Returns: true if r represents a value, annotation, object, variable, function whose type does not contain an undeduced placeholder type and that is not a constructor or destructor, enumerator, non-static data member, unnamed bit-field, direct base class relationship, data member description, or function parameter.
Otherwise, false.
consteval bool type_of(info r);
Constant When: has-type(r) is true.
Returns:
  • If r represents the parameter of a function F, then the type in the parameter-type-list of F ([dcl.fct]).
  • 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.
  • Otherwise, if r represents an annotation, then type_of(constant_of(r)).
  • Otherwise, if r represents an enumerator N of an enumeration E, then:
    • 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 of D, then a reflection of E.
    • Otherwise, a reflection of the type of N prior to the closing brace of the enum-specifier as specified in [dcl.enum].
  • Otherwise, if r represents a direct base class relationship , then a reflection of B.
  • Otherwise, for a data member description ([class.mem.general]), a reflection of the type T.
consteval info object_of(info r);
Constant When: r is a reflection representing either
  • an object with static storage duration ([basic.stc.general]), or
  • a variable that either declares or refers to such an object, and if that variable is a reference R, then either
    • R is usable in constant expressions ([expr.const]), or
    • the lifetime of R began within the core constant expression currently under evaluation.
Returns:
  • If r represents an object, then r.
  • Otherwise, if r represents a reference, then a reflection of the object referred to by that reference.
  • Otherwise, r represents a variable; a reflection of the object declared by that variable.
[Example 1: int x; int& y = x; static_assert(^^x != ^^y); // OK, r and y are different variables so their // reflections compare different static_assert(object_of((^^x) == object_of(^^y))); // OK, because y is a reference // to x, their underlying objects are the same — end example]
consteval info constant_of(info r);
Let R be a constant expression of type info such that R == r is true.
If r represents an annotation, then let C be its underlying constant.
Constant When: Either r represents an annotation or [: R :] is a valid splice-expression ([expr.prim.splice]).
Effects: Equivalent to: if constexpr (is_annotation(R)) { return C; } else { return reflect_constant([: R :]); }
[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 different static_assert(constant_of(^^x) == constant_of(^^y)); // OK, both constant_of(x) and // constant_of(^^y) represent the value 0 static_assert(constant_of(^^x) == reflect_constant(0)); // OK, likewise struct S { int m; }; constexpr S s {42}; static_assert(is_object(constant_of(^^s)) && is_object(reflect_object(s))); static_assert(constant_of(^^s) != // OK, template parameter object that is template-argument- reflect_object(s)); // equivalent to s is a different object than s static_assert(constant_of(^^s) == constant_of(reflect_object(s))); // OK consteval info fn() { constexpr int x = 42; return ^^x; } constexpr info r = constant_of(fn()); // error: x is outside its lifetime — end example]
consteval bool is_public(info r); consteval bool is_protected(info r); consteval bool is_private(info r);
Returns: true if r represents either
  • a class member or unnamed bit-field that is public, protected, or private, respectively, or
  • a direct base class relationship for which B is, respectively, a public, protected, or private base class of D.
Otherwise, false.
consteval bool is_virtual(info r);
Returns: true if r represents either a virtual member function or a direct base class relationship for which B is a virtual base class of D.
Otherwise, false.
consteval bool is_pure_virtual(info r); consteval bool is_override(info r);
Returns: true if r represents a member function that is pure virtual or overrides another member function, respectively.
Otherwise, false.
consteval bool is_final(info r);
Returns: true if r represents a final class or a final member function.
Otherwise, false.
consteval bool is_deleted(info r); consteval bool is_defaulted(info r);
Returns: true if r represents a function that is a deleted function ([dcl.fct.def.delete]) or defaulted function ([dcl.fct.def.default]), respectively.
Otherwise, false.
consteval bool is_user_provided(info r); consteval bool is_user_declared(info r);
Returns: true if r represents a function that is user-provided or user-declared ([dcl.fct.def.default]), respectively.
Otherwise, false.
consteval bool is_explicit(info r);
Returns: true if r represents a member function that is declared explicit.
Otherwise, false.
[Note 1: 
If r represents a member function template that is declared explicit, is_explicit(r) is still false because in general, such queries for templates cannot be answered.
— end note]
consteval bool is_noexcept(info r);
Returns: true if r represents a noexcept function type or a function with a non-throwing exception specification ([except.spec]).
Otherwise, false.
[Note 2: 
If r represents a function template that is declared noexcept, is_noexcept(r) is still false because in general, such queries for templates cannot be answered.
— end note]
consteval bool is_bit_field(info r);
Returns: true if r represents a bit-field, or if r represents a data member description ([class.mem.general]) for which W is not ⊥.
Otherwise, false.
consteval bool is_enumerator(info r); consteval bool is_annotation(info r);
Returns: true if r represents an enumerator or annotation, respectively.
Otherwise, false.
consteval bool is_const(info r); consteval bool is_volatile(info r);
Returns: true if r represents a const or volatile type, respectively, or a const- or volatile-qualified function type, respectively.
Otherwise, false.
consteval bool is_mutable_member(info r);
Returns: true if r represents a mutable non-static data member.
Otherwise, false.
consteval bool is_lvalue_reference_qualified(info r); consteval bool is_rvalue_reference_qualified(info r);
Let T be type_of(r) if has-type(r) is true.
Otherwise, let T be dealias(r).
Returns: true if T represents an lvalue- or rvalue-qualified function type, respectively.
Otherwise, false.
consteval bool has_static_storage_duration(info r); consteval bool has_thread_storage_duration(info r); consteval bool has_automatic_storage_duration(info r);
Returns: true if r represents an object or variable that has static, thread, or automatic storage duration, respectively ([basic.stc]).
Otherwise, false.
[Note 3: 
It is not possible to have a reflection representing an object or variable having dynamic storage duration.
— end note]
consteval bool has_internal_linkage(info r); consteval bool has_module_linkage(info r); consteval bool has_external_linkage(info r); consteval bool has_c_language_linkage(info r); consteval bool has_linkage(info r);
Returns: true if r represents a variable, function type, template, or namespace whose name has internal linkage, module linkage, C language linkage, or any linkage, respectively ([basic.link]).
Otherwise, false.
consteval bool is_complete_type(info r);
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]).
Otherwise, false.
consteval bool is_enumerable_type(info r);
A type T is enumerable from a point P if either
  • T is a class type complete at point P or
  • 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 of D ([dcl.enum]).
Returns: true if dealias(r) represents a type that is enumerable from some point in the evaluation context.
Otherwise, false.
[Example 3: class S; enum class E; static_assert(!is_enumerable_type(^^S)); static_assert(!is_enumerable_type(^^E)); class S { void mfn() { static_assert(is_enumerable_type(^^S)); } static_assert(!is_enumerable_type(^^S)); }; static_assert(is_enumerable_type(^^S)); enum class E { A = is_enumerable_type(^^E) ? 1 : 2 }; static_assert(is_enumerable_type(^^E)); static_assert(static_cast<int>(E::A) == 2); — end example]
consteval bool is_variable(info r);
Returns: true if r represents a variable.
Otherwise, false.
consteval bool is_type(info r); consteval bool is_namespace(info r);
Returns: true if r represents an entity whose underlying entity is a type or namespace, respectively.
Otherwise, false.
consteval bool is_type_alias(info r); consteval bool is_namespace_alias(info r);
Returns: true if r represents a type alias or namespace alias, respectively Otherwise, false.
[Note 4: 
A specialization of an alias template is a type alias.
— end note]
consteval bool is_function(info r);
Returns: true if r represents a function.
Otherwise, false.
consteval bool is_conversion_function(info r); consteval bool is_operator_function(info r); consteval bool is_literal_operator(info r);
Returns: true if r represents a function that is a conversion function ([class.conv.fct]), operator function ([over.oper]), or literal operator ([over.literal]), respectively.
Otherwise, false.
consteval bool is_special_member_function(info r); consteval bool is_constructor(info r); consteval bool is_default_constructor(info r); consteval bool is_copy_constructor(info r); consteval bool is_move_constructor(info r); consteval bool is_assignment(info r); consteval bool is_copy_assignment(info r); consteval bool is_move_assignment(info r); consteval bool is_destructor(info r);
Returns: true if r represents a function that is a special member function ([special]), a constructor, a default constructor, a copy constructor, a move constructor, an assignment operator, a copy assignment operator, a move assignment operator, or a destructor, respectively.
Otherwise, false.
consteval bool is_function_parameter(info r);
Returns: true if r represents a function parameter.
Otherwise, false.
consteval bool is_explicit_object_parameter(info r);
Returns: true if r represents a function parameter that is an explicit object parameter ([dcl.fct]).
Otherwise, false.
consteval bool has_default_argument(info r);
Returns: If r represenst a parameter P of a function F, then:
  • 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.
    Otherwise, false.
  • 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.
Otherwise, false.
consteval bool has_ellipsis_parameter(info r);
Returns: true if r represents a function type that has an ellipsis in its parameter-type-list ([dcl.fct]).
Otherwise, false.
consteval bool is_template(info r);
Returns: true if r represents a function template, class template, variable template, alias template, or concept.
Otherwise, false.
[Note 5: 
A template specialization is not a template.
For example, is_template(^^std​::​vector) is true but is_template(^^std​::​vector<int>) is false.
— end note]
consteval bool is_function_template(info r); consteval bool is_variable_template(info r); consteval bool is_class_template(info r); consteval bool is_alias_template(info r); consteval bool is_conversion_function_template(info r); consteval bool is_operator_function_template(info r); consteval bool is_literal_operator_template(info r); consteval bool is_constructor_template(info r); consteval bool is_concept(info r);
Returns: true if r represents a function template, variable template, class template, alias template, conversion function template, literal operator template, constructor template, or concept, respectively.
Otherwise, false.
consteval bool is_value(info r); consteval bool is_object(info r);
Returns: true if r represents a value or object, respectively.
Otherwise, false.
consteval bool is_structured_binding(info r);
Returns: true if r represents a structured binding.
Otherwise, false.
consteval bool is_class_member(info r); consteval bool is_namespace_member(info r); consteval bool is_nonstatic_data_member(info r); consteval bool is_static_member(info r); consteval bool is_base(info r);
Returns: true if r represents a class member, namespace member, non-static data member, static member, or direct base class relationship, respectively.
Otherwise, false.
consteval bool has_default_member_initializer(info r);
Returns: true if r represents a non-static data member that has a default member initializer.
Otherwise, false.
consteval bool has_parent(info r);
Returns:
  • If r represents the global namespace, then false.
  • Otherwise, if r represents an entity that has C language linkage ([dcl.link]), then false.
  • Otherwise, if r represents an enitity that has a language linkage other than C++ language linkage, then an implementation-defined value.
  • Otherwise, if r represents a type that is neither a class nor enumeration type, then false.
  • Otherwise, if r represents an enity or direct base class relationship, then true.
  • Otherwise, false.
consteval info parent_of(info r);
Constant When: has_parent(r) is true.
Returns:
  • 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 of such a union, then a reflection representing the innermost enclosing anonymous union.
  • Otherwise, if r represents an enumerator, then a reflection representing the corresponding enumeration type.
  • Otherwise, if r represents a direct base class relationship , then a reflection representing D.
  • 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.
    • If E is the function call oeprator of a closure type for a consteval-block-declaration ([dcl.pre]), then parent_of(​parent_of(^^E)).
      [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.
      — end note]
    • Otherwise, ^^E.
[Example 4: struct I { }; struct F : I { union { int o; }; enum N { A }; }; constexpr auto ctx = std::meta::access_context::current(); static_assert(parent_of(^^F) == ^^::); static_assert(parent_of(bases_of(^^F, ctx)[0]) == ^^F); static_assert(is_union_type(parent_of(^^F::o))); static_assert(parent_of(^^F::N) == ^^F); static_assert(parent_of(^^F::A) == ^^F::N); — end example]
consteval info dealias(info r);
Constant When: r represents an entity.
Returns: A reflection representing the underlying entity of what r represents.
[Example 5: using X = int; using Y = X; static_assert(dealias(^^int) == ^^int); static_assert(dealias(^^X) == ^^int); static_assert(dealias(^^Y) == ^^int); — end example]
consteval bool has_template_arguments(info r);
Returns: true if r represents a specialization of a function template, variable template, class template, or an alias template.
Otherwise, false.
consteval info template_of(info r);
Constant When: has_template_arguments(r) is true.
Returns: A reflection of the template of the specialization represented by r.
consteval vector<info> template_arguments_of(info r);
Constant When: has_template_arguments(r) is true.
Returns: A vector containing reflections of the template arguments of the template specialization represented by r, in the order in which they appear in the corresponding template argument list.
For a given template argument A, its corresponding reflection R is determined as follows:
  • If A denotes a type or type alias, then R is a reflection representing the underlying entity of A.
    [Note 7: 
    R always represents a type, never a type alias.
    — end note]
  • Otherwise, if A denotes a class template, variable template, concept, or alias template, then R is a reflection representing A.
  • Otherwise, A is a constant template argument ([temp.arg.nontype]).
    Let P be the corresponding template parameter.
    • If P has reference type, then R is a reflection representing the object or function referred to by A.
    • Otherwise, if P has class type, then R represents the corresponding template parameter object.
    • Otherwise, R is a reflection representing the value of A.
[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<int>); static_assert(template_of(^^Pair<char, char>) == ^^Pair); static_assert(template_arguments_of(^^Pair<int>).size() == 2); static_assert(template_arguments_of(^^Pair<int>)[0] == ^^int); static_assert(template_of(^^PairPtr<int>) == ^^PairPtr); static_assert(template_arguments_of(^^PairPtr<int>).size() == 1); struct S { }; int i; template<int, int&, S, template<class> class> struct X { }; constexpr auto T = ^^X<1, i, S{}, PairPtr>; static_assert(is_value(template_arguments_of(T)[0])); static_assert(is_object(template_arguments_of(T)[1])); static_assert(is_object(template_arguments_of(T)[2])); static_assert(template_arguments_of(T)[3] == ^^PairPtr); — end example]
consteval vector<info> parameters_of(info r);
Constant When: r represents a function or a function type.
Returns:
  • 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.
  • Otherwise, r represents a function type T; a vector containing reflections of the types in parameter-type-list ([dcl.fct]) of T, in the order in which they appear in the parameter-type-list.
consteval info variable_of(info r);
Constant When:
  • r represents a parameter of a function F and
  • 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]) associated with F.
Returns: The reflection of the parameter variable corresponding to r.
consteval info return_type_of(info r);
Constant When: Either r represents a function and has-type(r) is true or r represents a function type.
Returns: The reflection of the return type of the function or function type represented by r.