Неявные преобразования типов — ошибка компилятора


person Naveen    schedule 20.08.2010    source источник
comment
Я думаю, что Комо прав в этом случае. Даже g++ и Clang++ дают ту же ошибку. Ошибка, которую я получаю в случае g++: error: operands to ?: have different types 'TypesafeBool' and 'bool   -  person Prasoon Saurav    schedule 20.08.2010
comment
Один из хороших примеров, когда конструктор должен быть явным   -  person mukeshkumar    schedule 20.08.2010


Ответы (3)


Ошибка заключается в том, что тернарный оператор должен иметь один тип, а ваше выражение (1=1) ? f() : false имеет два типа — f() имеет тип TypesafeBool, а false имеет тип bool. Вы можете конвертировать между ними, но Комо не знает, что вы хотите использовать. Чтобы решить эту проблему, приведите одну из сторон тройки к типу другой: (1=1) ? f() : TypesafeBool(false).

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

person Andrew Aylett    schedule 20.08.2010
comment
Отличный ответ. Таким образом, проблема заключается в том, что вы можете конвертировать в обоих направлениях. Это настоящий позор, так как я хотел заменить bool, который сделал бы эту дополнительную проверку для меня. Однако я не могу засорять код приведениями повсюду. - person jkp; 20.08.2010
comment
Раздел 5.16/3 рассказывает о правилах довольно сонно :) - person Chubsdad; 20.08.2010
comment
@jkp: В некоторых случаях вы можете ограничить одно из преобразований - в этом случае это должно быть неявное преобразование bool->TypesafeBool, чтобы избежать двусмысленности. - person David Rodríguez - dribeas; 20.08.2010

Оба случая для оператора? результат должен иметь тот же тип. Естественный тип для них — TypesafeBool и bool. Поскольку существует неявное преобразование из bool в TypesafeBool и из bool в TypesafeBool, следует применить двусмысленность.

Правила C++ предотвращают тот факт, что результат затем используется в контексте, где ожидается TypesafeBool, или тот факт, что результат, как известно, принимается во внимание, чтобы предпочесть второй способ

TypesafeBool b = (1 == 1)? f() : TypesafeBool(false);

должно сработать.

person AProgrammer    schedule 20.08.2010

В продолжение комментария @hype в этой статье также выдвигается та же идея, но с конструктор с пометкой explicit. Это устраняет вашу двусмысленность.

Обратите внимание, что ваш пример будет работать нормально, если вы измените инициализацию b на

TypesafeBool b( (1==1) ? f() : false );

поскольку синтаксис = не позволяет вызывать TypesafeBool( bool ), когда он помечен как явный (потому что технически это композиция из двух конструкторов).

person Troubadour    schedule 20.08.2010