Ответ 1
a
не является постоянным выражением (см. стандартную цитату ниже), и поэтому:
a || 1
Не является также и постоянным выражением, хотя мы знаем, что выражение должно оцениваться как истинное. Этот стандарт требует оценки слева направо, и я не вижу никаких исключений, которые позволяли компилятору пропустить преобразование lvalue-to-rval a
.
а
const int a = 1;
Может использоваться в постоянном выражении, потому что он попадает в исключение из 5.20p2
(выделение мое):
преобразование lvalue-to-rvalue (4.1), если оно не применяется к
- нелетучий glvalue интегрального или перечисляемого типа, который ссылается на полную нелетучую константу объект с предшествующей инициализацией, инициализированный константным выражением или
- нестабильное значение glvalue, которое ссылается на подобъект строкового литерала (2.13.5) или
- нестабильное значение glvalue, которое относится к энергонезависимому объекту, определенному с помощью constexpr, или к которому относится к не изменяемому под-объекту такого объекта или
- нелетучий glvalue буквального типа, который относится к энергонезависимому объекту, срок службы которого начался в рамках оценки e
Это правило также объясняет, почему исходный регистр не является постоянным выражением, так как не применяется ни одно исключение.
Возможно, gcc
позволяет это:
int b[a || 1]{};
как массив переменной длины как расширение, хотя он должен предоставить предупреждение с помощью -pedantic
. Хотя это не объясняло бы случай static_assert, они могли бы постоянно складывать его, но я не думаю, что правило as-if позволит ему считаться постоянным выражением.
С >
Обновление, возможное расширение gcc
Из этого отчета об ошибке RHS логических операторов может отображать LHS в неизменном выражении, это выглядит как возможное расширение gcc:
Это компилируется без инцидентов, несмотря на использование непостоянного объекта в константное выражение:
int i; static_assert( i || true, "" ); static_assert( ! ( i && false ), "" );
Предполагается, что || и && являются коммутативными, но короткое замыкание работает только в одном направлении.
и в заключительном комментарии говорится:
Я думаю, что это целенаправленное языковое расширение, которое может использовать переключатель для отключения. Было бы неплохо, если static_assert всегда были строгими.
Это похоже на несоответствующее расширение, которое должно вызывать предупреждение при использовании флага -pedantic
, схожащего в тщетном вопросе в Является ли это совместимым расширением компилятора для обработки non-constexpr стандартные библиотечные функции как constexpr?.
С++ 11/С++ 14 Цитата
Раздел 5.20
- это раздел 5.19
в С++ 14 и С++ 11, соответствующая цитата из проекта стандарта С++ 14:
преобразование lvalue-to-rvalue (4.1), если оно не применяется к
нелетучий glvalue интегрального или перечисляемого типа, который ссылается на нелетучий const-объект с предыдущая инициализация, инициализированная константным выражением [Примечание: строковый литерал (2.14.5) соответствует массиву таких объектов. -end note] или
нестабильное значение glvalue, которое относится к энергонезависимому объекту, определенному с помощью constexpr, или к которому относится к не изменяемому под-объекту такого объекта, или
нелетучий glvalue литерального типа, который относится к энергонезависимому объекту, срок службы которого начался в рамках оценки e;
а для проекта стандарта С++ 11:
преобразование lvalue-to-rvalue (4.1), если оно не применяется к
glvalue интегрального или перечисляемого типа, который ссылается на нелетучий объект const с предшествующим инициализация, инициализированная постоянным выражением, или
glvalue типа literal, который ссылается на нелетучий объект, определенный с помощью constexpr, или который ссылается к под-объекту такого объекта, или
glvalue типа literal, который ссылается на энергонезависимый временный объект, чье время жизни не завершено, инициализировано постоянным выражением;