Да, диагностика правильная. constexpr
переменные должны быть инициализированы с помощью константного выражения, а a
не является константным выражением (это изменяемая переменная).
Цель constinit
( P1143 ) - этозаставить объявление переменной быть некорректным, если initialization не является константой. Он ничего не меняет в самой переменной, как, например, ее тип или что-то еще (в том смысле, что constexpr
неявно const
). Глупый пример:
struct T {
int i;
constexpr T(int i) : i(i) { }
T(char c) : i(c) { }
};
constinit T c(42); // ok
constinit T d('X'); // ill-formed
Это все, для чего constinit
, и единственное реальное правило - [dcl.constinit] / 2 :
Если переменная, объявленная с помощью спецификатора constinit
, имеет динамическую инициализацию ([basic.start.dynamic]), программа некорректна. [ Примечание : спецификатор constinit
обеспечивает инициализацию переменной во время статической инициализации ([basic.start.static]). - конечная нота ]
Константа в constinit
относится только к инициализации, а не к переменной и не к каким-либо типам. Обратите внимание, что он также не меняет тип выполняемой инициализации, он просто диагностирует, если выполняется неправильный тип.
In:
constinit int a = 0;
constexpr int b = a;
0
является константным выражением, поэтому инициализация a
является корректной. Как только мы преодолеем это, спецификатор ничего не сделает. Это эквивалентно:
int a = 0; // same behavior, a undergoes constant initialization
constexpr int b = a;
Это просто плохо сформировано.
но при постоянной инициализации его значение известно, поэтому его можно использовать для инициализации b
.
Конечно, в данный момент. Как насчет:
constinit int a = 0;
cin >> a;
constexpr int b = a;
Это явно не полетит. Разрешение этого потребовало бы расширения того, что является константным выражением (на мой взгляд, это уже самое сложное правило в стандарте), чтобы разрешить непостоянные переменные, но только сразу после инициализации? Сложность не стоит того, так как вы всегда можете написать:
constexpr int initializer = 0;
constinit int a = initializer;
constexpr int b = initializer;