2
// Copyright (C) 2000 John Maddock (john_maddock@compuserve.com)
3
// Copyright (C) 2000 Jeremy Siek (jsiek@lsc.nd.edu)
4
// Copyright (C) 1999, 2000 Jaakko Jļæ½rvi (jaakko.jarvi@cs.utu.fi)
6
// Permission to copy and use this software is granted,
7
// provided this copyright notice appears in all copies.
8
// Permission to modify the code and to distribute modified code is granted,
9
// provided this copyright notice appears in all copies, and a notice
10
// that the code was modified is included with the copyright notice.
12
// This software is provided "as is" without express or implied warranty,
13
// and with no claim as to its suitability for any purpose.
16
#ifndef BOOST_TT_IS_CONVERTIBLE_HPP_INCLUDED
17
#define BOOST_TT_IS_CONVERTIBLE_HPP_INCLUDED
19
#include "boost/type_traits/detail/yes_no_type.hpp"
20
#include "boost/type_traits/config.hpp"
21
#include "boost/type_traits/is_array.hpp"
22
#include "boost/type_traits/add_reference.hpp"
23
#include "boost/type_traits/ice.hpp"
25
#if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300)
26
# include "boost/type_traits/is_void.hpp"
29
// should be always the last #include directive
30
#include "boost/type_traits/detail/bool_trait_def.hpp"
34
// is one type convertable to another?
36
// there are multiple versions of the is_convertible
37
// template, almost every compiler seems to require its
40
// Thanks to Andrei Alexandrescu for the original version of the
41
// conversion detection technique!
46
// MS specific version:
48
#if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300)
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;
56
template< typename From >
57
struct does_conversion_exist
59
template< typename To > struct result_
61
static no_type BOOST_TT_DECL _m_check(...);
62
static yes_type BOOST_TT_DECL _m_check(To);
64
enum { value = sizeof( _m_check(_m_from) ) == sizeof(yes_type) };
69
struct does_conversion_exist<void>
71
template< typename To > struct result_
73
enum { value = ::boost::is_void<To>::value };
77
template <typename From, typename To>
78
struct is_convertible_basic_impl
79
: does_conversion_exist<From>::template result_<To>
83
#elif defined(__BORLANDC__) && (__BORLANDC__ < 0x560)
85
// special version for Borland compilers
86
// this version breaks when used for some
89
template <typename From, typename To>
90
struct is_convertible_impl
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
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);
102
static bool const value = sizeof( checker<To>::_m_check(_m_from) )
103
== sizeof(::boost::type_traits::yes_type);
107
#elif defined(__GNUC__) || defined(__BORLANDC__)
108
// special version for gcc compiler + recent Borland versions
109
// note that this does not pass UDT's through (...)
111
struct any_conversion
113
template <typename T> any_conversion(const volatile T&);
114
//template <typename T> any_conversion(T&);
117
template <typename T> struct checker
119
static boost::type_traits::no_type _m_check(any_conversion ...);
120
static boost::type_traits::yes_type _m_check(T, int);
123
template <typename From, typename To>
124
struct is_convertible_basic_impl
127
static bool const value = sizeof( detail::checker<To>::_m_check(_m_from, 0) )
128
== sizeof(::boost::type_traits::yes_type);
131
#elif (defined(BOOST_MSVC) && (BOOST_MSVC > 1310)) \
132
|| (defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 245) && !defined(__ICL))
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...
139
struct any_conversion
141
template <typename T> any_conversion(const volatile T&);
142
// we need this constructor to catch references to functions
143
// (which can not be cv-qualified):
144
template <typename T> any_conversion(T&);
147
template <typename From, typename To>
148
struct is_convertible_basic_impl
150
static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(any_conversion ...);
151
static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(To, int);
154
BOOST_STATIC_CONSTANT(bool, value =
155
sizeof( _m_check(_m_from, 0) ) == sizeof(::boost::type_traits::yes_type)
162
// This version seems to work pretty well for a wide spectrum of compilers,
163
// however it does rely on undefined behaviour by passing UDT's through (...).
165
template <typename From, typename To>
166
struct is_convertible_basic_impl
168
static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(...);
169
static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(To);
172
BOOST_STATIC_CONSTANT(bool, value =
173
sizeof( _m_check(_m_from) ) == sizeof(::boost::type_traits::yes_type)
177
#endif // is_convertible_impl
179
#if !defined(__BORLANDC__) || __BORLANDC__ > 0x551
180
template <typename From, typename To>
181
struct is_convertible_impl
183
typedef typename add_reference<From>::type ref_type;
184
BOOST_STATIC_CONSTANT(bool, value =
185
(::boost::type_traits::ice_and<
186
::boost::detail::is_convertible_basic_impl<ref_type,To>::value,
187
::boost::type_traits::ice_not<
188
::boost::is_array<To>::value
196
// Now add the full and partial specialisations
197
// for void types, these are common to all the
198
// implementation above:
200
#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
201
# define TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2_PART1(trait,spec1,spec2,value) \
202
BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC2(trait,spec1,spec2,value) \
203
BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC2(trait,spec1,spec2 const,value) \
204
BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC2(trait,spec1,spec2 volatile,value) \
205
BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC2(trait,spec1,spec2 const volatile,value) \
208
# define TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2(trait,spec1,spec2,value) \
209
TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2_PART1(trait,spec1,spec2,value) \
210
TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2_PART1(trait,spec1 const,spec2,value) \
211
TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2_PART1(trait,spec1 volatile,spec2,value) \
212
TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2_PART1(trait,spec1 const volatile,spec2,value) \
215
TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2(is_convertible,void,void,true)
217
# undef TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2
218
# undef TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2_PART1
221
BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC2(is_convertible,void,void,true)
222
#endif // BOOST_NO_CV_VOID_SPECIALIZATIONS
224
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
225
BOOST_TT_AUX_BOOL_TRAIT_IMPL_PARTIAL_SPEC2_1(typename To,is_convertible,void,To,false)
226
BOOST_TT_AUX_BOOL_TRAIT_IMPL_PARTIAL_SPEC2_1(typename From,is_convertible,From,void,false)
227
#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
228
BOOST_TT_AUX_BOOL_TRAIT_IMPL_PARTIAL_SPEC2_1(typename To,is_convertible,void const,To,false)
229
BOOST_TT_AUX_BOOL_TRAIT_IMPL_PARTIAL_SPEC2_1(typename To,is_convertible,void volatile,To,false)
230
BOOST_TT_AUX_BOOL_TRAIT_IMPL_PARTIAL_SPEC2_1(typename To,is_convertible,void const volatile,To,false)
231
BOOST_TT_AUX_BOOL_TRAIT_IMPL_PARTIAL_SPEC2_1(typename From,is_convertible,From,void const,false)
232
BOOST_TT_AUX_BOOL_TRAIT_IMPL_PARTIAL_SPEC2_1(typename From,is_convertible,From,void volatile,false)
233
BOOST_TT_AUX_BOOL_TRAIT_IMPL_PARTIAL_SPEC2_1(typename From,is_convertible,From,void const volatile,false)
235
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
237
} // namespace detail
239
BOOST_TT_AUX_BOOL_TRAIT_DEF2(is_convertible,From,To,(::boost::detail::is_convertible_impl<From,To>::value))
242
#if defined(__GNUC__)
244
// Declare specializations of is_convertible for all of the floating
245
// types to all of the integral types. This suppresses some nasty
248
# define TT_AUX_IS_CONVERTIBLE_SPEC(T1,T2) \
249
BOOST_TT_AUX_BOOL_TRAIT_SPEC2(is_convertible,T1,T2,true) \
252
# define TT_AUX_IS_CONVERTIBLE_SPEC_2(T1,T2) \
253
TT_AUX_IS_CONVERTIBLE_SPEC(T1,signed T2) \
254
TT_AUX_IS_CONVERTIBLE_SPEC(T1,unsigned T2) \
257
# define TT_AUX_IS_CONVERTIBLE_FROM_FLOAT_SPEC(F) \
258
TT_AUX_IS_CONVERTIBLE_SPEC(F,char) \
259
TT_AUX_IS_CONVERTIBLE_SPEC_2(F,char) \
260
TT_AUX_IS_CONVERTIBLE_SPEC_2(F,short) \
261
TT_AUX_IS_CONVERTIBLE_SPEC_2(F,int) \
262
TT_AUX_IS_CONVERTIBLE_SPEC_2(F,long) \
263
TT_AUX_IS_CONVERTIBLE_SPEC_2(F,long long) \
266
# define TT_AUX_IS_CONVERTIBLE_FROM_FLOAT_CV_SPEC(F) \
267
TT_AUX_IS_CONVERTIBLE_FROM_FLOAT_SPEC(F const) \
268
TT_AUX_IS_CONVERTIBLE_FROM_FLOAT_SPEC(F volatile) \
269
TT_AUX_IS_CONVERTIBLE_FROM_FLOAT_SPEC(F const volatile) \
272
TT_AUX_IS_CONVERTIBLE_FROM_FLOAT_CV_SPEC(float)
273
TT_AUX_IS_CONVERTIBLE_FROM_FLOAT_CV_SPEC(double)
274
TT_AUX_IS_CONVERTIBLE_FROM_FLOAT_CV_SPEC(long double)
276
# undef TT_AUX_IS_CONVERTIBLE_FROM_FLOAT_CV_SPEC
277
# undef TT_AUX_IS_CONVERTIBLE_FROM_FLOAT_SPEC
278
# undef TT_AUX_IS_CONVERTIBLE_SPEC_2
279
# undef TT_AUX_IS_CONVERTIBLE_SPEC
285
#include "boost/type_traits/detail/bool_trait_undef.hpp"
287
#endif // BOOST_TT_IS_CONVERTIBLE_HPP_INCLUDED