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