-
Notifications
You must be signed in to change notification settings - Fork 7
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:]); }