No no no no no. This approach still needs heap allocation, and you still need to chase a pointer for every access to your singleton. That's silly. There's a much better way. Here it is, roughly speaking.
template<typename T>
struct singleton_bss {
T& get() {
return * ((T*) &this->buffer[0]);
}
void init(T&& value) {
new ( (T*) &this->buffer[0] ) T(std::forward<T> (value));
}
union {
char buffer[sizeof(T)];
long align; // adjust to taste
};
};
singleton_bss<mything> g_thing;
This approach has the huge advantage of not doing any heap allocation. The storage for g_thing lives directly in bss, the portion of your processes' address space initialized by the operating system. g_thing.init() cannot fail if T's constructor is non-throwing --- singleton_bss allocates no memory!Access to g_thing is much more efficient than access to a typical singleton. There's no pointer-to-the-instance stored in the singleton, so there's no pointer chasing. Access to g_thing is exactly as efficient as access to a plain global variable, which is as efficient as variable access can be.
You can trivially construct a version of singleton_bss that does lazy initialization, takes multiple parameters, destroys the object on module unload, and so on.