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