arlo on 27 Jun 2003 15:37:02 -0000 |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
Re: [ALACPP] hot or not? |
Make Instance private, and then give a full smart pointer interface, including copy c'tors, equality operators and the like (all of which are trivial). Then it works. As is, however, it also encourages singleton-style use, which is difficult to refactor. Also, I frequently want more than one instance of a given type - one-per-something-else. So I'd extract the uniqueness portion into a policy, which will default to one per type. Thus: template < typename _T > class OnePerTypePolicy; template< typename _T, class _THolder = OnePerTypePolicy< _T > > class MonostatePtr : public _THolder { // c'tors, copy assignment, d'tor // Yes, make it copyable and copy-assignable, even though those // are no-ops. That way it can be used in a wide variety of situations, // eg, containers of monostates which are one-per-something-funky. _T* operator->() { /* ... */ } const _T* operator->() const { /* ... */ } volatile _T* operator->() volatile { /* ... */ } const volatile _T* operator->() const volatile { /* ... */ } _T& operator*() { /* ... */ } const _T& operator*() const { /* ... */ } volatile _T& operator*() volatile { /* ... */ } const volatile _T& operator*() const volatile { /* ... */ } }; // The truely simple version. It has problems, especially around the lifetime // of the static member. template< typename _T > class OnePerTypePolicy { protected: ~OnePerTypePolicy() {} // Just one fn to handle all const / volatile cases for this // policy, as they are all identical, and protected from mis-use // by the smart pointer class. Makes things simpler. _T& instance() const volatile { return const_cast< _T& >(instance_); } private: static _T instance_; }; // Then, of course, the following policies would also be defined: // load the instance from a specific "singletons" DLL. template< typename _T > class DLLSafeOnePerTypePolicy; // Use TSS. template< typename _T > class OnePerThreadPolicy; // Allow multiple monostates of the same held type, each named. template< typename _T, typename _Name > class OnePerNamePolicy; // Determine which instance it is by runtime indexing operation. template< typename _T > class AtRuntimePolicy { public: void set_index(int curIndex) { if(curIndex > instances_.size()) { instances_.resize(curIndex); } index_ = curIndex; } protected: // instance uses the current index to look it up in the vector. private: static std::vector< _T > instances_; int index_; }; /* the indexing one is perhaps extended to take a threading policy (default to single_threaded_unchecked), and the type of container to use, and the check in set_index is changed to use upper_bound and lower_bound, so that it'll work with maps. */ // Plus whatever the user wants. Were I writing this for my own use, I'd write the basic monostate, default it to DLLSafeOnePerType, and write only DLLSafeOnePerType and OnePerType. The rest are just examples of things that I've had to do from time to time, and are here to show how the policy on the monostate makes it trivial to implement them if I ever need them. And no, I've never needed the runtime indexed one - that was just in there to show how flexible the basic monostate is with just the one policy. Arlo > Consider: > > template<class T> > class MonoState > { > public: > T& Instance(void) { > static T singleton; > return singleton; > } > > T* operator->(void) { > return &Instance(); > } > }; > > Good or evil? > > I thought about implicit type conversion. operator T*() is equivalent to > operator->() and I can't get operator T&() to compile -- anyone know why? > It's what I really want. Then your MonoState usage looks like this: > > MonoState< Foo > aFoo; // gesundheit > > ... > > aFoo.DoBar(); // if this ain't easy to refactor, what is? _______________________________________________ alacpp mailing list alacpp@xxxxxxxxxxx http://lists.ellipsis.cx/mailman/listinfo/alacpp