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