You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
298 lines
8.4 KiB
298 lines
8.4 KiB
#ifndef BOOST_SERIALIZATION_VOID_CAST_HPP |
|
#define BOOST_SERIALIZATION_VOID_CAST_HPP |
|
|
|
// MS compatible compilers support #pragma once |
|
#if defined(_MSC_VER) && (_MSC_VER >= 1020) |
|
# 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 display 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 *>(1) |
|
) |
|
) - 1 |
|
) |
|
{ |
|
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 |
|
BOOST_DEDUCED_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 |
|
BOOST_DEDUCED_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
|
|
|