Title
Order of initialization of static data members of class templates
Status
cd1
Section
6.9.3.2 [basic.start.static]
Submitter
Jonathan H. Lundquist

Created on 2001-02-09.00:00:00 last changed 188 months ago

Messages

Date: 2002-04-15.00:00:00

[Moved to DR at 4/02 meeting.]

Date: 2001-10-15.00:00:00

Notes from 10/01 meeting:

The Core Working Group reaffirmed its previous decision.

Date: 2001-07-15.00:00:00

Note (07/01):

Brian McNamara argues against the proposed resolution. The following excerpt captures the central point of a long message on comp.std.c++:

I have a class for representing linked lists which looks something like
    template <class T>
    class List {
       ...  static List<T>* sentinel; ...
    };

    template <class T>
    List<T>* List<T>::sentinel( new List<T> ); // static member definition

The sentinel list node is used to represent "nil" (the null pointer cannot be used with my implementation, for reasons which are immaterial to this discussion). All of the List's non-static member functions and constructors depend upon the value of the sentinel. Under the proposed resolution for issue #270, Lists cannot be safely instantiated before main() begins, as the sentinel's initialization is "unordered".

(Some readers may propose that I should use the "singleton pattern" in the List class. This is undesirable, for reasons I shall describe at the end of this post at the location marked "[*]". For the moment, indulge me by assuming that "singleton" is not an adequate solution.)

Though this is a particular example from my own experience, I believe it is representative of a general class of examples. It is common to use static data members of a class to represent the "distinguished values" which are important to instances of that class. It is imperative that these values be initialized before any instances of the class are created, as the instances depend on the values.

In a comp.std.c++ posting on 28 Jul 2001, Brian McNamara proposes the following alternative resolution:

Replace the following sentence in 6.9.3.2 [basic.start.static] paragraph 1:

Objects with static storage duration defined in namespace scope in the same translation unit and dynamically initialized shall be initialized in the order in which their definition appears in the translation unit.
with
Objects with static storage duration defined in namespace scope shall be initialized in the order described below.
and then after paragraph 1, add this text:
Dynamic initialization is either ordered or quasi-ordered. Explicit specializations of class template static data members have ordered initialization. Other class template static data member instances have quasi-ordered initialization. All other objects defined in namespace scope have ordered initialization. The order of initialization is specified as follows:
  • Objects that are defined within a single translation unit and that have ordered initialization shall be initialized in the order of their definitions in the translation unit.
  • Objects that are defined only within a single translation unit and that have quasi-ordered initialization shall also be initialized in the order of their definitions in the translation unit -- that is, as though these objects had ordered initialization.
  • Objects that are defined within multiple translation units (which, therefore, must have quasi-ordered initialization) shall be initialized as follows: in exactly one translation unit (which one is unspecified), the object shall be treated as though it has ordered initialization; in the other translation units which define the object, the object will be initialized before all other objects that have ordered initialization in those translation units.
  • For any two objects, "X" and "Y", with static storage duration and defined in namespace scope, if the previous bullets do not imply a relationship for the initialization ordering between "X" and "Y", then the relative initialization order of these objects is unspecified.
along with a non-normative note along the lines of
[ Note: The intention is that translation units can each be compiled separately with no knowledge of what objects may be re-defined in other translation units. Each translation unit can contain a method which initializes all objects (both quasi-ordered and ordered) as though they were ordered. When these translation units are linked together to create an executable program, all of these objects can be initialized by simply calling the initialization methods (one from each translation unit) in any order. Quasi-ordered objects require some kind of guard to ensure that they are not initialized more than once (the first attempt to initialize such an object should succeed; any subsequent attempts should simply be ignored). ]

Erwin Unruh replies: There is a point which is not mentioned with this posting. It is the cost for implementing the scheme. It requires that each static template variable is instantiated in ALL translation units where it is used. There has to be a flag for each of these variables and this flag has to be checked in each TU where the instantiation took place.

I would reject this idea and stand with the proposed resolution of issue 270.

There just is no portable way to ensure the "right" ordering of construction.

Date: 2001-04-15.00:00:00

Proposed resolution (04/01, updated slightly 10/01):

Replace the following sentence in 6.9.3.2 [basic.start.static] paragraph 1:

Objects with static storage duration defined in namespace scope in the same translation unit and dynamically initialized shall be initialized in the order in which their definition appears in the translation unit.

with

Dynamic initialization of an object is either ordered or unordered. Explicit specializations and definitions of class template static data members have ordered initialization. Other class template static data member instances have unordered initialization. Other objects defined in namespace scope have ordered initialization. Objects defined within a single translation unit and with ordered initialization shall be initialized in the order of their definitions in the translation unit. The order of initialization is unspecified for objects with unordered initialization and for objects defined in different translation units.

Note that this wording is further updated by issue 362.

Date: 2001-04-15.00:00:00

Notes from 04/01 meeting:

Enforcing an order of initialization on static data members of class templates will result in substantial overhead on access to such variables. The problem is that the initialization be required as the result of instantiation in a function used in the initialization of a variable in another translation unit. In current systems, the order of initialization of static data data members of class templates is not predictable. The proposed resolution is to state that the order of initialization is undefined.

Date: 2016-02-15.00:00:00

The Standard does not appear to address how the rules for order of initialization apply to static data members of class templates.

Suggested resolution: Add the following verbiage to either 6.9.3.2 [basic.start.static] or 11.4.9.3 [class.static.data]:

Initialization of static data members of class templates shall be performed during the initialization of static data members for the first translation unit to have static initialization performed for which the template member has been instantiated. This requirement shall apply to both the static and dynamic phases of initialization.
History
Date User Action Args
2008-10-05 00:00:00adminsetstatus: wp -> cd1
2003-04-25 00:00:00adminsetstatus: dr -> wp
2002-05-10 00:00:00adminsetmessages: + msg663
2002-05-10 00:00:00adminsetstatus: ready -> dr
2001-11-09 00:00:00adminsetmessages: + msg545
2001-11-09 00:00:00adminsetstatus: review -> ready
2001-09-12 00:00:00adminsetmessages: + msg523
2001-05-20 00:00:00adminsetmessages: + msg482
2001-05-20 00:00:00adminsetmessages: + msg481
2001-05-20 00:00:00adminsetstatus: open -> review
2001-02-09 00:00:00admincreate