<br><br><div class="gmail_quote">Le 18 janvier 2012 04:16, Eli Friedman <span dir="ltr"><<a href="mailto:eli.friedman@gmail.com">eli.friedman@gmail.com</a>></span> a écrit :<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="HOEnZb"><div class="h5">On Tue, Jan 17, 2012 at 6:52 PM, Ryan Ericson <<a href="mailto:ryan.ericson@gmail.com">ryan.ericson@gmail.com</a>> wrote:<br>
> Code:<br>
><br>
> struct Base<br>
> {<br>
>    operator bool() const { return false; }<br>
> };<br>
><br>
> struct foo<br>
> {<br>
>    foo(const char* c) {}<br>
> };<br>
><br>
> struct Something : public Base<br>
> {<br>
>    void operator[](const foo& f) {}<br>
> };<br>
><br>
> int main()<br>
> {<br>
>    Something d;<br>
>    d["32"]<br>
>    return 0;<br>
> }<br>
><br>
> clang complains:<br>
> test4.cpp:22:6: error: use of overloaded operator '[]' is ambiguous<br>
> (with operand types 'Something' and 'const char [3]')<br>
>    d["32"]<br>
>    ~^~~~~<br>
> test4.cpp:16:10: note: candidate function<br>
>    void operator[](const foo& f) {}<br>
>         ^<br>
> test4.cpp:22:6: note: built-in candidate operator[](long, const char *)<br>
>    d["32"]<br>
>     ^<br>
> test4.cpp:22:6: note: built-in candidate operator[](long, const restrict char *)<br>
> test4.cpp:22:6: note: built-in candidate operator[](long, const volatile char *)<br>
> test4.cpp:22:6: note: built-in candidate operator[](long, const<br>
> volatile restrict char *)<br>
><br>
> It looks like it is considering between:<br>
> 1. d["32"] -> which will call Something::operator[] after 1 user<br>
> defined conversion through constructor<br>
> 2. "32"[d] -> which will call built in operator[] of const char* after<br>
> 1 user defined conversion through operator double AND 1 standard<br>
> conversion (promotion?) from bool to long<br>
<br>
</div></div>You aren't really stating it clearly, but yes, those are the relevant<br>
conversions.<br>
<div class="im"><br>
> My question is, why doesn't the compiler pick 1 when it seems to be a<br>
> better conversion sequence (cheaper according to the standard?).<br>
<br>
</div>The part you're missing is that in (1) there's a user-defined<br>
conversion applied to the second argument, and in (2) there's a<br>
user-defined conversion applied to the first argument.  Per<br>
[over.match.best]p1, they're ambiguous because one operator has a<br>
better conversion for the first argument, and one has a better<br>
conversion for the second argument.<br>
<br>
BTW, C++11 provides an easy way to avoid this whole mess: you can mark<br>
the operator bool explicit.<br>
<span class="HOEnZb"><font color="#888888"><br>
-Eli<br>
</font></span><div class="HOEnZb"><div class="h5"><br></div></div></blockquote><div><br>In the absence of C++11, you might settle for the Safe Bool Idiom:<br><br>class Base {<br>  typedef void (Base::*SafeBool)();<br>  void cannot_be_compared();<br>
<br>public:<br><br>  operator SafeBool () const { return false ? &Base::cannot_be_compared : 0; }<br><br>};<br><br>-- Matthieu <br></div></div>