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