为什么 class 成员模板定义需要重复其声明 'requires-clause'

Why does an out-of-class member template definition need a repetition of its declaration 'requires-clause'

这与以下问题有关:

换句话说,给定以下模板化结构 A 的代码,需要为 foo() 函数定义重复 requires-clause (根据上面链接问题中引用的标准段落)

template <typename T>
    requires std::integral<T> //'requires-clause'
struct A
{
    void foo();
};

template <typename T>
    requires std::integral<T> //This 'requires-clause' is required by the standard to be reiterated
void A<T>::foo()
{
    //
}

//Specialisations do not require explicit 'requires-clause'
template <>
void A<int>::foo()
{
    //
}

//Specialisation with a type that does not meet the constraint raises a compile-time error
template <>
void A<double>::foo() //Not allowed because std::integral(double) == false
{
    //
}

但我不知道为什么有必要对 [temp.class] 中描述的特定 class 成员重复 requires-clause。我想不出这种要求会产生影响的情况。在上面的示例中,如果 requires-clause 与结构定义一起使用,则任何实例化任何非整数类型的尝试都不会编译,因此 A<T>::foo() 是否也要求 std::integral<T> == true 是无关紧要的。据我所知,它在专业化期间也没有区别,因为任何尝试从整数专业化为不同类型(如本例所示)都会导致编译错误。

但是,我确信在标准中包含此要求是有正当理由的 - 谁能证明在定义中缺少此 requires-clause 会导致问题的情况?

根据 https://en.cppreference.com/w/cpp/language/constraints 的最后一节,您不仅可以根据参数还可以根据它们的约束来专门化模板。与参数特化一样,该标准也定义了约束的偏序,这样一个模板特化可能比另一个更受约束。

因此,例如,您的模板专业化可能更受限制 A:

template <typename T>
    requires std::unsigned_integral<T>
struct A
{
    void foo();
};

元素函数的不同实现foo:

template <typename T>
    requires std::unsigned_integral<T>
void A<T>::foo()
{
    // different implementation of foo() relying on T being unsigned integral
}

因此,如果 A<T>::foo 的两个版本的定义中没有 repeated requires 子句,编译器将不知道定义的 foo 属于 A 的哪个特化。