This is a follow-up question to how to avoid implicit cast from `double` to `int`?. Say I have the following code:
template <class T>
struct wrapper {
wrapper(const T&);
};
void f(wrapper<int>);
void f(wrapper<double>);
int main () {
f(1); // error: ambiguous call to overloaded function
}
See live example at Compiler Explorer; note that the behavior is the same for all major compilers
How come f(1)
is ambiguous? There are two conversion sequences:
1
-> const int&
via qualification conversion and reference binding -> wrapper<int>
via converting constructor1
-> const double&
via floating point conversion, temporary materialization, qualification conversion, and reference binding -> wrapper<double>
via converting constructorThe first conversion sequence looks better, so how come the first overload doesn't win?
The entire implicit conversion sequence consists of a user-defined conversion sequence:
A well-formed implicit conversion sequence is one of the following forms:
A user-defined conversion sequence consists of an initial standard conversion sequence followed by a user-defined conversion followed by a second standard conversion sequence.
The standard conversion sequence int -> const int&
is better than int -> const double&
, however, this is not considered. Both user-defined conversion sequences int -> wrapper<int>
and int -> wrapper<double>
are equally ranked by [over.ics.rank] p2, and the only distinction between user-defined conversion sequences in [over.ics.rank] p3.3 applies to the second standard conversion only.
Contrary to intuition:
wrapper<int> -> int
would be better than wrapper<int> -> double
if wrapper<T>
had an operator T
conversion function.int -> wrapper<int>
and int -> wrapper<double>
are equally ranked.