引导构造函数的越界定义 (c++20)

问题描述 投票:0回答:1

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

演示

叮当:

错误:“

test
”的外线定义与“
test<true>
”中的任何声明不匹配

Msvc:

错误 C2244:“

test<true>::test
”:无法将函数定义与现有声明匹配

c++ constructor c++20 requires-clause
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)
{}

这在所有 3 个编译器中都可以正常编译。

至于为什么你的原始版本可以编译 - 这是一个 GCC bug 96830。 Clang 是对的,代码格式错误,因为外线定义与模板定义不匹配(另请注意,

template<> ...
完全专业化 语法)。

参见 [temp.class.general]/3(强调我的):

当类模板的成员在类模板定义之外定义时,该成员定义将被定义为模板定义,其 template-head equivalent 与类模板相同。

[链接温度]/6:

两个 template-heads 等价,如果它们的 template-parameter-lists 具有相同的长度,相应的 template-parameters 是等价的,并且都使用 type-constraints 声明,如果其中一个是等价的template-parameter 是用 type-constraint 声明的,并且 如果 template-head 有一个requires-clause,那么它们都有requires-clauses,并且相应的约束表达式是等价的

另请参阅 [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>
© www.soinside.com 2019 - 2024. All rights reserved.