This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of WP status.

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

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