Перегрузка операторов преобразования C ++, перечисления, целые и символы - PullRequest
7 голосов
/ 15 сентября 2011

Когда я пытаюсь скомпилировать (с помощью gcc 4.3.4) этот фрагмент кода:

enum SimpleEnum {
    ONEVALUE
};

void myFunc(int a) {
}

void myFunc(char ch) {
}

struct MyClass {
    operator int() const { return 0; };
    operator SimpleEnum() const { return ONEVALUE; };
};

int main(int argc, char* argv[]) {
    myFunc(MyClass());
}

Я получаю эту ошибку:

test.cc: In function "int main(int, char**)":
test.cc:17: error: call of overloaded "myFunc(MyClass)" is ambiguous
test.cc:5: note: candidates are: void myFunc(int)
test.cc:8: note:                 void myFunc(char)

Мне кажется, я (почти) понимаю, чтопроблема в том, что (очень сильно упрощая), даже если я говорю о "char" и "enum", они все являются целыми числами, и тогда перегрузка неоднозначна.

Во всяком случае, вещь, которую я не оченьЯ понимаю, что если я уберу вторую перегрузку myFunc ИЛИ одного из операторов преобразования MyClass , у меня не будет ошибок компиляции.

Поскольку из-за этой проблемы я собираюсь изменить МНОГО старого кода (я портирую код из старой версии HP-UX aCC на g ++ 4.3.4 под Linux), я хотел бы лучше понять все это вЧтобы выбрать лучший способ изменить код.

Заранее благодарим за любую помощь.

Ответы [ 3 ]

4 голосов
/ 15 сентября 2011

Преобразование из MyClass неоднозначно, поскольку существует одно преобразование в int и одно в перечисление, которое само по себе неявно преобразуется в int, и оба являются одинаково хорошими преобразованиями.Вы можете просто сделать вызов явным, указав, какое преобразование вы хотите:

myfunc(int(MyClass()));

В качестве альтернативы, вы можете переосмыслить, почему у вас есть функция, которая имеет отдельные перегрузки для int и charвозможно, это тоже можно было бы переделать.

4 голосов
/ 15 сентября 2011

enum s являются типами в C ++ , в отличие от C.

Существуют неявные преобразования для enum -> char и enum -> int. Компилятор просто не знает, какой из них выбрать.

<Ч />

РЕДАКТИРОВАТЬ: После попытки с различными тестами:

  • При удалении определения для пользовательского преобразования MyClass -> int код компилируется.
  • Когда определение для void myFunc(int) удалено, компиляция не удалась.
  • Когда вы добавляете char() оператор преобразования для MyClass, компиляция завершается с той же ошибкой, как если бы это не было.

Итак, вывод, который я здесь придумаю, заключается в том, что в исходно опубликованном коде компилятор должен решить, какую из двух перегруженных версий myFunc следует вызвать. Поскольку оба преобразования возможны:

  1. MyClass до int через определяемый пользователем оператор преобразования.
  2. MyClass в int через пользовательское преобразование (MyClass в SimpleEnum) + неявное преобразование (SimpleEnum в char)

компилятор не знает, какой использовать.

1 голос
/ 15 сентября 2011

Я бы ожидал, что перегрузка int вызывается.Перепробовал несколько компиляторов и получил разные результаты.Если вы собираетесь что-либо удалить, удалите оператор преобразования пользователя в int, поскольку перечисления имеют стандартное преобразование в целые числа.

...