Update!
- Runtime checks added to throw an error if more than once instance of a singleton is ever created
- Compile-time check hack added to ensure that singletons aren't assigned from lvalues, which are misleading
- Added SMARTSINGLETON_STATIC mode which when defined automatically allocates your singletons in static memory (rather than heap), with no changes to your code required as long as your class has a default constructor.
Previously this wasn't a complete singleton technique as it did not perform runtime checks to detect an error if more than one instance of the singleton class is created. This version will automatically ensure that only one SmartSingleton is ever active, although it cannot know if somewhere in your code another instance is created like "Singleton::MyClass myClass = new Singleton::MyClass(...);"; for this a macro ("ENFORCE_SINGLETON_CONSTRUCTION;") can be added to your constructor to detect all possible singleton violations, although in most cases this really isn't necessary.
The new SMARTSINGLETON_STATIC mode allows you to almost automatically set your singletons to reside in static rather than heap memory, which is more efficient in most cases. The only change required is that your singleton class must implement a default constructor for the static allocation. You can still use other constructors in addition to that - calling "MyClass = new MyClass(...);" method will work as expected and still use static memory, although it might be preferred to call an initialize() method instead since using "new" in static mode requires that the SmartSingleton copy the data from the allocated memory to the static (this is done automatically of course, again no difference in usage code from the non-static version).
Another safety check is that now assigning an instance to an lvalue is not allowed:
Code: Select all
SmartSingleton<Singleton::MyClass> MySingleton;
...
Singleton::MyClass *myInstancePointer = new Singleton::MyClass(...);
MySingleton = myInstancePointer; //compile error
Code: Select all
SmartSingleton<Singleton::MyClass> MySingleton;
...
MySingleton = new Singleton::MyClass(...); //compiles and runs fine
Because this is confusing and error prone. For example if you tried to delete "myInstancePointer" yourself after assigning it to the SmartSingleton, your program would crash since ownership is transferred fully to the SmartSingleton when you do this and it expects to delete it automatically for you. Factory functions should still work fine.
Anyway, this was a fun little "template metaprogramming"-ish project, and will certainly make singletons a lot safer and easier for me. You can download the latest version from the first post of this thread.