fix doc example typo
[boost.git] / boost / type_traits / is_convertible.hpp
blobce522a08429fa6fec1faa2819048061a8e8eadd5
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.
12 #ifndef BOOST_TT_IS_CONVERTIBLE_HPP_INCLUDED
13 #define BOOST_TT_IS_CONVERTIBLE_HPP_INCLUDED
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
28 #if defined(__MWERKS__)
29 #include <boost/type_traits/is_function.hpp>
30 #include <boost/type_traits/remove_reference.hpp>
31 #endif
33 #endif // BOOST_IS_CONVERTIBLE
35 // should be always the last #include directive
36 #include <boost/type_traits/detail/bool_trait_def.hpp>
38 namespace boost {
40 #ifndef BOOST_IS_CONVERTIBLE
42 // is one type convertable to another?
44 // there are multiple versions of the is_convertible
45 // template, almost every compiler seems to require its
46 // own version.
48 // Thanks to Andrei Alexandrescu for the original version of the
49 // conversion detection technique!
52 namespace detail {
54 // MS specific version:
56 #if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300)
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;
64 template< typename From >
65 struct does_conversion_exist
67 template< typename To > struct result_
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) };
76 template<>
77 struct does_conversion_exist<void>
79 template< typename To > struct result_
81 enum { value = ::boost::is_void<To>::value };
85 template <typename From, typename To>
86 struct is_convertible_basic_impl
87 : does_conversion_exist<From>::template result_<To>
91 #elif defined(__BORLANDC__) && (__BORLANDC__ < 0x560)
93 // special version for Borland compilers
94 // this version breaks when used for some
95 // UDT conversions:
97 template <typename From, typename To>
98 struct is_convertible_impl
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
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);
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
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 (...)
119 struct any_conversion
121 template <typename T> any_conversion(const volatile T&);
122 template <typename T> any_conversion(T&);
125 template <typename T> struct checker
127 static boost::type_traits::no_type _m_check(any_conversion ...);
128 static boost::type_traits::yes_type _m_check(T, int);
131 template <typename From, typename To>
132 struct is_convertible_basic_impl
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);
139 #elif (defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 245) && !defined(__ICL)) \
140 || defined(__IBMCPP__) || defined(__HP_aCC)
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...
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 :-(
151 struct any_conversion
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&);
159 template <typename From, typename To>
160 struct is_convertible_basic_impl
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;
166 BOOST_STATIC_CONSTANT(bool, value =
167 sizeof( _m_check(_m_from, 0) ) == sizeof(::boost::type_traits::yes_type)
171 #elif defined(__DMC__)
173 struct any_conversion
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&);
181 template <typename From, typename To>
182 struct is_convertible_basic_impl
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;
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)
197 #elif defined(__MWERKS__)
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.
205 template <typename From, typename To,bool FromIsFunctionRef>
206 struct is_convertible_basic_impl_aux;
208 struct any_conversion
210 template <typename T> any_conversion(const volatile T&);
213 template <typename From, typename To>
214 struct is_convertible_basic_impl_aux<From,To,false /*FromIsFunctionRef*/>
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;
220 BOOST_STATIC_CONSTANT(bool, value =
221 sizeof( _m_check(_m_from, 0) ) == sizeof(::boost::type_traits::yes_type)
225 template <typename From, typename To>
226 struct is_convertible_basic_impl_aux<From,To,true /*FromIsFunctionRef*/>
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)
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
244 #else
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 (...).
250 template <typename From, typename To>
251 struct is_convertible_basic_impl
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)
266 #ifdef BOOST_MSVC
267 #pragma warning(pop)
268 #endif
271 #endif // is_convertible_impl
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
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) };
290 #elif !defined(__BORLANDC__) || __BORLANDC__ > 0x551
291 template <typename From, typename To>
292 struct is_convertible_impl
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)
307 #endif
309 template <bool trivial1, bool trivial2, bool abstract_target>
310 struct is_convertible_impl_select
312 template <class From, class To>
313 struct rebind
315 typedef is_convertible_impl<From, To> type;
319 template <>
320 struct is_convertible_impl_select<true, true, false>
322 template <class From, class To>
323 struct rebind
325 typedef true_type type;
329 template <>
330 struct is_convertible_impl_select<false, false, true>
332 template <class From, class To>
333 struct rebind
335 typedef false_type type;
339 template <>
340 struct is_convertible_impl_select<true, false, true>
342 template <class From, class To>
343 struct rebind
345 typedef false_type type;
349 template <typename From, typename To>
350 struct is_convertible_impl_dispatch_base
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;
369 template <typename From, typename To>
370 struct is_convertible_impl_dispatch
371 : public is_convertible_impl_dispatch_base<From, To>::type
375 // Now add the full and partial specialisations
376 // for void types, these are common to all the
377 // implementation above:
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 /**/
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 /**/
394 TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2(is_convertible,void,void,true)
396 # undef TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2
397 # undef TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2_PART1
399 #else
400 BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC2(is_convertible,void,void,true)
401 #endif // BOOST_NO_CV_VOID_SPECIALIZATIONS
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
416 } // namespace detail
418 BOOST_TT_AUX_BOOL_TRAIT_DEF2(is_convertible,From,To,(::boost::detail::is_convertible_impl_dispatch<From,To>::value))
420 #else
422 BOOST_TT_AUX_BOOL_TRAIT_DEF2(is_convertible,From,To,BOOST_IS_CONVERTIBLE(From,To))
424 #endif
426 } // namespace boost
428 #include <boost/type_traits/detail/bool_trait_undef.hpp>
430 #endif // BOOST_TT_IS_CONVERTIBLE_HPP_INCLUDED