类模板构造函数可以在c ++ 20中具有冗余的模板参数列表吗

cig*_*ien 4 c++ templates constructor language-lawyer c++20

据我所知,以下代码

template<typename T>
struct S {
    S<T>();
};
Run Code Online (Sandbox Code Playgroud)

是格式良好的,即使<T>在构造函数的声明中是多余的。

但是,在 gcc 主干上(但不是在 gcc10.2 上),-std=c++20这会出现错误:

error: expected unqualified-id before ')' token
    3 |     S<T>();
                 ^
Run Code Online (Sandbox Code Playgroud)

代码编译的铿锵树干-std=c++20。这是一个错误,还是 C++20 中尚未在所有编译器中实现的重大更改?

Sto*_*ica 7

事实上,发生了变化。它记录在 C++20 草案的兼容性部分。

[diff.cpp17.class]

2 受影响的子条款:[class.ctor] 和 [class.dtor]
更改:简单模板 ID 不再作为构造函数或析构函数的声明符ID 有效。
基本原理:删除可能容易出错的冗余选项。
对原始特性的影响:有效的 C++ 2017 代码可​​能无法在此国际标准中编译。例如:

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
};
Run Code Online (Sandbox Code Playgroud)

具体来说,措辞delta是这样的:

n4659 - C++17 标准草案 - [class.ctor]

1构造函数没有名字。在构造函数的声明中,声明符是形式为的函数声明符

ptr-declarator ( parameter-declaration-clause ) noexcept-specifier attribute-specifier-seq
Run Code Online (Sandbox Code Playgroud)

其中 ptr-declarator 仅由 id-expression、可选的属性说明符-seq 和可选的括号组成,并且 id-expression 具有以下形式之一:

  • 在属于类的成员规范但不是友元声明的成员声明中,id 表达式是直接封闭类的注入类名;
  • 在属于类模板的成员规范但不是友元声明的成员声明中, id-expression 是一个类名,用于命名直接封闭类模板的当前实例化;或者

n4861 - C++20 标准草案 - [class.ctor]

1构造函数由一个声明引入,该声明的声明符是一个函数声明符 ([dcl.fct])

ptr-declarator ( parameter-declaration-clause ) noexcept-specifier attribute-specifier-seq
Run Code Online (Sandbox Code Playgroud)

其中 ptr-declarator 仅由 id-expression、可选的属性说明符-seq 和可选的括号组成,并且 id-expression 具有以下形式之一:

  • 在属于类或类模板的成员规范但不是友元声明 ([class.friend]) 的成员声明中,id 表达式是注入的类名 ([class.pre])直接封闭实体或

如您所见,措辞发生了变化。C++20 现在在声明类模板的构造函数时需要注入的类名。S<T>是一个简单的模板 ID,用于命名专业化。在模板中,注入的类名只是S.

这是解决CWG 2237问题的一部分。

  • @cigien:“功能”或多或少是[意外引入](http://open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#1435)(*类名*可以是*simple-template-id*) 在 C++14 中,因此没有太多的兼容性原因来保留无用的东西,并建议可以显式地向构造函数提供模板参数。 (4认同)
  • @cigien - 无论如何,问题已链接。我倾向于同意 2237 中的推理。我个人没有使用或见过 simple-template-ids 用于在 C++ 测验之外定义构造函数。 (2认同)
  • @StoryTeller-UnslanderMonica 我今天才发现这曾经是有效的语法。 (2认同)