非法定义引导构造函数(C++20)

7

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;
}

演示

Clang:

错误: 'test' 的定义与 'test<true>' 中的任何声明都不匹配

Msvc:

错误 C2244: 'test<true>::test':无法将函数定义与现有声明匹配


2
我很想说,既然你已经专门化了构造函数,那么你不需要约束。 - Guillaume Racicot
1个回答

6
你正在声明有限制的构造函数但定义了两个无限制的特化版本。它们将永远不会匹配。
你可能想要的是:
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)
{}

这段代码在所有三个编译器中都可以编译通过。

关于为什么您的原始代码可以编译 - 这是GCC的一个错误96830。Clang是正确的,代码不规范,因为外部定义与模板定义不匹配(请注意template<> ...是完全特化语法)。

详见[temp.class.general]/3(注意强调部分):

当类模板的成员在类模板定义之外定义时,该成员的定义被定义为具有与类模板 等效的 模板头的模板定义。

[temp.over.link]/6

如果两个模板头具有相同长度的模板参数列表,对应的模板参数等效并且都声明了等效的类型约束(如果任何模板参数声明了类型约束),则这两个模板头等效的如果任何一个模板头具有requires子句,则它们都具有requires子句,并且相应的约束表达式是等效的

还请参见[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>

如何进行完全特化?添加 requires(true) 也不起作用 演示 - Jarod42
@Jarod42 根据这里的内容,应该可以编译。也许两个编译器都还不支持这个功能? - rustyx
非常感谢您的回答。完全特化并没有起作用,而且在这个主题上找到文档也不容易。在gcc中,完全特化(无需要求)可能有效,因为最终(混淆的)符号匹配...... - reder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接