Files
2025-10-25 03:02:53 +03:00

33 KiB
Raw Permalink Blame History

[meta.reflection.queries]

21 Metaprogramming library [meta]

21.4 Reflection [meta.reflection]

21.4.7 Reflection queries [meta.reflection.queries]

🔗

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

1

#

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

2

#

Returns:

  • (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]).

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

  • (2.3)

    Otherwise, if r represents an annotation, then type_of(constant_of(r)).

  • (2.4)

    Otherwise, if r represents an enumerator N of an enumeration E, then:

    • (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 of D, then a reflection of E.

    • (2.4.2)

      Otherwise, a reflection of the type of N prior to the closing brace of the enum-specifier as specified in [dcl.enum].

  • (2.5)

    Otherwise, if r represents a direct base class relationship (D,B), then a reflection of B.

  • (2.6)

    Otherwise, for a data member description (T,N,A,W,NUA) ([class.mem.general]), a reflection of the type T.

3

#

Throws: meta::exception unlesshas-type(r) is true.

🔗

consteval info object_of(info r);

4

#

Returns:

  • (4.1)

    If r represents an object, then r.

  • (4.2)

    Otherwise, if r represents a reference, then a reflection of the object referred to by that reference.

  • (4.3)

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

#

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

🔗

consteval info constant_of(info r);

6

#

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.

7

#

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

#

Throws: meta::exception unless either r represents an annotation or[: R :] is a validsplice-expression ([expr.prim.splice]).

🔗

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

9

#

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 (D,B) for which B is, respectively, a public, protected, or private base class of D.

Otherwise, false.

🔗

consteval bool is_virtual(info r);

10

#

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.

Otherwise, false.

🔗

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

11

#

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

12

#

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

13

#

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

14

#

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

15

#

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

16

#

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

17

#

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

Otherwise, false.

🔗

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

18

#

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

Otherwise, false.

🔗

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

19

#

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

Otherwise, let T be dealias(r).

20

#

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

21

#

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

22

#

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

Otherwise, let T be dealias(r).

23

#

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

24

#

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

25

#

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

26

#

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

27

#

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]).

28

#

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(E::A) == 2); — end example]

🔗

consteval bool is_variable(info r);

29

#

Returns: true if r represents a variable.

Otherwise, false.

🔗

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

30

#

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

31

#

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

32

#

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

33

#

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

34

#

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

35

#

Returns: true if r represents a function parameter.

Otherwise, false.

🔗

consteval bool is_explicit_object_parameter(info r);

36

#

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

37

#

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

  • (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. Otherwise, false.

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

Otherwise, false.

🔗

consteval bool has_ellipsis_parameter(info r);

38

#

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

39

#

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

Otherwise, false.

40

#

[Note 5:

A template specialization is not a template.

For example,is_template(^^std::vector) is true but is_template(^^std::vector) 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);

41

#

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

42

#

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

Otherwise, false.

🔗

consteval bool is_structured_binding(info r);

43

#

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

44

#

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

45

#

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

Otherwise, false.

🔗

consteval bool has_parent(info r);

46

#

Returns:

  • (46.1)

    If r represents the global namespace, then false.

  • (46.2)

    Otherwise, if r represents an entity that has C language linkage ([dcl.link]), then false.

  • (46.3)

    Otherwise, if r represents an entity that has a language linkage other than C++ language linkage, then an implementation-defined value.

  • (46.4)

    Otherwise, if r represents a type that is neither a class nor enumeration type, then false.

  • (46.5)

    Otherwise, if r represents an entity or direct base class relationship, then true.

  • (46.6)

    Otherwise, false.

🔗

consteval info parent_of(info r);

47

#

Returns:

  • (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 of such a union, then a reflection representing the innermost enclosing anonymous union.

  • (47.2)

    Otherwise, if r represents an enumerator, then a reflection representing the corresponding enumeration type.

  • (47.3)

    Otherwise, if r represents a direct base class relationship (D,B), then a reflection representing D.

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

    • (47.4.1)

      If E is the function call operator 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]

    • (47.4.2)

      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]

48

#

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

🔗

consteval info dealias(info r);

49

#

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]

50

#

Throws: meta::exception unlessr represents an entity.

🔗

consteval bool has_template_arguments(info r);

51

#

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

52

#

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

53

#

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

🔗

consteval vector<info> template_arguments_of(info r);

54

#

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:

  • (54.1)

    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]

  • (54.2)

    Otherwise, if A denotes a class template, variable template, concept, or alias template, then R is a reflection representing A.

  • (54.3)

    Otherwise, A is a constant template argument ([temp.arg.nontype]). Let P be the corresponding template parameter.

    • (54.3.1)

      If P has reference type, then R is a reflection representing the object or function referred to by A.

    • (54.3.2)

      Otherwise, if P has class type, then R represents the corresponding template parameter object.

    • (54.3.3)

      Otherwise, R is a reflection representing the value of A.

[Example 6: template<class T, class U = T> struct Pair { };template struct Pair<char, T> { };template using PairPtr = Pair<T*>;

static_assert(template_of(^^Pair) == ^^Pair);static_assert(template_of(^^Pair<char, char>) == ^^Pair);static_assert(template_arguments_of(^^Pair).size() == 2);static_assert(template_arguments_of(^^Pair)[0] == ^^int);

static_assert(template_of(^^PairPtr) == ^^PairPtr);static_assert(template_arguments_of(^^PairPtr).size() == 1);

struct S { };int i;template<int, int&, S, template 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

#

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

🔗

consteval vector<info> parameters_of(info r);

56

#

Returns:

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

  • (56.2)

    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.

57

#

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

🔗

consteval info variable_of(info r);

58

#

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

59

#

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

60

#

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

61

#

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