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

class_loader.h

00001 #ifndef s11n_CLASSLOADER_H_INCLUDED
00002 #define s11n_CLASSLOADER_H_INCLUDED 1
00003 ////////////////////////////////////////////////////////////////////////////////
00004 // class_loader.h:
00005 // a factory/template-based classloader framework
00006 // Author: stephan beal <stephan@s11n.net>
00007 // License: Public Domain
00008 ////////////////////////////////////////////////////////////////////////////////
00009 
00010 #include <string>
00011 #include <iostream>
00012 #include <sstream>
00013 #include <fstream>
00014 #include <cassert>
00015 #include <map>
00016 #include <algorithm>
00017 
00018 #include <stdlib.h> // getenv()
00019 
00020 
00021 #include <s11n/instantiator.h> // the underlying static classloader
00022 #include <s11n/phoenix.h> // shared object creator/manager
00023 #include <s11n/functor.h> // pair_entry_deallocator
00024 #include <s11n/cl_debuggering_macros.h> // COUT/CERR
00025 
00026 
00027 #include "config.h" // might have s11n_CLASS_LOADER_DEFAULT_PATH
00028 
00029 
00030 ////////////////////////////////////////////////////////////////////////////////
00031 #ifndef s11n_CLASSLOADER_DEBUG
00032    // If this is 0 then NO debugging output is emitted, regardless
00033    // of any preference set in class_loader_debug_level().
00034    // Setting it to one only means that debugging is enabled as long
00035    // as a preference has been set via class_loader_debug_level().
00036 #  define s11n_CLASSLOADER_DEBUG 1
00037 #  define s11n_CLASSLOADER_UNCONDITIONAL_DEBUG 0
00038     // ^^^^^ if 1 it will bypass the class_loader_debug_level() check
00039 #endif
00040 ////////////////////////////////////////////////////////////////////////////////
00041 
00042 
00043 ////////////////////////////////////////////////////////////////////////////////
00044 #if s11n_CLASSLOADER_DEBUG || s11n_CLASSLOADER_UNCONDITIONAL_DEBUG
00045 #  include <typeinfo>
00046 #  define s11n_CL_TYPENAME typeid((ThisType *)NULL).name()
00047 #  define s11n_CL_DEBUG if( s11n_CLASSLOADER_UNCONDITIONAL_DEBUG || s11n_CLASSLOADER_DEBUG ) if ( s11n_CLASSLOADER_UNCONDITIONAL_DEBUG || (0 != s11n::class_loader_debug_level()) ) CERR << s11n_CL_TYPENAME <<" "
00048 #else
00049 #  define s11n_CL_TYPENAME ""
00050 #  define s11n_CL_DEBUG if( 0 ) CERR
00051 #endif
00052 ////////////////////////////////////////////////////////////////////////////////
00053 
00054 
00055 
00056 
00057 namespace s11n
00058 {
00059 
00060         /**
00061            Utility function to help keep an instance count of T.  The
00062            returned reference should ONLY be modified from ctors and
00063            dtors of T.
00064         */
00065         template <typename T>
00066         size_t & inst_count() { static size_t c = 0; return c; }
00067 
00068 
00069         /**
00070            Sets the framework-wide debug level. This is shared by
00071            all class_loaders, regardless of their templatized types.
00072 
00073            Currently only two values are supported: zero (no
00074            debugging output) and non-zero (all debugging output).
00075 
00076            Note that this uses a compile-time default, which means
00077            that if compiled without debugging, some debug messages
00078            will not show up because they happen pre-main(),
00079            before a client can set the debug level.
00080         */
00081         void class_loader_debug_level( int dlevel );
00082 
00083         /**
00084            Returns the framework-wide debug level.
00085         */
00086         int class_loader_debug_level();
00087 
00088     /**
00089            A basic templates-based classloader implementation,
00090            intended to work in conjunction with s11n::instantiator
00091            for loading classes via registered object factories.
00092 
00093            Templatized on:
00094 
00095            BaseType - this is the type to which all loaded classes
00096            should be cast. This is analogous to libfun's
00097            fun::LoadableClass.
00098 
00099            KeyType - the key type to be used to search for
00100            classes. Historically this is a string, but any comparable
00101            type should work. It is important that KeyType support
00102            less-than ordering.
00103 
00104            UseSharedInstances - determines the ownership policy for
00105            pointers returned from load(). See load() and the
00106            library manual for full details. This parameter should
00107            be left as-is for most use-cases. Note that all
00108            factories are shared amongst class_loader<BaseType>'s, regardless
00109            of their sharing policy, so it is a bad idea to mix
00110            classloaders of the same BaseType with different
00111            sharing policies, as pointer ownership then becomes confusing.
00112 
00113            To make any given class classloadable by this class, call
00114            this macro one time (preferably from the class' header file):
00115 
00116 <pre>
00117 s11n_CLASSLOADER_REGISTER(BaseType,SubType);
00118 s11n_CLASSLOADER_REGISTER(SubType,SubType); // optional, and sometimes useful
00119 </pre>
00120 
00121     BaseType need not be ClassLoadable, but SubType must derive
00122     from (or be) BaseType.  The exact meanings of the parameters
00123     are discussed at length in the documentation for that macro, in
00124     the class_loader.h header file and in the libs11n manual.
00125 
00126         As a side-effect of it's template-ness, usage of this class is
00127         compile-time type-safe without the use of any casts.
00128 
00129 
00130         See cllite.h for a simplified client-side interface for this
00131         class, and lite.cpp for demonstration code.
00132 
00133         */
00134         template < class BaseType, class KeyType = std::string, bool UseSharedInstances = false >
00135         class class_loader
00136     {
00137         public:
00138                 /**
00139                    If this is true then calls to load(key) will always
00140                    return the same instance for the same key. This
00141                    *might* not apply to calls made post-main(), i.e.,
00142                    it might return different objects after main()
00143                    exits, but such calls are dubious, anyway.
00144                 */
00145                 static const bool use_shared_instances = UseSharedInstances;
00146 
00147                 /**
00148                    value_type is the base-most class type to be used
00149                    for loading.
00150 
00151                    Contrary to usage in some std::-namespace s11nasses,
00152                    value_type is not a pointer type, even though this
00153                    class deals only with pointers to value_type
00154                    objects. This is intended to ease the use of
00155                    value_type in many common contexts.
00156                 */
00157         typedef BaseType value_type;
00158 
00159                 /**
00160                    The key type used for class lookups. The default is
00161                    std::string.
00162                 */
00163         typedef KeyType key_type;
00164                 
00165                 
00166                 /** Convenience typedef. It's only public for documentation reasons. */
00167         typedef class_loader < value_type, key_type, use_shared_instances > ThisType;
00168                 /**
00169                    factory_type is a function pointer which takes no
00170                    arguments and returns a value_type pointer.
00171                    
00172                    todo: add proper functor support.
00173                 */
00174         typedef value_type *( *factory_type ) ();   // todo: investigate utility of: BaseType *(*factory_type)( key_type )
00175 //      typedef std::unary_function<void,value_type *> factory_type;
00176 
00177                 class_loader()
00178         {
00179                          ++inst_count<ThisType>();
00180                          //s11n_CL_DEBUG << "instance #" << inst_count<ThisType>()<<std::endl;
00181         }
00182 
00183 
00184         virtual ~class_loader()
00185         {
00186                         if( use_shared_instances )
00187                         { // might be optimized away by the compiler :)
00188                                 if( 0 == --inst_count<ThisType>() )
00189                                 {
00190                                         s11n_CL_DEBUG << "Cleaning up shared objects..." << std::endl;
00191                                         shared_inst_map & bob = shared_objects();
00192                                         std::for_each( bob.begin(), bob.end(), s11n::pair_entry_deallocator() );
00193                                 }
00194                         }
00195         }
00196 
00197                 /**
00198                    Functionally identical to load(key).
00199 
00200                    This is for use i making this class usable as a
00201                    functor, to clients can easily replace classloaders
00202                    in contexts which use functors to load classes.
00203                 */
00204                 value_type * operator()( const key_type & key )
00205                 {
00206                         return this->load( key );
00207                 }
00208 
00209                 /**
00210                    Returns a reference to a shared instance of this
00211                    classloader type.
00212                 */
00213                 static ThisType & shared()
00214                 {
00215                         return phoenix<ThisType>::instance();
00216                 }
00217 
00218         /**
00219                    Tries to instantiate an object using a factory
00220                    which has been mapped to the given key. Returns a
00221                    non-NULL pointer on success and NULL on error. The
00222                    caller takes ownership of the returned
00223                    pointer... UNLESS:
00224 
00225                    If ThisType::use_shared_instances is true then this
00226                    function will always return the same object for any
00227                    given key, and the client <b>DOES NOT</b> take
00228                    ownership of the returned pointer! The objects
00229                    will be deleted when the last class_loader of this type
00230                    destructs, almost certainly post-main().
00231 
00232 
00233                    Subclasses should override this function to
00234                    customize classloading behaviour.
00235 
00236                    The default implementation loads classes which
00237                    have been registered via:
00238 
00239                    - ThisType::register_factory()
00240 
00241                    - ThisType::register_subtype()
00242 
00243                    (Remember, the CLASSLOADER_REGISTER macro calls
00244                    those for you.)
00245                 */
00246         virtual value_type * load( const key_type & key ) const
00247         {
00248                         typename ThisType::alias_map::const_iterator alit = aliases().find( key );
00249 
00250                         key_type realkey = (aliases().end() == alit ) ? key : (*alit).second;
00251                         s11n_CL_DEBUG << ": load("<<realkey<<")"<<std::endl;
00252 
00253                         if( ThisType::use_shared_instances )
00254                         { // the compiler can hopefully optimize this out in most cases.
00255                                 value_type * ch = NULL;
00256                                 shared_inst_map & bob = shared_objects();
00257                                 typename shared_inst_map::iterator it = bob.find( realkey );
00258                                 if( bob.end() == it )
00259                                 {
00260                                         if( (ch = ThisType::instantiator_type::instantiate( realkey )) )
00261                                         { // ^^^^ yes, that's an assignment, not comparison
00262                                                 bob[realkey] = ch;
00263                                                 // don't insert NULLs because it breaks some use-cases.
00264                                         }
00265                                 }
00266                                 else
00267                                 {
00268                                         ch = (*it).second;
00269                                 }
00270                                 return ch;
00271                         }
00272 
00273                         return ThisType::instantiator_type::instantiate( realkey );
00274         }
00275 
00276                 /**
00277                    Convenience static version of load( key ), which
00278                    uses the class_loader returned by shared().
00279                    
00280                    Avoid using this, it will directly use
00281                    class_loader&lt;&gt;, bypassing any subclass-implemented
00282                    loading improvements (like DLL loading).
00283                 **/
00284                 static value_type * load_class( const key_type & key )
00285                 {
00286 
00287                         return shared().load( key );
00288                 }
00289 
00290                 /**
00291                    Returns true if the given key is registered. This is sometimes useful
00292                    for checking whether a factory needs to be re-registered, which
00293                    is sometimes necessary post-main(), when the internal map gets hosed
00294                    before clients are done using it.
00295                 */
00296                 static bool is_registered( const key_type & key )
00297                 {
00298                         return instantiator_type::is_registered( key );
00299                 }
00300 
00301         /**
00302 
00303                 register_factory() associates key with a factory
00304                 function.  If fp == 0 then a default factory is
00305                 used (normally this behaviour is just fine).
00306 
00307                 register_factory() probably should not be static, but
00308                 i'm not fully convinced that a non-static
00309                 implementation is useful, and a static implementation
00310                 eases use of this class. Since classloaders
00311                 must(?) all use the same definitions for all like-types,
00312                 anyway, it seems like a moot point. In any case,
00313                 static appears to ease client usage, so static it is.
00314                 */
00315         static void register_factory( const key_type & key, factory_type fp = 0 )
00316         {
00317                         s11n_CL_DEBUG << "register_factory("<<key<<")"<<std::endl;
00318             instantiator_type::register_factory( key, fp );
00319         }
00320 
00321                 /**
00322                    Convenience function which registers a factory
00323                    creating SubT pointers but returning value_type
00324                    pointers. A factory of 0 means to use a default
00325                    factory, generated by this library.
00326 
00327                    ACHTUNG: gcc 3.3.1 often gives parse errors when compiling
00328                    calls to this function, for reasons i don't understand:
00329 
00330                    e.g.:
00331 <pre>
00332                 classloader<BaseType,KeyType>().register_subtype<SubType>( classname,
00333                                                                   object_factory<BaseType,SubType>::new_instance
00334                                                                   );
00335 </pre>
00336 
00337 Gives me:
00338 <pre>
00339    s11n::classloader_register(const std::string&)':
00340 ../../include/s11n/s11n_core.h:112: error: parse error before `>' token
00341 
00342 </pre>
00343 
00344 IMO it's a compiler bug, but i don't know for sure. :/
00345 
00346 
00347                 */
00348                 template <typename SubT>
00349         static void register_subtype( const key_type & key, factory_type fp = 0 )
00350         {
00351                         s11n_CL_DEBUG << "register_subtype("<<key<<")" <<std::endl;
00352             register_factory( key, fp  ? fp : object_factory<value_type,SubT>::new_instance  );
00353         }
00354 
00355                 
00356                 /**
00357                   Aliases alias as equivalent to classname.
00358                   Calls to load(alias) will work exactly as if
00359                   load(classname) was called.
00360 
00361                 **/
00362                 static void alias( const key_type & alias, const key_type & classname )
00363                 {
00364                         s11n_CL_DEBUG << " alias("<<alias<<","<<classname<<")" <<std::endl;
00365                         ThisType::aliases()[alias] = classname;
00366                 }
00367 
00368 
00369 
00370                 /**
00371                    shared_inst_map is only used when
00372                    <code>use_shared_instances</code> is true. It holds
00373                    the shared classloaded objects.
00374                 */
00375                 typedef std::map<key_type,value_type *> shared_inst_map;
00376 
00377                 /**
00378                    If <tt>use_shared_instances</tt> is true this
00379                    stores the classloaded shared objects, otherwise it
00380                    holds nothing.
00381 
00382                    When called post-main() this function may return an
00383                    empty map.
00384 
00385                    This list is provided in the public interface
00386                    primarily so clients can do things like serialize
00387                    the list at application shutdown, provided
00388                    value_type supports such a feature.
00389                 */
00390                 static shared_inst_map & shared_objects()
00391                 {
00392                         return phoenix<shared_inst_map,ThisType>::instance();
00393                 }
00394 
00395 
00396         protected:
00397                 /** Used to store alias-to-classname mappings. */
00398                 typedef std::map<key_type,key_type> alias_map;
00399 
00400                 /**
00401                    Returns the map of classname aliases, keyed on aliases,
00402                    with their expansions as their values.
00403 
00404                    The returned map is guaranteed to be post-main()
00405                    safe in the sense that it will never return a dead
00406                    reference. It is not post-main() safe in the sense
00407                    that the aliases map will be depopulated at some
00408                    arbitrary point post-main() and the returned map is
00409                    not guaranteed to be populated after that point.
00410                  */
00411                 static alias_map & aliases()
00412                 {
00413                         return phoenix<alias_map,ThisType>::instance();
00414                 }
00415 
00416         private:
00417 
00418                 /**
00419                    Factories registered with this instantiator_type are
00420                    inherently loadable by this class.
00421 
00422                    The tasks of storing, looking up and calling
00423                    factories is delegated to this type.
00424                 */
00425         typedef s11n::instantiator < BaseType, KeyType > instantiator_type;
00426 
00427               
00428 
00429     }; // class_loader
00430 
00431 
00432 } // namespace
00433 
00434 
00435 #ifndef CLASSLOADER_REGISTERER_INCLUDED
00436 #define CLASSLOADER_REGISTERER_INCLUDED 1
00437 // this guard is necessary when compiling different-namespaced
00438 // versions of this code in the same compilation unit.
00439 namespace { // anonymous ns, important for linking reasons.
00440         /**
00441            Internal helper class used for registering classes. The
00442            whole point of this class is to create a unique (per
00443            compilation unit) variable which we can assign a
00444            meaningless value to. We accomplish uniqueness via the
00445            anonymous namespace and template parameters.
00446         */
00447         template <class BaseT,class SubT = BaseT, class KeyT = std::string >
00448         struct classloader_reg_placeholder
00449         {
00450                 /**
00451                    A no-meaning placeholder.
00452                  */
00453                 static bool reg;
00454                 /**
00455                    Maintenance note: reg is initialized via
00456                    calls to the CLASSLOADER_REGISTER macro.
00457                 */
00458         };
00459 } // namespace
00460 #endif //CLASSLOADER_REGISTERER_INCLUDED
00461 
00462 /**
00463    Call this macro one time to make your classes loadable by all
00464    class_loader<BaseT> instances.
00465 
00466    Parameters:
00467 
00468    - BaseT, the base-most class type. i.e., that which will be used by clients when they call:
00469 <pre>
00470 BaseType * foo = class_loader<BaseType>( "mynamespace::SubtypeOfBaseT" );
00471 </pre>
00472     The library documentation goes into much more detail about
00473     this.
00474 
00475    - SubT, an implementation class derived from BaseT.
00476 
00477    Example:
00478    <pre>
00479    CLASSLOADER_REGISTER(mynamespace::MyDocumentBase,mynamespace::MyDocument);
00480    </pre>
00481 
00482    i'd like to call CLASS_NAME(SubT) from this macro, but doing so
00483    causes template specialization collisions when CLASSLOADER_REGISTER
00484    is called, e.g., like so:
00485 
00486 <pre>
00487    s11n_CLASSLOADER_REGISTER(BaseT,SubT);
00488    s11n_CLASSLOADER_REGISTER(SubT,SubT);
00489 </pre>
00490 
00491    This is valid usage, however, and necessary in some client cases,
00492    so i can't kill it's usage with an automatic CLASS_NAME() :(.
00493 
00494    See s11n_CLASSLOADER_REGISTER[1-5] if you want to customize the
00495    registration behaviour or register one class with multiple KeyT's.
00496 */
00497 
00498 
00499 ////////////////////////////////////////////////////////////////////////
00500 // CLASSLOADER_REGISTER[1-5]:
00501 // Pneumonic for remembering which macro to call: the suffix is the
00502 // number of args to pass.
00503 // Variants 1-3 are only known to work for (KeyT = std::string).
00504 //
00505 // Example:
00506 //  CLASSLOADER_REGISTER4(BaseType,SubType,double,42.42)
00507 // registers SubType via:
00508 //      class_loader<BaseType>::register_subtype<SubType>( 42.42 ).
00509 //
00510 // Note that most of this macro duplication is to allow
00511 // various-namespaced versions of this code to live in the same client
00512 // tree. Ideally clients should use:
00513 //  s11n_CLASSLOADER_REGISTER()
00514 // instead of:
00515 //  CLASSLOADER_REGISTER()
00516 // but the latter is more convient for cases where different
00517 // namespaces is not an issue.
00518 ////////////////////////////////////////////////////////////////////////
00519 
00520 #define s11n_CLASSLOADER_REGISTER(BaseT,SubT) s11n_CLASSLOADER_REGISTER2(BaseT,SubT)
00521 #define s11n_CLASSLOADER_REGISTER1(BaseT) s11n_CLASSLOADER_REGISTER2(BaseT,BaseT)
00522 #define s11n_CLASSLOADER_REGISTER2(BaseT,SubT) s11n_CLASSLOADER_REGISTER3(BaseT,SubT,std::string)
00523 // #3 is only useful for KeyT == std::string. It is here only for consistency.
00524 #define s11n_CLASSLOADER_REGISTER3(BaseT,SubT,KeyT)  s11n_CLASSLOADER_REGISTER4(BaseT,SubT,KeyT,# SubT) 
00525 #define s11n_CLASSLOADER_REGISTER4(BaseT,SubT,KeyT,ThekeY) s11n_CLASSLOADER_REGISTER5(BaseT,SubT,KeyT,ThekeY,s11n)
00526 #define s11n_CLASSLOADER_REGISTER5(BaseT,SubT,KeyT,ThekeY,Cloader_namespacE) \
00527     namespace { \
00528         template <> bool classloader_reg_placeholder< BaseT,SubT,KeyT >::reg = \
00529         (Cloader_namespacE::class_loader< BaseT,KeyT >::register_subtype< SubT >( ThekeY ),true); \
00530     }
00531 ////////////////////////////////////////////////////////////////////////
00532 // set up some shortcuts:
00533 #ifndef CLASSLOADER_REGISTER
00534 #  define CLASSLOADER_REGISTER(BaseT,SubT) \
00535     s11n_CLASSLOADER_REGISTER2(BaseT,SubT)
00536 #  define CLASSLOADER_REGISTER1(BaseT) \
00537     s11n_CLASSLOADER_REGISTER1(BaseT)
00538 #  define CLASSLOADER_REGISTER2(BaseT,SubT) \
00539     s11n_CLASSLOADER_REGISTER2(BaseT,SubT)
00540 #  define CLASSLOADER_REGISTER3(BaseT,SubT,KeyT) \
00541     s11n_CLASSLOADER_REGISTER3(BaseT,SubT,KeyT) 
00542 #  define CLASSLOADER_REGISTER4(BaseT,SubT,KeyT,ThekeY) \
00543     s11n_CLASSLOADER_REGISTER4(BaseT,SubT,KeyT,ThekeY)
00544 #  define CLASSLOADER_REGISTER5(BaseT,SubT,KeyT,ThekeY,CLNameSpace) \
00545     s11n_CLASSLOADER_REGISTER5(BaseT,SubT,KeyT,ThekeY,CLNameSpace)
00546 #endif
00547 ////////////////////////////////////////////////////////////////////////
00548 
00549 /************************************************************************
00550 Documentation for the s11n_CLASSLOADER_ABSTRACT_BASE()
00551 family of macros.
00552 
00553 These are a way to registering abstract classes as base types. The root
00554 of the problem is that default factory object uses 'new BaseT', which
00555 will not work if BaseT is abstract (it fails at compile time).
00556 
00557 The current implementation has a maintenance hazard: as soon as
00558 class_loader stops using object_factory<> as it's default factory then
00559 this code will need to adjust to suit.
00560 
00561 Important notes:
00562 
00563 - generated helper code does not use an anonymous namespace, and is
00564 therfore more subject to ODR collisions than the CLASSSLOADER_REGISTER()
00565 macros are.
00566 
00567 - These macros may NOT be used in conjunction with the CLASSSLOADER_REGISTER()
00568 macros: these do effectively the same thing.
00569 
00570 ************************************************************************/
00571 
00572 #define s11n_CLASSLOADER_ABSTRACT_BASE(BaseT) \
00573     s11n_CLASSLOADER_ABSTRACT_BASE1(BaseT)
00574 
00575 #define s11n_CLASSLOADER_ABSTRACT_BASE1(BaseT) \
00576     s11n_CLASSLOADER_ABSTRACT_BASE2(BaseT,std::string)
00577 
00578 #define s11n_CLASSLOADER_ABSTRACT_BASE2(BaseT,KeyT) \
00579     s11n_CLASSLOADER_ABSTRACT_BASE3(BaseT,KeyT,# BaseT)
00580 
00581 #define s11n_CLASSLOADER_ABSTRACT_BASE3(BaseT,KeyT,ThekeY) \
00582     s11n_CLASSLOADER_ABSTRACT_BASE4(BaseT,KeyT,ThekeY,s11n)
00583 
00584 #define s11n_CLASSLOADER_ABSTRACT_BASE4(BaseT,KeyT,ThekeY,Cloader_namespacE) \
00585     namespace s11n { \
00586         template <> struct object_factory< BaseT > { \
00587         static BaseT * new_instance() { return 0; } \
00588         }; } \
00589     s11n_CLASSLOADER_REGISTER5(BaseT,BaseT,KeyT,ThekeY,Cloader_namespacE);
00590 
00591 
00592 
00593 /************************************************************************
00594 s11n_CLASSLOADER_ALIAS(BaseT,String,Alias,UniqueID)
00595 
00596 
00597 Note that using this macro is significantly more wasteful than simply
00598 calling class_loader<BaseT>::alias(Alias,String) [achtung: note reversed
00599 order of the args in the function and macro. Sorry.].
00600 
00601 BaseT must be registered with the classloader already.
00602 
00603 Alias is mapped as being functionally identical to String for purposes
00604 of class_loader<BaseT>::load().
00605 
00606 UniqueID is a kludge to get around ODR violations when applying
00607 multiple aliases for a single BaseT. Pass a unique number for each
00608 alias of BaseT.
00609 
00610 ************************************************************************/
00611 
00612 #ifndef CLASSLOADER_ALIASER_INCLUDED
00613 #define CLASSLOADER_ALIASER_INCLUDED 1
00614 // this guard is necessary when compiling different-namespaced
00615 // versions of this code in the same compilation unit.
00616 namespace {
00617 
00618         /**
00619            Kludge to avoid ODR violations while aliasing classes via
00620            class_loader at initialization.
00621         */
00622         template <typename T, int ID>
00623         struct classloader_alias_registerer
00624         {
00625                 static bool reg;
00626         };
00627 }
00628 #endif // CLASSLOADER_ALIASER_INCLUDED
00629 
00630 #define s11n_CLASSLOADER_ALIAS(BaseT,OriginalString,Alias,UniqueID) \
00631     namespace { \
00632         bool classloader_alias_registerer< BaseT, UniqueID >::reg = (\
00633             s11n::class_loader< BaseT >::alias( Alias, OriginalString  ),\
00634             UniqueID \
00635              ); \
00636     }
00637 
00638 #endif // s11n_CLASSLOADER_H_INCLUDED

Generated on Thu Jun 16 16:18:12 2005 for s11n by  doxygen 1.4.3-20050530