I have the following program:
#include <iostream>
namespace detail {
template <class T> char test(int T::*)
{
std::cout << "Came to one\n";
return 0;
}
template <class T> int test(...)
{
std::cout << "Came to two\n";
return 0;
}
}
struct A {};
int main()
{
detail::test<A>(0);
detail::test<int>(0);
}
When tested with g++ 4.8.2, it produces the following output:
Came to one Came to two
My question: why is the first version of detail::test
unambiguously chosen for the first call?
Update
In the absence of the first version of details::test
, the code from main
compiles fine. When it is there, the compiler thinks it's a better match for detail::test<A>()
than the second one.
Update 2
After reading about a pointer to member is well-formed even for incomplete types or without members of the designated type., I tried the following and it works.
struct A;
int main()
{
detail::test<A>(0);
detail::test<int>(0);
}
The C++11 standard has quite a few places to uncover concepts that I wouldn't have thought of.
The compiler goes through the Holy Trinity of Name Lookup, Argument Deduction and Overload Resolution. Name lookup finds two overloads for test
, and the argument deduction of a pointer to member will fail for a non-class type, but not for incomplete types or missing members. Finally, out of the viable candidates, overload resolution picks the best match (the ellipsis conversion being the lowest rank).
There are three relevant Standard quotes here:
According to the Example in 8.3.3 Pointers to members [dcl.mptr]/2 a pointer to member is well-formed even for incomplete types or without members of the designated type.
According to 14.8.2 Template argument deduction [temp.deduct]/8:
If a substitution results in an invalid type or expression, type deduction fails.
One of the many examples listed is:
Attempting to create “pointer to member of T” when T is not a class type.
Finally, according to 13.3.3.2 Ranking implicit conversion sequences [over.ics.rank] the ellipsis (...)
overload has the lowest rank of all implicit conversion sequences during overload resolution:
2 When comparing the basic forms of implicit conversion sequences (as defined in 13.3.3.1)
— a standard conversion sequence (13.3.3.1.1) is a better conversion sequence than a user-defined conversion sequence or an ellipsis conversion sequence, and
— a user-defined conversion sequence (13.3.3.1.2) is a better conversion sequence than an ellipsis conversion sequence (13.3.3.1.3).
Your first call detail::test<A>(0);
has two viable candidates, but it picks the first overload because it is a better match . The second call detail::test<int>(0);
gives a substition error on the first overload and therefore picks the second match.
In this instance, the first overload gets picked over the second because it is a better fit as far as the parameter conversion sequences are concerned - ellipsis conversion sequences rank last.
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