6

In the following two template functions, one tries to be more constrained:

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

When called with an int, Clang and GCC differ:

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

Which one is right?

Code: https://godbolt.org/z/x71zjzoTa

Barry
  • 286,269
  • 29
  • 621
  • 977
Amir Kirsh
  • 12,564
  • 41
  • 74

1 Answers1

6

Based on a feedback from Patrick Palka from GCC, it seems to be that Clang is wrong, and GCC is right in rejecting the code on ambiguity, as the function parameters that positionally correspond between the two templates are not of the same type, thus neither template should be more specialized than the other.

[temp.func.order]#6.2.2:

[...] if the function parameters that positionally correspond between the two templates are not of the same type, neither template is more specialized than the other.

An issue was opened for Clang: https://github.com/llvm/llvm-project/issues/53640

Of course if the function parameters are of the same type, both compilers agree that there is a more constrained template and prefer it.


It is worth noting (as the OP probably knows) that the ambiguity can be resolved by constraining both functions:

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

Code: https://godbolt.org/z/6GGWeTsW9

Amir Kirsh
  • 12,564
  • 41
  • 74