4428. Metafunctions should not be defined in terms of constant subexpressions

Section: 21.4.9 [meta.reflection.access.queries], 21.4.18 [meta.reflection.annotation], 21.4.15 [meta.reflection.array] Status: WP Submitter: Jonathan Wakely Opened: 2025-10-24 Last modified: 2025-11-11

Priority: Not Prioritized

View all other issues in [meta.reflection.access.queries].

View all issues with WP status.

Discussion:

Addresses US 102-209

"is a constant (sub)expression" is incorrect now that errors are reported via exceptions.

Previous resolution [SUPERSEDED]:

This wording is relative to N5014.

  1. Modify 21.4.9 [meta.reflection.access.queries] as indicated:

    consteval bool has_inaccessible_nonstatic_data_members(info r, access_context ctx);
    

    -5- Returns: true if is_accessible(R, ctx) is false for any R in nonstatic_data_members_of(r, access_context::unchecked()). Otherwise, false.

    -6- Throws: meta::exception unless

    • (6.1) — the evaluation of nonstatic_data_members_of(r, access_context::unchecked()) is a constant subexpression would not exit via an exception and
    • (6.2) — r does not represent a closure type.

    consteval bool has_inaccessible_bases(info r, access_context ctx);
    

    -5- Returns: true if is_accessible(R, ctx) is false for any R in bases_of(r, access_context::unchecked()). Otherwise, false.

    -6- Throws: meta::exception unless the evaluation of bases_of(r, access_context::unchecked()) is a constant subexpression would not exit via an exception.

  2. Modify 21.4.18 [meta.reflection.annotation] as indicated:

    consteval vector<info> annotations_of_with_type(info item, info type);
    

    -4- Returns: A vector containing each element e of annotations_of(item) where remove_const(type_of(e)) == remove_const(type) is true, preserving their order.

    -5- Throws: meta::exception unless

    • (5.1) — the evaluation of annotations_of(item) is a constant subexpression would not exit via an exception and
    • (5.2) — dealias(type) represents a type that is complete from some point in the evaluation context.

  3. Modify 21.4.15 [meta.reflection.array] as indicated:

    template<ranges::input_range R>
      consteval info reflect_constant_array(R&& r);
    

    -8- Let T be ranges::range_value_t<R>.

    -9- Mandates: T is a structural type (13.2 [temp.param]), is_constructible_v<T, ranges::range_reference_t<R>> is true, and is_copy_constructible_v<T> is true.

    -10- Let V be the pack of values of type info of the same size as r, where the ith element is reflect_constant(ei), where ei is the ith element of r.

    -11- Let P be

    • (11.1) — If sizeof...(V) > 0 is true, then the template parameter object (13.2 [temp.param]) of type const T[sizeof...(V)] initialized with {[:V:]...}.
    • (11.2) — Otherwise, the template parameter object of type array<T, 0> initialized with {}.

    -12- Returns: ^^P.

    -13- Throws: meta::exception unless the evaluation of reflect_constant(e) is a constant subexpression would not exit via an exception for every element e of r.

[Kona 2025-11-06; Jonathan removes change to 21.4.15 [meta.reflection.array] that was handled by LWG 4432.]

[Kona 2025-11-06; approved by LWG. Status changed: New → Immediate.]

[Kona 2025-11-08; Status changed: Immediate → WP.]

Proposed resolution:

This wording is relative to N5014.

  1. Modify 21.4.9 [meta.reflection.access.queries] as indicated:

    consteval bool has_inaccessible_nonstatic_data_members(info r, access_context ctx);
    

    -5- Returns: true if is_accessible(R, ctx) is false for any R in nonstatic_data_members_of(r, access_context::unchecked()). Otherwise, false.

    -6- Throws: meta::exception unless if

    • (6.1) — the evaluation of nonstatic_data_members_of(r, access_context::unchecked()) is a constant subexpression would exit via an exception and or
    • (6.2) — r does not represent represents a closure type.

    consteval bool has_inaccessible_bases(info r, access_context ctx);
    

    -7- Returns: true if is_accessible(R, ctx) is false for any R in bases_of(r, access_context::unchecked()). Otherwise, false.

    -8- Throws: meta::exception unless if the evaluation of bases_of(r, access_context::unchecked()) is a constant subexpression would exit via an exception.

  2. Modify 21.4.18 [meta.reflection.annotation] as indicated:

    consteval vector<info> annotations_of_with_type(info item, info type);
    

    -4- Returns: A vector containing each element e of annotations_of(item) where remove_const(type_of(e)) == remove_const(type) is true, preserving their order.

    -5- Throws: meta::exception unless

    • (5.1) — the evaluation of annotations_of(item) is a constant subexpression would not exit via an exception and
    • (5.2) — dealias(type) represents a type that is complete from some point in the evaluation context.