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
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00058 #ifndef __BBTKANY_H_INCLUDED__
00059 #define __BBTKANY_H_INCLUDED__
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 #include <sstream>
00073 #include "bbtkRTTI.h"
00074 #include "bbtkMessageManager.h"
00075 #include "bbtkException.h"
00076
00077 #include <boost/type_traits/is_pointer.hpp>
00078
00079 namespace bbtk
00080 {
00081
00082
00083
00084
00085
00086
00088 class anyplaceholder
00089 {
00090 public:
00091
00092 virtual ~anyplaceholder() {}
00093
00094 public:
00095
00097 virtual const std::type_info & type() const = 0;
00099 virtual const std::type_info & pointed_type() const = 0;
00100
00102 virtual bool is_pointer() const = 0;
00103
00106 virtual void* get_pointer() const = 0;
00107
00109 virtual void* get_pointer_to( const std::type_info& ) const = 0;
00110
00111 virtual anyplaceholder * clone() const = 0;
00112
00113 };
00114
00115
00116
00119 template<typename ValueType>
00120 class anyholder : public anyplaceholder
00121 {
00122 public:
00123
00124 anyholder(const ValueType & value)
00125 : held(value)
00126 {}
00127
00128 public:
00129
00130 virtual const std::type_info & type() const { return typeid(ValueType);}
00131 virtual bool is_pointer() const { return false; }
00132 virtual const std::type_info & pointed_type() const { return typeid(void); }
00133 virtual void* get_pointer() const { return 0; }
00134 virtual void* get_pointer_to( const std::type_info& ) const { return 0; }
00135 virtual anyplaceholder * clone() const { return new anyholder(held); }
00136
00137 public:
00138
00139 ValueType held;
00140
00141 };
00142
00143
00144
00146 template<typename ValueType>
00147 class anyholder<ValueType*> : public anyplaceholder
00148 {
00149 public:
00150
00151 anyholder(ValueType* const & value)
00152 : held(value)
00153 { }
00154
00155 public:
00156
00157 virtual const std::type_info & type() const
00158 {
00159 return typeid(ValueType*);
00160 }
00161
00162 virtual bool is_pointer() const { return true; }
00163 virtual const std::type_info & pointed_type() const { return typeid(ValueType); }
00164 virtual void* get_pointer() const {
00165 return (void*)held;
00166 }
00167 virtual void* get_pointer_to( const std::type_info& t) const
00168 {
00169 return run_time_up_or_down_cast(t,typeid(ValueType),held);
00170 }
00171
00172 virtual anyplaceholder * clone() const { return new anyholder(held); }
00173
00174 public:
00175
00176 ValueType* held;
00177
00178 };
00179
00180
00181
00205 template <template <class> class TypeTraits >
00206 class any
00207 {
00208 public:
00209 typedef any< TypeTraits > self;
00210
00211
00213 any()
00214 : content(0)
00215 {
00216 }
00217
00219 template<typename ValueType>
00220 any(const ValueType & value)
00221 : content(0)
00222 {
00223 bbtkDebugMessage("Data",1,
00224 bbtk::HumanTypeName<self>()<<" construction with <"
00225 <<bbtk::HumanTypeName<ValueType>()<<">"<<std::endl);
00226
00227
00228
00229
00230 if (accepts<ValueType>())
00231 {
00232 content = new anyholder<ValueType>(value);
00233 }
00234 else
00235 {
00236 bbtkError(bbtk::HumanTypeName<self>()
00237 <<" constructor : data of type <"
00238 <<bbtk::HumanTypeName<ValueType>()
00239 <<"> are not accepted by traits <"
00240 <<bbtk::HumanTypeName<TypeTraits<void> >()<<"> ");
00241 }
00242 }
00243
00245 any(const any & other)
00246 : content(other.content ? other.content->clone() : 0)
00247 {
00248 bbtkDebugMessage("Data",1,
00249 HumanTypeName<self>()
00250 <<" copy construction with new content : "
00251 <<HumanTypeName(type())
00252 <<std::endl);
00253 }
00254
00256 ~any()
00257 {
00258 delete content;
00259 }
00260
00261
00263 any & swap(any & rhs)
00264 {
00265 std::swap(content, rhs.content);
00266 return *this;
00267 }
00268
00270 template<typename ValueType>
00271 any & operator=(const ValueType & rhs)
00272 {
00273 bbtkDebugMessage("Data",1,
00274 HumanTypeName<self>()
00275 <<" operator= with data of type <"
00276 <<HumanTypeName<ValueType>()
00277 <<">"<<std::endl);
00278 if (accepts<ValueType>())
00279 {
00280 any(rhs).swap(*this);
00281 return *this;
00282 }
00283 else
00284 {
00285 bbtkError(HumanTypeName<self>()
00286 <<" operator= : data of type <"
00287 <<HumanTypeName<ValueType>()
00288 <<"> are not accepted by traits <"
00289 <<HumanTypeName<TypeTraits<void> >()<<"> ");
00290 }
00291
00292 }
00293
00295 any & operator=(const any & rhs)
00296 {
00297 bbtkDebugMessage("Data",1,
00298 HumanTypeName<self >()
00299 <<" operator=(const any&) with content : "
00300 <<HumanTypeName(rhs.type())<<std::endl);
00301
00302 any(rhs).swap(*this);
00303 return *this;
00304 }
00305
00306
00308 bool empty() const
00309 {
00310 return !content;
00311 }
00312
00314 const std::type_info & type() const
00315 {
00316 return content ? content->type() : typeid(void);
00317 }
00318
00320 const std::type_info & pointed_type() const
00321 {
00322 return content ? content->pointed_type() : typeid(void);
00323 }
00324
00325
00327 template<typename Type>
00328 inline bool contains()
00329 {
00330 return ( type() == typeid(Type) );
00331 }
00332
00334 inline bool contains_pointer()
00335 {
00336 return content->is_pointer() ;
00337 }
00338
00340 inline bool contains(TypeInfo t)
00341 {
00342 return ( (bool)(type() == t) );
00343 }
00344
00346 template<typename Type>
00347 inline bool accepts()
00348 {
00349 return TypeTraits<Type>::value;
00350 }
00351
00354 template<typename ValueType>
00355 inline const ValueType& get() const
00356 {
00357 bbtkDebugMessage("Data",1,
00358 HumanTypeName<self >()
00359 <<" get<"<<HumanTypeName<ValueType>()
00360 <<"> with content : "
00361 <<HumanTypeName(type())<<std::endl);
00362
00363 if ( type() == typeid(ValueType) )
00364 return static_cast< anyholder<ValueType> *>(content)->held;
00365
00366 bbtkError(HumanTypeName<self >()
00367 <<" get with type <"
00368 <<bbtk::HumanTypeName<ValueType>()
00369 <<"> does not match content type <"
00370 <<bbtk::HumanTypeName<>(type())<<">");
00371 }
00372
00373 template<typename ValueType>
00374 inline const ValueType* getP() const
00375 {
00376 if ( type() == typeid(ValueType) )
00377 return &static_cast< anyholder<ValueType> *>(content)->held;
00378
00379 bbtkError(HumanTypeName<self >()
00380 <<" getP with type <"
00381 <<bbtk::HumanTypeName<ValueType>()
00382 <<"> does not match content type <"
00383 <<bbtk::HumanTypeName<>(type())<<">");
00384 }
00385
00390 template<typename ValueType>
00391 inline const ValueType& unsafe_get() const
00392 {
00393 bbtkDebugMessage("Data",1,
00394 HumanTypeName<self>()
00395 <<"::unsafe_get<"
00396 <<HumanTypeName<ValueType>()<<"> with content : "
00397 <<HumanTypeName(this->type())
00398 <<std::endl);
00399
00400
00401
00402
00403
00404 if (content)
00405 return static_cast< anyholder<ValueType> * >(content)->held;
00406
00407 bbtkError(HumanTypeName<self >()
00408 <<"::usafe_get<"
00409 <<bbtk::HumanTypeName<ValueType>()
00410 <<"> : void content");
00411 }
00412
00413
00414 inline void* get_pointer() const
00415 {
00416 void* p = content->get_pointer();
00417 bbtkDebugMessage("Data",1,
00418 HumanTypeName<self>()
00419 <<"::get_pointer() with content <"
00420 <<HumanTypeName(this->type())
00421 <<"> : result = "
00422 << p
00423 <<std::endl);
00424 return p;
00425 }
00426
00427 inline void* get_pointer_to(const std::type_info& t) const
00428 {
00429 void* p = content->get_pointer_to(t);
00430 bbtkDebugMessage("Data",1,
00431 HumanTypeName<self>()
00432 <<"::get_pointer_to("<<HumanTypeName(t)
00433 <<") with content <"
00434 <<HumanTypeName(this->type())
00435 <<"> : result = "
00436 << p
00437 <<std::endl);
00438 return p;
00439 }
00440
00441 private:
00443 anyplaceholder * content;
00444
00445 };
00446
00447
00448
00450 template <typename T> struct thing { static const bool value = true; };
00451
00452 BBTK_DEFINE_HUMAN_READABLE_TYPE_NAME(bbtk::any<bbtk::thing>,"anything");
00453
00454
00456 template <typename T> struct integer { static const bool value; };
00457 template <class T> const bool integer<T>::value = false;
00458
00460 template <typename T> struct floating_point { static const bool value; };
00461 template <class T> const bool floating_point<T>::value = false;
00462
00463
00465 template <typename T> struct number { static const bool value; };
00466 template <class T> const bool number<T>::value =
00467 integer<T>::value || floating_point<T>::value ;
00468
00469
00474 #define BBTK_DECLARE_TYPE_TRAITS(NAME) \
00475 template <typename T> struct NAME { static const bool value; }; \
00476 template <class T> const bool NAME<T>::value = false;
00477
00478 #define BBTK_ADD_TO_TYPE_TRAITS(NAME,TYPE) \
00479 template <> bool NAME<TYPE>::value = true;
00480
00481
00482 }
00483
00484
00485
00486
00487
00488 #endif
00489