00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef LIB_META_TRAIT_H
00025 #define LIB_META_TRAIT_H
00026
00027
00028 #include "lib/meta/util.hpp"
00029 #include "lib/meta/duck-detector.hpp"
00030 #include "lib/wrapper.hpp"
00031
00032 #include <boost/type_traits/is_convertible.hpp>
00033 #include <boost/type_traits/is_arithmetic.hpp>
00034 #include <boost/type_traits/remove_reference.hpp>
00035 #include <boost/type_traits/remove_pointer.hpp>
00036 #include <boost/type_traits/remove_cv.hpp>
00037 #include <boost/utility/enable_if.hpp>
00038 #include <string>
00039
00040
00041 namespace boost{
00042 template<class X> class reference_wrapper;
00043 }
00044 namespace std {
00045 namespace tr1 {
00046 template<class X> class reference_wrapper;
00047 template<class X> class shared_ptr;
00048 }}
00049 namespace lumiera{
00050 template<class X, class B> class P;
00051 }
00052 namespace mobject{
00053 template<class X, class B> class Placement;
00054 }
00055
00056
00057 namespace lib {
00058 namespace meta {
00059
00060
00061
00068 template<typename X>
00069 struct Unwrap
00070 {
00071 typedef X Type;
00072
00073 static X&
00074 extract (X const& x)
00075 {
00076 return const_cast<X&> (x);
00077 }
00078 };
00079
00080 template<typename X>
00081 struct Unwrap<X*>
00082 {
00083 typedef typename boost::remove_cv<X>::type Type;
00084
00085 static Type&
00086 extract (const X* ptr)
00087 {
00088 ASSERT (ptr);
00089 return const_cast<Type&> (*ptr);
00090 }
00091 };
00092
00093 template<typename X>
00094 struct Unwrap<boost::reference_wrapper<X> >
00095 {
00096 typedef X Type;
00097
00098 static X&
00099 extract (boost::reference_wrapper<X> wrapped)
00100 {
00101 return wrapped;
00102 }
00103 };
00104
00105 template<typename X>
00106 struct Unwrap<std::tr1::reference_wrapper<X> >
00107 {
00108 typedef X Type;
00109
00110 static X&
00111 extract (std::tr1::reference_wrapper<X> wrapped)
00112 {
00113 return wrapped;
00114 }
00115 };
00116
00117 template<typename X>
00118 struct Unwrap<std::tr1::shared_ptr<X> >
00119 {
00120 typedef X Type;
00121
00122 static X&
00123 extract (std::tr1::shared_ptr<X> ptr)
00124 {
00125 ASSERT (ptr);
00126 return *ptr;
00127 }
00128 };
00129
00130 template<typename X, class B>
00131 struct Unwrap<lumiera::P<X, B> >
00132 {
00133 typedef X Type;
00134
00135 static X&
00136 extract (lumiera::P<X,B> ptr)
00137 {
00138 ASSERT (ptr);
00139 return *ptr;
00140 }
00141 };
00142
00143 template<typename X, class B>
00144 struct Unwrap<mobject::Placement<X, B> >
00145 {
00146 typedef X Type;
00147
00148 static X&
00149 extract (mobject::Placement<X,B> placement)
00150 {
00151 ASSERT (placement.isValid());
00152 return *placement;
00153 }
00154 };
00155
00156
00164 template<typename X>
00165 typename Unwrap<X>::Type&
00166 unwrap (X const& wrapped)
00167 {
00168 return Unwrap<X>::extract(wrapped);
00169 }
00170
00171
00172
00173
00175 template<typename X>
00176 struct Strip
00177 {
00178 typedef typename boost::remove_cv<X> ::type TypeUnconst;
00179 typedef typename boost::remove_reference<TypeUnconst>::type TypeReferred;
00180 typedef typename boost::remove_pointer<TypeReferred> ::type TypePointee;
00181 typedef typename boost::remove_cv<TypePointee> ::type TypePlain;
00182
00183 typedef typename Unwrap<TypePlain> ::Type Type;
00184 };
00185
00186
00187
00188
00193 template<typename TY>
00194 struct RefTraits
00195 {
00196 typedef TY* pointer;
00197 typedef TY& reference;
00198 typedef TY value_type;
00199 typedef value_type member_type;
00200 };
00201
00202 template<typename TY>
00203 struct RefTraits<TY *>
00204 {
00205 typedef TY* pointer;
00206 typedef TY& reference;
00207 typedef TY value_type;
00208 typedef pointer member_type;
00209 };
00210
00211 template<typename TY>
00212 struct RefTraits<TY &>
00213 {
00214 typedef TY* pointer;
00215 typedef TY& reference;
00216 typedef TY value_type;
00217 typedef lib::wrapper::AssignableRefWrapper<TY> member_type;
00218 };
00220
00221
00222
00223
00224
00225
00226
00227
00228
00233 template <typename TY>
00234 struct can_ToString
00235 {
00236 enum { value = boost::is_convertible<TY, std::string>::value
00237 };
00238 };
00239
00240
00252 template<typename X>
00253 struct can_lexical2string
00254 {
00255 enum { value = boost::is_arithmetic<X>::value
00256 };
00257 };
00258
00259
00260
00261
00265 template<typename T>
00266 class can_STL_ForEach
00267 {
00268 typedef typename Strip<T>::Type Type;
00269
00270 struct is_iterable
00271 {
00272 META_DETECT_NESTED(iterator);
00273 META_DETECT_FUNCTION(typename X::iterator, begin,(void));
00274 META_DETECT_FUNCTION(typename X::iterator, end ,(void));
00275
00276 enum { value = HasNested_iterator<Type>::value
00277 && HasFunSig_begin<Type>::value
00278 && HasFunSig_end<Type>::value
00279 };
00280 };
00281
00282 struct is_const_iterable
00283 {
00284 META_DETECT_NESTED(const_iterator);
00285 META_DETECT_FUNCTION(typename X::const_iterator, begin,(void) const);
00286 META_DETECT_FUNCTION(typename X::const_iterator, end ,(void) const);
00287
00288 enum { value = HasNested_const_iterator<Type>::value
00289 && HasFunSig_begin<Type>::value
00290 && HasFunSig_end<Type>::value
00291 };
00292 };
00293
00294
00295 public:
00296 enum { value = is_iterable::value
00297 || is_const_iterable::value
00298 };
00299 };
00300
00301
00308 template<typename T>
00309 class can_IterForEach
00310 {
00311 typedef typename Strip<T>::Type Type;
00312
00313 META_DETECT_NESTED(value_type);
00314 META_DETECT_OPERATOR_DEREF();
00315 META_DETECT_OPERATOR_INC();
00316
00317 public:
00318 enum{ value = boost::is_convertible<Type, bool>::value
00319 && HasNested_value_type<Type>::value
00320 && HasOperator_deref<Type>::value
00321 && HasOperator_inc<Type>::value
00322 };
00323 };
00324
00325
00326 }}
00327 #endif