[cfe-dev] Why doesn't this compile? clang implicit conversions & overload resolution

Eli Friedman eli.friedman at gmail.com
Tue Jan 17 19:16:10 PST 2012


On Tue, Jan 17, 2012 at 6:52 PM, Ryan Ericson <ryan.ericson at gmail.com> wrote:
> Code:
>
> struct Base
> {
>    operator bool() const { return false; }
> };
>
> struct foo
> {
>    foo(const char* c) {}
> };
>
> struct Something : public Base
> {
>    void operator[](const foo& f) {}
> };
>
> int main()
> {
>    Something d;
>    d["32"]
>    return 0;
> }
>
> clang complains:
> test4.cpp:22:6: error: use of overloaded operator '[]' is ambiguous
> (with operand types 'Something' and 'const char [3]')
>    d["32"]
>    ~^~~~~
> test4.cpp:16:10: note: candidate function
>    void operator[](const foo& f) {}
>         ^
> test4.cpp:22:6: note: built-in candidate operator[](long, const char *)
>    d["32"]
>     ^
> test4.cpp:22:6: note: built-in candidate operator[](long, const restrict char *)
> test4.cpp:22:6: note: built-in candidate operator[](long, const volatile char *)
> test4.cpp:22:6: note: built-in candidate operator[](long, const
> volatile restrict char *)
>
> It looks like it is considering between:
> 1. d["32"] -> which will call Something::operator[] after 1 user
> defined conversion through constructor
> 2. "32"[d] -> which will call built in operator[] of const char* after
> 1 user defined conversion through operator double AND 1 standard
> conversion (promotion?) from bool to long

You aren't really stating it clearly, but yes, those are the relevant
conversions.

> My question is, why doesn't the compiler pick 1 when it seems to be a
> better conversion sequence (cheaper according to the standard?).

The part you're missing is that in (1) there's a user-defined
conversion applied to the second argument, and in (2) there's a
user-defined conversion applied to the first argument.  Per
[over.match.best]p1, they're ambiguous because one operator has a
better conversion for the first argument, and one has a better
conversion for the second argument.

BTW, C++11 provides an easy way to avoid this whole mess: you can mark
the operator bool explicit.

-Eli




More information about the cfe-dev mailing list