class 模板构造函数在c++20 中可以有多余的模板参数列表吗
Can class template constructors have a redundant template parameter list in c++20
据我所知,以下code:
template<typename T>
struct S {
S<T>();
};
格式正确,即使构造函数声明中的 <T>
是多余的。
然而,在 gcc trunk 上(但不是在 gcc10.2 上),使用 -std=c++20
这给出了一个错误:
error: expected unqualified-id before ')' token
3 | S<T>();
^
code 使用 -std=c++20
在 clang trunk 上编译。这是一个错误,还是 c++20 中尚未在所有编译器中实现的重大更改?
事实上,发生了变化。它记录在 C++20 草案的兼容性部分。
[diff.cpp17.class]
2 Affected subclauses: [class.ctor] and [class.dtor]
Change: A simple-template-id is no longer valid as the declarator-id of a constructor or destructor.
Rationale: Remove potentially error-prone option for redundancy.
Effect on original feature: Valid C++ 2017 code may fail to compile in this International Standard. For example:
template<class T>
struct A {
A<T>(); // error: simple-template-id not allowed for constructor
A(int); // OK, injected-class-name used
~A<T>(); // error: simple-template-id not allowed for destructor
};
具体来说,delta的写法是这样的:
n4659 - C++17 standard draft - [class.ctor]
1 Constructors do not have names. In a declaration of a constructor,
the declarator is a function declarator of the form
ptr-declarator ( parameter-declaration-clause ) noexcept-specifier attribute-specifier-seq
where the ptr-declarator consists solely of an id-expression, an optional attribute-specifier-seq, and optional surrounding parentheses, and the id-expression has one of the following forms:
- in a member-declaration that belongs to the member-specification of a class but is not a friend declaration, the id-expression is the injected-class-name of the immediately-enclosing class;
- in a member-declaration that belongs to the member-specification of a class template but is not a friend declaration, the id-expression is
a class-name that names the current instantiation of the
immediately-enclosing class template; or
n4861 - C++20 standard draft - [class.ctor]
1 A constructor is introduced by a declaration whose declarator is a
function declarator ([dcl.fct]) of the form
ptr-declarator ( parameter-declaration-clause ) noexcept-specifier attribute-specifier-seq
where the ptr-declarator consists solely of an id-expression, an
optional attribute-specifier-seq, and optional surrounding
parentheses, and the id-expression has one of the following forms:
- in a member-declaration that belongs to the member-specification of a class or class template but is not a friend declaration
([class.friend]), the id-expression is the injected-class-name
([class.pre]) of the immediately-enclosing entity or
如您所见,措辞发生了变化。 C++20 现在在为 class 模板声明构造函数时需要注入的 class 名称。 S<T>
是一个简单的模板 ID,用于命名专业化。在模板中,注入的 class 名称只是 S
.
这是地址 CWG 2237 的一部分。
据我所知,以下code:
template<typename T>
struct S {
S<T>();
};
格式正确,即使构造函数声明中的 <T>
是多余的。
然而,在 gcc trunk 上(但不是在 gcc10.2 上),使用 -std=c++20
这给出了一个错误:
error: expected unqualified-id before ')' token
3 | S<T>();
^
code 使用 -std=c++20
在 clang trunk 上编译。这是一个错误,还是 c++20 中尚未在所有编译器中实现的重大更改?
事实上,发生了变化。它记录在 C++20 草案的兼容性部分。
[diff.cpp17.class]
2 Affected subclauses: [class.ctor] and [class.dtor]
Change: A simple-template-id is no longer valid as the declarator-id of a constructor or destructor.
Rationale: Remove potentially error-prone option for redundancy.
Effect on original feature: Valid C++ 2017 code may fail to compile in this International Standard. For example:template<class T> struct A { A<T>(); // error: simple-template-id not allowed for constructor A(int); // OK, injected-class-name used ~A<T>(); // error: simple-template-id not allowed for destructor };
具体来说,delta的写法是这样的:
n4659 - C++17 standard draft - [class.ctor]
1 Constructors do not have names. In a declaration of a constructor, the declarator is a function declarator of the form
ptr-declarator ( parameter-declaration-clause ) noexcept-specifier attribute-specifier-seq
where the ptr-declarator consists solely of an id-expression, an optional attribute-specifier-seq, and optional surrounding parentheses, and the id-expression has one of the following forms:
- in a member-declaration that belongs to the member-specification of a class but is not a friend declaration, the id-expression is the injected-class-name of the immediately-enclosing class;
- in a member-declaration that belongs to the member-specification of a class template but is not a friend declaration, the id-expression is a class-name that names the current instantiation of the immediately-enclosing class template; or
n4861 - C++20 standard draft - [class.ctor]
1 A constructor is introduced by a declaration whose declarator is a function declarator ([dcl.fct]) of the form
ptr-declarator ( parameter-declaration-clause ) noexcept-specifier attribute-specifier-seq
where the ptr-declarator consists solely of an id-expression, an optional attribute-specifier-seq, and optional surrounding parentheses, and the id-expression has one of the following forms:
- in a member-declaration that belongs to the member-specification of a class or class template but is not a friend declaration ([class.friend]), the id-expression is the injected-class-name ([class.pre]) of the immediately-enclosing entity or
如您所见,措辞发生了变化。 C++20 现在在为 class 模板声明构造函数时需要注入的 class 名称。 S<T>
是一个简单的模板 ID,用于命名专业化。在模板中,注入的 class 名称只是 S
.
这是地址 CWG 2237 的一部分。