6

在以下两个模板函数中,一个尝试受到更多约束:

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

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

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

哪一个是对的?

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

4

1 回答 1

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

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

于 2022-02-07T21:22:51.170 回答