类模板构造函数在c ++ 20中可以有一个冗余的模板参数列表吗
据我所知,以下代码:
template<typename T>
struct S {
S<T>();
};
是格式良好的,即使构造函数声明中的
是多余的.
is well-formed, even though the <T>
in the declaration of the constructor is redundant.
但是,在 gcc 主干上(但不是在 gcc10.2 上),使用 -std=c++20
会出现错误:
However, on gcc trunk (but not on gcc10.2), with -std=c++20
this gives an error:
error: expected unqualified-id before ')' token
3 | S<T>();
^
代码使用-std=c++20
.这是一个错误,还是 C++20 中尚未在所有编译器中实现的重大更改?
The code compiles on clang trunk with -std=c++20
. Is this a bug, or is this a breaking change in c++20 that is yet to be implemented in all compilers?
推荐答案
事实上发生了变化.它记录在 C++20 草案的兼容性部分.
There was a change, in fact. It's documented in the compatibility section of the C++20 draft.
[diff.cpp17.class]
2 受影响的子条款:[class.ctor] 和 [class.dtor]
更改:简单模板 ID 不再作为构造函数或析构函数的声明符 ID 有效.
基本原理:删除可能容易出错的冗余选项.
对原始特性的影响:有效的 C++ 2017 代码可??能无法在此国际标准中编译.例如:
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是这样的:
Specifically, the wording delta is this:
n4659 - C++17 标准草案 - [class.ctor]
n4659 - C++17 standard draft - [class.ctor]
1 构造函数没有名称.在构造函数的声明中,声明符是形式为
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
其中 ptr-declarator 仅由 id-expression、可选的属性说明符-seq 和可选的括号组成,并且 id-expression 具有以下形式之一:
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:
- 在属于类的成员规范但不是友元声明的成员声明中,id-expression 是直接封闭类的注入类名;
- 在属于类模板的成员规范但不是友元声明的成员声明中,id 表达式是命名当前实例化的类名立即封闭的类模板;或
n4861 - C++20 标准草案 - [class.ctor]
n4861 - C++20 standard draft - [class.ctor]
1 构造函数由其声明符的声明引入是一个形式的函数声明符 ([dcl.fct])
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
其中 ptr 声明符仅由一个 id 表达式组成,一个可选的属性说明符序列和可选的环绕括号,并且 id 表达式具有以下形式之一:
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:
- 在属于类或类模板的成员规范但不是友元声明的成员声明中([class.friend]),id-expression 是注入的类名([class.pre]) 的直接封闭实体或
如您所见,措辞发生了变化.C++20 现在在声明类模板的构造函数时需要注入的类名.S<T>
是一个简单的模板 id,用于命名专业化.在模板中,注入的类名只是S
.
As you can see, the wording changed. C++20 now requires the injected class name when declaring a constructor for a class template. S<T>
is a simple template id that names a specialization. Inside a template, the injected class name is simply S
.
这是解决 CWG 2237.
相关文章