Consider the following piece of code:
#include <iostream>
struct Foo {
static int const i = i + 1;
};
int main() {
std::cout << Foo::i << std::endl;
}
Clang version 3.7 compiles this and outputs 1
.
Live Demo
While GCC version 5.3 emits an error:
error: 'i' was not declared in this scope
Live Demo
Which one of the two compilers conforms to the C++ standard?
GCC is of course wrong to complain about the name being undeclared, since the point of declaration of i
is immediately after its declarator.
However, GCC is arguably right in rejecting the snippet overall. [class.static.data]/3:
If a non-volatile
const
static data member is of integral or enumeration type, its declaration in the class definition can specify a brace-or-equal-initializer in which every initializer-clause that is an assignment- expression is a constant expression (5.20).
And for [expr.const]/(2.7) not to fail, one of its four sub bullets must apply:
an lvalue-to-rvalue conversion (4.1) unless it is applied to
- a non-volatile glvalue of integral or enumeration type that refers to a complete non-volatile
const
object with a preceding initialization, initialized with a constant expression, or- a non-volatile glvalue that refers to a subobject of a string literal (2.13.5), or
- a non-volatile glvalue that refers to a non-volatile object defined with
constexpr
, or that refers to a non-mutable sub-object of such an object, or- a non-volatile glvalue of literal type that refers to a non-volatile object whose lifetime began within the evaluation of
e
;
(2.7.1) is the only plausible candidate, but since i
has not previously been initialized using an initializer, it doesn't apply.
Note that Clang is completely consistent:
constexpr int i = i;
void f() {
// constexpr int j = j; // error
static constexpr int h = h;
}
It appears that it treats i
as "properly" initialized in its initializer if it has static storage duration. I filed bug #26858.
A static const member initialized in-class must be initialized by a constant expression. In the initializer of i
, i
is not initialized by a constant expression (yet) and so is not a constant expression itself. In my view both compilers are guilty.
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