Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | 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 Tue Jul 20 10:46:47 2004 for s11n by doxygen 1.3.7