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