Repository navigation
CWG3111 [temp.param] Correctly handle template parameter objects of array type #791
Description
Full name of submitter: Dan Katz
Reference (section label): [temp.param], [meta.reflection.array], [meta.reflection.queries]
Issue description
The specification for std::meta::reflect_constant_array includes the following clause ([meta.reflection.array]/11.2):
- If
sizeof...(V) > 0istrue, then the template parameter object ([temp.param]) of typeconst T[sizeof...(V)]initialized with{[:V:][.](https://eel.is/c++draft/meta.reflection.array#11.1.sentence-1)..}.
However, the paragraph that introduces "template parameter objects" ([temp.param]/13) does not make it clear that such objects can have array type:
An
id-expressionnaming a constant template parameter of class typeTdenotes a static storage duration object of typeconst T, known as a template parameter object, which is template-argument-equivalent ([temp.type]) to the corresponding template argument after it has been converted to the type of the template parameter ([temp.arg.nontype]). No two template parameter objects are template-argument-equivalent.
This paragraph only seems to succeed in establishing that there are template parameter objects of class type. Indeed, there is good reason to think that there are no template parameter objects of array type, since [temp.param]/15 tells us that template arguments of array type undergo array-to-pointer conversion:
A constant template parameter of type "array of
T" or of function typeTis adjusted to be of type "pointer toT".
This same conversion is currently specified to occur when std::meta::constant_of is applied to a reflection that represents a variable of array type. However, that behavior changed during CWG review between P2996R11 (link) and P2996R12 (link) as we began to couple the function's behavior more closely to template parameter objects. As a consequence, the following no longer holds:
constexpr int is[] = {1, 2, 3};
constexpr std::meta::info r = std::meta::reflect_constant_array(is);
static_assert(std::meta::constant_of(^^is) == r); // error: 'constant_of(^^is)' is a reflection of a pointer value.I'd like to propose the following changes to address both concerns:
- Modify [temp.param]/13 to more clearly allow for template parameter objects of array type.
- Add a note after [temp.param]/13 clarifying that there can be template parameter objects of array type.
- Modify [meta.reflection.queries]/11.2 to define
constant_ofin terms ofreflect_constant_arrayinstead ofreflect_constantwhen the argument represents a variable or object having array type.
Suggested resolution
Modify [temp.param]/13 as follows:
Template parameter objects are static storage duration objects of non-volatile
consttype with the property that for every such objectO, any template parameter object that is template-argument-equivalent ([temp.type]) toOis necessarilyO. Anid-expressionnaming a constant template parameter of class typeTdenotesa static storage durationthe template parameter object of typeconst T, known as a template parameter object,which is template-argument-equivalent([temp.type])to the corresponding template argument after it has been converted to the type of the template parameter ([temp.arg.nontype]).No two template parameter objects are template-argument-equivalent.
Add the following note after [temp.param]13:
[ Note: There can be template parameter objects of array type ([meta.reflection.array]), but such objects are never denoted by an
id-expressionthat names a constant template parameter. — end note ]
Modify the specification of [meta.reflection.queries]/7 as follows:
Effects: Equivalent to:
if constexpr (is_annotation(R)) { return C; + } else if constexpr (is_array_type(type_of(R)) { + return reflect_constant_array([:R:]); } else { return reflect_constant([:R:]); }
Activity
t3nsor commentedon Oct 30, 2025
I find the proposed definition of "template parameter object" to be confusing: a definition that uses "with the property that" suggests that to determine whether something is a template parameter object, you check whether it has that property. This property should be in a separate sentence (as it currently is) to make it clear that it's not part of the definition.
katzdm commentedon Oct 30, 2025
Yeah, I hear that. I'm trying to separate the definition from the template parameter mechanism, since we evidently now have template parameter objects that are never consequent from an instantiation. On the other hand, their only prior definition was "the static storage duration objects that happen to be consequent from an instantiation." And yet, that property (i.e., unique under template-argument-equivalence) is their most important quality.
So I think the the confusion here is that "template parameter objects" is more correctly a "family" or "class" of not-very-special static storage duration objects. Here's another try:
Updated suggestion resolution
Modify [temp.param]/13 as follows:
Add the following note after [temp.param]/13:
Modify the specification of [meta.reflection.queries]/7 as follows:
katzdm commentedon Oct 31, 2025
Tomasz points out the issue also exists for function-to-pointer conversion:
Consider also the following:
This motivates the following updated change for [meta.reflection.queries]/7:
jensmaurer commentedon Nov 2, 2025
CWG3111
[-][temp.param] Correctly handle template parameter objects of array type[/-][+]CWG3111 [temp.param] Correctly handle template parameter objects of array type[/+]