为什么类外成员模板定义需要重复其声明“requires-clause”

Not*_*mer 6 c++ templates language-lawyer c++-concepts

这与以下问题有关:是否必须在成员定义之外重复类模板的 requires 子句?

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

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
{
    //
}
Run Code Online (Sandbox Code Playgroud)

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

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

bjh*_*end 2

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

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

template <typename T>
    requires std::unsigned_integral<T>
struct A
{
    void foo();
};
Run Code Online (Sandbox Code Playgroud)

使用元素函数的不同实现foo

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

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