void_cast.hpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  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:I wanted to displace from 0 here, but at least one compiler
  163. // treated 0 by not shifting it at all.
  164. reinterpret_cast<std::ptrdiff_t>(
  165. static_cast<Derived *>(
  166. reinterpret_cast<Base *>(8)
  167. )
  168. ) - 8
  169. )
  170. {
  171. recursive_register();
  172. }
  173. template <class Derived, class Base>
  174. void_caster_primitive<Derived, Base>::~void_caster_primitive(){
  175. recursive_unregister();
  176. }
  177. template <class Derived, class Base>
  178. class BOOST_SYMBOL_VISIBLE void_caster_virtual_base :
  179. public void_caster
  180. {
  181. virtual bool has_virtual_base() const {
  182. return true;
  183. }
  184. public:
  185. virtual void const * downcast(void const * const t) const {
  186. const Derived * d =
  187. dynamic_cast<const Derived *>(
  188. static_cast<const Base *>(t)
  189. );
  190. return d;
  191. }
  192. virtual void const * upcast(void const * const t) const {
  193. const Base * b =
  194. dynamic_cast<const Base *>(
  195. static_cast<const Derived *>(t)
  196. );
  197. return b;
  198. }
  199. void_caster_virtual_base();
  200. virtual ~void_caster_virtual_base();
  201. };
  202. #ifdef BOOST_MSVC
  203. #pragma warning(pop)
  204. #endif
  205. template <class Derived, class Base>
  206. void_caster_virtual_base<Derived,Base>::void_caster_virtual_base() :
  207. void_caster(
  208. & (type_info_implementation<Derived>::type::get_const_instance()),
  209. & (type_info_implementation<Base>::type::get_const_instance())
  210. )
  211. {
  212. recursive_register(true);
  213. }
  214. template <class Derived, class Base>
  215. void_caster_virtual_base<Derived,Base>::~void_caster_virtual_base(){
  216. recursive_unregister();
  217. }
  218. template <class Derived, class Base>
  219. struct BOOST_SYMBOL_VISIBLE void_caster_base :
  220. public void_caster
  221. {
  222. typedef
  223. typename mpl::eval_if<boost::is_virtual_base_of<Base,Derived>,
  224. mpl::identity<
  225. void_cast_detail::void_caster_virtual_base<Derived, Base>
  226. >
  227. ,// else
  228. mpl::identity<
  229. void_cast_detail::void_caster_primitive<Derived, Base>
  230. >
  231. >::type type;
  232. };
  233. } // void_cast_detail
  234. template<class Derived, class Base>
  235. BOOST_DLLEXPORT
  236. inline const void_cast_detail::void_caster & void_cast_register(
  237. Derived const * /* dnull = NULL */,
  238. Base const * /* bnull = NULL */
  239. ){
  240. typedef
  241. typename mpl::eval_if<boost::is_virtual_base_of<Base,Derived>,
  242. mpl::identity<
  243. void_cast_detail::void_caster_virtual_base<Derived, Base>
  244. >
  245. ,// else
  246. mpl::identity<
  247. void_cast_detail::void_caster_primitive<Derived, Base>
  248. >
  249. >::type typex;
  250. return singleton<typex>::get_const_instance();
  251. }
  252. template<class Derived, class Base>
  253. class BOOST_SYMBOL_VISIBLE void_caster :
  254. public void_cast_detail::void_caster_base<Derived, Base>::type
  255. {
  256. };
  257. } // namespace serialization
  258. } // namespace boost
  259. #ifdef BOOST_MSVC
  260. # pragma warning(pop)
  261. #endif
  262. #include <boost/config/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
  263. #endif // BOOST_SERIALIZATION_VOID_CAST_HPP