The C++ specification (e.g. C++17 [class.static] §2) says:
The definition of a static data member is in the scope of its class.
With an example (taken from C++14 spec):
int g();
struct X {
static int g();
};
struct Y : X {
static int i;
};
int Y::i = g(); // equivalent to Y::g();
The exact wording and example in the specification have changed over the years, for some unknown reasons, C++11 and C++14 have a quite similar example as the above, C++17 and C++20 preferred an example initializing from a static data member. The C++20 wording is also much more concise. But it seems that there is no actual change in this rule.
It seems that this rule doesn't work well for inheritance of a templated class:
template<int VALUE>
struct base {
static int foo() { return VALUE; }
static constexpr int z = -1;
};
template<int VALUE>
struct foobar: base<VALUE> {
static int x1;
static int x2;
static int y1;
static int y2;
};
int foo() { return 42; }
int z = 999;
template<int VALUE>
int foobar<VALUE>::x1 = foobar::foo();
template<int VALUE>
int foobar<VALUE>::x2 = foo();
template<int VALUE>
int foobar<VALUE>::y1 = foobar::z;
template<int VALUE>
int foobar<VALUE>::y2 = z;
int main() {
std::cout << foobar<10>::x1 << ' ' << foobar<10>::x2 << ' '
<< foobar<10>::y1 << ' ' << foobar<10>::y2;
}
Output:
10 42 -1 999
Both GCC 10.2 and Clang 5.0.0 agree on the above (surprising?) output.
Is it the right output, or is it a bug in both compilers?
The expected output, expecting that calling foo()
, in the context of a static member initialization, would behave as calling foobar::foo()
, etc., should be:
10 10 -1 -1
Note: the behavior for inheritance as well as for a template class without inheritance and a template base with a non-template derived, all seems to work correctly.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…