The following snippet works fine in Clang 3.5 but not in GCC 4.9.2:
int main() { constexpr volatile int i = 5; }
with error:
error: both 'volatile' and 'constexpr' cannot be used here
If I inspect the assembly that Clang generates, it shows 5
as expected:
movl $5, -4(%rsp)
In GCC, constexpr int i = 5
is optimized away, but volatile int i = 5
also shows 5
in the assembly. volatile const int i = 5
compiles in both compilers. It's not a foreign concept for something to be both volatile and const at the same time.
Which compiler is correct by the standards?
A const int var can be dynamically set to a value at runtime and once it is set to that value, it can no longer be changed. A constexpr int var cannot be dynamically set at runtime, but rather, at compile time. And once it is set to that value, it can no longer be changed.
Understanding constexpr Specifier in C++ constexpr is a feature added in C++ 11. The main idea is a performance improvement of programs by doing computations at compile time rather than run time.
A static constexpr variable has to be set at compilation, because its lifetime is the the whole program. Without the static keyword, the compiler isn't bound to set the value at compilation, and could decide to set it later. So, what does constexpr mean?
Yes. I believe putting such const ness is always a good practice wherever you can. For example in your class if a given method is not modifying any member then you always tend to put a const keyword in the end.
Yes, this is valid, there was defect report 1688: Volatile constexpr variables that was filed for this, saying:
There does not appear to be language in the current wording stating that constexpr cannot be applied to a variable of volatile-qualified type. Also, the wording in 5.19 [expr.const] paragraph 2 referring to “a non-volatile object defined with constexpr” might lead one to infer that the combination is permitted but that such a variable cannot appear in a constant expression. What is the intent?
it was rejected as not a defect(NAD), the response and rationale was:
The combination is intentionally permitted and could be used in some circumstances to force constant initialization.
As the DR points out such a variable is itself not usable in a constant expression:
constexpr volatile int i = 5; constexpr int y = i ; // Not valid since i is volatile
Section [expr.const]/2 includes all the cases that makes a conditional-expression not a core constant expression including:
an lvalue-to-rvalue conversion (4.1) unless it is applied to
and all the exception require:
[...]that refers to a non-volatile [...] object [...]
Quoting N4140 [dcl.constexpr]/9:
A
constexpr
specifier used in an object declaration declares the object asconst
. Such an object shall have literal type and shall be initialized.
Literal type is defined in [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.
Scalar type is in paragraph 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
is arithmetic, so volatile int
is a scalar type and hence a literal type. constexpr volatile int i = 5;
is thus a well-formed declaration.
Interestingly, an expression that evaluates i
cannot be a core-constant-expression since it applies an lvalue-to-rvalue conversion to a glvalue of volatile type ([expr.const]/2). Consequently, expressions that evaluate i
are neither integral constant expressions nor constant expressions. I'm not sure that the constexpr
in that declaration has any effect beyond making i
implicitly const
, and (nod to @T.C.) requiring its initializer to be a constant expression.
I've reported this as GCC bug 65327, we'll see what the GCC folks have to say.
2015-03-16 Update: Bug has been fixed for GCC 5.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With