[meta.reflection.queries]

21 Metaprogramming library [meta]

21.4.7 Reflection queries [meta.reflection.queries]

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

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

Otherwise, false.

consteval info type_of(info r);

Returns:

  • 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, if r represents a direct base class relationship , then a reflection of B.

Throws: meta​::​exception unless has-type(r) is true.

consteval info object_of(info r);

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.

Throws: meta​::​exception unless 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.

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

consteval info constant_of(info r);

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

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

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

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

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

Returns: true if r represents either

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

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

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

Otherwise, let T be dealias(r).

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

Otherwise, false.

consteval bool is_mutable_member(info r);

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

Otherwise, false.

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

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

Otherwise, let T be dealias(r).

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

Otherwise, false.

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

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

Otherwise, false.

[Note 3:

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

— end note]

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

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

Otherwise, false.

consteval bool has_c_language_linkage(info r);

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

Otherwise, false.

consteval bool is_complete_type(info r);

Returns: true if is_type(r) is 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);

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

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

Otherwise, false.

consteval bool is_function_parameter(info r);

Returns: true if r represents a function parameter.

Otherwise, false.

consteval bool is_explicit_object_parameter(info r);

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

Otherwise, false.

consteval bool has_default_argument(info r);

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

  • 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 or function type that has an ellipsis in its parameter-type-list ([dcl.fct]).

Otherwise, false.

consteval bool is_template(info r);

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

Otherwise, false.

[Note 5:

A template specialization is not a template.

For example, is_template(^^std​::​vector) is 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, operator function template, literal operator template, constructor template, or concept, respectively.

Otherwise, false.

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

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

Otherwise, false.

consteval bool is_structured_binding(info r);

Returns: true if r represents a structured binding.

Otherwise, false.

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

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

Otherwise, false.

consteval bool has_default_member_initializer(info r);

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

Otherwise, false.

consteval bool has_parent(info r);

Returns:

  • 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 entity 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 entity or direct base class relationship, then true.

consteval info parent_of(info r);

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.

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

Throws: meta​::​exception unless has_parent(r) is true.

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

consteval info dealias(info r);

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

Otherwise, r.

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

consteval bool has_template_arguments(info r);

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

Otherwise, false.

consteval info template_of(info r);

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

Throws: meta​::​exception unless has_template_arguments(r) is true.

consteval vector<info> template_arguments_of(info r);

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

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

  • 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.

  • 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.

Throws: meta​::​exception unless has_template_arguments(r) is true.

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

consteval vector<info> parameters_of(info r);

Returns:

  • 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.

Throws: meta​::​exception unless r represents a function or a function type.

consteval info variable_of(info r);

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

Throws: meta​::​exception unless

  • 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.

consteval info return_type_of(info r);

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

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