I am trying to get the following setup right:
A given application (with multiple source files, compilation units) has global variables of type class A defined in many compilation units.
These should be “managed” by a new to introduce class B (where only 1 instance should exist) in the sense that upon creation they “register” themselves at instance of class B and at destruction “sign off”.
Setting the thing up for the constructors to work is fairly straight-forward. One can use:
types.h:
class B {
static B& Instance() {
static B singleton;
return singleton;
}
void registerA( const A& a ) {
// whatever
}
};
class A {
A() { B::Instance().registerA( this ); }
};
How to get the destructors right? If using:
class A {
A() { B::Instance().registerA( this ); }
~A() { B::Instance().signoffA( this ); }
};
then the destructor of B might be called before the destructor of A.
Then the instance of class A signs off at a just newly created instance of B.
The test case would be a multi source file setup with definitions of instances of class A in a namespace:
file1.cc
#include "types.h"
namespace C {
A a;
}
file2.cc
#include "types.h"
namespace C {
A b;
}
I guess on can do such thing easily with Boost smart pointers. However, if possible I would like to avoid using additional libraries to keep dependence as low as possible.
One thing that might help: All global variables are in a named namespace.
I think you’re fine. Here’s 3.6.3 on “Termination”:
Suppose you have the following setup:
Now whatever happens, the first constructor of a static
A-type object will callB::get(), which sequences the construction of the staticimplobject before the completion of the firstA-constructor. By the above clause, this guarantees that the destructor of theB impl-object is sequenced after all theA-destructors.