use*_*570 3 c++ templates errata class-template
我看到这个关于 SO 的问题的答案,该问题与类模板的默认构造函数的声明相关,该声明表示由于CWG1435,以下代码不是有效的 C++ :
template <class T> class Stack {
public:
Stack<T>(); //IS THIS VALID?
};
Run Code Online (Sandbox Code Playgroud)
而另一个答案说上面的例子是有效的C++。有两个来源可以证明上述示例有效:
否则,它被视为类型名称,相当于模板名称后跟 <> 中包含的类模板的模板参数
因此,正如我们所看到的,两个链接的答案提出了相反的主张,我不知道哪一个是正确的。所以我的问题是这两个答案哪个是正确的。也就是说,声明Stack<T>();是否有效 C++。
PS:我问的是 C++11 及以后的现代 C++ 含义。
显示的代码片段对于 C++20 之前版本有效,但对于 C++20 及以上版本无效,如下所述。
1 -- 构造函数没有名字。在构造函数的声明中,声明符是以下形式的函数声明符:
ptr-declarator ( parameter-declaration-clause ) noexcept-specifieropt attribute-specifier-seqopt其中 ptr 声明符仅由id-expression、可选的 attribute-specifier-seq 和可选的括号组成,并且 id-expression 具有以下形式之一:
1.2 -- 在属于类模板的成员规范但不是友元声明的成员声明中,id-表达式是一个类名,它命名直接封闭类模板的当前实例;或者
(引用结束)
这意味着在C++17中,我们可以使用Stack<T>();作为构造函数声明。
1 -- 构造函数由声明引入,其声明符是函数声明符 ([dcl.fct]),其形式为:
ptr-declarator ( parameter-declaration-clause ) noexcept-specifieropt attribute-specifier-seqopt其中 ptr 声明符仅由 id-表达式、可选的属性说明符-seq 和可选的括号组成,并且 id-表达式具有以下形式之一:
1.1 -- 在属于类或类模板的成员规范但不是友元声明 ([class.friend]) 的成员声明中,id表达式是注入的类名称 ([class.friend])。 pre]) 的直接封闭实体或
因此,正如我们所看到的,声明类模板的构造函数需要注入的类名(在您的示例中存在Stack,但不在您的示例中)。Stack<T>
这意味着您给定的代码对于 C++20 无效。
diff.cpp17.class#2也提到了同样的事情:
受影响的子条款:[class.ctor] 和 [class.dtor]
更改:简单模板 id 不再有效作为构造函数或析构函数的声明符 id。
理由:删除可能容易出错的冗余选项。
对原始功能的影响:有效的 C++ 2017 代码可能无法在此版本的 C++ 中编译。例如:
Run Code Online (Sandbox Code Playgroud)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 };
| 归档时间: |
|
| 查看次数: |
173 次 |
| 最近记录: |