2

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?

Zebrafish
  • 11,682
  • 3
  • 43
  • 119
  • **Global** static objects are initialized in the order of their appearance. The two static class members are not global objects. – Pete Becker Sep 01 '21 at 13:35
  • [This might help](https://stackoverflow.com/questions/1421671/when-are-static-c-class-members-initialized) – NotAProgrammer Sep 01 '21 at 13:35
  • @NotAProgrammer In that answer of that you linked, doesn't this mean it should be initialised before it's used? ---> "The other guaranteed thing is that initialization of static objects from a translation unit will be done before use of any object or function from this translation unit:" – Zebrafish Sep 01 '21 at 13:39
  • @PeteBecker Even in namespace scope? In order of appearance? Just not classes, structs? – Zebrafish Sep 01 '21 at 14:08

1 Answers1

0

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.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • I'm not understanding. In which cases would their order be defined? If they weren't templated members? If they weren't in a class? If they weren't inlined? – Zebrafish Sep 01 '21 at 13:44