comparison DEPENDENCIES/generic/include/boost/serialization/smart_cast.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children c530137014c0
comparison
equal deleted inserted replaced
15:663ca0da4350 16:2665513ce2d3
1 #ifndef BOOST_SERIALIZATION_SMART_CAST_HPP
2 #define BOOST_SERIALIZATION_SMART_CAST_HPP
3
4 // MS compatible compilers support #pragma once
5 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
6 # pragma once
7 #endif
8
9 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
10 // smart_cast.hpp:
11
12 // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
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
17 // See http://www.boost.org/libs/serialization for updates, documentation, and revision history.
18
19 // casting of pointers and references.
20
21 // In casting between different C++ classes, there are a number of
22 // rules that have to be kept in mind in deciding whether to use
23 // static_cast or dynamic_cast.
24
25 // a) dynamic casting can only be applied when one of the types is polymorphic
26 // Otherwise static_cast must be used.
27 // b) only dynamic casting can do runtime error checking
28 // use of static_cast is generally un checked even when compiled for debug
29 // c) static_cast would be considered faster than dynamic_cast.
30
31 // If casting is applied to a template parameter, there is no apriori way
32 // to know which of the two casting methods will be permitted or convenient.
33
34 // smart_cast uses C++ type_traits, and program debug mode to select the
35 // most convenient cast to use.
36
37 #include <exception>
38 #include <typeinfo>
39 #include <cstddef> // NULL
40
41 #include <boost/config.hpp>
42 #include <boost/static_assert.hpp>
43
44 #include <boost/type_traits/is_base_and_derived.hpp>
45 #include <boost/type_traits/is_polymorphic.hpp>
46 #include <boost/type_traits/is_pointer.hpp>
47 #include <boost/type_traits/is_reference.hpp>
48 #include <boost/type_traits/is_same.hpp>
49 #include <boost/type_traits/remove_pointer.hpp>
50 #include <boost/type_traits/remove_reference.hpp>
51
52 #include <boost/mpl/eval_if.hpp>
53 #include <boost/mpl/if.hpp>
54 #include <boost/mpl/or.hpp>
55 #include <boost/mpl/and.hpp>
56 #include <boost/mpl/not.hpp>
57 #include <boost/mpl/identity.hpp>
58
59 #include <boost/serialization/throw_exception.hpp>
60
61 namespace boost {
62 namespace serialization {
63 namespace smart_cast_impl {
64
65 template<class T>
66 struct reference {
67
68 struct polymorphic {
69
70 struct linear {
71 template<class U>
72 static T cast(U & u){
73 return static_cast< T >(u);
74 }
75 };
76
77 struct cross {
78 template<class U>
79 static T cast(U & u){
80 return dynamic_cast< T >(u);
81 }
82 };
83
84 template<class U>
85 static T cast(U & u){
86 // if we're in debug mode
87 #if ! defined(NDEBUG) \
88 || defined(__BORLANDC__) && (__BORLANDC__ <= 0x560) \
89 || defined(__MWERKS__)
90 // do a checked dynamic cast
91 return cross::cast(u);
92 #else
93 // borland 5.51 chokes here so we can't use it
94 // note: if remove_reference isn't function for these types
95 // cross casting will be selected this will work but will
96 // not be the most efficient method. This will conflict with
97 // the original smart_cast motivation.
98 typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
99 BOOST_DEDUCED_TYPENAME mpl::and_<
100 mpl::not_<is_base_and_derived<
101 BOOST_DEDUCED_TYPENAME remove_reference< T >::type,
102 U
103 > >,
104 mpl::not_<is_base_and_derived<
105 U,
106 BOOST_DEDUCED_TYPENAME remove_reference< T >::type
107 > >
108 >,
109 // borland chokes w/o full qualification here
110 mpl::identity<cross>,
111 mpl::identity<linear>
112 >::type typex;
113 // typex works around gcc 2.95 issue
114 return typex::cast(u);
115 #endif
116 }
117 };
118
119 struct non_polymorphic {
120 template<class U>
121 static T cast(U & u){
122 return static_cast< T >(u);
123 }
124 };
125 template<class U>
126 static T cast(U & u){
127 #if defined(__BORLANDC__)
128 return mpl::eval_if<
129 boost::is_polymorphic<U>,
130 mpl::identity<polymorphic>,
131 mpl::identity<non_polymorphic>
132 >::type::cast(u);
133 #else
134 typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
135 boost::is_polymorphic<U>,
136 mpl::identity<polymorphic>,
137 mpl::identity<non_polymorphic>
138 >::type typex;
139 return typex::cast(u);
140 #endif
141 }
142 };
143
144 template<class T>
145 struct pointer {
146
147 struct polymorphic {
148 // unfortunately, this below fails to work for virtual base
149 // classes. need has_virtual_base to do this.
150 // Subject for further study
151 #if 0
152 struct linear {
153 template<class U>
154 static T cast(U * u){
155 return static_cast< T >(u);
156 }
157 };
158
159 struct cross {
160 template<class U>
161 static T cast(U * u){
162 T tmp = dynamic_cast< T >(u);
163 #ifndef NDEBUG
164 if ( tmp == 0 ) throw_exception(std::bad_cast());
165 #endif
166 return tmp;
167 }
168 };
169
170 template<class U>
171 static T cast(U * u){
172 // if we're in debug mode
173 #if ! defined(NDEBUG) || defined(__BORLANDC__) && (__BORLANDC__ <= 0x560)
174 // do a checked dynamic cast
175 return cross::cast(u);
176 #else
177 // borland 5.51 chokes here so we can't use it
178 // note: if remove_pointer isn't function for these types
179 // cross casting will be selected this will work but will
180 // not be the most efficient method. This will conflict with
181 // the original smart_cast motivation.
182 typedef
183 BOOST_DEDUCED_TYPENAME mpl::eval_if<
184 BOOST_DEDUCED_TYPENAME mpl::and_<
185 mpl::not_<is_base_and_derived<
186 BOOST_DEDUCED_TYPENAME remove_pointer< T >::type,
187 U
188 > >,
189 mpl::not_<is_base_and_derived<
190 U,
191 BOOST_DEDUCED_TYPENAME remove_pointer< T >::type
192 > >
193 >,
194 // borland chokes w/o full qualification here
195 mpl::identity<cross>,
196 mpl::identity<linear>
197 >::type typex;
198 return typex::cast(u);
199 #endif
200 }
201 #else
202 template<class U>
203 static T cast(U * u){
204 T tmp = dynamic_cast< T >(u);
205 #ifndef NDEBUG
206 if ( tmp == 0 ) throw_exception(std::bad_cast());
207 #endif
208 return tmp;
209 }
210 #endif
211 };
212
213 struct non_polymorphic {
214 template<class U>
215 static T cast(U * u){
216 return static_cast< T >(u);
217 }
218 };
219
220 template<class U>
221 static T cast(U * u){
222 #if defined(__BORLANDC__)
223 return mpl::eval_if<
224 boost::is_polymorphic<U>,
225 mpl::identity<polymorphic>,
226 mpl::identity<non_polymorphic>
227 >::type::cast(u);
228 #else
229 typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
230 boost::is_polymorphic<U>,
231 mpl::identity<polymorphic>,
232 mpl::identity<non_polymorphic>
233 >::type typex;
234 return typex::cast(u);
235 #endif
236 }
237
238 };
239
240 template<class TPtr>
241 struct void_pointer {
242 template<class UPtr>
243 static TPtr cast(UPtr uptr){
244 return static_cast<TPtr>(uptr);
245 }
246 };
247
248 template<class T>
249 struct error {
250 // if we get here, its because we are using one argument in the
251 // cast on a system which doesn't support partial template
252 // specialization
253 template<class U>
254 static T cast(U u){
255 BOOST_STATIC_ASSERT(sizeof(T)==0);
256 return * static_cast<T *>(NULL);
257 }
258 };
259
260 } // smart_cast_impl
261
262 // this implements:
263 // smart_cast<Target *, Source *>(Source * s)
264 // smart_cast<Target &, Source &>(s)
265 // note that it will fail with
266 // smart_cast<Target &>(s)
267 template<class T, class U>
268 T smart_cast(U u) {
269 typedef
270 BOOST_DEDUCED_TYPENAME mpl::eval_if<
271 BOOST_DEDUCED_TYPENAME mpl::or_<
272 boost::is_same<void *, U>,
273 boost::is_same<void *, T>,
274 boost::is_same<const void *, U>,
275 boost::is_same<const void *, T>
276 >,
277 mpl::identity<smart_cast_impl::void_pointer< T > >,
278 // else
279 BOOST_DEDUCED_TYPENAME mpl::eval_if<boost::is_pointer<U>,
280 mpl::identity<smart_cast_impl::pointer< T > >,
281 // else
282 BOOST_DEDUCED_TYPENAME mpl::eval_if<boost::is_reference<U>,
283 mpl::identity<smart_cast_impl::reference< T > >,
284 // else
285 mpl::identity<smart_cast_impl::error< T >
286 >
287 >
288 >
289 >::type typex;
290 return typex::cast(u);
291 }
292
293 // this implements:
294 // smart_cast_reference<Target &>(Source & s)
295 template<class T, class U>
296 T smart_cast_reference(U & u) {
297 return smart_cast_impl::reference< T >::cast(u);
298 }
299
300 } // namespace serialization
301 } // namespace boost
302
303 #endif // BOOST_SERIALIZATION_SMART_CAST_HPP