Цитирование N4140 [dcl.constexpr]/9:
A constexpr
specifier used in an object declaration declares the object as const
. Such an object shall have literal type and shall be initialized.
Буквенного типа определен в [basic.types]/10:
A type is a literal type if it is:
(10.1) — void
; or
(10.2) — a scalar type; or
(10.3) — a reference type; or
(10.4) — an array of literal type; or
(10.5) — a class type (Clause 9) that has all of the following properties:
(10.5.1) — it has a trivial destructor,
(10.5.2) — it is an aggregate type (8.5.1) or has at least one constexpr
constructor or constructor template that is not a copy or move constructor, and
(10.5.3) — all of its non-static data members and base classes are of non-volatile literal types.
Скалярного типа в пункте 9:
Arithmetic types (3.9.1), enumeration types, pointer types, pointer to member types (3.9.2), std::nullptr_t
, and cv-qualified versions of these types (3.9.3) are collectively called scalar types.
int
является арифметическим, поэтому volatile int
является скалярным типом и, следовательно, литералом. Таким образом, constexpr volatile int i = 5;
является хорошо сформированной декларацией.
Интересно отметить, что выражение, которое оценивает i
не может быть ядра-постоянная выражением, поскольку он применяет к именующему-Rvalue-преобразование в glvalue летучего типа ([expr.const]/2). Следовательно, выражения, которые оценивают i
, не являются интегральными постоянными выражениями или постоянные выражения. Я не уверен, что constexpr
в этой декларации имеет какой-либо эффект, за исключением того, что i
неявно const
и (отклик к @T.C.), требующий, чтобы его инициализатор являлся постоянным выражением.
Я сообщил об этом как GCC bug 65327, посмотрим, что скажут люди GCC.
2015-03-16 Обновление: исправлена ошибка для GCC 5.
Что это вы пытаетесь выразить? Они по существу противоположны. Константа никогда не изменится, как только она будет установлена, но изменчивость почти гарантированно изменится (возможно, из другого потока). – TheBuzzSaw
'constexpr' и' const' не то же самое –
@TheBuzzSaw: 'volatile' не означает, что что-то имеет тенденцию к изменению. это просто означает, что доступ к памяти может иметь побочные эффекты, поэтому компилятор должен рассматривать его как I/O. Очень удобно использовать 'volatile' в системе, даже если значение гарантированно останется неизменным. – Mehrdad