Repository navigation
CWG3111 [temp.param] Correctly handle template parameter objects of array type #791
Description
Activity
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.
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.
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:
There is a (possibly empty) set of static storage duration objects of non-volatile
consttype, called template parameter objects, for which no two such objects are template-argument-equivalent ([temp.type]). Anid-expressionnaming a constant template parameter of class typeTdenotesa static storage duration object of typethe template parameter object which is template-argument-equivalentconst T, known as a template parameter object,([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:]); }Tomasz points out the issue also exists for function-to-pointer conversion:
void f() {} constexpr auto *fptr = &f; constexpr auto &fref = f; static_assert(constant_of(^^fptr) == constant_of(^^fref)); // currently holds
Consider also the following:
template <auto &F> void tfn() {} void f() {} constexpr auto &fref = f; static_assert(constant_of(^^fref) == template_arguments_of(^^tfn<f>)[0]); // currently fails
This motivates the following updated change for [meta.reflection.queries]/7:
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 if constexpr (is_function_type(type_of(R)) { + return reflect_function([:R:]); } else { return reflect_constant([:R:]); }- changed the title
[-][temp.param] Correctly handle template parameter objects of array type[/-][+]CWG3111 [temp.param] Correctly handle template parameter objects of array type[/+]on Nov 2, 2025
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_arrayincludes the following clause ([meta.reflection.array]/11.2):However, the paragraph that introduces "template parameter objects" ([temp.param]/13) does not make it clear that such objects can have array type:
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:
This same conversion is currently specified to occur when
std::meta::constant_ofis 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:I'd like to propose the following changes to address both concerns:
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:
Add the following note after [temp.param]13:
Modify the specification of [meta.reflection.queries]/7 as follows: