Ответ 1
Это законно.
Для каждой функции constexpr
должны быть некоторые значения аргументов, которые приводят к постоянному выражению (§7.1.5/5):
Для функции
constexpr
, если значения аргументов функции не существуют что подстановка функции вызовет постоянство выражение (5.19), программа плохо сформирована; не требуется диагностика.
Обратите внимание, что это не означает, что каждое возможное значение аргумента должно приводить к постоянному выражению. divide
явно имеет некоторые значения аргументов, которые приводят к постоянному выражению: divide(1, 1)
- простой пример. Таким образом, определение очевидно.
Но можно ли вызывать divide(1, 0)
? Да, оно может. Практически нет никакой разницы между вызовом функции constexpr
или "нормальной" функцией (§7.1.5/7):
Вызов функции
constexpr
вызывает тот же результат, что и вызов эквивалентная функция неconstexpr
во всех отношениях, за исключением того, что a вызов функцииconstexpr
может появляться в постоянном выражении.
Обратите внимание, что вызовы функций constexpr
могут отображаться в постоянных выражениях, но ничто не запрещает им не приводить к постоянным выражениям. Это предназначено для вызова функций constexpr
с аргументами времени компиляции и времени выполнения (в противном случае полезность constexpr
будет несколько ограничена).
Для полноты, посмотрим, что делает постоянное выражение (§5.19/2):
Условное выражение является выражением постоянной константы, если оно включает одно из следующего в качестве потенциально оцениваемого подвыражения (§3.2), но подвыражения логического И (§5.14), логического ИЛИ (§5.15), и условные (§5.16) операции, которые не оцениваются, не являются считается [...].
Итак, divide(1, 1)
является константным выражением, но divide(1, 0)
не является. Если вы использовали divide(1, 0)
в параметре шаблона, программа была бы плохо сформирована. Но в остальном это прекрасно.