Use of overloaded operator '[]' is ambiguous with template cast operator
The issue is that there is one conversion on each path:
- first from
"abc"
tostd::string
and thenoperator[]
call. - second from
x
tostd::ptrdiff_t
and then theoperator[]
for anstd::ptrdiff_t
and aconst char*
.
So the solution is to make the conversion operator explicit
:
int operator[](const std::string& str) { return x + str[0]; }
template <typename T>
explicit operator T() { return x; } // (1) fails only in clang
GCC is wrong. The template case shouldn't make any difference.
[over.match.best]/1 says:
Define ICSi(F) as follows:
...
let ICSi(F) denote the implicit conversion sequence that converts the i-th argument in the list to the type of the i-th parameter of viable function F. [over.best.ics] defines the implicit conversion sequences and [over.ics.rank] defines what it means for one implicit conversion sequence to be a better conversion sequence or worse conversion sequence than another.
Given these definitions, a viable function F1 is defined to be a better function than another viable function F2 if for all arguments i, ICSi(F1) is not a worse conversion sequence than ICSi(F2), and ...
The two viable candidates are
int operator[](X&, std::string); // F1
const char& operator[](std::ptrdiff_t, const char*); // F2
... and ICS1(F1) (X -> X&
) is better than ICS1(F2) (X -> std::ptrdiff_t
), no matter whether or not X -> std::ptrdiff_t
is through a template conversion function, but ICS2(F1) (const char[4] -> std::string
) is worse than ICS2(F2) (const char[4] -> const char*
). So neither function is better than the other, resulting in ambiguity.
This has been reported as a GCC bug.