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

abstract_creator.h

00001 #ifndef s11n_ABSTRACT_CREATOR_H_INCLUDED
00002 #define s11n_ABSTRACT_CREATOR_H_INCLUDED 1
00003 
00004 ////////////////////////////////////////////////////////////////////////
00005 // abstract_creatore.h:
00006 // Defines a difficult-to-describe class. See the docs.
00007 //
00008 //    Author: stephan beal <stephan@s11n.net>
00009 //    License: Public Domain
00010 ////////////////////////////////////////////////////////////////////////
00011 
00012 #include <cassert>
00013 #ifdef NDEBUG
00014 #  undef NDEBUG // force assert()
00015 #endif
00016 
00017 #include <string>
00018 #include "s11n_core.h" // classload
00019 #include <s11n/class_name.h>
00020 
00021 namespace s11n
00022 {
00023 
00024         /**
00025            abstract_creator is a helper to avoid some code having to
00026            know if a type is created on a stack or the heap. This
00027            makes some template code easier to write, as it avoids
00028            syntax errors when trying something like:
00029 
00030 <pre>
00031 if( object type is a pointer type ) delete(object);
00032 else { ... }
00033 </pre>
00034 
00035            This implementation creates items the stack via the default
00036            ctor. If instantiated with (T *) a pointer/heap-based
00037            specialization is activated instead.
00038 
00039            Designed for use with, e.g., ListType::value_type, which
00040            will may be, e.g., either T or (T *).
00041 
00042            These objects contain no state information.
00043         */
00044         template <typename T>
00045         struct abstract_creator
00046         {
00047                 /** Same as (T). */
00048                 typedef T value_type;
00049 
00050                 /** Same as (T). */
00051                 typedef T base_value_type;
00052 
00053                 /**
00054                    This implementation does nothing and returns true.
00055 
00056                    The string argument is bogus for this implementation,
00057                    and is used by the pointer specialization to implement
00058                    polymorphic classloading of value_type.
00059                 */
00060                 static bool create( value_type & v,
00061                                     const std::string & = std::string()  )
00062                 {
00063                         return true;
00064                 }
00065 
00066                 /**
00067                    Assigs lhs to rhs and true.
00068                 */
00069                 static void assign( value_type &lhs, const value_type & rhs )
00070                 {
00071                         lhs = rhs;
00072                         return;
00073                 }
00074 
00075                 /**
00076                    Returns a copy of.
00077                 */
00078                 static value_type copy( const value_type & rhs )
00079                 {
00080                         return rhs;
00081                 }
00082 
00083                 /**
00084                    Does nothing in this specialization. Specializations
00085                    which allocate resources are expected to release them here.
00086 
00087                    Note that release() exists because using a static boolean
00088                    to flag a clean-up mode won't work:
00089 
00090 <pre>
00091 typedef double T;
00092 T val;
00093 if( val is a pointer type ) { delete( val ); }
00094 else ...
00095 </pre>
00096 
00097                    That will only work when T is actually a pointer type.
00098                    Thus the following workaround:
00099 
00100 <pre>
00101 typedef [some type] T;
00102 T val;
00103 typedef abstract_creator&lt;T&gt; AC;
00104 assert( AC::create(val) ); // fine for (T) or (T *)
00105 ... use val ...
00106 AC::release(val); // deletes pointers. No-op for value types
00107 </pre>
00108         That works with pointers or non-pointers, and simply does nothing
00109                 for non-pointers.
00110 
00111                 See object_reference_wrapper for a type which can wrap
00112                 function calls to objects using the dot notation,
00113                 regardless of their pointerness.
00114                  */
00115                 static void release( value_type & )
00116                 {
00117                         return;
00118                 }
00119 
00120         }; // abstract_creator<T>
00121 
00122         /**
00123            A specialization of abstract_creator to create objects on
00124            the heap, using the s11n classloader.
00125         */
00126         template <typename T>
00127         struct abstract_creator<T *>
00128         {
00129                 /** Same as (T *). */
00130                 typedef T * value_type;
00131  
00132                /** Same as (T). */
00133                 typedef T base_value_type;
00134 
00135                 /**
00136                    Tries to create a value_type object,
00137                    using classload&lt;base_value_type&gt;( key )
00138                    to create it. v is assigned to it's value, which
00139                    may be 0. Returns true if an object is created,
00140                    else false.
00141 
00142                    The caller owns the returned object.
00143 
00144                    Maintenance note: new classloader registrations may
00145                    need to be installed as new types show up,
00146                    especially for streamables/PODs (because those
00147                    aren't normally registered as classes), or this
00148                    function won't handle them. In s11n this
00149                    registration is handled by most of the various
00150                    proxy installation macros.
00151                 */
00152                 static bool create(  value_type & v,
00153                                      const std::string & implclass = std::string() /* guess! */  )
00154                 {
00155                         const std::string key = 
00156                                 (! implclass.empty())
00157                                 ? implclass
00158                                 : ::classname<value_type>();
00159 
00160                         v = classload<base_value_type>( key );
00161                         //CERR << "create("<<key<<")=" <<std::hex<<v <<"\n";
00162                         return 0 != &v;
00163                 }
00164 
00165                 /**
00166                    Creates a MONOMORPHIC copy of rhs and returns it.
00167 
00168                    This copy is only useful for non-polymorphic
00169                    types.
00170                 */
00171                 static value_type copy( const value_type & rhs )
00172                 {
00173                         return new base_value_type(rhs);
00174                 }
00175 
00176                 /**
00177                    Returns rhs.
00178                 */
00179                 static void assign( value_type &lhs, const value_type & rhs )
00180                 {
00181                         lhs = rhs;
00182                         return;
00183                 }
00184 
00185 
00186                 /**
00187                    Deletes v and assigns it to 0.
00188                  */
00189                 static void release( value_type & v )
00190                 {
00191                         //CERR << "release(" << std::hex<<v<<")\n";
00192                         delete( v );
00193                         v = 0;
00194                 }
00195         }; // abstract_creator<T *>
00196 
00197 
00198 } // namespace
00199 
00200 #endif // s11n_ABSTRACT_CREATOR_H_INCLUDED
00201 

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