void_cast.hpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. #ifndef BOOST_SERIALIZATION_VOID_CAST_HPP
  2. #define BOOST_SERIALIZATION_VOID_CAST_HPP
  3. // MS compatible compilers support #pragma once
  4. #if defined(_MSC_VER)
  5. # pragma once
  6. #endif
  7. /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
  8. // void_cast.hpp: interface for run-time casting of void pointers.
  9. // (C) Copyright 2002-2009 Robert Ramey - http://www.rrsd.com .
  10. // Use, modification and distribution is subject to the Boost Software
  11. // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  12. // http://www.boost.org/LICENSE_1_0.txt)
  13. // gennadiy.rozental@tfn.com
  14. // See http://www.boost.org for updates, documentation, and revision history.
  15. #include <cstddef> // for ptrdiff_t
  16. #include <boost/config.hpp>
  17. #include <boost/noncopyable.hpp>
  18. #include <boost/serialization/smart_cast.hpp>
  19. #include <boost/serialization/singleton.hpp>
  20. #include <boost/serialization/force_include.hpp>
  21. #include <boost/serialization/type_info_implementation.hpp>
  22. #include <boost/serialization/extended_type_info.hpp>
  23. #include <boost/type_traits/is_virtual_base_of.hpp>
  24. #include <boost/serialization/void_cast_fwd.hpp>
  25. #include <boost/serialization/config.hpp>
  26. #include <boost/config/abi_prefix.hpp> // must be the last header
  27. #ifdef BOOST_MSVC
  28. # pragma warning(push)
  29. # pragma warning(disable : 4251 4231 4660 4275)
  30. #endif
  31. namespace boost {
  32. namespace serialization {
  33. class extended_type_info;
  34. // Given a void *, assume that it really points to an instance of one type
  35. // and alter it so that it would point to an instance of a related type.
  36. // Return the altered pointer. If there exists no sequence of casts that
  37. // can transform from_type to to_type, return a NULL.
  38. BOOST_SERIALIZATION_DECL void const *
  39. void_upcast(
  40. extended_type_info const & derived,
  41. extended_type_info const & base,
  42. void const * const t
  43. );
  44. inline void *
  45. void_upcast(
  46. extended_type_info const & derived,
  47. extended_type_info const & base,
  48. void * const t
  49. ){
  50. return const_cast<void*>(void_upcast(
  51. derived,
  52. base,
  53. const_cast<void const *>(t)
  54. ));
  55. }
  56. BOOST_SERIALIZATION_DECL void const *
  57. void_downcast(
  58. extended_type_info const & derived,
  59. extended_type_info const & base,
  60. void const * const t
  61. );
  62. inline void *
  63. void_downcast(
  64. extended_type_info const & derived,
  65. extended_type_info const & base,
  66. void * const t
  67. ){
  68. return const_cast<void*>(void_downcast(
  69. derived,
  70. base,
  71. const_cast<void const *>(t)
  72. ));
  73. }
  74. namespace void_cast_detail {
  75. class BOOST_SYMBOL_VISIBLE void_caster :
  76. private boost::noncopyable
  77. {
  78. friend
  79. BOOST_SERIALIZATION_DECL void const *
  80. boost::serialization::void_upcast(
  81. extended_type_info const & derived,
  82. extended_type_info const & base,
  83. void const * const
  84. );
  85. friend
  86. BOOST_SERIALIZATION_DECL void const *
  87. boost::serialization::void_downcast(
  88. extended_type_info const & derived,
  89. extended_type_info const & base,
  90. void const * const
  91. );
  92. protected:
  93. BOOST_SERIALIZATION_DECL void recursive_register(bool includes_virtual_base = false) const;
  94. BOOST_SERIALIZATION_DECL void recursive_unregister() const;
  95. virtual bool has_virtual_base() const = 0;
  96. public:
  97. // Data members
  98. const extended_type_info * m_derived;
  99. const extended_type_info * m_base;
  100. /*const*/ std::ptrdiff_t m_difference;
  101. void_caster const * const m_parent;
  102. // note that void_casters are keyed on value of
  103. // member extended type info records - NOT their
  104. // addresses. This is necessary in order for the
  105. // void cast operations to work across dll and exe
  106. // module boundries.
  107. bool operator<(const void_caster & rhs) const;
  108. const void_caster & operator*(){
  109. return *this;
  110. }
  111. // each derived class must re-implement these;
  112. virtual void const * upcast(void const * const t) const = 0;
  113. virtual void const * downcast(void const * const t) const = 0;
  114. // Constructor
  115. void_caster(
  116. extended_type_info const * derived,
  117. extended_type_info const * base,
  118. std::ptrdiff_t difference = 0,
  119. void_caster const * const parent = 0
  120. ) :
  121. m_derived(derived),
  122. m_base(base),
  123. m_difference(difference),
  124. m_parent(parent)
  125. {}
  126. virtual ~void_caster(){}
  127. };
  128. #ifdef BOOST_MSVC
  129. # pragma warning(push)
  130. # pragma warning(disable : 4251 4231 4660 4275 4511 4512)
  131. #endif
  132. template <class Derived, class Base>
  133. class BOOST_SYMBOL_VISIBLE void_caster_primitive :
  134. public void_caster
  135. {
  136. virtual void const * downcast(void const * const t) const {
  137. const Derived * d =
  138. boost::serialization::smart_cast<const Derived *, const Base *>(
  139. static_cast<const Base *>(t)
  140. );
  141. return d;
  142. }
  143. virtual void const * upcast(void const * const t) const {
  144. const Base * b =
  145. boost::serialization::smart_cast<const Base *, const Derived *>(
  146. static_cast<const Derived *>(t)
  147. );
  148. return b;
  149. }
  150. virtual bool has_virtual_base() const {
  151. return false;
  152. }
  153. public:
  154. void_caster_primitive();
  155. virtual ~void_caster_primitive();
  156. };
  157. template <class Derived, class Base>
  158. void_caster_primitive<Derived, Base>::void_caster_primitive() :
  159. void_caster(
  160. & type_info_implementation<Derived>::type::get_const_instance(),
  161. & type_info_implementation<Base>::type::get_const_instance(),
  162. /* note about displacement:
  163. * displace 0: at least one compiler treated 0 by not shifting it at all
  164. * displace by small value (8): caused ICE on certain mingw gcc versions */
  165. reinterpret_cast<std::ptrdiff_t>(
  166. static_cast<Derived *>(
  167. reinterpret_cast<Base *>(1 << 20)
  168. )
  169. ) - (1 << 20)
  170. )
  171. {
  172. recursive_register();
  173. }
  174. template <class Derived, class Base>
  175. void_caster_primitive<Derived, Base>::~void_caster_primitive(){
  176. recursive_unregister();
  177. }
  178. template <class Derived, class Base>
  179. class BOOST_SYMBOL_VISIBLE void_caster_virtual_base :
  180. public void_caster
  181. {
  182. virtual bool has_virtual_base() const {
  183. return true;
  184. }
  185. public:
  186. virtual void const * downcast(void const * const t) const {
  187. const Derived * d =
  188. dynamic_cast<const Derived *>(
  189. static_cast<const Base *>(t)
  190. );
  191. return d;
  192. }
  193. virtual void const * upcast(void const * const t) const {
  194. const Base * b =
  195. dynamic_cast<const Base *>(
  196. static_cast<const Derived *>(t)
  197. );
  198. return b;
  199. }
  200. void_caster_virtual_base();
  201. virtual ~void_caster_virtual_base();
  202. };
  203. #ifdef BOOST_MSVC
  204. #pragma warning(pop)
  205. #endif
  206. template <class Derived, class Base>
  207. void_caster_virtual_base<Derived,Base>::void_caster_virtual_base() :
  208. void_caster(
  209. & (type_info_implementation<Derived>::type::get_const_instance()),
  210. & (type_info_implementation<Base>::type::get_const_instance())
  211. )
  212. {
  213. recursive_register(true);
  214. }
  215. template <class Derived, class Base>
  216. void_caster_virtual_base<Derived,Base>::~void_caster_virtual_base(){
  217. recursive_unregister();
  218. }
  219. template <class Derived, class Base>
  220. struct BOOST_SYMBOL_VISIBLE void_caster_base :
  221. public void_caster
  222. {
  223. typedef
  224. typename mpl::eval_if<boost::is_virtual_base_of<Base,Derived>,
  225. mpl::identity<
  226. void_cast_detail::void_caster_virtual_base<Derived, Base>
  227. >
  228. ,// else
  229. mpl::identity<
  230. void_cast_detail::void_caster_primitive<Derived, Base>
  231. >
  232. >::type type;
  233. };
  234. } // void_cast_detail
  235. template<class Derived, class Base>
  236. BOOST_DLLEXPORT
  237. inline const void_cast_detail::void_caster & void_cast_register(
  238. Derived const * /* dnull = NULL */,
  239. Base const * /* bnull = NULL */
  240. ){
  241. typedef
  242. typename mpl::eval_if<boost::is_virtual_base_of<Base,Derived>,
  243. mpl::identity<
  244. void_cast_detail::void_caster_virtual_base<Derived, Base>
  245. >
  246. ,// else
  247. mpl::identity<
  248. void_cast_detail::void_caster_primitive<Derived, Base>
  249. >
  250. >::type typex;
  251. return singleton<typex>::get_const_instance();
  252. }
  253. template<class Derived, class Base>
  254. class BOOST_SYMBOL_VISIBLE void_caster :
  255. public void_cast_detail::void_caster_base<Derived, Base>::type
  256. {
  257. };
  258. } // namespace serialization
  259. } // namespace boost
  260. #ifdef BOOST_MSVC
  261. # pragma warning(pop)
  262. #endif
  263. #include <boost/config/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
  264. #endif // BOOST_SERIALIZATION_VOID_CAST_HPP