red*_*der 6 c++ constructor require c++20
g++ 愉快地接受以下代码,而 clang 和 msvc 能够匹配行外定义。
知道为什么吗?
template <bool B>
struct test
{
test() requires (B);
test() requires(!B);
};
template <>
test<true>::test()
{}
template <>
test<false>::test()
{}
int main()
{
test<false> a;
test<true> b;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
铛:
错误:超出行的“定义
test”不匹配中的任何声明“test<true>”
msvc:
错误 C2244:“
test<true>::test”:无法将函数定义与现有声明匹配
您正在声明受约束的构造函数,但定义了两个不受约束的特化。那些永远不会匹配。
你的意思可能是:
template <bool B>
struct test
{
test() requires (B);
test() requires(!B);
};
template <bool B>
test<B>::test() requires (B)
{}
template <bool B>
test<B>::test() requires (!B)
{}
Run Code Online (Sandbox Code Playgroud)
这在所有 3 个编译器中都可以正常编译。
至于为什么你的原始版本编译 - 这是一个 GCC 错误96830。Clang 是对的,代码格式错误,因为外部定义与模板定义不匹配(还要注意,这template<> ...是完整的专业化语法)。
见[temp.class.general]/3(强调我的):
当在类模板定义之外定义类模板的成员时,成员定义被定义为模板定义,其模板头等 同于类模板的模板头。
如果它们的模板参数列表具有相同的长度,则两个模板头是等效的,相应的模板参数是等效的,并且都使用类型约束声明,如果模板参数声明为类型约束,并且如果要么模板头有一个requires-clause,它们都有requires-clauses,对应的constraint-expressions 是等价的。
另请参阅[temp.mem.func]/1以获取在外声明受约束成员的示例:
template<typename T> struct S {
void f() requires C<T>;
void g() requires C<T>;
};
template<typename T>
void S<T>::f() requires C<T> { } // OK
template<typename T>
void S<T>::g() { } // error: no matching function in S<T>
Run Code Online (Sandbox Code Playgroud)