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

class_name.h

00001 #ifndef s11n_CLASS_NAME_H_INCLUDED
00002 #define s11n_CLASS_NAME_H_INCLUDED 1
00003 #include <cassert>
00004 #include <string>
00005 #include <typeinfo>
00006 #include <iostream> // cerr
00007 
00008 #include <map>
00009 #include "phoenix.h"
00010 
00011 
00012 namespace { // ns is not strictly necessary: works in global-scope as well.
00013         // anonymous NS is very helpful in some contexts, though.
00014 
00015         /**
00016            A utility class to provide human-usable class names,
00017            available at runtime.
00018 
00019            It MUST be specialized to work.
00020 
00021            Call one of these macros:
00022 
00023 <pre>
00024 CLASS_NAME(Type)
00025 CLASS_NAME_ALIAS(Type,AliasForType)
00026 </pre>
00027 
00028     from a class' header file (not an impl file, for complex
00029     linking reasons). It may only be called one time per Type per
00030     compilation unit, or you will get specialization collisions at
00031     compile time.
00032 
00033         Caveats:
00034 
00035            - template types with commas in the names will break the
00036            macro, requiring hand-specialization for these types.
00037 
00038            - typedef'd names will get their typedef'd name registered,
00039            not their real name. Maybe a feature, maybe not.
00040 
00041            - classes which want to use class_name on themselves will
00042            have to do some forward declarations and call CLASS_NAME()
00043            before using it.
00044 
00045            To get proper names for such cases you must hand-specialize
00046            this class. See the macros for a sample implementation, or
00047            the class_names shell script which should have come with
00048            this class.
00049         */
00050         template <class T>
00051         struct class_name
00052         {
00053                 typedef T value_type;
00054                 /** returns the class name for class T. */
00055                 static const char * name()
00056                 {
00057                         static const std::string tid = typeid((value_type *)0).name();
00058                         std::cerr << "this class_name<typeid=["
00059                                 + tid
00060                                 + "]> is unspecialized! See class_name.h for the solution!\n";
00061                         return tid.c_str();
00062                 }
00063 //                 const static bool bogus;
00064                 // ^^^ try to force instantiation of this class
00065         };
00066 //         template <typename T> const bool class_name< T >::bogus = (class_name< T >::name(),
00067 //                                                              true);
00068 
00069         /**
00070            A specialization to avoid the necessity to register, e.g.,
00071            CLASS_NAME(Foo) and CLASS_NAME(Foo *). Note that it returns
00072            the exact same name as the non-pointer variant, as this
00073            part is not relevant for the purposes i put this class
00074            through (classloading/[de]serializing), and in fact the
00075            extra token requires a lot of extra work down-stream.
00076         */
00077 //         template <class T>
00078 //         struct class_name<T *>
00079 //         {
00080 //                 typedef T base_type;
00081 //                 static const char * name()
00082 //                 {
00083 //                         return class_name<base_type>::name();
00084 //                 }
00085 //         };
00086         template <class T>
00087         struct class_name<const T *>
00088         {
00089                 typedef T base_type;
00090                 static const char * name()
00091                 {
00092                         return class_name<base_type>::name();
00093                 }
00094 //                 const static bool bogus;
00095         };
00096 //         template <typename T> const bool class_name< T const * >::bogus = (class_name< T const * >::name(),
00097 //                                                                      true);
00098 
00099         template <class T>
00100         struct class_name<T *>
00101         {
00102                 typedef T base_type;
00103                 static const char * name()
00104                 {
00105                         return class_name<base_type>::name();
00106                 }
00107         };
00108 } // namespace
00109 
00110 /**
00111    Shorthand form of class_name<T>::name().
00112 */
00113 template <typename T>
00114 const char * classname()
00115 {
00116         return class_name<T>::name();
00117 }
00118 
00119 
00120 namespace {
00121 ////////////////////////////////////////////////////////////////////////////////
00122 // i get internal compiler errors with these: (gcc 3.3.1)
00123 ////////////////////////////////////////////////////////////////////////////////
00124 //         template <class K, class M>
00125 //         struct class_name< std::map<K,M> >
00126 //         {
00127 //                 typedef K key_type;
00128 //                 typedef M mapped_type;
00129 //                 typedef std::map<key_type,mapped_type> base_type;
00130 //                 static const char * name()
00131 //                 {
00132 // //                         static const std::string n = 
00133 // //               std::string("std::map") + "<" +
00134 // //               ::classname< key_type >() + "," + 
00135 // //               ::classname< mapped_type >() + ">"; 
00136 // //                         return n.c_str();
00137 //                         return classname.c_str();
00138 //                 }
00139 //                 static std::string classname;
00140 
00141 //         };
00142 //         template <class K, class M>
00143 //         std::string class_name< std::map<K,M> >::classname = 
00144 //              std::string("std::map") + "<" +
00145 //              ::classname< K >() + "," + 
00146 //              ::classname< M >() + ">"; 
00147 
00148 
00149 //         template <class F, class S>
00150 //         struct class_name< std::pair<F,S> >
00151 //         {
00152 //                 typedef F first_type;
00153 //                 typedef S second_type;
00154 //                 typedef std::pair<first_type,second_type> base_type;
00155 //                 static const char * name()
00156 //                 {
00157 //                         return classname.c_str();
00158 //                 }
00159 //                 static std::string classname;
00160 
00161 //         };
00162 //         template <class F, class S>
00163 //         std::string class_name< std::pair<F,S> >::classname = 
00164 //              std::string("std::pair") + "<" +
00165 //              ::classname< F >() + "," + 
00166 //              ::classname< S >() + ">"; 
00167 
00168 
00169 //         template <class V>
00170 //         struct class_name< std::list<V> >
00171 //         {
00172 //                 typedef V value_type;
00173 //                 static const char * name()
00174 //                 {
00175 //                         return classname.c_str();
00176 //                 }
00177 //                 static std::string classname;
00178 //         };
00179 //         template <class V>
00180 //         std::string class_name< std::list<V> >::classname = 
00181 //              std::string("std::pair") + "<" +
00182 //              ::classname< V >() + ">"; 
00183 
00184 
00185 }
00186 
00187 ////////////////////////////////////////////////////////////////////////        
00188 //    Creates a class_name<> specialization for Type, using the class
00189 //    name Alias.
00190 ////////////////////////////////////////////////////////////////////////        
00191 #define CLASS_NAME_ALIAS(Type,Alias) \
00192     namespace { template <> \
00193     struct class_name< Type > {  static const char * name() { return # Alias;  } };}
00194 
00195 #define CLASS_NAME(Type) CLASS_NAME_ALIAS(Type,Type)
00196 ////////////////////////////////////////////////////////////////////////        
00197 
00198 
00199 
00200 #endif // s11n_CLASS_NAME_H_INCLUDED

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