]> git.lyx.org Git - lyx.git/blob - boost/boost/type_traits/is_convertible.hpp
update boost to pre-1.30.0
[lyx.git] / boost / boost / type_traits / is_convertible.hpp
1
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\84rvi (jaakko.jarvi@cs.utu.fi)
5 //
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.
11 //
12 // This software is provided "as is" without express or implied warranty, 
13 // and with no claim as to its suitability for any purpose.
14 //
15
16 #ifndef BOOST_TT_IS_CONVERTIBLE_HPP_INCLUDED
17 #define BOOST_TT_IS_CONVERTIBLE_HPP_INCLUDED
18
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"
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__)
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(BOOST_MSVC) && (BOOST_MSVC >= 1310) && _MSC_FULL_VER > 13102292) \
132       || (defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 245) && !defined(__ICL))
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 struct any_conversion
140 {
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&);
145 };
146
147 template <typename From, typename To>
148 struct is_convertible_basic_impl
149 {
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);
152             static From _m_from;
153
154     BOOST_STATIC_CONSTANT(bool, value = 
155         sizeof( _m_check(_m_from, 0) ) == sizeof(::boost::type_traits::yes_type)
156         );
157 };
158
159 #else
160
161 //
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 (...).
164 //
165 template <typename From, typename To>
166 struct is_convertible_basic_impl
167 {
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);
170     static From _m_from;
171
172     BOOST_STATIC_CONSTANT(bool, value =
173         sizeof( _m_check(_m_from) ) == sizeof(::boost::type_traits::yes_type)
174         );
175 };
176
177 #endif // is_convertible_impl
178
179 #if !defined(__BORLANDC__) || __BORLANDC__ > 0x551
180 template <typename From, typename To>
181 struct is_convertible_impl
182 {
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
189             >::value
190         >::value)
191         );
192 };
193 #endif
194
195 //
196 // Now add the full and partial specialisations
197 // for void types, these are common to all the
198 // implementation above:
199 //
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) \
206     /**/
207
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) \
213     /**/
214
215     TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2(is_convertible,void,void,true)
216
217 #   undef TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2
218 #   undef TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2_PART1
219
220 #else
221     BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC2(is_convertible,void,void,true)
222 #endif // BOOST_NO_CV_VOID_SPECIALIZATIONS
223
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)
234 #endif
235 #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
236
237 } // namespace detail
238
239 BOOST_TT_AUX_BOOL_TRAIT_DEF2(is_convertible,From,To,(::boost::detail::is_convertible_impl<From,To>::value))
240
241
242 #if defined(__GNUC__)
243
244 // Declare specializations of is_convertible for all of the floating
245 // types to all of the integral types. This suppresses some nasty
246 // warnings
247
248 #   define TT_AUX_IS_CONVERTIBLE_SPEC(T1,T2) \
249     BOOST_TT_AUX_BOOL_TRAIT_SPEC2(is_convertible,T1,T2,true) \
250     /**/
251
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) \
255     /**/
256
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) \
264     /**/
265
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) \
270     /**/
271
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)
275
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
280
281 #endif // __GNUC__
282
283 } // namespace boost
284
285 #include "boost/type_traits/detail/bool_trait_undef.hpp"
286
287 #endif // BOOST_TT_IS_CONVERTIBLE_HPP_INCLUDED