The point of this construct is to impose a construction order (and thus a destruction order).
Construction
Since these are local static variables, the order of construction is determined by the order in which their respective Instance
functions are called for the first time.
Since that is done in main
, the construction order is fully specified.
The only way to make the order unspecified is if you use them in static initialisation in different translation units, for instance if one has
C& the_c = C::Instance();
and the other has
D& the_d = D::Instance();
Destruction
The destruction of objects with static storage is the reverse of the order of construction.
3.6.3, Termination, paragraph 1:
If the completion of the constructor or dynamic initialization of an
object with static storage duration is sequenced before that of
another, the completion of the destructor of the second is sequenced
before the initiation of the destructor of the first.
So the destruction order is fully specified by the construction order.
Note that this singleton construct is well specified even if one of them depends on the other, regardless of translation unit.
That is, this is perfectly safe, and it doesn't matter where it's defined:
class C {
public:
static C& Instance() {
static C c(D::Instance());
return c;
}
~C(){ m_d.doSomething(); } // Yes, this is safe.
private:
C(D& d) : m_d(d) { m_d.doSomething(); } // Yes, this is safe.
D& m_d;
};