00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifndef ADOBE_ANY_REGULAR_HPP
00011 #define ADOBE_ANY_REGULAR_HPP
00012
00013 #include <adobe/config.hpp>
00014
00015 #include <adobe/any_regular_fwd.hpp>
00016
00017 #include <boost/mpl/bool.hpp>
00018 #include <boost/mpl/if.hpp>
00019 #include <boost/noncopyable.hpp>
00020 #include <boost/operators.hpp>
00021 #include <boost/static_assert.hpp>
00022 #include <boost/type_traits/has_nothrow_copy.hpp>
00023 #include <boost/type_traits/is_pointer.hpp>
00024 #include <boost/type_traits/is_reference.hpp>
00025 #include <boost/type_traits/is_same.hpp>
00026 #include <boost/type_traits/remove_const.hpp>
00027 #include <boost/type_traits/remove_pointer.hpp>
00028 #include <boost/type_traits/remove_reference.hpp>
00029 #include <boost/concept_check.hpp>
00030
00031 #include <adobe/conversion.hpp>
00032 #include <adobe/cstdint.hpp>
00033 #include <adobe/empty.hpp>
00034 #include <adobe/memory.hpp>
00035 #include <adobe/move.hpp>
00036 #include <adobe/typeinfo.hpp>
00037 #include <adobe/regular_concept.hpp>
00038
00039 #include <adobe/implementation/swap.hpp>
00040
00041 #if defined(ADOBE_STD_SERIALIZATION)
00042 #include <iosfwd>
00043 #endif
00044
00045
00046
00047 namespace adobe {
00048
00150
00151
00152 namespace implementation {
00153
00154 enum { vtable_version = 1 };
00155
00156 struct any_regular_interface_t;
00157
00158 struct vtable_t
00159 {
00160 typedef any_regular_interface_t interface_type;
00161
00162 adobe::uintptr_t version;
00163 void (*destruct)(const interface_type&);
00164 type_info_t (*type_info)(const interface_type&);
00165 interface_type* (*clone)(const interface_type&, void*);
00166 interface_type* (*move_clone)(interface_type&, void*);
00167 void (*assign)(interface_type&, const interface_type&);
00168 bool (*equals)(const interface_type&, const interface_type&);
00169 void (*exchange)(interface_type&, interface_type&);
00170 };
00171
00172
00173
00174 BOOST_STATIC_ASSERT(sizeof(vtable_t) == 8 * sizeof(void*));
00175
00176
00177
00178 union pad_vtable_t
00179 {
00180 const vtable_t* vtable_m;
00181 double pad_m;
00182 };
00183
00184 BOOST_STATIC_ASSERT(sizeof(pad_vtable_t) == sizeof(double));
00185
00186
00187
00188 struct any_regular_interface_t {
00189 typedef any_regular_interface_t interface_type;
00190
00191 any_regular_interface_t(const vtable_t& x) { object_m.vtable_m = &x; }
00192
00193 pad_vtable_t object_m;
00194
00195 void destruct() const { return object_m.vtable_m->destruct(*this); }
00196 type_info_t type_info() const { return object_m.vtable_m->type_info(*this); }
00197 interface_type* clone(void* x) const { return object_m.vtable_m->clone(*this, x); }
00198 interface_type* move_clone(void* x) { return object_m.vtable_m->move_clone(*this, x); }
00199 void assign(const interface_type& x) { object_m.vtable_m->assign(*this, x); }
00200 bool equals(const interface_type& x) const { return object_m.vtable_m->equals(*this, x); }
00201 void exchange(interface_type& x) { object_m.vtable_m->exchange(*this, x); }
00202 };
00203
00204
00205
00206 template <typename T>
00207 struct any_regular_model_local : any_regular_interface_t, boost::noncopyable
00208 {
00209 typedef any_regular_interface_t interface_type;
00210
00211 T object_m;
00212
00213 static const vtable_t vtable_s;
00214
00215 any_regular_model_local() : interface_type(vtable_s), object_m() { }
00216
00217 template <typename U>
00218 explicit any_regular_model_local(const U& x, typename copy_sink<U, T>::type = 0)
00219 : interface_type(vtable_s), object_m(x) { }
00220
00221 template <typename U>
00222 explicit any_regular_model_local(U x, typename move_sink<U, T>::type = 0)
00223 : interface_type(vtable_s), object_m(move(x)) { }
00224
00225 static const any_regular_model_local& self(const interface_type& x)
00226 { return static_cast<const any_regular_model_local&>(x); }
00227
00228 static any_regular_model_local& self(interface_type& x)
00229 { return static_cast<any_regular_model_local&>(x); }
00230
00231 static type_info_t type_info(const interface_type&)
00232 { return adobe::type_info<T>(); }
00233
00234 static void destruct(const interface_type& x)
00235 { self(x).~any_regular_model_local(); }
00236
00237 static interface_type* clone(const interface_type& x, void* storage)
00238 { return ::new(storage) any_regular_model_local(self(x).object_m); }
00239
00240 static interface_type* move_clone(interface_type& x, void* storage)
00241 { return ::new(storage) any_regular_model_local(move(self(x).object_m)); }
00242
00243 static void assign(interface_type& x, const interface_type& y)
00244 { self(x).object_m = self(y).object_m; }
00245
00246 static bool equals(const interface_type& x, const interface_type& y)
00247 { return self(x).object_m == self(y).object_m; }
00248
00249 static void exchange(interface_type& x, interface_type& y)
00250 { swap(self(x).object_m, self(y).object_m); }
00251
00252 const T& get() const { return object_m; }
00253 T& get() { return object_m; }
00254 };
00255
00256 BOOST_STATIC_ASSERT(sizeof(any_regular_model_local<double>) == 16);
00257
00258 template <typename T>
00259 const vtable_t any_regular_model_local<T>::vtable_s
00260 = {
00261 #ifndef NDEBUG
00262 short_name<T>::value,
00263 #else
00264 vtable_version,
00265 #endif
00266 &any_regular_model_local::destruct,
00267 &any_regular_model_local::type_info,
00268 &any_regular_model_local::clone,
00269 &any_regular_model_local::move_clone,
00270 &any_regular_model_local::assign,
00271 &any_regular_model_local::equals,
00272 &any_regular_model_local::exchange,
00273 };
00274
00275 template <typename T>
00276 struct any_regular_model_remote : any_regular_interface_t, boost::noncopyable
00277 {
00278 BOOST_CLASS_REQUIRE(T, adobe, RegularConcept);
00279
00280 typedef any_regular_interface_t interface_type;
00281
00282 struct object_t;
00283 typedef capture_allocator<object_t> allocator_type;
00284
00285 struct object_t : boost::noncopyable
00286 {
00287 aligned_storage<allocator_type> alloc_m;
00288 T data_m;
00289 };
00290
00291 static object_t* new_copy(const T& x)
00292 {
00293 allocator_type a;
00294 object_t* result = a.allocate(1);
00295 construct(&result->alloc_m, aligned_storage<allocator_type>(a));
00296 try {
00297 construct(&result->data_m, x);
00298 } catch (...) {
00299 destroy(&result->alloc_m);
00300 a.deallocate(result, 1);
00301 }
00302 return result;
00303 }
00304
00305 static object_t* new_move(T& x)
00306 {
00307 allocator_type a;
00308 object_t* result = a.allocate(1);
00309 construct(&result->alloc_m, aligned_storage<allocator_type>(a));
00310 try {
00311 move_construct(&result->data_m, x);
00312 } catch (...) {
00313 destroy(&result->alloc_m);
00314 a.deallocate(result, 1);
00315 }
00316 return result;
00317 }
00318
00319 object_t* object_ptr_m;
00320
00321 static const vtable_t vtable_s;
00322
00323 template <typename U>
00324 explicit any_regular_model_remote(const U& x, typename copy_sink<U, T>::type = 0)
00325 : interface_type(vtable_s), object_ptr_m(new_copy(x))
00326 { }
00327
00328 template <typename U>
00329 explicit any_regular_model_remote(U x, typename move_sink<U, T>::type = 0)
00330 : interface_type(vtable_s), object_ptr_m(new_move(x))
00331 { }
00332
00333 any_regular_model_remote(move_from<any_regular_model_remote> x)
00334 : interface_type(vtable_s), object_ptr_m(x.source.object_ptr_m) { x.source.object_ptr_m = 0; }
00335
00336 ~any_regular_model_remote()
00337 {
00338 if (object_ptr_m) {
00339 allocator_type a = object_ptr_m->alloc_m.get();
00340 destroy(&object_ptr_m->alloc_m);
00341 destroy(&object_ptr_m->data_m);
00342 a.deallocate(object_ptr_m, 1);
00343 }
00344 }
00345
00346 static const any_regular_model_remote& self(const interface_type& x)
00347 { return static_cast<const any_regular_model_remote&>(x); }
00348
00349 static any_regular_model_remote& self(interface_type& x)
00350 { return static_cast<any_regular_model_remote&>(x); }
00351
00352 static type_info_t type_info(const interface_type&)
00353 { return adobe::type_info<T>(); }
00354
00355 static void destruct(const interface_type& x)
00356 { return self(x).~any_regular_model_remote(); }
00357
00358 static interface_type* clone(const interface_type& x, void* storage)
00359 { return ::new(storage) any_regular_model_remote(self(x).get()); }
00360
00361 static interface_type* move_clone(interface_type& x, void* storage)
00362 { return ::new(storage) any_regular_model_remote(move_from<any_regular_model_remote>(self(x))); }
00363
00364 static void assign(interface_type& x, const interface_type& y)
00365 { self(x).get() = self(y).get(); }
00366
00367 static bool equals(const interface_type& x, const interface_type& y)
00368 { return self(x).get() == self(y).get(); }
00369
00370 static void exchange(interface_type& x, interface_type& y)
00371 { return swap(self(x).object_ptr_m, self(y).object_ptr_m); }
00372
00373 const T& get() const { return object_ptr_m->data_m; }
00374 T& get() { return object_ptr_m->data_m; }
00375 };
00376
00377 BOOST_STATIC_ASSERT(sizeof(any_regular_model_remote<double>) <= 16);
00378
00379 template <typename T>
00380 const vtable_t any_regular_model_remote<T>::vtable_s
00381 = {
00382 #ifndef NDEBUG
00383 short_name<T>::value,
00384 #else
00385 vtable_version,
00386 #endif
00387 &any_regular_model_remote::destruct,
00388 &any_regular_model_remote::type_info,
00389 &any_regular_model_remote::clone,
00390 &any_regular_model_remote::move_clone,
00391 &any_regular_model_remote::assign,
00392 &any_regular_model_remote::equals,
00393 &any_regular_model_remote::exchange,
00394 };
00395
00396
00397
00398 }
00399
00400
00401
00402 namespace version_1 {
00403
00404
00405
00456 class any_regular_t : boost::equality_comparable<any_regular_t, any_regular_t>
00457 {
00458 typedef implementation::any_regular_interface_t interface_type;
00459 typedef double storage_t[2];
00460
00461 #ifndef ADOBE_NO_DOCUMENTATION
00462
00463 template <typename T>
00464 struct traits
00465 {
00466 typedef typename promote<T>::type promote_type;
00467 BOOST_CLASS_REQUIRE(promote_type, adobe, RegularConcept);
00468
00469 typedef promote_type& reference_type;
00470 typedef const promote_type& const_reference_type;
00471
00472 typedef implementation::any_regular_model_local<promote_type> regular_model_local_type;
00473 typedef implementation::any_regular_model_remote<promote_type> regular_model_remote_type;
00474
00475 typedef boost::mpl::bool_<(sizeof(regular_model_local_type)
00476 <= sizeof(storage_t))
00477 && (boost::has_nothrow_copy<promote_type>::value
00478 || is_movable<promote_type>::value)> use_local_type;
00479
00480 typedef typename boost::mpl::if_<use_local_type,
00481 regular_model_local_type,
00482 regular_model_remote_type>::type model_type;
00483
00484 typedef typename boost::mpl::if_c<
00485 boost::is_same<promote_type, T>::value,
00486 reference_type, T>::type result_type;
00487
00488 typedef typename boost::mpl::if_c<
00489 boost::is_same<promote_type, T>::value,
00490 const_reference_type, T>::type const_result_type;
00491 };
00492
00493 template <typename T> struct helper;
00494 template <typename T> friend struct helper;
00495
00496 #endif
00497
00498 public:
00505 any_regular_t() { ::new (storage()) traits<empty_t>::model_type(); }
00506
00507 any_regular_t(const any_regular_t& x) { x.object().clone(storage()); }
00508
00509 any_regular_t(move_from<any_regular_t> x) { x.source.object().move_clone(storage()); }
00510
00511 any_regular_t& operator=(any_regular_t x)
00512 {
00513 object().destruct();
00514 x.object().move_clone(storage());
00515 return *this;
00516 }
00517
00518 ~any_regular_t() { object().destruct(); }
00527 template <typename T>
00528 explicit any_regular_t(const T& x, typename copy_sink<T>::type = 0)
00529 { ::new (storage()) typename traits<T>::model_type(x); }
00530
00531 template <typename T>
00532 explicit any_regular_t(T x, typename move_sink<T>::type = 0)
00533 { ::new (storage()) typename traits<T>::model_type(move(x)); }
00534
00548 template <typename T>
00549 bool cast(T& x) const
00550 {
00551 if (type_info() != adobe::type_info<typename promote<T>::type>()) return false;
00552 x = cast<T>();
00553 return true;
00554 }
00555
00556 template <typename T>
00557 typename traits<T>::const_result_type cast() const
00558 { return helper<T>::cast(*this); }
00559
00569 template <typename T>
00570 typename traits<T>::result_type cast()
00571 { return helper<T>::cast(*this); }
00572
00586 template <typename T>
00587 any_regular_t& assign(const T& x, typename copy_sink<T>::type = 0)
00588 { return helper<T>::assign(*this, x); }
00589
00590 template <typename T>
00591 any_regular_t& assign(T x, typename move_sink<T>::type = 0)
00592 {
00593 object().destruct();
00594 ::new (storage()) typename traits<T>::model_type(move(x));
00595 return *this;
00596 }
00597
00598 any_regular_t& assign(any_regular_t x)
00599 {
00600 object().destruct();
00601 x.object().move_clone(storage());
00602 return *this;
00603 }
00604
00614 type_info_t type_info() const { return object().type_info(); }
00615
00623 template <typename T>
00624 struct transform
00625 {
00626 typedef typename traits<T>::promote_type result_type;
00627
00628 typename traits<T>::result_type operator () (any_regular_t& x) const
00629 { return x.cast<T>(); }
00630
00631 typename traits<T>::const_result_type operator () (const any_regular_t& x) const
00632 { return x.cast<T>(); }
00633 };
00634
00635 #if defined(ADOBE_STD_SERIALIZATION)
00636 friend std::ostream& operator<<(std::ostream& out, const any_regular_t& value);
00637 #endif
00638
00639 friend bool operator==(const any_regular_t& x, const any_regular_t& y);
00640 friend void swap(any_regular_t& x, any_regular_t& y);
00641
00642 private:
00643 any_regular_t(move_from<interface_type> x) { x.source.move_clone(storage()); }
00644
00645 interface_type& object() { return *static_cast<interface_type*>(storage()); }
00646 const interface_type& object() const { return *static_cast<const interface_type*>(storage()); }
00647
00648 void* storage() { return &data_m; }
00649 const void* storage() const { return &data_m; }
00650
00651 storage_t data_m;
00652
00653 #ifndef ADOBE_NO_DOCUMENTATION
00654
00655 #ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
00656 public:
00657 #else
00658 template <typename, typename> friend struct adobe::runtime_cast_t;
00659 #endif
00660
00661 template <typename T>
00662 T* ptr_cast()
00663 { return helper<T>::ptr_cast(*this); }
00664
00665 #endif
00666 };
00667
00668 #ifndef ADOBE_NO_DOCUMENTATION
00669
00670 BOOST_STATIC_ASSERT((sizeof(any_regular_t) == 16));
00671
00672 inline bool operator == (const any_regular_t& x, const any_regular_t& y)
00673 { return (x.type_info() == y.type_info()) && x.object().equals(y.object()); }
00674
00675 inline void swap(any_regular_t& x, any_regular_t& y)
00676 {
00677 any_regular_t::interface_type& a(x.object());
00678 any_regular_t::interface_type& b(y.object());
00679
00680 if (a.type_info() == b.type_info()) { a.exchange(b); return; }
00681
00682
00683 any_regular_t tmp((move_from<any_regular_t::interface_type>(a)));
00684 a.destruct();
00685
00686
00687 b.move_clone(x.storage());
00688 b.destruct();
00689
00690
00691 tmp.object().move_clone(y.storage());
00692 }
00693
00694 #endif
00695
00696
00697
00698 #ifndef ADOBE_NO_DOCUMENTATION
00699
00700 template <typename T>
00701 struct any_regular_t::helper
00702 {
00703 static inline T* ptr_cast(any_regular_t& r)
00704 {
00705 if (r.type_info() != adobe::type_info<T>())
00706 return 0;
00707 return &reinterpret_cast<typename traits<T>::model_type&>(r.object()).get();
00708 }
00709
00710 static inline typename traits<T>::const_result_type cast(const any_regular_t& r)
00711 {
00712 typedef typename traits<T>::promote_type promote_type;
00713
00714 if (r.type_info() != adobe::type_info<promote_type>())
00715 throw bad_cast(r.type_info(), adobe::type_info<promote_type>());
00716 return static_cast<typename traits<T>::const_result_type>(
00717 reinterpret_cast<const typename traits<T>::model_type&>(r.object()).get());
00718 }
00719
00720 static inline typename traits<T>::result_type cast(any_regular_t& r)
00721 {
00722 typedef typename traits<T>::promote_type promote_type;
00723
00724 if (r.type_info() != adobe::type_info<promote_type>())
00725 throw bad_cast(r.type_info(), adobe::type_info<promote_type>());
00726 return static_cast<typename traits<T>::result_type>(
00727 reinterpret_cast<typename traits<T>::model_type&>(r.object()).get());
00728 }
00729
00730 static inline any_regular_t& assign(any_regular_t& r, const T& x)
00731 {
00732 typedef typename promote<T>::type promote_type;
00733
00734 if (r.type_info() == adobe::type_info<promote_type>())
00735 r.cast<promote_type>() = static_cast<promote_type>(x);
00736 else
00737 {
00738 any_regular_t result(x);
00739 swap(r, result);
00740 }
00741 return r;
00742 }
00743 };
00744
00745
00746
00747 template <>
00748 struct any_regular_t::helper<any_regular_t>
00749 {
00750 static inline any_regular_t* ptr_cast(any_regular_t& r)
00751 { return &r; }
00752
00753 static inline const any_regular_t& cast(const any_regular_t& r)
00754 { return r; }
00755
00756 static inline any_regular_t& cast(any_regular_t& r)
00757 { return r; }
00758 };
00759
00760 #endif
00761
00762
00763
00764 }
00765
00766
00767
00774 inline bool empty(const any_regular_t& x) { return x.type_info() == type_info<empty_t>(); }
00775
00776
00777
00782 template <typename R>
00783 struct runtime_cast_t<R, const any_regular_t>
00784 {
00785 R operator()(const any_regular_t& x) const
00786 {
00787 typedef typename boost::remove_const<typename boost::remove_reference<R>::type>::type
00788 result_type;
00789
00790 BOOST_STATIC_ASSERT((boost::is_reference<R>::value));
00791
00792
00793 BOOST_STATIC_ASSERT((boost::is_same<typename promote<result_type>::type, result_type>::value));
00794
00795 return x.cast<result_type>();
00796 }
00797 };
00798
00799
00800
00801 template <typename R>
00802 struct runtime_cast_t<R, any_regular_t>
00803 {
00804 R operator()(any_regular_t& x) const
00805 {
00806 typedef typename boost::remove_reference<R>::type result_type;
00807
00808 BOOST_STATIC_ASSERT((boost::is_reference<R>::value));
00809
00810
00811 BOOST_STATIC_ASSERT((boost::is_same<typename promote<result_type>::type, result_type>::value));
00812
00813 return x.cast<result_type>();
00814 }
00815 };
00816
00817
00818
00819 template <typename R>
00820 struct runtime_cast_t<R, any_regular_t*>
00821 {
00822 R operator()(any_regular_t* x) const
00823 {
00824 typedef typename boost::remove_pointer<R>::type result_type;
00825
00826 BOOST_STATIC_ASSERT((boost::is_pointer<R>::value));
00827
00828
00829 BOOST_STATIC_ASSERT((boost::is_same<typename promote<result_type>::type, result_type>::value));
00830
00831 return x->ptr_cast<result_type>();
00832 }
00833 };
00834
00835
00836
00837 template <typename R>
00838 struct runtime_cast_t<R, const any_regular_t*>
00839 {
00840 R operator()(const any_regular_t* x) const
00841 {
00842 typedef typename boost::remove_const<typename boost::remove_pointer<R>::type>::type
00843 result_type;
00844
00845 BOOST_STATIC_ASSERT((boost::is_pointer<R>::value));
00846
00847
00848 BOOST_STATIC_ASSERT((boost::is_same<typename promote<result_type>::type, result_type>::value));
00849
00850 if (x->type_info() != type_info<result_type>()) return 0;
00851 return &x->cast<result_type>();
00852 }
00853 };
00854
00855
00856
00857 }
00858
00859
00860
00861 ADOBE_NAME_TYPE_0("any_regular_t:version_1:adobe", adobe::version_1::any_regular_t)
00862
00863
00864
00865 #endif
00866
00867