This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115e. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-11-11
(From submission #506.)
Consider:
template <int> struct S {} v;
Is this a declaration of a class template or a declaration of a variable template, or neither? Implementations uniformly reject.
Another example:
template<class T> typedef struct C F;
Proposed resolution (approved by CWG 2024-04-05):
Change in 13.1 [temp.pre] paragraph 2 through 5 as follows:
The declaration in a template-declaration (if any) shall
The declaration shall not be an export-declaration or a simple-declaration whose decl-specifier-seq contains typedef.
- declare or define a function, a class, or a variable, or
- define a member function, a member class, a member enumeration, or a static data member of a class template or of a class nested within a class template, or
- define a member template of a class or class template, or
- be a deduction-guide, or
- be an alias-declaration.
A template-declaration is a declaration.Ifthe template-declaration declares a member of C, and the nested-name-specifier is treated as a non-dependent reference to C for the purpose of further interpreting the declaration. Otherwise:
- the declaration in a template-declaration introduces an entity using a declarative nested-name-specifier (7.5.5.3 [expr.prim.id.qual]) that is dependent and equivalent to the injected-class-name of a class template or class template partial specialization C, and
- the template-head of the template-declaration is equivalent to that of C,
[ Example:
- A class template is introduced by a template-declaration whose declaration is a simple-declaration that either contains a class-specifier in its decl-specifier-seq or consists solely of an elaborated-type-specifier.
- A function template is introduced by a template-declaration whose declaration declares a function.
- An alias template is introduced by a template-declaration whose declaration is an alias-declaration.
- A variable template is introduced by a template-declaration whose declaration declares a variable.
template<typename T> struct A { template<typename U> struct B; template<typename U> struct B<U*> { template<typename V> void f(); }; }; template<typename T> // #1 template<typename U> // #2 template<typename V> // #3 void A<T>::B<U*>::f() {}The template-declaration #1 declares a member of the class template A, because A<T> is equivalent to the injected-class-name of A. The template-declaration #2 declares a member of the class template partial specialization A<T>::B<U*>, because A<T>::B<U*> is equivalent to the injected-class-name of the partial specialization when A<T> is treated as a non-dependent reference to the primary template A. The template-declaration #3 declares a function template that is a member of the class template partial specialization. -- end example ]A declaration introduced by a template declaration of a variable is a variable template.A variable template at class scope is a static data member template. [ Example: ... ][Note 2: A template-declaration can appear only as a namespace scope or class scope declaration. —end note]
Its declaration shall not be an export-declaration.A template-declaration shall declare exactly one template or member of a template. [ Example:template <int> struct S {} v; // error: declares both a class template and a variable template template <int> struct V *v; // OK: declares a variable template-- end example ] In a function template declaration, the unqualified-id of the declarator-id shall be a name. [Note 3: A class or variable template declaration of a simple-template-id declares a partial specialization (13.7.6 [temp.spec.partial]). —end note]In a template-declaration, explicit specialization, or explicit instantiation, the init-declarator-list in the declaration shall contain at most one declarator. [ Note: When such a declaration is used to declare a class template, no declarator is permitted, because the declarator would be considered to declare a variable or function template in addition to the class template. -- end note ]
CWG 2024-06-26
This drafting lacks the required positional association of template-heads with the respective component of the nested-name-specifier.
Possible resolution (rebased on the current Working Draft):
Change in 13.1 [temp.pre] paragraph 2 through 5 as follows:
The declaration in a template-declaration (if any) shall
The declaration shall not be an export-declaration or a simple-declaration whose decl-specifier-seq contains typedef.
- declare or define a function, a class, or a variable, or
- define a member function, a member class, a member enumeration, or a static data member of a class template or of a class nested within a class template, or
- define a member template of a class or class template, or
- be a friend-type-declaration, or
- be a deduction-guide, or
- be an alias-declaration.
A template-declaration is a declaration.Ifthe template-declaration declares a member of C, and the nested-name-specifier is treated as a non-dependent reference to C for the purpose of further interpreting the declaration. For a template-declaration whose declaration is another template-declaration, the template-head is associated with the positionally corresponding simple-template-id component of the declarative nested-name-specifier. Otherwise:
- the declaration in a template-declaration introduces an entity using a declarative nested-name-specifier (7.5.5.3 [expr.prim.id.qual]) that is dependent and equivalent to the injected-class-name of a class template or class template partial specialization C, and
- the template-head of the template-declaration is equivalent to that of C,
[ Example:
- A class template is introduced by a template-declaration whose declaration is a simple-declaration that either contains a class-specifier in its decl-specifier-seq or consists solely of an elaborated-type-specifier.
- A function template is introduced by a template-declaration whose declaration declares a function.
- An alias template is introduced by a template-declaration whose declaration is an alias-declaration.
- A variable template is introduced by a template-declaration whose declaration declares a variable.
template<typename T> struct A { template<typename U> struct B; template<typename U> struct B<U*> { template<typename V> void f(); }; }; template<typename T> // #1 template<typename U> // #2 template<typename V> // #3 void A<T>::B<U*>::f() {}The template-declaration #1 declares a member of the class template A, because A<T> is equivalent to the injected-class-name of A. The template-declaration #2 declares a member of the class template partial specialization A<T>::B<U*>, because A<T>::B<U*> is equivalent to the injected-class-name of the partial specialization when A<T> is treated as a non-dependent reference to the primary template A. The template-declaration #3 declares a function template that is a member of the class template partial specialization. -- end example ]A declaration introduced by a template declaration of a variable is a variable template.A variable template at class scope is a static data member template. [ Example: ... ][Note 2: A template-declaration can appear only as a namespace scope or class scope declaration. —end note]
Its declaration shall not be an export-declaration.A template-declaration shall declare exactly one template or member of a template. [ Example:template <int> struct S {} v; // error: declares both a class template and a variable template template <int> struct V *v; // OK: declares a variable template-- end example ] In a function template declaration, the unqualified-id of the declarator-id shall be a name. [Note 3: A class or variable template declaration of a simple-template-id declares a partial specialization (13.7.6 [temp.spec.partial]). —end note]In a template-declaration, explicit specialization, or explicit instantiation, the init-declarator-list in the declaration shall contain at most one declarator. [ Note: When such a declaration is used to declare a class template, no declarator is permitted, because the declarator would be considered to declare a variable or function template in addition to the class template. -- end note ]