类模板的 requires 子句是否必须在成员定义之外重复?

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)

这是要报告的错误吗?

Sto*_*ica 6

应该为 GCC 提交错误,因为它接受代码,即使类外成员的声明没有等效的模板头。

[temp.class]

3当类模板的成员函数、成员类、成员枚举、静态数据成员或类模板的成员模板在类模板 定义之外定义时,成员定义被定义为模板定义,其中 模板头等同于类模板([temp.over.link])。

[temp.over.link]

6如果它们的模板参数列表具有相同的长度,则两个模板头是等效的,相应的模板参数是等效的,并且都使用类型约束声明,如果模板参数声明为类型约束,则它们是等效的,并且如果模板头有一个requires-clause,则它们都有requires-clause,并且相应的constraint-expressions 是等价的。

模板头的等效要求两者都具有等效的 requires 子句。省略它完全打破了等价性。

  • 此处提交:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96830 (3认同)