|
1 |
|
2 // Copyright 2000 John Maddock (john@johnmaddock.co.uk) |
|
3 // Copyright 2000 Jeremy Siek (jsiek@lsc.nd.edu) |
|
4 // Copyright 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi) |
|
5 // |
|
6 // Use, modification and distribution are subject to the Boost Software License, |
|
7 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
|
8 // http://www.boost.org/LICENSE_1_0.txt). |
|
9 // |
|
10 // See http://www.boost.org/libs/type_traits for most recent version including documentation. |
|
11 |
|
12 #ifndef BOOST_TT_IS_CONVERTIBLE_HPP_INCLUDED |
|
13 #define BOOST_TT_IS_CONVERTIBLE_HPP_INCLUDED |
|
14 |
|
15 #include <boost/type_traits/intrinsics.hpp> |
|
16 #ifndef BOOST_IS_CONVERTIBLE |
|
17 #include <boost/type_traits/detail/yes_no_type.hpp> |
|
18 #include <boost/type_traits/config.hpp> |
|
19 #include <boost/type_traits/is_array.hpp> |
|
20 #include <boost/type_traits/add_reference.hpp> |
|
21 #include <boost/type_traits/ice.hpp> |
|
22 #include <boost/type_traits/is_arithmetic.hpp> |
|
23 #include <boost/type_traits/is_void.hpp> |
|
24 #ifndef BOOST_NO_IS_ABSTRACT |
|
25 #include <boost/type_traits/is_abstract.hpp> |
|
26 #endif |
|
27 |
|
28 #if defined(__MWERKS__) |
|
29 #include <boost/type_traits/is_function.hpp> |
|
30 #include <boost/type_traits/remove_reference.hpp> |
|
31 #endif |
|
32 |
|
33 #endif // BOOST_IS_CONVERTIBLE |
|
34 |
|
35 // should be always the last #include directive |
|
36 #include <boost/type_traits/detail/bool_trait_def.hpp> |
|
37 |
|
38 namespace boost { |
|
39 |
|
40 #ifndef BOOST_IS_CONVERTIBLE |
|
41 |
|
42 // is one type convertable to another? |
|
43 // |
|
44 // there are multiple versions of the is_convertible |
|
45 // template, almost every compiler seems to require its |
|
46 // own version. |
|
47 // |
|
48 // Thanks to Andrei Alexandrescu for the original version of the |
|
49 // conversion detection technique! |
|
50 // |
|
51 |
|
52 namespace detail { |
|
53 |
|
54 // MS specific version: |
|
55 |
|
56 #if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300) |
|
57 |
|
58 // This workaround is necessary to handle when From is void |
|
59 // which is normally taken care of by the partial specialization |
|
60 // of the is_convertible typename. |
|
61 using ::boost::type_traits::yes_type; |
|
62 using ::boost::type_traits::no_type; |
|
63 |
|
64 template< typename From > |
|
65 struct does_conversion_exist |
|
66 { |
|
67 template< typename To > struct result_ |
|
68 { |
|
69 static no_type BOOST_TT_DECL _m_check(...); |
|
70 static yes_type BOOST_TT_DECL _m_check(To); |
|
71 static From _m_from; |
|
72 enum { value = sizeof( _m_check(_m_from) ) == sizeof(yes_type) }; |
|
73 }; |
|
74 }; |
|
75 |
|
76 template<> |
|
77 struct does_conversion_exist<void> |
|
78 { |
|
79 template< typename To > struct result_ |
|
80 { |
|
81 enum { value = ::boost::is_void<To>::value }; |
|
82 }; |
|
83 }; |
|
84 |
|
85 template <typename From, typename To> |
|
86 struct is_convertible_basic_impl |
|
87 : does_conversion_exist<From>::template result_<To> |
|
88 { |
|
89 }; |
|
90 |
|
91 #elif defined(__BORLANDC__) && (__BORLANDC__ < 0x560) |
|
92 // |
|
93 // special version for Borland compilers |
|
94 // this version breaks when used for some |
|
95 // UDT conversions: |
|
96 // |
|
97 template <typename From, typename To> |
|
98 struct is_convertible_impl |
|
99 { |
|
100 #pragma option push -w-8074 |
|
101 // This workaround for Borland breaks the EDG C++ frontend, |
|
102 // so we only use it for Borland. |
|
103 template <typename T> struct checker |
|
104 { |
|
105 static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(...); |
|
106 static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(T); |
|
107 }; |
|
108 |
|
109 static From _m_from; |
|
110 static bool const value = sizeof( checker<To>::_m_check(_m_from) ) |
|
111 == sizeof(::boost::type_traits::yes_type); |
|
112 #pragma option pop |
|
113 }; |
|
114 |
|
115 #elif defined(__GNUC__) || defined(__BORLANDC__) && (__BORLANDC__ < 0x600) |
|
116 // special version for gcc compiler + recent Borland versions |
|
117 // note that this does not pass UDT's through (...) |
|
118 |
|
119 struct any_conversion |
|
120 { |
|
121 template <typename T> any_conversion(const volatile T&); |
|
122 template <typename T> any_conversion(T&); |
|
123 }; |
|
124 |
|
125 template <typename T> struct checker |
|
126 { |
|
127 static boost::type_traits::no_type _m_check(any_conversion ...); |
|
128 static boost::type_traits::yes_type _m_check(T, int); |
|
129 }; |
|
130 |
|
131 template <typename From, typename To> |
|
132 struct is_convertible_basic_impl |
|
133 { |
|
134 static From _m_from; |
|
135 static bool const value = sizeof( detail::checker<To>::_m_check(_m_from, 0) ) |
|
136 == sizeof(::boost::type_traits::yes_type); |
|
137 }; |
|
138 |
|
139 #elif (defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 245) && !defined(__ICL)) \ |
|
140 || defined(__IBMCPP__) || defined(__HP_aCC) |
|
141 // |
|
142 // This is *almost* an ideal world implementation as it doesn't rely |
|
143 // on undefined behaviour by passing UDT's through (...). |
|
144 // Unfortunately it doesn't quite pass all the tests for most compilers (sigh...) |
|
145 // Enable this for your compiler if is_convertible_test.cpp will compile it... |
|
146 // |
|
147 // Note we do not enable this for VC7.1, because even though it passes all the |
|
148 // type_traits tests it is known to cause problems when instantiation occurs |
|
149 // deep within the instantiation tree :-( |
|
150 // |
|
151 struct any_conversion |
|
152 { |
|
153 template <typename T> any_conversion(const volatile T&); |
|
154 // we need this constructor to catch references to functions |
|
155 // (which can not be cv-qualified): |
|
156 template <typename T> any_conversion(T&); |
|
157 }; |
|
158 |
|
159 template <typename From, typename To> |
|
160 struct is_convertible_basic_impl |
|
161 { |
|
162 static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(any_conversion ...); |
|
163 static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(To, int); |
|
164 static From _m_from; |
|
165 |
|
166 BOOST_STATIC_CONSTANT(bool, value = |
|
167 sizeof( _m_check(_m_from, 0) ) == sizeof(::boost::type_traits::yes_type) |
|
168 ); |
|
169 }; |
|
170 |
|
171 #elif defined(__DMC__) |
|
172 |
|
173 struct any_conversion |
|
174 { |
|
175 template <typename T> any_conversion(const volatile T&); |
|
176 // we need this constructor to catch references to functions |
|
177 // (which can not be cv-qualified): |
|
178 template <typename T> any_conversion(T&); |
|
179 }; |
|
180 |
|
181 template <typename From, typename To> |
|
182 struct is_convertible_basic_impl |
|
183 { |
|
184 // Using '...' doesn't always work on Digital Mars. This version seems to. |
|
185 template <class T> |
|
186 static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(any_conversion, float, T); |
|
187 static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(To, int, int); |
|
188 static From _m_from; |
|
189 |
|
190 // Static constants sometime cause the conversion of _m_from to To to be |
|
191 // called. This doesn't happen with an enum. |
|
192 enum { value = |
|
193 sizeof( _m_check(_m_from, 0, 0) ) == sizeof(::boost::type_traits::yes_type) |
|
194 }; |
|
195 }; |
|
196 |
|
197 #elif defined(__MWERKS__) |
|
198 // |
|
199 // CW works with the technique implemented above for EDG, except when From |
|
200 // is a function type (or a reference to such a type), in which case |
|
201 // any_conversion won't be accepted as a valid conversion. We detect this |
|
202 // exceptional situation and channel it through an alternative algorithm. |
|
203 // |
|
204 |
|
205 template <typename From, typename To,bool FromIsFunctionRef> |
|
206 struct is_convertible_basic_impl_aux; |
|
207 |
|
208 struct any_conversion |
|
209 { |
|
210 template <typename T> any_conversion(const volatile T&); |
|
211 }; |
|
212 |
|
213 template <typename From, typename To> |
|
214 struct is_convertible_basic_impl_aux<From,To,false /*FromIsFunctionRef*/> |
|
215 { |
|
216 static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(any_conversion ...); |
|
217 static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(To, int); |
|
218 static From _m_from; |
|
219 |
|
220 BOOST_STATIC_CONSTANT(bool, value = |
|
221 sizeof( _m_check(_m_from, 0) ) == sizeof(::boost::type_traits::yes_type) |
|
222 ); |
|
223 }; |
|
224 |
|
225 template <typename From, typename To> |
|
226 struct is_convertible_basic_impl_aux<From,To,true /*FromIsFunctionRef*/> |
|
227 { |
|
228 static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(...); |
|
229 static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(To); |
|
230 static From _m_from; |
|
231 BOOST_STATIC_CONSTANT(bool, value = |
|
232 sizeof( _m_check(_m_from) ) == sizeof(::boost::type_traits::yes_type) |
|
233 ); |
|
234 }; |
|
235 |
|
236 template <typename From, typename To> |
|
237 struct is_convertible_basic_impl: |
|
238 is_convertible_basic_impl_aux< |
|
239 From,To, |
|
240 ::boost::is_function<typename ::boost::remove_reference<From>::type>::value |
|
241 > |
|
242 {}; |
|
243 |
|
244 #else |
|
245 |
|
246 // |
|
247 // This version seems to work pretty well for a wide spectrum of compilers, |
|
248 // however it does rely on undefined behaviour by passing UDT's through (...). |
|
249 // |
|
250 template <typename From, typename To> |
|
251 struct is_convertible_basic_impl |
|
252 { |
|
253 static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(...); |
|
254 static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(To); |
|
255 static From _m_from; |
|
256 #ifdef BOOST_MSVC |
|
257 #pragma warning(push) |
|
258 #pragma warning(disable:4244) |
|
259 #if BOOST_WORKAROUND(_MSC_FULL_VER, >= 140050000) |
|
260 #pragma warning(disable:6334) |
|
261 #endif |
|
262 #endif |
|
263 BOOST_STATIC_CONSTANT(bool, value = |
|
264 sizeof( _m_check(_m_from) ) == sizeof(::boost::type_traits::yes_type) |
|
265 ); |
|
266 #ifdef BOOST_MSVC |
|
267 #pragma warning(pop) |
|
268 #endif |
|
269 }; |
|
270 |
|
271 #endif // is_convertible_impl |
|
272 |
|
273 #if defined(__DMC__) |
|
274 // As before, a static constant sometimes causes errors on Digital Mars. |
|
275 template <typename From, typename To> |
|
276 struct is_convertible_impl |
|
277 { |
|
278 typedef typename add_reference<From>::type ref_type; |
|
279 enum { value = |
|
280 (::boost::type_traits::ice_and< |
|
281 ::boost::type_traits::ice_or< |
|
282 ::boost::detail::is_convertible_basic_impl<ref_type,To>::value, |
|
283 ::boost::is_void<To>::value |
|
284 >::value, |
|
285 ::boost::type_traits::ice_not< |
|
286 ::boost::is_array<To>::value |
|
287 >::value |
|
288 >::value) }; |
|
289 }; |
|
290 #elif !defined(__BORLANDC__) || __BORLANDC__ > 0x551 |
|
291 template <typename From, typename To> |
|
292 struct is_convertible_impl |
|
293 { |
|
294 typedef typename add_reference<From>::type ref_type; |
|
295 BOOST_STATIC_CONSTANT(bool, value = |
|
296 (::boost::type_traits::ice_and< |
|
297 ::boost::type_traits::ice_or< |
|
298 ::boost::detail::is_convertible_basic_impl<ref_type,To>::value, |
|
299 ::boost::is_void<To>::value |
|
300 >::value, |
|
301 ::boost::type_traits::ice_not< |
|
302 ::boost::is_array<To>::value |
|
303 >::value |
|
304 >::value) |
|
305 ); |
|
306 }; |
|
307 #endif |
|
308 |
|
309 template <bool trivial1, bool trivial2, bool abstract_target> |
|
310 struct is_convertible_impl_select |
|
311 { |
|
312 template <class From, class To> |
|
313 struct rebind |
|
314 { |
|
315 typedef is_convertible_impl<From, To> type; |
|
316 }; |
|
317 }; |
|
318 |
|
319 template <> |
|
320 struct is_convertible_impl_select<true, true, false> |
|
321 { |
|
322 template <class From, class To> |
|
323 struct rebind |
|
324 { |
|
325 typedef true_type type; |
|
326 }; |
|
327 }; |
|
328 |
|
329 template <> |
|
330 struct is_convertible_impl_select<false, false, true> |
|
331 { |
|
332 template <class From, class To> |
|
333 struct rebind |
|
334 { |
|
335 typedef false_type type; |
|
336 }; |
|
337 }; |
|
338 |
|
339 template <> |
|
340 struct is_convertible_impl_select<true, false, true> |
|
341 { |
|
342 template <class From, class To> |
|
343 struct rebind |
|
344 { |
|
345 typedef false_type type; |
|
346 }; |
|
347 }; |
|
348 |
|
349 template <typename From, typename To> |
|
350 struct is_convertible_impl_dispatch_base |
|
351 { |
|
352 #if !BOOST_WORKAROUND(__HP_aCC, < 60700) |
|
353 typedef is_convertible_impl_select< |
|
354 ::boost::is_arithmetic<From>::value, |
|
355 ::boost::is_arithmetic<To>::value, |
|
356 #ifndef BOOST_NO_IS_ABSTRACT |
|
357 ::boost::is_abstract<To>::value |
|
358 #else |
|
359 false |
|
360 #endif |
|
361 > selector; |
|
362 #else |
|
363 typedef is_convertible_impl_select<false, false, false> selector; |
|
364 #endif |
|
365 typedef typename selector::template rebind<From, To> isc_binder; |
|
366 typedef typename isc_binder::type type; |
|
367 }; |
|
368 |
|
369 template <typename From, typename To> |
|
370 struct is_convertible_impl_dispatch |
|
371 : public is_convertible_impl_dispatch_base<From, To>::type |
|
372 {}; |
|
373 |
|
374 // |
|
375 // Now add the full and partial specialisations |
|
376 // for void types, these are common to all the |
|
377 // implementation above: |
|
378 // |
|
379 #ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS |
|
380 # define TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2_PART1(trait,spec1,spec2,value) \ |
|
381 BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC2(trait,spec1,spec2,value) \ |
|
382 BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC2(trait,spec1,spec2 const,value) \ |
|
383 BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC2(trait,spec1,spec2 volatile,value) \ |
|
384 BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC2(trait,spec1,spec2 const volatile,value) \ |
|
385 /**/ |
|
386 |
|
387 # define TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2(trait,spec1,spec2,value) \ |
|
388 TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2_PART1(trait,spec1,spec2,value) \ |
|
389 TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2_PART1(trait,spec1 const,spec2,value) \ |
|
390 TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2_PART1(trait,spec1 volatile,spec2,value) \ |
|
391 TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2_PART1(trait,spec1 const volatile,spec2,value) \ |
|
392 /**/ |
|
393 |
|
394 TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2(is_convertible,void,void,true) |
|
395 |
|
396 # undef TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2 |
|
397 # undef TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2_PART1 |
|
398 |
|
399 #else |
|
400 BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC2(is_convertible,void,void,true) |
|
401 #endif // BOOST_NO_CV_VOID_SPECIALIZATIONS |
|
402 |
|
403 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
|
404 BOOST_TT_AUX_BOOL_TRAIT_IMPL_PARTIAL_SPEC2_1(typename To,is_convertible,void,To,false) |
|
405 BOOST_TT_AUX_BOOL_TRAIT_IMPL_PARTIAL_SPEC2_1(typename From,is_convertible,From,void,true) |
|
406 #ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS |
|
407 BOOST_TT_AUX_BOOL_TRAIT_IMPL_PARTIAL_SPEC2_1(typename To,is_convertible,void const,To,false) |
|
408 BOOST_TT_AUX_BOOL_TRAIT_IMPL_PARTIAL_SPEC2_1(typename To,is_convertible,void volatile,To,false) |
|
409 BOOST_TT_AUX_BOOL_TRAIT_IMPL_PARTIAL_SPEC2_1(typename To,is_convertible,void const volatile,To,false) |
|
410 BOOST_TT_AUX_BOOL_TRAIT_IMPL_PARTIAL_SPEC2_1(typename From,is_convertible,From,void const,true) |
|
411 BOOST_TT_AUX_BOOL_TRAIT_IMPL_PARTIAL_SPEC2_1(typename From,is_convertible,From,void volatile,true) |
|
412 BOOST_TT_AUX_BOOL_TRAIT_IMPL_PARTIAL_SPEC2_1(typename From,is_convertible,From,void const volatile,true) |
|
413 #endif |
|
414 #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
|
415 |
|
416 } // namespace detail |
|
417 |
|
418 BOOST_TT_AUX_BOOL_TRAIT_DEF2(is_convertible,From,To,(::boost::detail::is_convertible_impl_dispatch<From,To>::value)) |
|
419 |
|
420 #else |
|
421 |
|
422 BOOST_TT_AUX_BOOL_TRAIT_DEF2(is_convertible,From,To,BOOST_IS_CONVERTIBLE(From,To)) |
|
423 |
|
424 #endif |
|
425 |
|
426 } // namespace boost |
|
427 |
|
428 #include <boost/type_traits/detail/bool_trait_undef.hpp> |
|
429 |
|
430 #endif // BOOST_TT_IS_CONVERTIBLE_HPP_INCLUDED |