Consider the following code:
template<typename>
struct S
{
operator S<int&>();
};
template<typename T>
void f(S<T&>);
int main()
{
f(S<int&&>{}); // gcc ok
// clang error
}
gcc uses the conversion operator on the temporary argument, returning S<int&>
which is matched by S<T&>
, and accepts the call.
clang doesn't consider the conversion operator, fails to match T&
against int&&
, and rejects the call.
So what does the language say should happen here?
GCC is certainly wrong here: T&
and T&&
are different rows in [temp.deduct.type]/8 and are thus incompatible. Why it does so is not clear. It would make more sense to err in the other direction: if the parameter were declared as S<T&&>
and the argument were of type S<int&>
, there would at least be a T
(i.e., int&
) such that (due to reference collapsing) the parameter and argument types were the same. (There would also be the easy mistake to make to say that a universal reference was involved.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With