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

问题描述

据我所知,以下code

template<typename T>
struct S {
    S<T>();
};

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

但是,在gcc中继上(但在gcc10.2上不是),如果使用-std=c++20,则会出现错误

error: expected unqualified-id before ')' token
    3 |     S<T>();
                 ^

code-std=c++20的clang干线上编译。这是一个错误,还是c ++ 20中一项尚未在所有编译器中实现的重大更改?

解决方法

实际上有一个变化。 C ++ 20草案的兼容性部分对此进行了记录。

[diff.cpp17.class]

2 受影响的条款:[class.ctor]和[class.dtor]
更改:simple-template-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
};

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

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

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

ptr-declarator ( parameter-declaration-clause ) noexcept-specifier attribute-specifier-seq

其中ptr-declarator仅由一个id表达式,一个可选的attribute-specifier-seq和可选的括号组成,并且id-expression具有以下形式之一:

  • 在属于类的成员规范但不属于朋友声明的成员声明中,id-expression是立即封闭的类的注入类名称;
  • 在属于类模板的成员规范但不是朋友声明的成员声明中,id-expression为 一个类名,用于命名当前实例化 立即封闭类模板;或

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

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

ptr-declarator ( parameter-declaration-clause ) noexcept-specifier attribute-specifier-seq

其中ptr-declarator仅由id表达式, 可选的attribute-specifier-seq和可选的环境 括号,并且id表达式具有以下形式之一:

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

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

这是寻址CWG 2237的一部分。