
Dave Handley wrote:
Providing an allocator template is essentially what is done in Loki so that would suffice to resolve this particular difference.
I have recently converted my code to CRTP form and noticed an inherent problem with creating an allocator template now. Because the derived class is the final singleton class, and its ctor and dtor are protected, there is no way to give a generic allocator the right to create the object. Even attempting to write a secret friendly shortcut through the base can't work, because the base doesn't have access to its children's protected members. I'm trying to use the template specialization method that Herb Sutter mentions in Exceptional C++ Style #15, putting protected templated functions in the base and then specializing the child versions to get access to the ctor. Unfortunately, all my attempts have failed. Here is a stripped down example of what I am trying (destruction would be virtually identical, and thus is omited): template < typename T > class AllocateUsingNew { public: static T * Create ( ) { T * p = reinterpret_cast < T * > ( new char [ sizeof ( T ) ] ); try { return T :: Allocation :: Construct ( p ); } catch ( ... ) { delete [] reinterpret_cast < char * > ( p ); throw; } } }; template < typename T, typename A = AllocateUsingNew < T > > class Singleton { public: class Allocation { private: friend A; // allow the allocator access to Allocation::Create static void Create ( T * p ) { T :: Create < T > ( p ); // call the derived specialization? } }; friend Allocation; // allow allocation access to Create protected: template < typename T > static void Create ( T * p ); // undefined base template that derived should inherit }; template < typename T > void T :: Create < T > ( T * p ) // specialize derived's Create method? { new ( p ) T; } Any suggestions?
Sorry, I think you have misunderstood me. I know that the dependencies method can be used in different ways, but it is still only a single policy. The reason for providing completely different policies for the lifetime policy is just that different projects require different solutions. I know for example that the dependencies model would fall down very quickly in the system I code in at present. We have a singleton that is the root of the tree that contains all the data in the system. Everyone uses this singleton, but doesn't tend to hold out references (dependencies). Under your dependency model, we would be almost forced to place a dependency in the main function - but here lies the problem. We actually have a number of different products which share the code base, but provide different main functions (and a few key interface classes) - this would mean we are coupling the main singleton to loads of places in the code. Using lifetimes, we can trivially make sure that this is the last singleton to come down.
Or... you could just add a static dependency to that specific singleton in the code where the singleton is defined ;)
I'm not saying dependencies are wrong - I'm just saying that a generic implementation should really provide the choice. I prefer to use longevities - you clearly prefer the dependencies - other people prefer to use Phoenix Singletons (singletons that re-create themselves from their own ashes if they are re-accessed after destruction).
Alright, I can accept that there may be different lifetime models that are needed. The phoenix singleton, however, is already handled by my current model, which attaches a dependency to the smart singleton pointer when GetInst is called. Unfortunately, I have been looking at the Loki singleton code (hopefully the book will get here soon), and am having trouble seeing how a dependency model could be implemented with Loki's lifetime traits model. Could you give me an example of how this could be achieved? -Jason