lean cpp library
A lean C++ library providing efficient utility classes for high-performance C++ applications.
strip.h
00001 /*****************************************************/
00002 /* lean Meta                    (c) Tobias Zirr 2011 */
00003 /*****************************************************/
00004 
00005 #ifndef LEAN_META_STRIP
00006 #define LEAN_META_STRIP
00007 
00008 #include "../cpp0x.h"
00009 
00010 namespace lean
00011 {
00012 namespace meta
00013 {
00014 
00016 template <class Type>
00017 struct strip_reference
00018 {
00020     typedef Type type;
00022     static const bool stripped = false;
00023 
00025     template <class Other>
00026     struct undo
00027     {
00029         typedef Other type;
00030     };
00031 };
00032 
00033 #ifndef DOXYGEN_SKIP_THIS
00034 
00035 template <class Type>
00036 struct strip_reference<Type&>
00037 {
00038     typedef Type type;
00039     static const bool stripped = true;
00040     template <class Other>
00041     struct undo { typedef Other& type; };
00042 };
00043 
00044 #ifndef LEAN0X_NO_RVALUE_REFERENCES
00045 template <class Type>
00046 struct strip_reference<Type&&>
00047 {
00048     typedef Type type;
00049     static const bool stripped = true;
00050     template <class Other>
00051     struct undo { typedef Other&& type; };
00052 };
00053 #endif
00054 
00055 #endif
00056 
00058 template <class Type>
00059 struct inh_strip_reference : public strip_reference<Type>::type { };
00060 
00062 template <class Type>
00063 struct strip_const
00064 {
00066     typedef Type type;
00068     static const bool stripped = false;
00069 
00071     template <class Other>
00072     struct undo
00073     {
00075         typedef Other type;
00076     };
00077 };
00078 
00079 #ifndef DOXYGEN_SKIP_THIS
00080 
00081 template <class Type>
00082 struct strip_const<const Type>
00083 {
00084     typedef Type type;
00085     static const bool stripped = true;
00086     template <class Other>
00087     struct undo { typedef const Other type; };
00088 };
00089 
00090 #endif
00091 
00093 template <class Type>
00094 struct strip_volatile
00095 {
00097     typedef Type type;
00099     static const bool stripped = false;
00100 
00102     template <class Other>
00103     struct undo
00104     {
00106         typedef Other type;
00107     };
00108 };
00109 
00110 #ifndef DOXYGEN_SKIP_THIS
00111 
00112 template <class Type>
00113 struct strip_volatile<volatile Type>
00114 {
00115     typedef Type type;
00116     static const bool stripped = true;
00117     template <class Other>
00118     struct undo { typedef volatile Other type; };
00119 };
00120 
00121 #endif
00122 
00124 template <class Type>
00125 struct strip_modifiers
00126 {
00128     typedef typename strip_volatile<typename strip_const<Type>::type>::type type;
00130     static const bool stripped = strip_volatile<Type>::stripped || strip_const<Type>::stripped;
00131 
00133     template <class Other>
00134     struct undo
00135     {
00137         typedef typename strip_const<Type>::template undo<typename strip_volatile<Type>::template undo<Other>::type>::type type;
00138     };
00139 };
00140 
00142 template <class Type>
00143 struct strip_modref
00144 {
00146     typedef typename strip_reference<Type>::type value_type;
00148     typedef typename strip_modifiers<value_type>::type type;
00150     static const bool stripped = strip_reference<Type>::stripped || strip_modifiers<value_type>::stripped;
00151 
00153     template <class Other>
00154     struct undo
00155     {
00157         typedef typename strip_reference<Type>::template undo<typename strip_modifiers<value_type>::template undo<Other>::type>::type type;
00158     };
00159 };
00160 
00162 template <class Type>
00163 struct inh_strip_modref : public strip_modref<Type>::type { };
00164 
00165 namespace impl
00166 {
00167 
00168 template <class Type>
00169 struct do_strip_pointer
00170 {
00171     typedef Type type;
00172     static const bool stripped = false;
00173     template <class Other>
00174     struct undo { typedef Other type; };
00175 };
00176 
00177 template <class Type>
00178 struct do_strip_pointer<Type*>
00179 {
00180     typedef Type type;
00181     static const bool stripped = true;
00182     template <class Other>
00183     struct undo { typedef Other* type; };
00184 };
00185 
00186 } // namespace
00187 
00189 template <class Type>
00190 struct strip_pointer
00191 {
00193     typedef typename strip_modifiers<Type>::type pointer;
00195     typedef typename impl::do_strip_pointer<pointer>::type type;
00197     static const bool stripped = impl::do_strip_pointer<pointer>::stripped;
00198 
00200     template <class Other>
00201     struct undo
00202     {
00204         typedef typename impl::do_strip_pointer<pointer>::template undo<Other>::type pointer;
00206         typedef typename strip_modifiers<Type>::template undo<pointer>::type type;
00207     };
00208 };
00209 
00211 template <class Type>
00212 struct inh_strip_pointer : public strip_pointer<Type>::type { };
00213 
00214 namespace impl
00215 {
00216 
00217 template <class Type>
00218 struct do_strip_array
00219 {
00220     typedef Type type;
00221     static const bool stripped = false;
00222     template <class Other>
00223     struct undo { typedef Other type; };
00224 };
00225 
00226 template <class Type>
00227 struct do_strip_array<Type[]>
00228 {
00229     typedef Type type;
00230     static const bool stripped = true;
00231     template <class Other>
00232     struct undo { typedef Other type[]; };
00233 };
00234 
00235 template <class Type, size_t Size>
00236 struct do_strip_array<Type[Size]>
00237 {
00238     typedef Type type;
00239     static const bool stripped = true;
00240     template <class Other>
00241     struct undo { typedef Other type[Size]; };
00242 };
00243 
00244 } // namespace
00245 
00247 template <class Type>
00248 struct strip_array
00249 {
00251     typedef typename strip_modifiers<Type>::type array;
00253     typedef typename impl::do_strip_array<array>::type type;
00255     static const bool stripped = impl::do_strip_array<array>::stripped;
00256 
00258     template <class Other>
00259     struct undo
00260     {
00262         typedef typename impl::do_strip_array<array>::template undo<Other>::type array;
00264         typedef typename strip_modifiers<Type>::template undo<array>::type type;
00265     };
00266 };
00267 
00269 template <class Type>
00270 struct inh_strip_array : public strip_array<Type>::type { };
00271 
00272 namespace impl
00273 {
00274 
00275 template <class Type, bool Continue = true>
00276 struct do_rec_strip_modifiers
00277 {
00278     typedef Type type;
00279     static const bool stripped = false;
00280 };
00281 
00282 template <class Type>
00283 struct do_rec_strip_modifiers<Type, true>
00284 {
00285     typedef strip_modref<Type> modref_stripper;
00286     typedef strip_array<typename modref_stripper::type> array_stripper;
00287     typedef strip_pointer<typename array_stripper::type> pointer_stripper;
00288     static const bool continue_stripping = array_stripper::stripped || pointer_stripper::stripped;
00289 
00290     static const bool stripped = modref_stripper::stripped
00291         || do_rec_strip_modifiers<typename pointer_stripper::type, continue_stripping>::stripped;
00292 
00293     typedef typename array_stripper::template undo<
00294                 typename pointer_stripper::template undo<
00295                     typename do_rec_strip_modifiers<typename pointer_stripper::type, continue_stripping>::type
00296                 >::type
00297             >::type type;
00298 };
00299 
00300 } // namespace
00301 
00303 template <class Type>
00304 struct rec_strip_modifiers
00305 {
00307     typedef typename impl::do_rec_strip_modifiers<Type>::type type;
00309     static const bool stripped = impl::do_rec_strip_modifiers<Type>::stripped;
00310 };
00311 
00313 template <class Type>
00314 struct identity
00315 {
00317     typedef Type type;
00318 };
00319 
00320 } // namespace
00321 
00322 using meta::strip_array;
00323 using meta::strip_pointer;
00324 using meta::strip_reference;
00325 using meta::strip_const;
00326 using meta::strip_volatile;
00327 using meta::strip_modifiers;
00328 using meta::strip_modref;
00329 using meta::rec_strip_modifiers;
00330 using meta::identity;
00331 
00332 using meta::inh_strip_pointer;
00333 using meta::inh_strip_array;
00334 using meta::inh_strip_reference;
00335 using meta::inh_strip_modref;
00336 
00337 } // namespace
00338 
00339 #endif