stlab.adobe.com Adobe Systems Incorporated

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     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> // T models Regular
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 } // namespace implementation
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     // x->tmp
00683     any_regular_t tmp((move_from<any_regular_t::interface_type>(a)));
00684     a.destruct();
00685     
00686     // y->x
00687     b.move_clone(x.storage());
00688     b.destruct();
00689     
00690     // tmp->y
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 } // namespace version_1
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         /* 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.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         /* There is no auto-promotion through the new interface. Soon promotion will be disabled. */
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         /* There is no auto-promotion through the new interface. Soon promotion will be disabled. */
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         /* There is no auto-promotion through the new interface. Soon promotion will be disabled. */
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 } // namespace adobe
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 /**************************************************************************************************/

Copyright © 2006-2007 Adobe Systems Incorporated.

Use of this website signifies your agreement to the Terms of Use and Online Privacy Policy.

Search powered by Google