Ответ 1
В случае объявления функции спецификатор constexpr
является утверждением, сделанным компилятором, о том, что объявляемая функция может быть оценена в постоянном выражении, то есть в выражении, которое может быть оценено во время компиляции. Тем не менее инициализация объекта внутри декларации не должна иметь constexpr
внутри своего спецификатора объявления как константное выражение.
Короче: функция constexpr
может означать постоянное выражение, но инициализация константного выражения не нуждается в том, что связанное объявление имеет спецификатор constexpr
.
Вы можете проверить это в стандарте С++ [dcl.constexpr]:
Вызов функции constexpr приводит к тому же результату, что и вызов эквивалентной функции, отличной от constexpr, в во всех отношениях, кроме того, что
- вызов функции constexpr может появляться в константном выражении [...]
Это оценка выражения, которое определяет, является ли выражение константное выражение [expr.const]:
Выражение e является выражением основной константы, если оценка для e [...] не оценивает одно из следующих выражений [...]
Объявление не является выражением, поэтому инициализация объявляемого объекта является константным выражением независимо от наличия или отсутствия спецификатора constexpr
в объявлении.
Наконец, в [dcl.constexpr] указано, что функция constexpr
должна быть такой, чтобы существовали параметры, для которых его тело можно оценить как константное выражение:
Для функции constexpr или конструктора constexpr, которая не является ни дефолтом, ни шаблоном, если аргумент отсутствует существуют такие значения, что вызов функции или конструктора может быть оцененным подвыражением основное константное выражение (8.20), или, для конструктора, постоянный инициализатор для некоторого объекта (6.6.2), программа плохо сформирована, не требуется диагностика.
Когда вы объявляете constexpr int a
, компилятор ожидает, чтобы a
был инициализирован константным выражением, а выражение foo({1,2})
является постоянным выражением, поэтому ваш код хорошо сформирован.
PS: Тем не менее, спецификаторы объявлений (static, thread_local = > static) в объявлении локальной функции функции подразумевают, что функция не может быть объявлена constexpr
.