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