Skip to content

CWG3111 [temp.param] Correctly handle template parameter objects of array type #791

@katzdm

Description

@katzdm

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) > 0 is true, then the template parameter object ([temp.param]) of type const 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-expression naming a constant template parameter of class type T denotes a static storage duration object of type const 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 type T is adjusted to be of type "pointer to T".

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:

  1. Modify [temp.param]/13 to more clearly allow for template parameter objects of array type.
  2. Add a note after [temp.param]/13 clarifying that there can be template parameter objects of array type.
  3. Modify [meta.reflection.queries]/11.2 to define constant_of in terms of reflect_constant_array instead of reflect_constant when 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 const type with the property that for every such object O, any template parameter object that is template-argument-equivalent ([temp.type]) to O is necessarily O. An id-expression naming a constant template parameter of class type T denotes a static storage duration the template parameter object of type const 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-expression that 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:]);
  }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions