Этот пример, похоже, компилируется с VC10 и gcc (хотя моя версия gcc очень старая).
EDIT: Р. Мартиньо Фернандес попробовал это на gcc 4.7, и поведение по-прежнему остается прежним.
struct Base
{
operator double() const { return 0.0; }
};
struct foo
{
foo(const char* c) {}
};
struct Something : public Base
{
void operator[](const foo& f) {}
};
int main()
{
Something d;
d["32"];
return 0;
}
Но clang жалуется:
test4.cpp:19:6: error: use of overloaded operator '[]' is ambiguous (with operand types 'Something' and 'const char [3]')
d["32"]
~^~~~~
test4.cpp:13:10: note: candidate function
void operator[](const foo& f) {}
^
test4.cpp:19:6: note: built-in candidate operator[](long, const char *)
d["32"]
^
test4.cpp:19:6: note: built-in candidate operator[](long, const restrict char *)
test4.cpp:19:6: note: built-in candidate operator[](long, const volatile char *)
test4.cpp:19:6: note: built-in candidate operator[](long, const volatile restrict char *)
Разрешение перегрузки рассматривает две возможные функции при просмотре этого выражения:
- вызов Something:: operator [] (после пользовательского преобразования)
- вызов встроенного оператора для const char * (подумайте "32" [d]) (после того, как пользовательское преобразование и стандартное преобразование удвоятся дольше).
Если бы я написал d["32"]
как d.operator[]("32")
, тогда разрешение перегрузки не будет даже смотреть на вариант 2, а clang также будет компилироваться отлично.
EDIT: (разъяснение вопросов)
Это, по-видимому, сложная область в разрешении перегрузки, и из-за этого я бы очень признателен за ответы, которые подробно объясняют разрешение перегрузки в этом случае и цитируют стандарт (если есть некоторые неясные/неизвестное правило).
Если clang является правильным, я также заинтересован в том, чтобы знать, почему эти два являются двусмысленными/один не является предпочтительным по сравнению с другим. Ответ, вероятно, должен был бы объяснить, как разрешение перегрузки рассматривает неявные преобразования (как пользовательские, так и стандартные преобразования) для двух кандидатов и почему один не лучше другого.
Примечание: если оператор double() заменен на оператор bool(), все три (clang, vc, gcc) откажутся компилировать с аналогичной неоднозначной ошибкой.