Files
cppdraft_translate/cppdraft/meta/reflection/define/aggregate.md
2025-10-25 03:02:53 +03:00

10 KiB
Raw Blame History

[meta.reflection.define.aggregate]

21 Metaprogramming library [meta]

21.4 Reflection [meta.reflection]

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

🔗

namespace std::meta {struct data_member_options {struct name-type { // exposition onlytemplaterequires constructible_from<u8string, T>consteval name-type(T&&); templaterequires constructible_from<string, T>consteval name-type(T&&); private: variant<u8string, string> contents; // exposition only};

optional<name-type> name; optional alignment; optional bit_width; bool no_unique_address = false; };}

1

#

The classes data_member_options and data_member_options::name-type are consteval-only types ([basic.types.general]), and are not structural types ([temp.param]).

🔗

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

2

#

Effects: Initializes contents with u8string(std::forward(value)).

🔗

template<class T> requires [constructible_from](concept.constructible#concept:constructible_from "18.4.11Concept constructible_­from[concept.constructible]")<string, T> consteval name-type(T&& value);

3

#

Effects: Initializes contents with string(std::forward(value)).

[Note 1:

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

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

equally well.

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

— end note]

🔗

consteval info data_member_spec(info type, data_member_options options);

4

#

Returns: A reflection of a data member description(T,N,A,W,NUA) ([class.mem.general]) where

T is the type represented by dealias(type),

N is either the identifier encoded by options.name or ⊥ if options.name does not contain a value,

A is either the alignment value held by options.alignment or ⊥ if options.alignment does not contain a value,

W is either the value held by options.bit_width or ⊥ if options.bit_width does not contain a value, and

NUA is the value held by options.no_unique_address.

[Note 2:

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

— end note]

5

#

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

dealias(type) represents either an object type or a reference type;

if options.name contains a value, then:

holds_alternative(options.name->contents) is true and get(options.name->contents) contains a valid identifier ([lex.name]) that is not a keyword ([lex.key]) when interpreted with UTF-8, or

holds_alternative(options.name->contents) is true and get(options.name->contents) contains a valid identifier ([lex.name]) that is not a keyword ([lex.key]) when interpreted with the ordinary literal encoding;

[Note 3: The name corresponds to the spelling of an identifier token after phase 6 of translation ([lex.phases]). Lexical constructs like universal-character-names ([lex.universal.char]) are not processed and will cause evaluation to fail. For example, R"(\u03B1)" is an invalid identifier and is not interpreted as "α". — end note]

if options.name does not contain a value, then options.bit_width contains a value;

if options.bit_width contains a value V, then

is_integral_type(type) || is_enum_type(type) is true,

options.alignment does not contain a value,

options.no_unique_address is false, and

if V equals 0, then options.name does not contain a value; and

if options.alignment contains a value, it is an alignment value ([basic.align]) not less than alignment_of(type).

🔗

consteval bool is_data_member_spec(info r);

6

#

Returns: true if r represents a data member description.

Otherwise, false.

🔗

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

7

#

Let C be the class represented by class_type and rK be the Kth reflection value in mdescrs.

For every rK in mdescrs, let (TK,NK,AK,WK,NUAK) be the corresponding data member description represented by rK.

8

#

Constant When:

C is incomplete from every point in the evaluation context; [Note 4: C can be a class template specialization for which there is a reachable definition of the class template. In this case, the injected declaration is an explicit specialization. — end note]

is_data_member_spec(rK) is true for every rK;

is_complete_type(TK) is true for every rK; and

for every pair (rK,rL) where K<L, if NK is not ⊥ and NL is not ⊥, then either:

NK != NL is true or

NK == u8"" is true. [Note 5: Every provided identifier is unique or "". — end note]

9

#

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

  • (9.1)

    The target scope of D is the scope to which C belongs ([basic.scope.scope]).

  • (9.2)

    The locus of D follows immediately after the core constant expression currently under evaluation.

  • (9.3)

    The characteristic sequence of D ([expr.const]) is the sequence of reflection values rK.

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

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

      If NK is ⊥, MK is an unnamed bit-field. Otherwise, MK is a non-static data member whose name is the identifier determined by the character sequence encoded by NK in UTF-8.

    • (9.5.2)

      The type of MK is TK.

    • (9.5.3)

      MK is declared with the attribute no_unique_address if and only if NUAK is true.

    • (9.5.4)

      If WK is not ⊥, MK is a bit-field whose width is that value. Otherwise, MK is not a bit-field.

    • (9.5.5)

      If AK is not ⊥, MK has the alignment-specifier alignas(AK). Otherwise, MK has no alignment-specifier.

  • (9.6)

    For every rL in mdescrs such that K<L, the declaration corresponding to rK precedes the declaration corresponding to rL.

10

#

Returns: class_type.