PHD*_*PHD 5 c++ templates language-lawyer c++-concepts c++20
当使用该requires子句的类模板的成员在类外定义时,gcc如果requires未指定,则clang不会抱怨,而会。
考虑下面的代码片段:
#include <concepts>
template<typename Container>
requires std::integral<typename Container::value_type>
class Foo {
public:
void func();
};
template<typename Container>
void Foo<Container>::func()
{}
Run Code Online (Sandbox Code Playgroud)
编译使用gcc没有抱怨。
同时clang报如下错误:
? clang++ -std=c++2a test.cpp
test.cpp:10:1: error: requires clause differs in template redeclaration
template<typename Container>
^
test.cpp:4:19: note: previous template declaration is here
requires std::integral<typename Container::value_type>
^
1 error generated.
Run Code Online (Sandbox Code Playgroud)
如果我改变定义如下:
template<typename Container>
requires std::integral<typename Container::value_type>
void Foo<Container>::func()
{}
Run Code Online (Sandbox Code Playgroud)
现在clang不抱怨了。
输出gcc --version:
gcc (GCC) 10.2.0
Run Code Online (Sandbox Code Playgroud)
输出clang --version:
clang version 10.0.1
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
Run Code Online (Sandbox Code Playgroud)
这是要报告的错误吗?
应该为 GCC 提交错误,因为它接受代码,即使类外成员的声明没有等效的模板头。
[temp.class]
3当类模板的成员函数、成员类、成员枚举、静态数据成员或类模板的成员模板在类模板 定义之外定义时,成员定义被定义为模板定义,其中 模板头等同于类模板([temp.over.link])。
[temp.over.link]
6如果它们的模板参数列表具有相同的长度,则两个模板头是等效的,相应的模板参数是等效的,并且都使用类型约束声明,如果模板参数声明为类型约束,则它们是等效的,并且如果模板头有一个requires-clause,则它们都有requires-clause,并且相应的constraint-expressions 是等价的。
模板头的等效要求两者都具有等效的 requires 子句。省略它完全打破了等价性。