00001 /** @file rutz/traits.h various traits classes for determining type 00002 characteristics at compile time */ 00003 00004 /////////////////////////////////////////////////////////////////////// 00005 // 00006 // Copyright (c) 2001-2004 California Institute of Technology 00007 // Copyright (c) 2004-2007 University of Southern California 00008 // Rob Peters <rjpeters at usc dot edu> 00009 // 00010 // created: Fri May 18 16:13:27 2001 00011 // commit: $Id: traits.h 8249 2007-04-12 06:03:40Z rjpeters $ 00012 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/rutz/traits.h $ 00013 // 00014 // -------------------------------------------------------------------- 00015 // 00016 // This file is part of GroovX. 00017 // [http://ilab.usc.edu/rjpeters/groovx/] 00018 // 00019 // GroovX is free software; you can redistribute it and/or modify it 00020 // under the terms of the GNU General Public License as published by 00021 // the Free Software Foundation; either version 2 of the License, or 00022 // (at your option) any later version. 00023 // 00024 // GroovX is distributed in the hope that it will be useful, but 00025 // WITHOUT ANY WARRANTY; without even the implied warranty of 00026 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00027 // General Public License for more details. 00028 // 00029 // You should have received a copy of the GNU General Public License 00030 // along with GroovX; if not, write to the Free Software Foundation, 00031 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 00032 // 00033 /////////////////////////////////////////////////////////////////////// 00034 00035 #ifndef GROOVX_RUTZ_TRAITS_H_UTC20050626084021_DEFINED 00036 #define GROOVX_RUTZ_TRAITS_H_UTC20050626084021_DEFINED 00037 00038 namespace rutz 00039 { 00040 /// Basic type traits class. 00041 template <class T> 00042 struct type_traits 00043 { 00044 typedef T deref_t; 00045 typedef T stack_t; 00046 }; 00047 00048 /// Specialization of type traits for pointers. 00049 template <class T> 00050 struct type_traits<T*> 00051 { 00052 typedef T pointee_t; 00053 typedef T deref_t; 00054 }; 00055 00056 /// Specialization of type traits for references. 00057 template <class T> 00058 struct type_traits<T&> 00059 { 00060 typedef T stack_t; 00061 }; 00062 00063 /// Specialization of type traits for const references. 00064 template <class T> 00065 struct type_traits<const T&> 00066 { 00067 typedef T stack_t; 00068 }; 00069 00070 /// Select between two types based on a compile-time constant boolean expression. 00071 template <bool test, class if_true, class if_false> 00072 struct select_if 00073 { 00074 typedef if_true result_t; 00075 }; 00076 00077 /// Specialization of select_if for 'false'. 00078 template <class if_true, class if_false> 00079 struct select_if<false, if_true, if_false> 00080 { 00081 typedef if_false result_t; 00082 }; 00083 00084 namespace traits 00085 { 00086 /** dummy type */ struct yes_type { char x; }; 00087 /** dummy type */ struct no_type { yes_type x[2]; }; 00088 } 00089 00090 /// Helper class for is_sub_super. 00091 template <class T> 00092 struct type_match 00093 { 00094 static traits::yes_type foo(T* p); 00095 static traits::no_type foo(...); 00096 }; 00097 00098 /// Determine whether sub derives from super. 00099 template <class sub, class super> 00100 struct is_sub_super 00101 { 00102 enum { sz = sizeof(type_match<super>::foo(static_cast<sub*>(0))) }; 00103 00104 enum 00105 { 00106 result = ((sz == sizeof(traits::yes_type)) ? 1 : 0) 00107 }; 00108 }; 00109 00110 /// Remove const/volative qualifiers 00111 00112 // From boost/type_traits/is_class.hpp: 00113 template <class U> traits::yes_type is_class_tester(void(U::*)(void)); 00114 template <class U> traits::no_type is_class_tester(...); 00115 00116 /// Traits class to tell us whether T is a class type or not. 00117 template <typename T> 00118 struct is_class 00119 { 00120 enum 00121 { 00122 value = (sizeof(is_class_tester<T>(0)) 00123 == sizeof(traits::yes_type)) 00124 }; 00125 }; 00126 00127 /// Helper struct for telling whether T is a polymorphic type or not. 00128 /** The implementation trick here is that, if T is NOT polymorphic, 00129 then if we derive a new type from T that has virtual functions, 00130 then its sizeof() should increase to make room for the vtable 00131 pointer. On the other hand, if T is already polymorphic, then it 00132 already has a vtable ptr and so adding a new virtual function 00133 won't change sizeof() the derived type. */ 00134 template <class T> 00135 struct is_polymorphic_imp1 00136 { 00137 typedef T ncvT; 00138 00139 struct d1 : public ncvT 00140 { 00141 d1(); 00142 ~d1()throw(); 00143 char padding[256]; 00144 }; 00145 00146 struct d2 : public ncvT 00147 { 00148 d2(); 00149 virtual ~d2() throw(); 00150 00151 struct unique{}; 00152 virtual void unique_name_to_invt200507011541(unique*); 00153 00154 char padding[256]; 00155 }; 00156 00157 enum { value = (sizeof(d2) == sizeof(d1)) }; 00158 }; 00159 00160 template <class T> 00161 struct is_polymorphic_imp2 00162 { 00163 enum { value = false }; 00164 }; 00165 00166 template <bool is_class> 00167 struct is_polymorphic_selector 00168 { 00169 template <class T> 00170 struct rebind 00171 { 00172 typedef is_polymorphic_imp2<T> type; 00173 }; 00174 }; 00175 00176 template <> 00177 struct is_polymorphic_selector<true> 00178 { 00179 template <class T> 00180 struct rebind 00181 { 00182 typedef is_polymorphic_imp1<T> type; 00183 }; 00184 }; 00185 00186 /// Traits class to tell whether T is a polymorphic type (i.e. has virtual functions). 00187 template <class T> 00188 struct is_polymorphic 00189 { 00190 typedef is_polymorphic_selector<is_class<T>::value> selector; 00191 typedef typename selector::template rebind<T> binder; 00192 typedef typename binder::type imp_type; 00193 enum { value = imp_type::value }; 00194 }; 00195 00196 template <class T, bool polymorphic = is_polymorphic<T>::value > 00197 struct full_object_caster; 00198 00199 template <class T> 00200 struct full_object_caster<T, false> 00201 { 00202 static const void* cast(const T* p) { return static_cast<const void*>(p); } 00203 }; 00204 00205 template <class T> 00206 struct full_object_caster<T, true> 00207 { 00208 static const void* cast(const T* p) { return dynamic_cast<const void*>(p); } 00209 }; 00210 00211 /// Cast a pointer to the beginning of the full object. 00212 /** Here we select between static_cast and dynamic_cast depending on 00213 whether T is polymorphic. */ 00214 template <class T> 00215 inline const void* full_object_cast(const T* p) 00216 { 00217 return full_object_caster<T>::cast(p); 00218 } 00219 00220 } 00221 00222 static const char __attribute__((used)) vcid_groovx_rutz_traits_h_utc20050626084021[] = "$Id: traits.h 8249 2007-04-12 06:03:40Z rjpeters $ $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/rutz/traits.h $"; 00223 #endif // !GROOVX_RUTZ_TRAITS_H_UTC20050626084021_DEFINED