c++ - Why is this circular template instantiation legal? -
i don't understand compiler's doing here:
#include <iostream> using namespace std; // non-default-constructable struct struct x { x(int v) : x(v) {} const int x; }; template< typename t> struct { static const x a; }; // trigger compiler error if try instantiate default template template< typename t > const x a<t>::a; template<> struct a<int> { static const x a; }; template<> struct a<float> { static const x a; }; // not infinitely circular? const x a<int>::a = x(a<float>::a.x + 1); const x a<float>::a = x(a<int>::a.x + 1); int main() { // error expected, a<bool>::a cannot default-constructed // cout << a<bool>::a.x << endl; // compiles , prints "1 2" cout << a<int>::a.x << " " << a<float>::a.x << endl; return 0; }
i have expected 2 specialized definitions of a
generate compiler error, since both initialized using value of other, , there isn't default constructor fall on. apparently, compiles in ideone , prints 1 2
. how did compiler arrive conclusion 2 instances of x
should initialized these values?
that happens side effect of initialization of non-local variables. standard says:
3.6.2 initialization of non-local variables [basic.start.init]
...
... variables static storage duration (3.7.1) or thread storage duration (3.7.2) shall zero-initialized (8.5) before other initialization takes place...
... static initialization shall performed before dynamic initialization takes place. dynamic initialization of non-local variable static storage duration unordered if variable implicitly or explicitly instantiated specialization, , otherwise ordered [ note: explicitly specialized static data member or variable template specialization has ordered initialization. —end note ] variables ordered initialization defined within single translation unit shall initialized in order of definitions in translation unit.
that's happens here:
a<int>::a
,a<float>::a
both 0 initialized- they initialized in order of definitions
- first
a<int>::a
reads lies ina<float>::a
0 because of previous 0 initialization, adds 1 , initialized 1 - then
a<float>::a
gets value of initializeda<int>::a
1, adds 1 , initialized 2
- first
that means formed program.
but same paragraph says later:
if initialization of object obj1 refers object obj2 of namespace scope potentially requiring dynamic initialization , defined later in same translation unit, unspecified whether value of obj2 used value of initialized obj2 (because obj2 statically initialized) or value of obj2 merely zero-initialized
so unsure whether output required 1 2, or whether 2, 1 if dynamic initialization of a<int>::a
first triggers dynamic initialization of a<float>::a
Comments
Post a Comment