Why doesn't this compile? clang implicit conversions & overload resolution

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

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

I'm absolutely not an expert in overload resolution nor implicit
conversions, and may have said some incorrect things. Would appreciate
to get some explanation for this =).

Thanks,
Ryan

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

In the absence of C++11, you might settle for the Safe Bool Idiom:

class Base {
typedef void (Base::*SafeBool)();
void cannot_be_compared();

public:

operator SafeBool () const { return false ? &Base::cannot_be_compared : 0; }

};

– Matthieu