Fist of all, singletons are the design errors we fight to avoid, not to embellish!
i just want a straight explanation that i don't need to decrypt |
Made extra hard by swallowed angle brackets! I'm pretty sure "template instance()" in your copy-paste was meant to be "template<class T> instance()" and later on "AbstractAssetRegister::instance()" was meant to be "AbstractAssetRegister::instance<AssetRegister>()"
can't quite get an understanding of lazy initialization |
with regards to singletons, this means
1) if the instance() function is never called, no object is ever created
2) on the first call to the instance() function, the object is created
3) all subsequent calls to the instance() function return the object created on that first call
in C++, this is most efficiently done with function-local statics because that's precisely what they do
1 2 3 4
|
Type& instance() {
static Type obj;
return obj;
}
| |
although you may sometimes see Java-inspired pointer acrobatics instead, and in fact may have to use a pointer for this assignment, though it doesn't have to be complicated.
Once an instance of a type has been created, that instance will always be returned, regardless if the function is called with a different type |
This is even worse than a regular singleton!
If I decypher this correctly, they want user code to be
1 2 3
|
AbstractAssetRegister& a1 = AbstractAssetRegister::instance<AssetRegister>(); // creates and returns an AssetRegister
AbstractAssetRegister& a2 = AbstractAssetRegister::instance<AssetRegister>(); // returns the already-created AssetRegister
AbstractAssetRegister& a3 = AbstractAssetRegister::instance<OtherRegister>(); // returns the already-created AssetRegister (!)
| |
since the type of the object to be created is not known until runtime, it will have to be dynamically-allocated, so..
something like this
1 2 3 4 5 6 7 8 9 10 11 12 13
|
struct AbstractAssetRegister {
template<class T>
static AbstractAssetRegister& instance() {
if (!obj) obj = std::make_unique<T>(); // not thread-safe (unlike function-local static)
return *obj;
}
// needs a virtual destructor, I'm keeping this minimal to show the singleton part
private:
static std::unique_ptr<AbstractAssetRegister> obj;
};
std::unique_ptr<AbstractAssetRegister> AbstractAssetRegister::obj;
struct AssetRegister : AbstractAssetRegister {};
struct OtherRegister : AbstractAssetRegister {};
| |
live demo (with the destructor too):
https://wandbox.org/permlink/2aBLUU4Kp5d6vxn7
Make some constructors private to taste (after all, singletons should offer no way to be constucted other than that "instance" thing)