For the following code:
class A {};
template <typename T> void f(T& a) {}
template <typename T> void f(T&& a) {}
int main() {
A a;
f(a);
}
clang++ binds the call to the first overload, while g++ reports ambiguous call. Which one is taking the correct action?
Both gcc 4.9.0 20140302 and clang 3.5 (trunk 202594) correctly pick the first version. As hvd kindly gave me the references in comments:
It was a subtle issue, there was a defect report,
The gcc implementation prior 4.9 implemented the earlier defect, see Template overload resolution ambiguous for T&&
versus T&
The corresponding part in the standard is 14.8.2.4 [temp.deduct.partial], paragraph 9:
If, for a given type, deduction succeeds in both directions (i.e., the types are identical after the transformations above) and both
P
andA
were reference types (before being replaced with the type referred to above):
— if the type from the argument template was an lvalue reference and the type from the parameter template was not, the argument type is considered to be more specialized than the other; otherwise,
— if the type from the argument template is more cv-qualified than the type from the parameter template (as described above), the argument type is considered to be more specialized than the other; otherwise,
— neither type is more specialized than the other.
By the way, watch The Universal Reference/Overloading Collision Conundrum video why overloading on universal references is a bad idea. In short, consider the following example:
#include <iostream>
#include <utility>
struct A { bool guts_stolen; };
void steal_guts(A&& a) {
a.guts_stolen = true;
}
template <typename T> void f(const T& a) {
// ^^^^^ note the const!
std::cout << "T&\n";
}
template <typename T> void f(T&& a) {
std::cout << "T&&\n";
steal_guts(std::move(a));
}
int main() {
A a{ false };
f(a);
std::cout << "Guts stolen? " << std::boolalpha << a.guts_stolen << std::endl;
}
If you run the program, it will print
T&&
Guts stolen? true
which is not at all what you would expect just by looking at A a{ false }; f(a);
.
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