bbtkAny.h
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00036 #ifndef __BBTKANY_H_INCLUDED__
00037 #define __BBTKANY_H_INCLUDED__
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 #include <sstream>
00051 #include "bbtkRTTI.h"
00052 #include "bbtkMessageManager.h"
00053 #include "bbtkException.h"
00054
00055 #include <boost/type_traits/is_pointer.hpp>
00056
00057 namespace bbtk
00058 {
00059
00060
00061
00062
00063
00064
00066 class anyplaceholder
00067 {
00068 public:
00069
00070 virtual ~anyplaceholder() {}
00071
00072 public:
00073
00075 virtual const std::type_info & type() const = 0;
00077 virtual const std::type_info & pointed_type() const = 0;
00078
00080 virtual bool is_pointer() const = 0;
00081
00084 virtual void* get_pointer() const = 0;
00085
00087 virtual void* get_pointer_to( const std::type_info& ) const = 0;
00088
00089 virtual anyplaceholder * clone() const = 0;
00090
00091 };
00092
00093
00094
00097 template<typename ValueType>
00098 class anyholder : public anyplaceholder
00099 {
00100 public:
00101
00102 anyholder(const ValueType & value)
00103 : held(value)
00104 {}
00105
00106 public:
00107
00108 virtual const std::type_info & type() const { return typeid(ValueType);}
00109 virtual bool is_pointer() const { return false; }
00110 virtual const std::type_info & pointed_type() const { return typeid(void); }
00111 virtual void* get_pointer() const { return 0; }
00112 virtual void* get_pointer_to( const std::type_info& ) const { return 0; }
00113 virtual anyplaceholder * clone() const { return new anyholder(held); }
00114
00115 public:
00116
00117 ValueType held;
00118
00119 };
00120
00121
00122
00124 template<typename ValueType>
00125 class anyholder<ValueType*> : public anyplaceholder
00126 {
00127 public:
00128
00129 anyholder(ValueType* const & value)
00130 : held(value)
00131 { }
00132
00133 public:
00134
00135 virtual const std::type_info & type() const
00136 {
00137 return typeid(ValueType*);
00138 }
00139
00140 virtual bool is_pointer() const { return true; }
00141 virtual const std::type_info & pointed_type() const { return typeid(ValueType); }
00142 virtual void* get_pointer() const {
00143 return (void*)held;
00144 }
00145 virtual void* get_pointer_to( const std::type_info& t) const
00146 {
00147 return run_time_up_or_down_cast(t,typeid(ValueType),held);
00148 }
00149
00150 virtual anyplaceholder * clone() const { return new anyholder(held); }
00151
00152 public:
00153
00154 ValueType* held;
00155
00156 };
00157
00158
00159
00183 template <template <class> class TypeTraits >
00184 class any
00185 {
00186 public:
00187 typedef any< TypeTraits > self;
00188
00189
00191 any()
00192 : content(0)
00193 {
00194 }
00195
00197 template<typename ValueType>
00198 any(const ValueType & value)
00199 : content(0)
00200 {
00201 bbtkDebugMessage("Data",1,
00202 bbtk::HumanTypeName<self>()<<" construction with <"
00203 <<bbtk::HumanTypeName<ValueType>()<<">"<<std::endl);
00204
00205
00206
00207
00208 if (accepts<ValueType>())
00209 {
00210 content = new anyholder<ValueType>(value);
00211 }
00212 else
00213 {
00214 bbtkError(bbtk::HumanTypeName<self>()
00215 <<" constructor : data of type <"
00216 <<bbtk::HumanTypeName<ValueType>()
00217 <<"> are not accepted by traits <"
00218 <<bbtk::HumanTypeName<TypeTraits<void> >()<<"> ");
00219 }
00220 }
00221
00223 any(const any & other)
00224 : content(other.content ? other.content->clone() : 0)
00225 {
00226 bbtkDebugMessage("Data",1,
00227 HumanTypeName<self>()
00228 <<" copy construction with new content : "
00229 <<HumanTypeName(type())
00230 <<std::endl);
00231 }
00232
00234 ~any()
00235 {
00236 delete content;
00237 }
00238
00239
00241 any & swap(any & rhs)
00242 {
00243 std::swap(content, rhs.content);
00244 return *this;
00245 }
00246
00248 template<typename ValueType>
00249 any & operator=(const ValueType & rhs)
00250 {
00251 bbtkDebugMessage("Data",1,
00252 HumanTypeName<self>()
00253 <<" operator= with data of type <"
00254 <<HumanTypeName<ValueType>()
00255 <<">"<<std::endl);
00256 if (accepts<ValueType>())
00257 {
00258 any(rhs).swap(*this);
00259 return *this;
00260 }
00261 else
00262 {
00263 bbtkError(HumanTypeName<self>()
00264 <<" operator= : data of type <"
00265 <<HumanTypeName<ValueType>()
00266 <<"> are not accepted by traits <"
00267 <<HumanTypeName<TypeTraits<void> >()<<"> ");
00268 }
00269
00270 }
00271
00273 any & operator=(const any & rhs)
00274 {
00275 bbtkDebugMessage("Data",1,
00276 HumanTypeName<self >()
00277 <<" operator=(const any&) with content : "
00278 <<HumanTypeName(rhs.type())<<std::endl);
00279
00280 any(rhs).swap(*this);
00281 return *this;
00282 }
00283
00284
00286 bool empty() const
00287 {
00288 return !content;
00289 }
00290
00292 const std::type_info & type() const
00293 {
00294 return content ? content->type() : typeid(void);
00295 }
00296
00298 const std::type_info & pointed_type() const
00299 {
00300 return content ? content->pointed_type() : typeid(void);
00301 }
00302
00303
00305 template<typename Type>
00306 inline bool contains()
00307 {
00308 return ( type() == typeid(Type) );
00309 }
00310
00312 inline bool contains_pointer()
00313 {
00314 return content ? content->is_pointer() : false;
00315 }
00316
00318 inline bool contains(TypeInfo t)
00319 {
00320 return ( (bool)((type() == t)!=0) );
00321 }
00322
00324 template<typename Type>
00325 inline bool accepts()
00326 {
00327 return TypeTraits<Type>::value;
00328 }
00329
00332 template<typename ValueType>
00333 inline const ValueType& get() const
00334 {
00335 bbtkDebugMessage("Data",1,
00336 HumanTypeName<self >()
00337 <<" get<"<<HumanTypeName<ValueType>()
00338 <<"> with content : "
00339 <<HumanTypeName(type())<<std::endl);
00340
00341 if ( type() == typeid(ValueType) )
00342 return static_cast< anyholder<ValueType> *>(content)->held;
00343
00344 bbtkError(HumanTypeName<self >()
00345 <<" get with type <"
00346 <<bbtk::HumanTypeName<ValueType>()
00347 <<"> does not match content type <"
00348 <<bbtk::HumanTypeName<>(type())<<">");
00349 }
00350
00351 template<typename ValueType>
00352 inline const ValueType* getP() const
00353 {
00354 if ( type() == typeid(ValueType) )
00355 return &static_cast< anyholder<ValueType> *>(content)->held;
00356
00357 bbtkError(HumanTypeName<self >()
00358 <<" getP with type <"
00359 <<bbtk::HumanTypeName<ValueType>()
00360 <<"> does not match content type <"
00361 <<bbtk::HumanTypeName<>(type())<<">");
00362 }
00363
00368 template<typename ValueType>
00369 inline const ValueType& unsafe_get() const
00370 {
00371 bbtkDebugMessage("Data",1,
00372 HumanTypeName<self>()
00373 <<"::unsafe_get<"
00374 <<HumanTypeName<ValueType>()<<"> with content : "
00375 <<HumanTypeName(this->type())
00376 <<std::endl);
00377
00378
00379
00380
00381
00382 if (content)
00383 return static_cast< anyholder<ValueType> * >(content)->held;
00384
00385 bbtkError(HumanTypeName<self >()
00386 <<"::usafe_get<"
00387 <<bbtk::HumanTypeName<ValueType>()
00388 <<"> : void content");
00389 }
00390
00391
00392 inline void* get_pointer() const
00393 {
00394 void* p = content->get_pointer();
00395 bbtkDebugMessage("Data",1,
00396 HumanTypeName<self>()
00397 <<"::get_pointer() with content <"
00398 <<HumanTypeName(this->type())
00399 <<"> : result = "
00400 << p
00401 <<std::endl);
00402 return p;
00403 }
00404
00405 inline void* get_pointer_to(const std::type_info& t) const
00406 {
00407 void* p = content->get_pointer_to(t);
00408 bbtkDebugMessage("Data",1,
00409 HumanTypeName<self>()
00410 <<"::get_pointer_to("<<HumanTypeName(t)
00411 <<") with content <"
00412 <<HumanTypeName(this->type())
00413 <<"> : result = "
00414 << p
00415 <<std::endl);
00416 return p;
00417 }
00418
00419 private:
00421 anyplaceholder * content;
00422
00423 };
00424
00425
00426
00428 template <typename T> struct thing { static const bool value = true; };
00429
00430 BBTK_DEFINE_HUMAN_READABLE_TYPE_NAME(bbtk::any<bbtk::thing>,"anything");
00431
00432
00434 template <typename T> struct integer { static const bool value; };
00435 template <class T> const bool integer<T>::value = false;
00436
00438 template <typename T> struct floating_point { static const bool value; };
00439 template <class T> const bool floating_point<T>::value = false;
00440
00441
00443 template <typename T> struct number { static const bool value; };
00444 template <class T> const bool number<T>::value =
00445 integer<T>::value || floating_point<T>::value ;
00446
00447
00452 #define BBTK_DECLARE_TYPE_TRAITS(NAME) \
00453 template <typename T> struct NAME { static const bool value; }; \
00454 template <class T> const bool NAME<T>::value = false;
00455
00456 #define BBTK_ADD_TO_TYPE_TRAITS(NAME,TYPE) \
00457 template <> bool NAME<TYPE>::value = true;
00458
00459
00460 }
00461
00462
00463
00464
00465
00466 #endif
00467