具有不同参数类型的受约束函数模板与无约束函数模板

Ami*_*rsh 6 c++ templates c++20 function-templates-overloading

在下面的两个模板函数中,我们尝试了更多的约束:

template<typename T>
concept SmallVar = (sizeof(T) <= sizeof(int));

void print(SmallVar auto t) { // 1
    std::cout << t << std::endl;
}

void print(const auto& t) {   // 2 
    std::cout << t << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

当使用 int 调用时,Clang 和 GCC 有所不同:

int main() {
    print(6);  // clang accepts and prefers 1, gcc sees here ambiguity
}
Run Code Online (Sandbox Code Playgroud)

哪一个是正确的?

代码: https: //godbolt.org/z/x71zjzoTa

Ami*_*rsh 6

根据GCC 的 Patrick Palka 的反馈,Clang 似乎是错误的,而 GCC 在拒绝歧义代码方面是正确的,因为两个模板之间位置对应的函数参数不是同一类型,因此两者都不是模板应该比其他模板更专业。

[temp.func.order]#6.2.2 :

[...] 如果两个模板之间位置对应的函数参数不是同一类型,则两个模板都不比另一个更专业。

为 Clang 提出了一个问题:https ://github.com/llvm/llvm-project/issues/53640

当然,如果函数参数的类型相同,则两个编译器都同意存在更受约束的模板并且更喜欢它


值得注意的是(OP 可能知道)可以通过约束两个函数来解决歧义:

template<SmallVar T>
void print(T t) {
    std::cout << t << std::endl;
}

template<typename T> requires (!SmallVar<T>)
void print(const T& t) {
    std::cout << t << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

代码: https: //godbolt.org/z/6GGWeTsW9