What is the initialization order for static data elements of the template class in the file?

In this file, if I have,

struct A { static int a; }; struct B { static int b; }; int A::a; int B::b; 

Then I can always expect A::a be initialized to B::b . Now for the same file, take the template case,

 template<typename T> struct X { static T t; }; template<typename T> T X<T>::t; 

Suppose that X is created using A and B , and its static member is used arbitrarily somewhere in the code as X<A>::t and X<B>::t , then what should be the initialization order template static member X<T>::t; ? Is it defined correctly?

+7
source share
4 answers

While templates have only one definition (for example, you have only one translation unit), it is clearly defined. Static members are initialized in the order in which custom patterns are created in contexts that require the definition of a static data item. From paragraph 14.7.1 / 1 [temp.inst] of the C ++ 03 standard (my emphasis):

If the template template specification has not been explicitly created (14.7.2) or explicitly specialized (14.7.3), the class template specialization is implicitly created when the specialization is referenced in a context that requires a fully defined type of object or when the completeness of the class type affects the semantics of the program. Implicit instantiation of a template specialization causes implicit creation of declarations, but not default definitions or arguments, class member functions, member classes, static data elements, and member templates; and this causes the implicit creation of definitions of membership anonymous unions. If a class template member or member template has not been explicitly created or has not been explicitly specialized, a member specialization is implicitly created when the specialization is referenced in a context that requires a member definition; in particular, initialization (and any side effects associated with it) of a static data member does not occur if the static data member itself is not used in such a way that a definition of the static data member is required.

ยง14.7.1 / 7 also states:

Implicit creation of a class template does not result in an implicit instance of any static data members of this class.

However, things get complicated when you have several translation units that define a template. In ยง3.2 / 5 [basic.def.odr] it is stated:

There can be more than one definition of a class type (section 9), an enumeration type (7.2), an inline function with external communication (7.1.2), a class template (section 14), a non-static function template (14.5.5), a static data member of a class template (14.5.1.3), a member function of a class template (14.5.1.1) or a specialized specialization of a template for which some template parameters are not specified (14.7, 14.5.4) in the program, provided that each definition appears in a different translation unit and when provided that the definitions satisfy the following requirements. Given such an object named D, defined in more than one translation unit, then

(list of conditions ...)

If the definitions of D satisfy all these requirements, then the program should behave as if there was one definition of D. If the definitions of D do not satisfy these requirements, then the behavior is undefined.

Please note that the standard does not indicate which definition is taken as one definition only if some definition is selected. Thus, if several translation blocks create templates in different orders, there is no guarantee that it will be an initialization order.

+4
source

The following is my observation (based on gcc):

Everything that appears first is first created.

If in a given translation unit (i.e. a pre-processed .cpp file), if the compiler (parser) sees the use of X<A>::t first, then an instance is created first, or first it sees X<B>::t , then it is created first. Note that this is before compilation (not runtime).

For example,

 struct A { static int a; }; struct B { static int b; }; template<typename T> struct X { static T t; }; template<typename T> T X<T>::t; void foo () { B *p = &(X<B>::t); } int main () { A *p = &(X<A>::t); foo(); } 

Result:

 X<B>::t instantiated first X<A>::t instantiated second 

Cause:

X<B>::t appears first inside foo()

+1
source

From C ++ 0x draft standard , section 3.6.2:

Dynamic initialization of a non-local variable with a static storage duration is either ordered or disordered. Definitions of explicitly specialized classes of static elements of a template template ordered initialization. Other static elements of the class template template (i.e., Implicitly or explicitly created instances) have unordered initialization. Other non-local variables with static storage duration ordered initialization. Variables with ordered initialization defined within a single translation unit must be initialized in the order of their definitions in the translation unit.

So, to answer your question, static data elements of explicitly created templates are not guaranteed to be initialized in any particular order in C ++ 0x.

I leave it to others to find the appropriate language (or lack thereof) in earlier standards.

+1
source

From 14.7.2 / 7:

Explicit instantiation of the specialization of a class template implies the creation of instances of all its elements that previously were not explicitly specialized in the translation unit, which contains explicit instantiation.

So, we can conclude that templates that are explicitly created have their own static members created / built in the same order.

However, for implicitly created templates, we go to 14.7.1 / 1:

... in particular, the initialization (and any side effects associated with it) of the static data element does not occur if the static data element is not itself used in a way that requires the definition of the static data a member exists.

From this, I do not think that we can safely draw any conclusions about the order in which they can be created for implicitly created templates.

+1
source

All Articles