Ответ 1
Одно из правил для основных константных выражений состоит в том, что мы не можем оценить:
id-выражение, которое ссылается на переменную или элемент данных ссылочного типа, если ссылка не имеет предыдущей инициализации и либо
- он инициализируется константным выражением или
- его время жизни начиналось с оценки e;
b
- это id-выражение, которое ссылается на переменную ссылочного типа с предшествующей инициализацией. Однако он инициализируется из a
. Является ли a
постоянным выражением? Из [expr.const]/6:
Постоянное выражение представляет собой либо выражение константы ядра glvalue, которое относится к объекту, который является допустимым результатом константного выражения (как определено ниже), или константным выражением основного значения prvalue, значение которого удовлетворяет следующим ограничениям: [... ]
Сущность является допустимым результатом постоянного выражения, если это объект со статической продолжительностью хранения, который либо не является временным объектом, либо является временным объектом, значение которого удовлетворяет указанным выше ограничениям, либо оно является функцией.
a
- выражение константы ядра glvalue (оно не затрагивает никаких ограничений в expr.const/2), однако это не объект со статической продолжительностью хранения. И это не функция.
Следовательно, a
не является постоянным выражением. И b
, как результат, не инициализируется из константного выражения и поэтому не может использоваться в основном постоянном выражении. И, таким образом, инициализация c
плохо сформирована, поскольку она не является постоянным выражением. Объявите a
как static constexpr int
, и gcc и clang принимают программу.
С++, вы волшебный зверь.