Ответ 1
Инициализатор для переменной constexpr
должен быть константным выражением (С++ 11 §7.1.5/9):
A
constexpr
спецификатор, используемый в объявлении объекта, объявляет объект какconst
. Такой объект должен иметь буквальный тип и должен быть инициализирован. Если он инициализируется вызовом конструктора, [...]. В противном случае, или если спецификаторconstexpr
используется в декларации ссылки, каждое полное выражение, которое появляется в его инициализаторе, должно быть постоянным выражением.
Обратите внимание на следующие требования для постоянного выражения (§5.19/2):
Условное выражение является выражением основной константы, если оно не связано с одним из следующих как потенциально оцениваемое подвыражение, но подвыражения [...] условных операций, которые не оцениваются, не считаются
[...]
вызов функции
constexpr
с аргументами, которые при замене подстановкой вызова функции (7.1.5) не вызывают константное выражение;[...]
выражение throw (15.1).
Подстановка функции для функции constexpr
определяется следующим образом (§7.1.5/5):
Подстановка функции вызова для вызова функции
constexpr
[...] означает неявное преобразование каждого аргумента в соответствующий тип параметра, как если бы с помощью инициализации копирования, подставляя это преобразованное выражение для каждого использования соответствующего параметра в function-body и [...], неявно преобразуя полученное возвращаемое выражение или braced-init-list в возвращаемый тип функции, как если бы это произошло путем инициализации копии. Такая замена не меняет значения.
Как мы видели выше (§5.19/2), подвыражения условных операций, которые не оцениваются, не рассматриваются. f(42)
не является постоянным выражением, потому что, когда вы выполняете подстановку вызова функции на f
, это приводит к выражению с выражением throw
на стороне оцениваемой условной операции. С другой стороны, для f(41)
throw
заканчивается на стороне, которая не оценивается.
Таким образом, программа плохо сформирована. Не имеет значения, действительно ли инициализатор достигнут или нет, потому что программа не должна компилироваться.