void_cast.hpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  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) && (_MSC_VER >= 1020)
  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/weak_ptr.hpp>
  17. #include <boost/noncopyable.hpp>
  18. #include <boost/serialization/config.hpp>
  19. #include <boost/serialization/smart_cast.hpp>
  20. #include <boost/serialization/singleton.hpp>
  21. #include <boost/serialization/force_include.hpp>
  22. #include <boost/serialization/type_info_implementation.hpp>
  23. #include <boost/serialization/extended_type_info.hpp>
  24. #include <boost/type_traits/is_virtual_base_of.hpp>
  25. #include <boost/config/abi_prefix.hpp> // must be the last header
  26. #ifdef BOOST_MSVC
  27. # pragma warning(push)
  28. # pragma warning(disable : 4251 4231 4660 4275)
  29. #endif
  30. namespace boost {
  31. namespace serialization {
  32. class extended_type_info;
  33. // Given a void *, assume that it really points to an instance of one type
  34. // and alter it so that it would point to an instance of a related type.
  35. // Return the altered pointer. If there exists no sequence of casts that
  36. // can transform from_type to to_type, return a NULL.
  37. BOOST_SERIALIZATION_DECL(void const *)
  38. void_upcast(
  39. extended_type_info const & derived,
  40. extended_type_info const & base,
  41. void const * const t
  42. );
  43. inline void *
  44. void_upcast(
  45. extended_type_info const & derived,
  46. extended_type_info const & base,
  47. void * const t
  48. ){
  49. return const_cast<void*>(void_upcast(
  50. derived,
  51. base,
  52. const_cast<void const *>(t)
  53. ));
  54. }
  55. BOOST_SERIALIZATION_DECL(void const *)
  56. void_downcast(
  57. extended_type_info const & derived,
  58. extended_type_info const & base,
  59. void const * const t
  60. );
  61. inline void *
  62. void_downcast(
  63. extended_type_info const & derived,
  64. extended_type_info const & base,
  65. void * const t
  66. ){
  67. return const_cast<void*>(void_downcast(
  68. derived,
  69. base,
  70. const_cast<void const *>(t)
  71. ));
  72. }
  73. namespace void_cast_detail {
  74. class BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY()) void_caster :
  75. private boost::noncopyable
  76. {
  77. friend
  78. BOOST_SERIALIZATION_DECL(void const *)
  79. boost::serialization::void_upcast(
  80. extended_type_info const & derived,
  81. extended_type_info const & base,
  82. void const * const
  83. );
  84. friend
  85. BOOST_SERIALIZATION_DECL(void const *)
  86. boost::serialization::void_downcast(
  87. extended_type_info const & derived,
  88. extended_type_info const & base,
  89. void const * const
  90. );
  91. protected:
  92. void recursive_register(bool includes_virtual_base = false) const;
  93. void recursive_unregister() const;
  94. public:
  95. // Data members
  96. const extended_type_info * m_derived;
  97. const extended_type_info * m_base;
  98. boost::weak_ptr<const extended_type_info> m_derived_observer;
  99. boost::weak_ptr<const extended_type_info> m_base_observer;
  100. /*const*/ std::ptrdiff_t m_difference;
  101. const bool m_heap; // allocated on the heap
  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. bool heap = false
  120. ) :
  121. m_derived(derived),
  122. m_base(base),
  123. m_derived_observer(derived->get_weak_ptr()),
  124. m_base_observer(base->get_weak_ptr()),
  125. m_difference(difference),
  126. m_heap(heap)
  127. {}
  128. virtual ~void_caster(){}
  129. };
  130. template <class Derived, class Base>
  131. class void_caster_primitive :
  132. public void_caster
  133. {
  134. virtual void const * downcast(void const * const t) const {
  135. const Derived * d =
  136. boost::serialization::smart_cast<const Derived *, const Base *>(
  137. static_cast<const Base *>(t)
  138. );
  139. return d;
  140. }
  141. virtual void const * upcast(void const * const t) const {
  142. const Base * b =
  143. boost::serialization::smart_cast<const Base *, const Derived *>(
  144. static_cast<const Derived *>(t)
  145. );
  146. return b;
  147. }
  148. public:
  149. void_caster_primitive();
  150. ~void_caster_primitive();
  151. };
  152. template <class Derived, class Base>
  153. void_caster_primitive<Derived, Base>::void_caster_primitive() :
  154. void_caster(
  155. & type_info_implementation<Derived>::type::get_const_instance(),
  156. & type_info_implementation<Base>::type::get_const_instance(),
  157. // note:I wanted to display from 0 here, but at least one compiler
  158. // treated 0 by not shifting it at all.
  159. reinterpret_cast<std::ptrdiff_t>(
  160. static_cast<Derived *>(
  161. reinterpret_cast<Base *>(1)
  162. )
  163. ) - 1
  164. )
  165. {
  166. recursive_register();
  167. }
  168. template <class Derived, class Base>
  169. void_caster_primitive<Derived, Base>::~void_caster_primitive(){
  170. recursive_unregister();
  171. }
  172. template <class Derived, class Base>
  173. class void_caster_virtual_base :
  174. public void_caster
  175. {
  176. public:
  177. virtual void const * downcast(void const * const t) const {
  178. const Derived * d =
  179. dynamic_cast<const Derived *>(
  180. static_cast<const Base *>(t)
  181. );
  182. return d;
  183. }
  184. virtual void const * upcast(void const * const t) const {
  185. const Base * b =
  186. dynamic_cast<const Base *>(
  187. static_cast<const Derived *>(t)
  188. );
  189. return b;
  190. }
  191. void_caster_virtual_base();
  192. ~void_caster_virtual_base();
  193. };
  194. template <class Derived, class Base>
  195. void_caster_virtual_base<Derived,Base>::void_caster_virtual_base() :
  196. void_caster(
  197. & (type_info_implementation<Derived>::type::get_const_instance()),
  198. & (type_info_implementation<Base>::type::get_const_instance())
  199. )
  200. {
  201. recursive_register(true);
  202. }
  203. template <class Derived, class Base>
  204. void_caster_virtual_base<Derived,Base>::~void_caster_virtual_base(){
  205. recursive_unregister();
  206. }
  207. } // void_cast_detail
  208. // Register a base/derived pair. This indicates that it is possible
  209. // to upcast a void pointer from Derived to Base and downcast a
  210. // void pointer from Base to Derived. Note bogus arguments to workaround
  211. // bug in msvc 6.0
  212. template<class Derived, class Base>
  213. BOOST_DLLEXPORT
  214. inline const void_cast_detail::void_caster & void_cast_register(
  215. const Derived * dnull,
  216. const Base * bnull
  217. ) BOOST_USED;
  218. template<class Derived, class Base>
  219. BOOST_DLLEXPORT
  220. inline const void_cast_detail::void_caster & void_cast_register(
  221. Derived const * /* dnull = NULL */,
  222. Base const * /* bnull = NULL */
  223. ){
  224. typedef
  225. BOOST_DEDUCED_TYPENAME mpl::eval_if<boost::is_virtual_base_of<Base,Derived>,
  226. mpl::identity<
  227. void_cast_detail::void_caster_virtual_base<Derived, Base>
  228. >
  229. ,// else
  230. mpl::identity<
  231. void_cast_detail::void_caster_primitive<Derived, Base>
  232. >
  233. >::type typex;
  234. return singleton<typex>::get_const_instance();
  235. }
  236. } // namespace serialization
  237. } // namespace boost
  238. #ifdef BOOST_MSVC
  239. # pragma warning(pop)
  240. #endif
  241. #include <boost/config/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
  242. #endif // BOOST_SERIALIZATION_VOID_CAST_HPP