Created on 2025-11-27.00:00:00 last changed 6 days ago
Proposed resolution:
This wording is relative to N5014 amended with changes from LWG 4432.
Modify [meta.define.static] as indicated:
template<ranges::input_range R> consteval info reflect_constant_array(R&& r);
[…]-8- Let
TU be ranges::range_value_t<R> and T be remove_all_extents_<U>ei be static_cast<T>(*iti), where iti is an iterator to the ith element of `r`.-9- Mandates:
- (9.1) — T is a structural type ([temp.param]),
is_constructible_v<T, ranges::range_reference_t<R>> is `true`, and- (9.2) — `T` satisfies `copy_constructible`, and
- (9.3) — if `U` is not an array type, then is_constructible_v<T, ranges::range_reference_t<R>> is `true`.
-10- Let `V` be the pack of values of type `info` of the same size as `r`, where the ith element is
and iti is an iterator to the ith element of `r`.
- (10.1) — reflect_constant_array(*iti) if U is an array type,
- (10.2) — reflect_constant(static_cast<T>(*iti)
ei) otherwise,-11- Let P be
- (11.1) — If sizeof...(V) > 0 is `true`, then the template parameter object ([temp.param]) of type const `T[sizeof...(V)]`
initialized with `{[:V:]...}`, such that P[I] is template-argument-equivalent ([temp.type]) to the object represented by V...[I] for all I in the range [`0`, `sizeof...(V)`).- (11.2) — Otherwise, the template parameter object of type const array<T, 0> initialized with `{}`.
-12- Returns: ^^P.
-13- Throws: Any exception thrown by operations on `r` or on iterators and sentinels referring to `r`. Any exception thrown by the evaluation of any argument of `reflect_constant`.
ei, or`meta::exception` if evaluation of anyreflect_constant(ei)evaluation of reflect_constant or reflect_constant_array would exit via an exception.
template<class T> consteval const remove_cvref_t<T>* define_static_object(T&& t);
-15- Effects:Equivalent to:
using U = remove_cvref_t<T>; if constexpr (meta::is_class_type(^^U)) { return addressof(meta::extract<const U&>(meta::reflect_constant(std::forward<T>(t)))); } else if constexpr (meta::is_array_type(^^U)) { return addressof(meta::extract<const U&>(meta::reflect_constant_array(std::forward<T>(t)))); } else { return define_static_array(span(addressof(t), 1)).data(); }
[ 2025-12-05; LWG telecon. Wording tweaks ]
As any array type (even of structural types) is not considered an structural type, per [temp.param] p12, any invocation of `reflect_constant_array`/`define_static_array` with a multidimensional array or `span` of arrays is ill-formed due to the Mandates in [meta.define.static] p8 that requires range value type to be structural.
As a consequence, `constant_of` currently supports only single-dimensional arrays (reflect_constant_array strips outermost extents), while multi-dimensional arrays are rejected.
Furthermore, `define_static_object` currently uses define_static_array(span(addressof(t), 1)).data(), for array types. Since for `T[N]` input this creates an multidimensional `T[1][N]` constant parameter object, this function does not support arrays at all. Creating a distinct template parameter object leads to emission of (otherwise unnecessary) additional symbols, and breaks the invariant that for all supported object types &constant_of(o) == define_static_object(o). We should use `reflect_constant_array` for arrays directly.
The Throws clause of `reflect_constant_array` was updated to include any exception thrown by iteration over range.
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2025-12-05 17:38:59 | admin | set | messages: + msg15785 |
| 2025-11-27 10:55:33 | admin | set | messages: + msg15767 |
| 2025-11-27 00:00:00 | admin | create | |