#ifndef BOOST_SERIALIZATION_VOID_CAST_HPP #define BOOST_SERIALIZATION_VOID_CAST_HPP // MS compatible compilers support #pragma once #if defined(_MSC_VER) # pragma once #endif /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 // void_cast.hpp: interface for run-time casting of void pointers. // (C) Copyright 2002-2009 Robert Ramey - http://www.rrsd.com . // Use, modification and distribution is subject to the Boost Software // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // gennadiy.rozental@tfn.com // See http://www.boost.org for updates, documentation, and revision history. #include <cstddef> // for ptrdiff_t #include <boost/config.hpp> #include <boost/noncopyable.hpp> #include <boost/serialization/smart_cast.hpp> #include <boost/serialization/singleton.hpp> #include <boost/serialization/force_include.hpp> #include <boost/serialization/type_info_implementation.hpp> #include <boost/serialization/extended_type_info.hpp> #include <boost/type_traits/is_virtual_base_of.hpp> #include <boost/serialization/void_cast_fwd.hpp> #include <boost/serialization/config.hpp> #include <boost/config/abi_prefix.hpp> // must be the last header #ifdef BOOST_MSVC # pragma warning(push) # pragma warning(disable : 4251 4231 4660 4275) #endif namespace boost { namespace serialization { class extended_type_info; // Given a void *, assume that it really points to an instance of one type // and alter it so that it would point to an instance of a related type. // Return the altered pointer. If there exists no sequence of casts that // can transform from_type to to_type, return a NULL. BOOST_SERIALIZATION_DECL(void const *) void_upcast( extended_type_info const & derived, extended_type_info const & base, void const * const t ); inline void * void_upcast( extended_type_info const & derived, extended_type_info const & base, void * const t ){ return const_cast<void*>(void_upcast( derived, base, const_cast<void const *>(t) )); } BOOST_SERIALIZATION_DECL(void const *) void_downcast( extended_type_info const & derived, extended_type_info const & base, void const * const t ); inline void * void_downcast( extended_type_info const & derived, extended_type_info const & base, void * const t ){ return const_cast<void*>(void_downcast( derived, base, const_cast<void const *>(t) )); } namespace void_cast_detail { class BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY()) void_caster : private boost::noncopyable { friend BOOST_SERIALIZATION_DECL(void const *) boost::serialization::void_upcast( extended_type_info const & derived, extended_type_info const & base, void const * const ); friend BOOST_SERIALIZATION_DECL(void const *) boost::serialization::void_downcast( extended_type_info const & derived, extended_type_info const & base, void const * const ); protected: void recursive_register(bool includes_virtual_base = false) const; void recursive_unregister() const; virtual bool has_virtual_base() const = 0; public: // Data members const extended_type_info * m_derived; const extended_type_info * m_base; /*const*/ std::ptrdiff_t m_difference; void_caster const * const m_parent; // note that void_casters are keyed on value of // member extended type info records - NOT their // addresses. This is necessary in order for the // void cast operations to work across dll and exe // module boundries. bool operator<(const void_caster & rhs) const; const void_caster & operator*(){ return *this; } // each derived class must re-implement these; virtual void const * upcast(void const * const t) const = 0; virtual void const * downcast(void const * const t) const = 0; // Constructor void_caster( extended_type_info const * derived, extended_type_info const * base, std::ptrdiff_t difference = 0, void_caster const * const parent = 0 ) : m_derived(derived), m_base(base), m_difference(difference), m_parent(parent) {} virtual ~void_caster(){} }; #ifdef BOOST_MSVC # pragma warning(push) # pragma warning(disable : 4251 4231 4660 4275 4511 4512) #endif template <class Derived, class Base> class void_caster_primitive : public void_caster { virtual void const * downcast(void const * const t) const { const Derived * d = boost::serialization::smart_cast<const Derived *, const Base *>( static_cast<const Base *>(t) ); return d; } virtual void const * upcast(void const * const t) const { const Base * b = boost::serialization::smart_cast<const Base *, const Derived *>( static_cast<const Derived *>(t) ); return b; } virtual bool has_virtual_base() const { return false; } public: void_caster_primitive(); virtual ~void_caster_primitive(); }; template <class Derived, class Base> void_caster_primitive<Derived, Base>::void_caster_primitive() : void_caster( & type_info_implementation<Derived>::type::get_const_instance(), & type_info_implementation<Base>::type::get_const_instance(), // note:I wanted to displace from 0 here, but at least one compiler // treated 0 by not shifting it at all. reinterpret_cast<std::ptrdiff_t>( static_cast<Derived *>( reinterpret_cast<Base *>(8) ) ) - 8 ) { recursive_register(); } template <class Derived, class Base> void_caster_primitive<Derived, Base>::~void_caster_primitive(){ recursive_unregister(); } template <class Derived, class Base> class void_caster_virtual_base : public void_caster { virtual bool has_virtual_base() const { return true; } public: virtual void const * downcast(void const * const t) const { const Derived * d = dynamic_cast<const Derived *>( static_cast<const Base *>(t) ); return d; } virtual void const * upcast(void const * const t) const { const Base * b = dynamic_cast<const Base *>( static_cast<const Derived *>(t) ); return b; } void_caster_virtual_base(); virtual ~void_caster_virtual_base(); }; #ifdef BOOST_MSVC #pragma warning(pop) #endif template <class Derived, class Base> void_caster_virtual_base<Derived,Base>::void_caster_virtual_base() : void_caster( & (type_info_implementation<Derived>::type::get_const_instance()), & (type_info_implementation<Base>::type::get_const_instance()) ) { recursive_register(true); } template <class Derived, class Base> void_caster_virtual_base<Derived,Base>::~void_caster_virtual_base(){ recursive_unregister(); } template <class Derived, class Base> struct void_caster_base : public void_caster { typedef typename mpl::eval_if<boost::is_virtual_base_of<Base,Derived>, mpl::identity< void_cast_detail::void_caster_virtual_base<Derived, Base> > ,// else mpl::identity< void_cast_detail::void_caster_primitive<Derived, Base> > >::type type; }; } // void_cast_detail template<class Derived, class Base> BOOST_DLLEXPORT inline const void_cast_detail::void_caster & void_cast_register( Derived const * /* dnull = NULL */, Base const * /* bnull = NULL */ ){ typedef typename mpl::eval_if<boost::is_virtual_base_of<Base,Derived>, mpl::identity< void_cast_detail::void_caster_virtual_base<Derived, Base> > ,// else mpl::identity< void_cast_detail::void_caster_primitive<Derived, Base> > >::type typex; return singleton<typex>::get_const_instance(); } template<class Derived, class Base> class void_caster : public void_cast_detail::void_caster_base<Derived, Base>::type { }; } // namespace serialization } // namespace boost #ifdef BOOST_MSVC # pragma warning(pop) #endif #include <boost/config/abi_suffix.hpp> // pops abi_suffix.hpp pragmas #endif // BOOST_SERIALIZATION_VOID_CAST_HPP