[meta.reflection.define.aggregate]

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

## 21.4 Reflection [[meta.reflection]](meta.reflection#define.aggregate)

### 21.4.16 Reflection class definition generation [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](#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"))[.](#1.sentence-1)

[ð](#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](#2)

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

*Effects*: Initializes *contents* with u8string(std​::​forward<T>(value))[.](#2.sentence-1)

[ð](#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](#3)

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

*Effects*: Initializes *contents* with string(std​::​forward<T>(value))[.](#3.sentence-1)

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

The class *name-type* allows
the function data_member_spec to accept
an ordinary string literal (or string_view, string, etc[.](#3.sentence-2))

or a UTF-8 string literal (or u8string_view, u8string, etc[.](#3.sentence-3))

equally well[.](#3.sentence-4)

[*Example [1](#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](#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)](#4.1)

T is the type represented by dealias(type),

- [(4.2)](#4.2)

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

- [(4.3)](#4.3)

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

- [(4.4)](#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)](#4.5)

NUA is the value held by options.no_unique_address[.](#4.sentence-1)

[*Note [2](#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)[.](#4.sentence-2)

â *end note*]

[5](#5)

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

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

- [(5.1)](#5.1)

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

- [(5.2)](#5.2)

if options.name contains a value, then:
  * [(5.2.1)](#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)](#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](#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"))[.](#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[.](#5.2.sentence-2)
  For example, R"(\u03B1)" is an invalid identifier
 and is not interpreted as "Î±"[.](#5.2.sentence-3)
 â *end note*]

- [(5.3)](#5.3)

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

- [(5.4)](#5.4)

if options.bit_width contains a value V, then
  * [(5.4.1)](#5.4.1)

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

  * [(5.4.2)](#5.4.2)

options.alignment does not contain a value,

  * [(5.4.3)](#5.4.3)

options.no_unique_address is false, and

  * [(5.4.4)](#5.4.4)

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

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

[ð](#lib:is_data_member_spec)

`consteval bool is_data_member_spec(info r);
`

[6](#6)

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

*Returns*: true if r represents a data member description[.](#6.sentence-1)

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

[ð](#lib:define_aggregate)

`template<[reflection_range](meta.reflection.substitute#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](#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[.](#7.sentence-1)

For every rK in mdescrs,
let (TK,NK,AK,WK,NUAK) be
the corresponding data member description represented by rK[.](#7.sentence-2)

[8](#8)

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

*Constant When*: 

- [(8.1)](#8.1)

C is incomplete from every point in the evaluation context;
  [*Note [4](#note-4)*:
  C can be a class template specialization
 for which there is a reachable definition of the class template[.](#8.1.sentence-1)
  In this case,
 the injected declaration is an explicit specialization[.](#8.1.sentence-2)
 â *end note*]

- [(8.2)](#8.2)

is_data_member_spec(rK) is true for every rK;

- [(8.3)](#8.3)

is_complete_type(TK) is true for every rK; and

- [(8.4)](#8.4)

for every pair (rK,rL) where K<L,
 if NK is not â¥ and NL is not â¥,
 then either:
  * [(8.4.1)](#8.4.1)

NK != NL is true or

  * [(8.4.2)](#8.4.2)

NK == u8"_" is true[.](#8.sentence-1)
      [*Note [5](#note-5)*:
      Every provided identifier is unique or "_"[.](#8.4.2.sentence-2)
 â *end note*]

[9](#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)](#9.1)

  The target scope of D is the scope to which C belongs ([[basic.scope.scope]](basic.scope.scope "6.4.1 General"))[.](#9.1.sentence-1)

- [(9.2)](#9.2)

  The locus of D follows immediately after the core constant expression
 currently under evaluation[.](#9.2.sentence-1)

- [(9.3)](#9.3)

  The characteristic sequence of D ([[expr.const]](expr.const "7.7 Constant expressions"))
 is the sequence of reflection values rK[.](#9.3.sentence-1)

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

- [(9.5)](#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)](#9.5.1)

      If NK is â¥, MK is an unnamed bit-field[.](#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[.](#9.5.1.sentence-2)

  * [(9.5.2)](#9.5.2)

      The type of MK is TK[.](#9.5.2.sentence-1)

  * [(9.5.3)](#9.5.3)

      MK is declared with the attribute [[no_unique_address]] if and only if NUAK is true[.](#9.5.3.sentence-1)

  * [(9.5.4)](#9.5.4)

      If WK is not â¥, MK is a bit-field whose width is that value[.](#9.5.4.sentence-1)
      Otherwise, MK is not a bit-field[.](#9.5.4.sentence-2)

  * [(9.5.5)](#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)[.](#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]")[.](#9.5.5.sentence-2)

- [(9.6)](#9.6)

  For every rL in mdescrs such that K<L,
 the declaration corresponding to rK precedes the declaration corresponding to rL[.](#9.6.sentence-1)

[10](#10)

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

*Returns*: class_type[.](#10.sentence-1)
