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     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 /**************************************************************************************************/

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