【问题标题】:Can class template constructors have a redundant template parameter list in c++20c++20中类模板构造函数可以有冗余模板参数列表吗
【发布时间】:2020-12-10 07:35:26
【问题描述】:

据我所知,以下code

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

格式正确,即使构造函数声明中的&lt;T&gt; 是多余的。

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

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

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

【问题讨论】:

  • “格式正确”确定吗? class.ctor/1据我所知,那里没有生产允许模板参数。
  • @n.'pronouns'm。好吧,如果它对语言的更改,那么您将不会在最新草案中找到规则:) 如果它从来没有形成良好的格式,为什么它不是格式错误的?似乎没有编译器可以为任何版本诊断此问题。那是UB吗?
  • 您有什么样的改变? &lt;T&gt; 从来没有被允许在那里。编译器不需要诊断未实例化模板中的错误。一旦模板被实例化,gcc 和 msvc 就会诊断它。 clang 没有,但这似乎是一个unrelated bug
  • 我收回我的话,显然我不明白它是如何工作的。

标签: c++ templates constructor language-lawyer c++20


【解决方案1】:

事实上,发生了变化。它记录在 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-expression、可选的 attribute-specifier-seq 和可选的圆括号组成,并且 id-expression 具有以下形式之一:

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

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

1 构造函数由声明符为 形式的函数声明符([dcl.fct])

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

其中 ptr-declarator 仅由一个 id 表达式组成,一个 可选的属性说明符序列和可选的环绕 括号,并且 id 表达式具有以下形式之一:

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

如您所见,措辞发生了变化。 C++20 现在在为类模板声明构造函数时需要注入的类名。 S&lt;T&gt; 是一个简单的模板 id,用于命名一个特化。在模板中,注入的类名只是S

这是寻址CWG 2237的一部分。

【讨论】:

  • 啊,那么这是一个突破性的变化?以前是允许的,但不是来自c++20?
  • @cigien - 看起来是这样。我看看能不能找出具体的改动原因
  • @cigien - 无论如何,问题已链接。我倾向于同意 2237 中的推理。我个人没有使用或见过用于定义 c++ 测验之外的构造函数的简单模板 ID。
  • @StoryTeller-UnslanderMonica 当我发现这甚至是有效的语法时,我已经老了几天。
  • @cigien:“特征”或多或少是accidentally introducedclass-name 可以是simple-template-id)在 C++14 中,所以没有太多的兼容性理由来保留一些无用的东西,并建议可以显式地向构造函数提供模板参数。
猜你喜欢
  • 2011-02-11
  • 2014-04-21
  • 1970-01-01
  • 2018-05-18
  • 2018-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多