any_regular.hpp
Go to the documentation of this file.
00001 /* 00002 Copyright 2005-2007 Adobe Systems Incorporated 00003 Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt 00004 or a copy at http://stlab.adobe.com/licenses.html) 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 // Ensure that the vtable_t has a fixed layout regardless of alignment or packing. 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; // unused padding 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> // T models Regular 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 explicit any_regular_model_local(T x) 00218 : interface_type(vtable_s), object_m(adobe::move(x)) { } 00219 00220 static const any_regular_model_local& self(const interface_type& x) 00221 { return static_cast<const any_regular_model_local&>(x); } 00222 00223 static any_regular_model_local& self(interface_type& x) 00224 { return static_cast<any_regular_model_local&>(x); } 00225 00226 static type_info_t type_info(const interface_type&) 00227 { return adobe::type_info<T>(); } 00228 00229 static void destruct(const interface_type& x) 00230 { self(x).~any_regular_model_local(); } 00231 00232 static interface_type* clone(const interface_type& x, void* storage) 00233 { return ::new(storage) any_regular_model_local(self(x).object_m); } 00234 00235 static interface_type* move_clone(interface_type& x, void* storage) 00236 { return ::new(storage) any_regular_model_local(adobe::move(self(x).object_m)); } 00237 00238 static void assign(interface_type& x, const interface_type& y) 00239 { self(x).object_m = self(y).object_m; } 00240 00241 static bool equals(const interface_type& x, const interface_type& y) 00242 { return self(x).object_m == self(y).object_m; } 00243 00244 static void exchange(interface_type& x, interface_type& y) 00245 { swap(self(x).object_m, self(y).object_m); } 00246 00247 const T& get() const { return object_m; } 00248 T& get() { return object_m; } 00249 }; 00250 00251 BOOST_STATIC_ASSERT(sizeof(any_regular_model_local<double>) == 16); 00252 00253 template <typename T> 00254 const vtable_t any_regular_model_local<T>::vtable_s 00255 = { 00256 #ifndef NDEBUG 00257 short_name<T>::value, 00258 #else 00259 vtable_version, 00260 #endif 00261 &any_regular_model_local::destruct, 00262 &any_regular_model_local::type_info, 00263 &any_regular_model_local::clone, 00264 &any_regular_model_local::move_clone, 00265 &any_regular_model_local::assign, 00266 &any_regular_model_local::equals, 00267 &any_regular_model_local::exchange, 00268 }; 00269 00270 template <typename T> // T models Regular 00271 struct any_regular_model_remote : any_regular_interface_t, boost::noncopyable 00272 { 00273 BOOST_CLASS_REQUIRE(T, adobe, RegularConcept); 00274 00275 typedef any_regular_interface_t interface_type; 00276 00277 struct object_t; 00278 typedef capture_allocator<object_t> allocator_type; 00279 00280 struct object_t : boost::noncopyable 00281 { 00282 aligned_storage<allocator_type> alloc_m; 00283 T data_m; 00284 }; 00285 00286 static object_t* new_move(T& x) 00287 { 00288 allocator_type a; 00289 object_t* result = a.allocate(1); 00290 construct(&result->alloc_m, aligned_storage<allocator_type>(a)); 00291 construct(&result->data_m, adobe::move(x)); 00292 return result; 00293 } 00294 00295 object_t* object_ptr_m; 00296 00297 static const vtable_t vtable_s; 00298 00299 explicit any_regular_model_remote(T x) 00300 : interface_type(vtable_s), object_ptr_m(new_move(x)) 00301 { } 00302 00303 any_regular_model_remote(move_from<any_regular_model_remote> x) 00304 : interface_type(vtable_s), object_ptr_m(x.source.object_ptr_m) { x.source.object_ptr_m = 0; } 00305 00306 ~any_regular_model_remote() 00307 { 00308 if (object_ptr_m) { 00309 allocator_type a = object_ptr_m->alloc_m.get(); 00310 destroy(&object_ptr_m->alloc_m); 00311 destroy(&object_ptr_m->data_m); 00312 a.deallocate(object_ptr_m, 1); 00313 } 00314 } 00315 00316 static const any_regular_model_remote& self(const interface_type& x) 00317 { return static_cast<const any_regular_model_remote&>(x); } 00318 00319 static any_regular_model_remote& self(interface_type& x) 00320 { return static_cast<any_regular_model_remote&>(x); } 00321 00322 static type_info_t type_info(const interface_type&) 00323 { return adobe::type_info<T>(); } 00324 00325 static void destruct(const interface_type& x) 00326 { return self(x).~any_regular_model_remote(); } 00327 00328 static interface_type* clone(const interface_type& x, void* storage) 00329 { return ::new(storage) any_regular_model_remote(self(x).get()); } 00330 00331 static interface_type* move_clone(interface_type& x, void* storage) 00332 { return ::new(storage) any_regular_model_remote(move_from<any_regular_model_remote>(self(x))); } 00333 00334 static void assign(interface_type& x, const interface_type& y) 00335 { self(x).get() = self(y).get(); } 00336 00337 static bool equals(const interface_type& x, const interface_type& y) 00338 { return self(x).get() == self(y).get(); } 00339 00340 static void exchange(interface_type& x, interface_type& y) 00341 { return swap(self(x).object_ptr_m, self(y).object_ptr_m); } 00342 00343 const T& get() const { return object_ptr_m->data_m; } 00344 T& get() { return object_ptr_m->data_m; } 00345 }; 00346 00347 BOOST_STATIC_ASSERT(sizeof(any_regular_model_remote<double>) <= 16); 00348 00349 template <typename T> 00350 const vtable_t any_regular_model_remote<T>::vtable_s 00351 = { 00352 #ifndef NDEBUG 00353 short_name<T>::value, 00354 #else 00355 vtable_version, 00356 #endif 00357 &any_regular_model_remote::destruct, 00358 &any_regular_model_remote::type_info, 00359 &any_regular_model_remote::clone, 00360 &any_regular_model_remote::move_clone, 00361 &any_regular_model_remote::assign, 00362 &any_regular_model_remote::equals, 00363 &any_regular_model_remote::exchange, 00364 }; 00365 00366 /**************************************************************************************************/ 00367 00368 } // namespace implementation 00369 00370 /**************************************************************************************************/ 00371 00372 namespace version_1 { 00373 00374 /**************************************************************************************************/ 00375 00426 class any_regular_t : boost::equality_comparable<any_regular_t, any_regular_t> 00427 { 00428 typedef implementation::any_regular_interface_t interface_type; 00429 typedef double storage_t[2]; 00430 00431 #ifndef ADOBE_NO_DOCUMENTATION 00432 00433 template <typename T> 00434 struct traits 00435 { 00436 typedef typename promote<T>::type promote_type; 00437 BOOST_CLASS_REQUIRE(promote_type, adobe, RegularConcept); 00438 00439 typedef promote_type& reference_type; 00440 typedef const promote_type& const_reference_type; 00441 00442 typedef implementation::any_regular_model_local<promote_type> regular_model_local_type; 00443 typedef implementation::any_regular_model_remote<promote_type> regular_model_remote_type; 00444 00445 typedef boost::mpl::bool_<(sizeof(regular_model_local_type) 00446 <= sizeof(storage_t)) 00447 && (boost::has_nothrow_copy<promote_type>::value 00448 || is_movable<promote_type>::value)> use_local_type; 00449 00450 typedef typename boost::mpl::if_<use_local_type, 00451 regular_model_local_type, 00452 regular_model_remote_type>::type model_type; 00453 00454 typedef typename boost::mpl::if_c< 00455 boost::is_same<promote_type, T>::value, 00456 reference_type, T>::type result_type; 00457 00458 typedef typename boost::mpl::if_c< 00459 boost::is_same<promote_type, T>::value, 00460 const_reference_type, T>::type const_result_type; 00461 }; 00462 00463 template <typename T> struct helper; 00464 template <typename T> friend struct helper; 00465 00466 #endif 00467 00468 public: 00475 any_regular_t() { ::new (storage()) traits<empty_t>::model_type(); } 00476 00477 any_regular_t(const any_regular_t& x) { x.object().clone(storage()); } 00478 00479 any_regular_t(move_from<any_regular_t> x) { x.source.object().move_clone(storage()); } 00480 00481 any_regular_t& operator=(any_regular_t x) 00482 { 00483 object().destruct(); 00484 x.object().move_clone(storage()); 00485 return *this; 00486 } 00487 00488 ~any_regular_t() { object().destruct(); } 00497 template <typename T> 00498 explicit any_regular_t(T x) 00499 { ::new (storage()) typename traits<T>::model_type(adobe::move(x)); } 00500 00514 template <typename T> 00515 bool cast(T& x) const 00516 { 00517 if (type_info() != adobe::type_info<typename promote<T>::type>()) return false; 00518 x = cast<T>(); 00519 return true; 00520 } 00521 00522 template <typename T> 00523 typename traits<T>::const_result_type cast() const 00524 { return helper<T>::cast(*this); } 00525 00535 template <typename T> 00536 typename traits<T>::result_type cast() 00537 { return helper<T>::cast(*this); } 00538 00552 template <typename T> 00553 any_regular_t& assign(T x) 00554 { 00555 object().destruct(); 00556 ::new (storage()) typename traits<T>::model_type(adobe::move(x)); 00557 return *this; 00558 } 00559 00560 any_regular_t& assign(any_regular_t x) 00561 { 00562 object().destruct(); 00563 x.object().move_clone(storage()); 00564 return *this; 00565 } 00566 00576 type_info_t type_info() const { return object().type_info(); } 00577 00585 template <typename T> 00586 struct transform 00587 { 00588 typedef typename traits<T>::promote_type result_type; 00589 00590 typename traits<T>::result_type operator () (any_regular_t& x) const 00591 { return x.cast<T>(); } 00592 00593 typename traits<T>::const_result_type operator () (const any_regular_t& x) const 00594 { return x.cast<T>(); } 00595 }; 00596 00597 #if defined(ADOBE_STD_SERIALIZATION) 00598 friend std::ostream& operator<<(std::ostream& out, const any_regular_t& value); 00599 #endif 00600 00601 friend bool operator==(const any_regular_t& x, const any_regular_t& y); 00602 friend void swap(any_regular_t& x, any_regular_t& y); 00603 00604 private: 00605 any_regular_t(move_from<interface_type> x) { x.source.move_clone(storage()); } 00606 00607 interface_type& object() { return *static_cast<interface_type*>(storage()); } 00608 const interface_type& object() const { return *static_cast<const interface_type*>(storage()); } 00609 00610 void* storage() { return &data_m; } 00611 const void* storage() const { return &data_m; } 00612 00613 storage_t data_m; 00614 00615 #ifndef ADOBE_NO_DOCUMENTATION 00616 00617 #ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS 00618 public: 00619 #else 00620 template <typename, typename> friend struct adobe::runtime_cast_t; 00621 #endif 00622 00623 template <typename T> 00624 T* ptr_cast() 00625 { return helper<T>::ptr_cast(*this); } 00626 00627 #endif 00628 }; 00629 00630 #ifndef ADOBE_NO_DOCUMENTATION 00631 00632 BOOST_STATIC_ASSERT((sizeof(any_regular_t) == 16)); 00633 00634 inline bool operator == (const any_regular_t& x, const any_regular_t& y) 00635 { return (x.type_info() == y.type_info()) && x.object().equals(y.object()); } 00636 00637 inline void swap(any_regular_t& x, any_regular_t& y) 00638 { 00639 any_regular_t::interface_type& a(x.object()); 00640 any_regular_t::interface_type& b(y.object()); 00641 00642 if (a.type_info() == b.type_info()) { a.exchange(b); return; } 00643 00644 // x->tmp 00645 any_regular_t tmp((move_from<any_regular_t::interface_type>(a))); 00646 a.destruct(); 00647 00648 // y->x 00649 b.move_clone(x.storage()); 00650 b.destruct(); 00651 00652 // tmp->y 00653 tmp.object().move_clone(y.storage()); 00654 } 00655 00656 #endif 00657 00658 /**************************************************************************************************/ 00659 00660 #ifndef ADOBE_NO_DOCUMENTATION 00661 00662 template <typename T> 00663 struct any_regular_t::helper 00664 { 00665 static inline T* ptr_cast(any_regular_t& r) 00666 { 00667 if (r.type_info() != adobe::type_info<T>()) 00668 return 0; 00669 return &reinterpret_cast<typename traits<T>::model_type&>(r.object()).get(); 00670 } 00671 00672 static inline typename traits<T>::const_result_type cast(const any_regular_t& r) 00673 { 00674 typedef typename traits<T>::promote_type promote_type; 00675 00676 if (r.type_info() != adobe::type_info<promote_type>()) 00677 throw bad_cast(r.type_info(), adobe::type_info<promote_type>()); 00678 return static_cast<typename traits<T>::const_result_type>( 00679 reinterpret_cast<const typename traits<T>::model_type&>(r.object()).get()); 00680 } 00681 00682 static inline typename traits<T>::result_type cast(any_regular_t& r) 00683 { 00684 typedef typename traits<T>::promote_type promote_type; 00685 00686 if (r.type_info() != adobe::type_info<promote_type>()) 00687 throw bad_cast(r.type_info(), adobe::type_info<promote_type>()); 00688 return static_cast<typename traits<T>::result_type>( 00689 reinterpret_cast<typename traits<T>::model_type&>(r.object()).get()); 00690 } 00691 00692 static inline any_regular_t& assign(any_regular_t& r, const T& x) 00693 { 00694 typedef typename promote<T>::type promote_type; 00695 00696 if (r.type_info() == adobe::type_info<promote_type>()) 00697 r.cast<promote_type>() = static_cast<promote_type>(x); 00698 else 00699 { 00700 any_regular_t result(x); 00701 swap(r, result); 00702 } 00703 return r; 00704 } 00705 }; 00706 00707 /**************************************************************************************************/ 00708 00709 template <> 00710 struct any_regular_t::helper<any_regular_t> 00711 { 00712 static inline any_regular_t* ptr_cast(any_regular_t& r) 00713 { return &r; } 00714 00715 static inline const any_regular_t& cast(const any_regular_t& r) 00716 { return r; } 00717 00718 static inline any_regular_t& cast(any_regular_t& r) 00719 { return r; } 00720 }; 00721 00722 #endif 00723 00724 /**************************************************************************************************/ 00725 00726 } // namespace version_1 00727 00728 /**************************************************************************************************/ 00729 00736 inline bool empty(const any_regular_t& x) { return x.type_info() == type_info<empty_t>(); } 00737 00738 /**************************************************************************************************/ 00739 00744 /**************************************************************************************************/ 00745 00746 template <typename R> 00747 struct runtime_cast_t<R, const any_regular_t> 00748 { 00749 R operator()(const any_regular_t& x) const 00750 { 00751 typedef typename boost::remove_const<typename boost::remove_reference<R>::type>::type 00752 result_type; 00753 00754 BOOST_STATIC_ASSERT((boost::is_reference<R>::value)); 00755 00756 /* There is no auto-promotion through the new interface. Soon promotion will be disabled. */ 00757 BOOST_STATIC_ASSERT((boost::is_same<typename promote<result_type>::type, result_type>::value)); 00758 00759 return x.cast<result_type>(); 00760 } 00761 }; 00762 00763 /**************************************************************************************************/ 00764 00765 template <typename R> 00766 struct runtime_cast_t<R, any_regular_t> 00767 { 00768 R operator()(any_regular_t& x) const 00769 { 00770 typedef typename boost::remove_reference<R>::type result_type; 00771 00772 BOOST_STATIC_ASSERT((boost::is_reference<R>::value)); 00773 00774 /* There is no auto-promotion through the new interface. Soon promotion will be disabled. */ 00775 BOOST_STATIC_ASSERT((boost::is_same<typename promote<result_type>::type, result_type>::value)); 00776 00777 return x.cast<result_type>(); 00778 } 00779 }; 00780 00781 /**************************************************************************************************/ 00782 00783 template <typename R> 00784 struct runtime_cast_t<R, any_regular_t*> 00785 { 00786 R operator()(any_regular_t* x) const 00787 { 00788 typedef typename boost::remove_pointer<R>::type result_type; 00789 00790 BOOST_STATIC_ASSERT((boost::is_pointer<R>::value)); 00791 00792 /* There is no auto-promotion through the new interface. Soon promotion will be disabled. */ 00793 BOOST_STATIC_ASSERT((boost::is_same<typename promote<result_type>::type, result_type>::value)); 00794 00795 return x->ptr_cast<result_type>(); 00796 } 00797 }; 00798 00799 /**************************************************************************************************/ 00800 00801 template <typename R> 00802 struct runtime_cast_t<R, const any_regular_t*> 00803 { 00804 R operator()(const any_regular_t* x) const 00805 { 00806 typedef typename boost::remove_const<typename boost::remove_pointer<R>::type>::type 00807 result_type; 00808 00809 BOOST_STATIC_ASSERT((boost::is_pointer<R>::value)); 00810 00811 /* There is no auto-promotion through the new interface. Soon promotion will be disabled. */ 00812 BOOST_STATIC_ASSERT((boost::is_same<typename promote<result_type>::type, result_type>::value)); 00813 00814 if (x->type_info() != type_info<result_type>()) return 0; 00815 return &x->cast<result_type>(); 00816 } 00817 }; 00818 00819 /**************************************************************************************************/ 00820 00821 } // namespace adobe 00822 00823 /**************************************************************************************************/ 00824 00825 ADOBE_NAME_TYPE_0("any_regular_t:version_1:adobe", adobe::version_1::any_regular_t) 00826 00827 /**************************************************************************************************/ 00828 00829 #endif 00830 00831 /**************************************************************************************************/ |