N4424 introduces inline variables (ones that can be defined in multiple translation units, useful in header-only libraries), but it is not in C++14. I have been using the following method to emulate it:
// a.hpp
#pragma once // to simplify
inline A& a_init() { static A a_obj; return a_obj; }
static A& a = a_init();
and
// b.hpp
#pragma once // to simplify
#include "a.hpp"
inline B& b_init() { static B b_obj{ use(a) }; return b_obj; }
static B& b = b_init();
The cpp files uses a and b. Nothing else uses a_init and b_init.
I think that:
- amust be initialized before- b, in every translation unit that includes- b;
- As nothing else calls b_init,b_initis only called when initializingb. From 1 at that timeamust have been initialized (a_initmust have returned);
- a_objis initialized when- a_initis called, so is- b_objfor- b_init;
- Combining 2 and 3, a_objandaare initialized before the calling ofb_init, thus theuse(a)is safe and the initialization order must beA() < B()(A()returns, thenB()is called);
- Destructors run in the reverse order of the completion of their construction, so ~B() < ~A().
Is my reasoning correct? Is this a working emulation of inline A a; inline B b{ use(a) }; and guarantees the order of A() < B() < ~B() < ~A()?