Why is static initialization order happening like this?

Viewed 106

I know that there are big problems with static initialization order in c++, basically there's no guarantees in it across translation units, however in the same translation unit there should be the guarantee that static objects are initialised in order that they appear. So why is this happening?

#include <iostream>

struct Foo {};

class SequentialTypeIDDispenser
{
private:
    static inline int count = 0;
public:
    static int init() { std::cout << "initialising static member\n"; return count++; }
    template <typename type>
    static inline int ID = init();

};
 

class Horse
{public:
    static char init()
    {
        // Doesn't work, prints 0 all three times
        std::cout << SequentialTypeIDDispenser::template ID<char> << "\n";
        std::cout << SequentialTypeIDDispenser::template ID<double> << "\n";
        std::cout << SequentialTypeIDDispenser::template ID<float> << "\n";

        return 0;
    }
    static inline char member = init();
// Why is this being initialised before the static 
// members of the above class?
};

int main()
{


    // Now it works
    std::cout << SequentialTypeIDDispenser::template ID<char> << "\n";
    std::cout << SequentialTypeIDDispenser::template ID<double> << "\n";
    std::cout << SequentialTypeIDDispenser::template ID<float> << "\n";
    
    Horse horse;
    
}

The printed output is:

0
0
0
initialising static member
initialising static member
initialising static member
0
1
2

So we have a case where a static class member is being initialised before a static class member above it. Why is this happening?

Also, there is the other issue I don't understand, why if the program didn't get around to initialising the IDs yet, why is it printing 0? Is this just as undefined accident?

1 Answers

Your variables are dynamically initialized, with unordered initialization:

Unordered dynamic initialization, which applies only to (static/thread-local) class template static data members ... that aren't explicitly specialized. Initialization of such static variables is indeterminately sequenced with respect to all other dynamic initialization ...

[Emphasis mine]

Initialization order is indeterminate for your case.

Also, dynamic allocations might be deferred:

It is implementation-defined whether dynamic initialization happens-before the first statement of the main function

So it is possible that proper initialization might happen after the first statement of the main function, or at least before one of the variablea are ODR used.

Related