]> git.donarmstrong.com Git - rsem.git/blob - boost/type_traits/is_convertible.hpp
c05c297eaf9b8208c081aeec63e4c49ef52db9e6
[rsem.git] / boost / type_traits / is_convertible.hpp
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( boost::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(BOOST_MSVC_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