Ошибка компилятора для условного оператора "?:" При использовании с оператором приведения типов - PullRequest
9 голосов
/ 30 ноября 2011

Следующий код в простейшей форме:

struct X {
  operator char () const { return 'a'; }
};

int main ()
{
  X obj, *p = &obj;
  char a = *p;  // ok
  char c = (true)? *p : 'z';
}

Этот код выдает ошибку компилятора как

ошибка: операнды в?: Имеют разные типы ‘X’ и ‘char’

Почему *p не разрешается до char, если в class X нет оператора двусмысленности? Правильно ли такое ложное сообщение об ошибке или это ошибка g ++?

[ Обновление Примечание: интересно этот сценарий не генерирует такую ​​ошибку ]

Ответы [ 3 ]

8 голосов
/ 30 ноября 2011

Кажется, это ошибка компилятора. Я проверил это в спецификации, Стандарт ясно говорит (§5.16 / 3 - C ++ 03),

В противном случае, если второй и третий операнды имеют разные типы и имеют либо (возможно, cv-квалифицированный) тип класса, делается попытка преобразовать каждый из этих операндов в тип другого .

, а остальная часть раздела объясняет, как выполняется преобразование. Ничто не останавливает *p от неявного преобразования в тип char, используя пользовательский оператор преобразования.

Кроме того, я скомпилировал его с (GCC) 4.5.0. Это не дает ошибки, с опцией -pedantic. Пробовал это -std=c++98 и -std=c++0x. Все еще нет ошибки.

Определенно, это ошибка компилятора.

2 голосов
/ 29 декабря 2011

Есть проблемы с неявным преобразованием между классами для условного оператора?: В определенных версиях G ++.Также, в зависимости от версии, вы можете либо увидеть ошибку, либо вы можете / не можете / увидеть такую ​​ошибку , однако все три ваших семпла правильно помечены G ++ .

Это меньшеответа на исходный вопрос, но повторной сертификации исходного постера и других, что может быть связано с ложными ошибками в компиляторе G ++ и поведением преобразования для типов классов, как указано в ISOC ++: 2003 5.16 / 3 [expr.cond] / 3 (также обрисовано в общих чертах выше @Nawaz)

Один пример, демонстрирующий обратное отображение исходного образца плаката, где может происходить неявное преобразование в обоих направлениях, но не помеченное здесь .

Я скомпилировал это на G ++ v3.4.6, v4.1.2, v4.2.1 и v4.5.0 (windows) и не увидел никаких проблем, потому что, как снова @Nawaz сказал, что это правильное поведение вISOC ++: 2003 spec.

Однако, когда я перешел по ссылке на вашей странице IDEONE , определение структуры было другим и , что является корнем вашей ошибки.

struct X
{
  char ch;
  X(const char c) : ch(c) {}

  operator char () const { return ch; }
};

int main ()
{
  X obj('a'), *p = &obj;
  char a = *p; // ok
  char c = (true)? *p : 'b';
}

Тогда, как указано выше, структура отличается, и я получаю ошибку, которую вы видите. Это правильная ошибка, поскольку 'z' может быть преобразовано в X или char, а из-за конструктора 'z' также может быть преобразовано в X - двунаправленность X / 'z', поэтому компилятор должен остановиться. Однако, с небольшим изменением, его можно пропустить, и это точно та же ошибка, что и ошибка GNU G ++, опубликованная выше.

Если вы преобразуете свой пример выше в образец указателя, он потерпит неудачу.Указатель на символ, указатель на int или что-то еще.

Хотя это и не было связано, я подумал, что было бы неплохо выделить что-то, что меня часто замечало при кросс-портировании между Windows / Linux.MSVC с радостью пройдет такие преобразования часто, если посчитает, что преобразование является «безопасным», или часто может предлагать предупреждение о том, что преобразование выполняется с риском потери точности - я не уверен, что является триггером для его разрешения.

0 голосов
/ 30 ноября 2011

Ошибка правильная.операнды ?: имеют разные типы: 'X' первый и 'char' второй.Компилятор не может знать, что вы хотите, чтобы в конце выражения было символом - что произойдет позже, после оценки всего выражения (true)? *p : 'z'; - оценки, которую нельзя выполнить в первую очередь из-за несоответствия типов.*

...