Рассмотрим следующий класс:
class Foo
{
public:
void operator [] (const std::string& s) { }
void operator [] (std::size_t idx) { }
};
Здесь, учитывая экземпляр Foo f
, выражение f[0]
не является двусмысленным, потому что компилятор выбирает вторую перегрузку. Аналогично, выражение f["abc"]
не является двусмысленным, потому что компилятор выбирает первую перегрузку (так как a const char*
преобразуется в std::string
).
Итак, почему же тогда, что если у нас есть два базовых класса, каждый с другой перегрузкой, то возникает внезапная двусмысленность?
Предположим, что:
class Base1
{
public:
void operator [] (const std::string& s) { }
};
class Base2
{
public:
void operator [] (std::size_t idx) { }
};
class Derived : public Base1, public Base2
{ };
Теперь, если мы скажем:
Derived d;
d[0];
Компилятор жалуется:
error: request for member ‘operator[]’ is ambiguous
d[0];
^
note: candidates are: void Base2::operator[](std::size_t)
void operator [] (std::size_t idx) { }
^
note: void Base1::operator[](const string&)
void operator [] (const std::string& s) { }
Почему факт, что обе перегрузки операторов теперь находятся в базовых классах, вызывает какую-либо двусмысленность? И есть ли способ решить это?
EDIT: может ли это быть ошибкой компилятора (я использую GCC 4.8.1)