00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifndef ADOBE_POLY_HPP
00010 #define ADOBE_POLY_HPP
00011
00012 #include <adobe/config.hpp>
00013
00014
00015 #include <boost/type_traits/is_base_of.hpp>
00016 #include <boost/type_traits/remove_reference.hpp>
00017 #include <boost/type_traits/remove_pointer.hpp>
00018 #include <boost/utility/enable_if.hpp>
00019 #include <boost/mpl/or.hpp>
00020 #include <boost/mpl/if.hpp>
00021 #include <boost/mpl/bool.hpp>
00022 #include <boost/type_traits/has_nothrow_constructor.hpp>
00023
00024 #include <adobe/move.hpp>
00025 #include <adobe/implementation/swap.hpp>
00026 #include <adobe/typeinfo.hpp>
00027
00028
00029
00030 namespace adobe {
00031
00032
00048 #if !defined(ADOBE_NO_DOCUMENTATION)
00049
00050 template <typename T, typename U>
00051 struct is_base_derived_or_same : boost::mpl::or_<boost::is_base_of<T, U>,
00052 boost::is_base_of<U, T>,
00053 boost::is_same<T, U> > {};
00054 #endif
00055
00056
00057
00058
00066 struct poly_copyable_interface {
00067 virtual poly_copyable_interface* clone(void*) const = 0;
00068 virtual poly_copyable_interface* move_clone(void*) = 0;
00069 virtual void* cast() = 0;
00070 virtual const void* cast() const = 0;
00071 virtual const std::type_info& type_info() const = 0;
00072
00073
00074 virtual void assign(const poly_copyable_interface& x) = 0;
00075
00076
00077 virtual void exchange(poly_copyable_interface& x) = 0;
00078
00079 virtual ~poly_copyable_interface() {}
00080 };
00081
00082
00083
00084 #if !defined(ADOBE_NO_DOCUMENTATION)
00085
00086
00087
00088 namespace implementation {
00089
00090
00091
00092 template <typename ConcreteType, typename Interface>
00093 struct poly_state_remote : Interface
00094 {
00095 typedef ConcreteType value_type;
00096 typedef Interface interface_type;
00097
00098 const value_type& get() const { return *value_ptr_m; }
00099 value_type& get() { return *value_ptr_m; }
00100
00101 poly_state_remote(move_from<poly_state_remote> x)
00102 : value_ptr_m(x.source.value_ptr_m){ x.source.value_ptr_m = NULL; }
00103
00104 template <typename U>
00105 explicit poly_state_remote(const U& x, typename copy_sink<U, value_type>::type = 0)
00106 : value_ptr_m(::new value_type(x)) { }
00107
00108 template <typename U>
00109 explicit poly_state_remote(U x, typename move_sink<U, value_type>::type = 0)
00110 : value_ptr_m(::new value_type(move(x))) { }
00111
00112 ~poly_state_remote()
00113 { delete value_ptr_m; }
00114
00115
00116 void assign(const poly_copyable_interface& x)
00117 { *value_ptr_m = *static_cast<const poly_state_remote&>(x).value_ptr_m; }
00118
00119 const std::type_info& type_info() const
00120 { return typeid(value_type); }
00121 const void* cast() const { return value_ptr_m; }
00122 void* cast() { return value_ptr_m; }
00123
00124
00125 void exchange(poly_copyable_interface& x)
00126 { return std::swap(value_ptr_m, static_cast<poly_state_remote&>(x).value_ptr_m); }
00127
00128
00129 friend bool operator==(const poly_state_remote& x, const poly_state_remote& y)
00130 { return *x.value_ptr_m == *y.value_ptr_m; }
00131
00132 value_type* value_ptr_m;
00133 };
00134
00135
00136
00137 template <typename ConcreteType, typename Interface>
00138 struct poly_state_local : Interface
00139 {
00140 typedef ConcreteType value_type;
00141 typedef Interface interface_type;
00142
00143 const value_type& get() const { return value_m; }
00144 value_type& get() { return value_m; }
00145
00146 poly_state_local(move_from<poly_state_local> x)
00147 : value_m(move(x.source.value_m)){ }
00148
00149 template <typename U>
00150 explicit poly_state_local(const U& x, typename copy_sink<U, value_type>::type = 0)
00151 : value_m(x) { }
00152
00153 template <typename U>
00154 explicit poly_state_local(U x, typename move_sink<U, value_type>::type = 0)
00155 : value_m(move(x)) { }
00156
00157
00158 void assign(const poly_copyable_interface& x)
00159 { value_m = static_cast<const poly_state_local&>(x).value_m; }
00160
00161 const std::type_info& type_info() const
00162 { return typeid(value_type); }
00163 const void* cast() const { return &value_m; }
00164 void* cast() { return &value_m; }
00165
00166
00167 void exchange(poly_copyable_interface& x)
00168 { return std::swap(value_m, static_cast<poly_state_local&>(x).value_m); }
00169
00170
00171 friend bool operator==(const poly_state_local& x, const poly_state_local& y)
00172 { return x.value_m == y.value_m; }
00173
00174 value_type value_m;
00175 };
00176
00177
00178
00179
00180 typedef double storage_t[2];
00181
00182 template<typename T, int N=sizeof(storage_t)>
00183 struct is_small
00184 {
00185 enum { value = sizeof(T) <= N && (boost::has_nothrow_constructor<typename T::value_type>::value ||
00186 boost::is_same<std::string, typename T::value_type>::value) };
00187
00188 };
00189
00190
00191
00192 template <typename F>
00193 struct poly_instance : F {
00194 typedef typename F::value_type value_type;
00195 typedef typename F::interface_type interface_type;
00196
00197 poly_instance(const value_type& x): F(x){ }
00198 poly_instance(move_from<poly_instance> x) : F(move_from<F>(x.source)) { }
00199
00200 poly_copyable_interface* clone(void* storage) const
00201 { return ::new (storage) poly_instance(this->get()); }
00202
00203 poly_copyable_interface* move_clone(void* storage)
00204 { return ::new (storage) poly_instance(move_from<poly_instance>(*this)); }
00205 };
00206
00207
00208
00209 template <typename T>
00210 class has_equals {
00211 typedef bool (T::*E)(const T&) const;
00212 typedef char (&no_type)[1];
00213 typedef char (&yes_type)[2];
00214 template <E e> struct sfinae { typedef yes_type type; };
00215 template <class U>
00216 static typename sfinae<&U::equals>::type test(int);
00217 template <class U>
00218 static no_type test(...);
00219 public:
00220 enum {value = sizeof(test<T>(1)) == sizeof(yes_type)};
00221 };
00222
00223
00224
00225 }
00226
00227
00228
00229 #endif
00230
00231
00232
00233
00241 template <typename ConcreteType, typename Interface>
00242 struct optimized_storage_type :
00243 boost::mpl::if_<implementation::is_small<implementation::poly_state_local<ConcreteType, Interface> >,
00244 implementation::poly_state_local<ConcreteType, Interface>,
00245 implementation::poly_state_remote<ConcreteType, Interface> > {
00246 };
00247
00248
00249
00250
00262 template <typename I, template <typename> class Instance>
00263 struct poly_base {
00264
00265 template <typename T, template <typename> class U>
00266 friend struct poly_base;
00267
00268 typedef I interface_type;
00269
00270
00271 template <typename T>
00272 explicit poly_base(const T& x,
00273 typename copy_sink<T>::type = 0,
00274 typename boost::disable_if<boost::is_base_of<poly_base, T> >::type* = 0)
00275 { ::new (storage()) implementation::poly_instance<Instance<T> >(x); }
00276
00277 template <typename T>
00278 explicit poly_base(T x,
00279 typename move_sink<T>::type = 0,
00280 typename boost::disable_if<boost::is_base_of<poly_base, T> >::type* = 0)
00281 { ::new (storage()) implementation::poly_instance<Instance<T> >(move(x)); }
00282
00283
00284
00285
00286
00287 template <typename J, template <typename> class K>
00288 explicit poly_base(const poly_base<J, K>& x ,
00289 typename boost::enable_if<is_base_derived_or_same<I, J> >::type* dummy = 0)
00290 {
00291 if(boost::is_base_of<J, I>::value)
00292 dynamic_cast<const I&>(static_cast<const poly_copyable_interface&>(x.interface_ref()));
00293 x.interface_ref().clone(storage());
00294 }
00295
00296 poly_base(const poly_base& x) { x.interface_ref().clone(storage()); }
00297
00298 poly_base(move_from<poly_base> x) { x.source.interface_ref().move_clone(storage()); }
00299
00300 friend inline void swap(poly_base& x, poly_base& y)
00301 {
00302 interface_type& a(x.interface_ref());
00303 interface_type& b(y.interface_ref());
00304
00305 if (a.type_info() == b.type_info()) { a.exchange(b); return; }
00306
00307
00308 poly_base tmp(move(x));
00309 a.~interface_type();
00310
00311
00312 b.move_clone(x.storage());
00313 b.~interface_type();
00314
00315
00316 tmp.interface_ref().move_clone(y.storage());
00317 }
00318
00319 poly_base& operator=(poly_base x)
00320 {
00321 interface_ref().~interface_type();
00322 x.interface_ref().move_clone(storage());
00323 return *this;
00324 }
00325 ~poly_base() { interface_ref().~interface_type(); }
00326
00327 template <typename J, template <typename> class K>
00328 static bool is_dynamic_convertible_from(const poly_base<J, K>& x)
00329 {
00330 return dynamic_cast<const I*>(static_cast<const poly_copyable_interface*>(&x.interface_ref()));
00331 }
00332
00333 template <typename J>
00334 bool is_dynamic_convertible_to() const
00335 {
00336 return dynamic_cast<const J*>(static_cast<const poly_copyable_interface*>(&interface_ref())) != NULL;
00337 }
00338
00339 const std::type_info& type_info() const
00340 { return interface_ref().type_info(); }
00341
00342 template <typename T> const T& cast() const
00343 {
00344 if (type_info() != typeid(T))
00345 throw bad_cast(type_info(), typeid(T));
00346 return *static_cast<const T*>(interface_ref().cast());
00347 }
00348
00349 template <typename T> T& cast()
00350 {
00351 if (type_info() != typeid(T))
00352 throw bad_cast(type_info(), typeid(T));
00353 return *static_cast<T*>(interface_ref().cast());
00354 }
00355
00356 template <typename T> bool cast(T& x) const
00357 {
00358 if (type_info() != typeid(T))
00359 return false;
00360 x = cast<T>();
00361 return true;
00362 }
00363
00364 template <typename T> poly_base& assign(const T& x)
00365 {
00366 if (type_info() == typeid(T))
00367 cast<T>() = x;
00368 else
00369 {
00370 poly_base tmp(x);
00371 swap(*this, tmp);
00372 }
00373 return *this;
00374 }
00375
00376
00377 template <typename J, template <typename> class K>
00378 typename boost::enable_if<is_base_derived_or_same<I, J> >::type
00379 assign(const poly_base<J, K>& x)
00380 {
00381 if(boost::is_base_of<J, I>::value)
00382 dynamic_cast<I&>(static_cast<J&>(*x.interface_ptr()));
00383 interface_ref().~interface_type();
00384 x.interface_ref().clone(storage());
00385 }
00386
00387 const interface_type* operator->() const
00388 { return &interface_ref(); }
00389
00390 interface_type* operator->()
00391 { return &interface_ref(); }
00392
00393 interface_type& interface_ref()
00394 { return *static_cast<interface_type*>(storage()); }
00395
00396 const interface_type& interface_ref() const
00397 { return *static_cast<const interface_type *>(storage()); }
00398
00399 void* storage() { return &data_m; }
00400 const void* storage() const { return &data_m; }
00401
00402 implementation::storage_t data_m;
00403
00404 };
00405
00406 template <class J, template <typename> class K>
00407 inline typename boost::enable_if<implementation::has_equals<J>, bool>::type
00408 operator==(const poly_base<J, K>& x, const poly_base<J, K>& y)
00409 { return x.interface_ref().equals(y.interface_ref()); }
00410
00411
00412
00413
00424 template <class F>
00425 class poly : public F
00426 {
00427 public:
00433 template <typename T>
00434 explicit poly(const T& x) : F(x) {}
00435
00436 poly(move_from<poly> x) : F(move_from<F>(x.source)) {}
00437
00438 poly& operator=(poly x) { static_cast<F&>(*this) = move(static_cast<F&>(x)); return *this; }
00439
00440 poly() : F() {}
00441 };
00442
00443
00444
00459 template <typename T, typename U>
00460 T poly_cast(poly<U>& x)
00461 {
00462 typedef typename boost::remove_reference<T>::type target_type;
00463 typedef typename target_type::interface_type target_interface_type;
00464 if(!x.template is_dynamic_convertible_to<target_interface_type>())
00465 throw bad_cast(typeid(poly<U>), typeid(T));
00466 return reinterpret_cast<T>(x);
00467 }
00468
00469
00470
00478 template <typename T, typename U>
00479 T poly_cast(const poly<U>& x)
00480 {
00481 typedef typename boost::remove_reference<T>::type target_type;
00482 typedef typename target_type::interface_type target_interface_type;
00483 if(!x.template is_dynamic_convertible_to<target_interface_type>())
00484 throw bad_cast(typeid(poly<U>), typeid(T));
00485 return reinterpret_cast<T>(x);
00486 }
00487
00488
00489
00505 template <typename T, typename U>
00506 T poly_cast(poly<U>* x)
00507 {
00508 typedef typename boost::remove_pointer<T>::type target_type;
00509 typedef typename target_type::interface_type target_interface_type;
00510 return x->template is_dynamic_convertible_to<target_interface_type>()
00511 ? reinterpret_cast<T>(x)
00512 : NULL;
00513 }
00514
00515
00516
00525 template <typename T, typename U>
00526 T poly_cast(const poly<U>* x)
00527 {
00528 typedef typename boost::remove_pointer<T>::type target_type;
00529 typedef typename target_type::interface_type target_interface_type;
00530 return x->template is_dynamic_convertible_to<target_interface_type>()
00531 ? reinterpret_cast<T>(x)
00532 : NULL;
00533 }
00534
00535
00536
00544 template <class T>
00545 inline bool operator!=(const poly<T>& x, const poly<T>& y)
00546 {
00547 return !(x == y);
00548 }
00549
00550
00552
00553
00554
00555 }
00556
00557
00558
00559 #endif
00560
00561