The style guide at both my previous and current employers explicitly forbids having global non-0 statics for this exact reason: code that runs before main() is very unusual. Many assumptions do not hold.
A far better way is to use function-local statics. A static variable inside a function is initialized when execution reaches that point when the function is being called. Furthermore, such initialization is thread safe so that one initialization happens despite multiple concurrent calls of the function.
The only exception to that style guide rule is the new constinit in C++20. It is sometimes called linker-initialized to make it even clearer that the program didn't do anything to initialize it, the linker did.
> Furthermore, such initialization is thread safe so that one initialization happens despite multiple concurrent calls of the function.
IIRC, there are some popular compilers in which initialization of static variables inside functions is not thread safe (even though AFAIK the C++ standard said they should be).
The compiler I was thinking of was indeed MSVC. From a quick web search, it seems that more recent versions of MSVC have changed them to be thread safe by default, so if you can make sure that your code will never be compiled on older MSVC versions (and that nobody will ever use the compiler option which disables the thread-safe initialization), it might be fine to depend on it.
True as of msvc 2015 which is 8.5 years old at this point. I agree it’s weird that you can disable it but libraries retaining correctness in the face of random compiler flags is hard (eg ffast-math is a common one that can break your floating point library)
A far better way is to use function-local statics. A static variable inside a function is initialized when execution reaches that point when the function is being called. Furthermore, such initialization is thread safe so that one initialization happens despite multiple concurrent calls of the function.
The only exception to that style guide rule is the new constinit in C++20. It is sometimes called linker-initialized to make it even clearer that the program didn't do anything to initialize it, the linker did.