Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members

instantiator.h

00001 #ifndef s11n_INSTANTIATOR_H_INCLUDED
00002 #define s11n_INSTANTIATOR_H_INCLUDED 1
00003 // Author: stephan beal <stephan@s11n.net>
00004 // License: Public Domain
00005 
00006 #include <string>
00007 #include <map>
00008 
00009 #include <functional>
00010 
00011 #include "phoenix.h" // i don't like this dep, but i also don't like
00012                      // what happens in some cases when i don't use
00013                      // phoenix. :/
00014 
00015 namespace s11n
00016 {
00017 
00018     /**
00019            object_factory is a helper object factory for the classes
00020            instantiator and class_loader.
00021 
00022            SubT must derive from (or be) T and must be Default
00023            Constructuable on the heap. In short, the following must be
00024            able to succeed:
00025 
00026 <pre>
00027 T * foo = new SubT;
00028 </pre>
00029         */
00030 
00031     template < class T, class SubT = T >
00032         struct object_factory
00033     {
00034                 /**
00035                    A typedef for the first template parameter for this
00036                    type.
00037                 */
00038                 typedef T result_type;
00039 
00040                 /**
00041                    A typedef for the second template parameter for this
00042                    type.
00043                 */
00044                 typedef SubT actual_type;
00045 
00046         /**
00047                    This creates a new SubT, which is assumed to be a
00048                    subclass of T.  It can be used as a factory for
00049                    instantiator & class_loader.
00050                 */
00051         static result_type *new_instance()
00052         {
00053             return new actual_type;
00054         }
00055 
00056                 /**
00057                    A convenience factory to assist in the registration
00058                    of abstract base types. It can be used as a factory
00059                    for such types, avoiding the problem that the default
00060                    factory will try to use 'new T', which won't work
00061                    with abstract types.
00062 
00063                    It always returns 0.
00064                 */
00065         static result_type * no_instance()
00066         {
00067             return 0;
00068         }
00069 
00070 
00071                 /**
00072                    Same as new_instance();
00073                 */
00074                 result_type * operator()() const
00075                 {
00076                         return new_instance();
00077                 }
00078     };
00079 
00080         /** Internal marker class */
00081         struct instantiator_sharing_context {};
00082 
00083         /**
00084            instantiator is essentially a static classloader, capable of
00085            loading classes by using registered factories for a given
00086            set of keys (e.g., class names).
00087 
00088            Classloaders, at least in my experience, need to be able to
00089            load all classes which derive from some given type. Without
00090            a common base class, one can't safely attempt to cast from
00091            an arbitrary pointer to the type we want to load. That's
00092            where the BaseType parameter comes in. All objects
00093            instantiated via this loader must inherit from BaseType.
00094 
00095            KeyType is a type which specifies the type of key used to
00096            look up classes, defaulting to std::string.
00097 
00098            Both BaseType and KeyType must be Default Constructable on
00099            the heap (e.g., via new BaseType()).
00100 
00101            This class holds no state, thus it can be copied quickly.
00102 
00103            Sample usage:
00104 <pre>
00105 typedef instantiator&lt;MyClass&gt; CL;
00106 CL::register_factory( "my_key" );
00107 MyClass *foo = CL::load( "some_key" ); // == NULL
00108 foo = CL::instantiate( "my_key" ); // == a new object
00109 </pre>
00110 
00111           Note that all instantiators of the same type use the same
00112           object factories. The ContextType template parameter can be
00113           used to limit the scope of the object factory registrations
00114           to a specific context: instantiators with different Contexts
00115           use different maps. ContextType is only used as a type, and
00116           is never instantiated by this class.
00117         */
00118     template < class BaseType,
00119                    class KeyType = std::string,
00120                    class ContextType = instantiator_sharing_context
00121                    >
00122         class instantiator
00123     {
00124         public:
00125                 /**
00126                    A typedef for the BaseType used by this class.
00127                 */
00128         typedef BaseType value_type;
00129 
00130                 /**
00131                    A typedef for the KeyType used by this class.
00132                 */
00133         typedef KeyType key_type;
00134 
00135                 /** Same as ContextType */
00136                 typedef ContextType context_type;
00137 
00138                 /**
00139                    Same as KeyType, for conformance with the the
00140                    Adaptable Unary Functor model.
00141                  */
00142                 typedef KeyType argument_type;
00143 
00144                 /**
00145                    Same as (BaseType *), for conformance with the
00146                    Adaptable Unary Functor model.
00147                 */
00148                 typedef BaseType * result_type;
00149 
00150                 /**
00151                    Convenience typedef.
00152                  */
00153         typedef instantiator< BaseType, KeyType, ContextType > ThisType;
00154 
00155 
00156                 /**
00157                    The type of factories used by this class: a
00158                    function taking void and returning (value_type
00159                    *). See factory_map().
00160 
00161                    todo: implement proper functor support.
00162                 */
00163                 typedef value_type *( *factory_type ) ();
00164 
00165                 /**
00166                    Internal container type used for mapping keys to
00167                    factories.
00168                 */
00169         typedef std::map < key_type, factory_type > object_factory_map;
00170 
00171 
00172         /**
00173                    Tries to instantiate an instance of value_type
00174                    using the given key. Returns NULL if no class could
00175                    be loaded for the given key.
00176 
00177                    The caller takes responsibility for the returned pointer.
00178                 */
00179         static value_type * instantiate( const key_type & key )
00180         {
00181             typename object_factory_map::const_iterator it = factory_map().find( key );
00182             if ( it != factory_map().end() )    // found a factory?
00183             {
00184                 return ( it->second ) ();   // run our factory.
00185             }
00186             return 0;
00187         }
00188 
00189                 /**
00190                    Same as instantiate( key ).
00191                  */
00192                 result_type operator()( const argument_type & key )
00193                 {
00194                         return instantiate( key );
00195                 }
00196 
00197 
00198         /**
00199                    Registers a factory using the given key. If fp is
00200                    NULL then a default factory is used. Note that fp
00201                    may not return a type other than
00202                    ThisType::value_type *, but the actual object it
00203                    creates may be a polymorphic subclass of
00204                    value_type. See the object_factory class for a
00205                    factory which does this subtype-to-base conversion.
00206                 */
00207         static void register_factory( const key_type & key, factory_type fp = 0 )
00208         {
00209                         if( ! fp ) fp = object_factory<value_type>::new_instance;
00210                         factory_map().insert( object_factory_map::value_type( key, fp ) );
00211                 }
00212 
00213         /**
00214                    Convenience wrapper around register_factory( key,
00215                    factory_for_SubOfBaseType ).
00216 
00217                    Registers a factory for ThisType::value_type, using
00218                    the given key and a default factory for producing
00219                    SubOfBaseType objects. SubOfBaseType must be a
00220                    subtype of ThisType::value_type.
00221                 */
00222                 template <typename SubOfBaseType>
00223         static void register_subtype( const key_type & key, factory_type fp = 0 )
00224         {
00225                         if( ! fp ) fp = object_factory<value_type,SubOfBaseType>::new_instance;
00226                         register_factory( key, fp );
00227         }
00228 
00229 
00230                 /**
00231                    Returns the internal key-to-factory map. It is safe
00232                    for clients to modify this except in multi-threaded
00233                    environments, and then all guarantees go out the
00234                    window. That said, it should never be necessary for
00235                    clients to use this.
00236 
00237                    It is safe to call this post-main(), but such calls
00238                    may return an empty map!
00239                 */
00240         static object_factory_map & factory_map()
00241         {
00242             return phoenix<object_factory_map,ThisType>::instance();
00243         }
00244 
00245                 /**
00246                    Returns true if the given key is registered. This is sometimes useful
00247                    for checking whether a factory needs to be re-registered, which
00248                    is sometimes necessary post-main(), when the internal map gets hosed
00249                    before clients are done using it.
00250                 */
00251                 static bool is_registered( const key_type & key )
00252                 {
00253                         return factory_map().end() != factory_map().find( key );
00254                 }
00255 
00256 
00257     }; // class instantiator
00258 
00259 } // namespace
00260 #endif // s11n_INSTANTIATOR_H_INCLUDED

Generated on Tue Oct 26 18:25:59 2004 for s11n by  doxygen 1.3.9.1