Предположим, у меня есть функция с подписью [[noreturn]] void die(int exit_code);
, Если я напишу заявление:
check_some_condition() or die(EXIT_FAILURE);
Я получаю сообщение об ошибке (с GCC 5.4.0):
error: expression must have bool type (or be convertible to bool)
но почему проверяется тип, если компилятор знает, что при входе в эту функцию возвращаемое значение не имеет значения; и если условие проверяется, тип возвращаемого значения не имеет значения?
Редактировать: Есть ли формулировка стандарта относительно [[noreturn]]
не решить этот вопрос, то есть ослабить требования к типам, чтобы «узаконить» такие выражения?
noreturn
не сообщает компилятору, что функция не возвращает значения. Он сообщает компилятору, что функция не вернется. Это также не влияет на тип возвращаемого значения функции.
В выражении компилятор должен проверить, что операнды выражений имеют допустимые типы. В выражении, как check_some_condition() or die(EXIT_FAILURE)
, что требует возвращаемого типа обоих check_some_condition()
а также die()
быть проверенным. noreturn
не влияет на тип возвращаемого значения функции, поэтому не влияет на необходимость этой проверки. Если функция возвращает void
выражение неверно.
Концепция, которую вы ищете, называется тип дна. В системе типов нижний тип — это тип, который можно преобразовать в любой другой тип. (Также сравните это с верхний тип, к которому все типы конвертируемы.)
Тип bottom — идеальный кандидат на функцию, которая не возвращает. Присвоить его чему-либо безопасно, именно потому, что это назначение никогда не произойдет. Если бы в C ++ был нижний тип, и если вы объявили свою функцию как возвращающую нижний тип, ваш фрагмент мог бы быть абсолютно законным, и ваши ожидания были бы правильными.
К сожалению, C ++ не имеет такого типа. Как уже отмечалось, [[noreturn]]
это не тип — это атрибут, который используется для выражения намерения (другим программистам и оптимизатору) способом, ортогональным системе типов. Что касается проверки типов, то возвращаемый тип функции по-прежнему void
и это не может быть преобразовано в логическое значение.
Каждое выражение должно иметь четко определенный тип, точку. Таким образом, даже если функция не возвращается, она все равно должна иметь возможность оценить тип выражения check_some_condition() or die(EXIT_FAILURE)
И из этого следует, что возвращаемый тип функции должен быть жизнеспособным для использования в логической операции.