source: NonGTP/Boost/boost/type_traits/is_convertible.hpp @ 857

Revision 857, 11.4 KB checked in by igarcia, 18 years ago (diff)
Line 
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„rvi (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#ifndef BOOST_NO_IS_ABSTRACT
22#include "boost/type_traits/is_abstract.hpp"
23#endif
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
32namespace 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
44namespace 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.
53using ::boost::type_traits::yes_type;
54using ::boost::type_traits::no_type;
55
56template< typename From >
57struct 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
68template<>
69struct does_conversion_exist<void>
70{
71    template< typename To > struct result_
72    {
73        enum { value = ::boost::is_void<To>::value };
74    };
75};
76
77template <typename From, typename To>
78struct 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//
89template <typename From, typename To>
90struct 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__) && (__BORLANDC__ < 0x600)
108// special version for gcc compiler + recent Borland versions
109// note that this does not pass UDT's through (...)
110
111struct any_conversion
112{
113    template <typename T> any_conversion(const volatile T&);
114    template <typename T> any_conversion(T&);
115};
116
117template <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
123template <typename From, typename To>
124struct 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(__EDG_VERSION__) && (__EDG_VERSION__ >= 245) && !defined(__ICL)) \
132      || defined(__IBMCPP__) || defined(__HP_aCC)
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// Note we do not enable this for VC7.1, because even though it passes all the
140// type_traits tests it is known to cause problems when instantiation occurs
141// deep within the instantiation tree :-(
142//
143struct any_conversion
144{
145    template <typename T> any_conversion(const volatile T&);
146    // we need this constructor to catch references to functions
147    // (which can not be cv-qualified):
148    template <typename T> any_conversion(T&);
149};
150
151template <typename From, typename To>
152struct is_convertible_basic_impl
153{
154    static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(any_conversion ...);
155    static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(To, int);
156       static From _m_from;
157
158    BOOST_STATIC_CONSTANT(bool, value =
159        sizeof( _m_check(_m_from, 0) ) == sizeof(::boost::type_traits::yes_type)
160        );
161};
162
163#elif defined(__DMC__)
164
165struct any_conversion
166{
167    template <typename T> any_conversion(const 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
173template <typename From, typename To>
174struct is_convertible_basic_impl
175{
176    // Using '...' doesn't always work on Digital Mars. This version seems to.
177    template <class T>
178    static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(any_conversion,  float, T);
179    static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(To, int, int);
180    static From _m_from;
181
182    // Static constants sometime cause the conversion of _m_from to To to be
183    // called. This doesn't happen with an enum.
184    enum { value =
185        sizeof( _m_check(_m_from, 0, 0) ) == sizeof(::boost::type_traits::yes_type)
186        };
187};
188
189#else
190
191//
192// This version seems to work pretty well for a wide spectrum of compilers,
193// however it does rely on undefined behaviour by passing UDT's through (...).
194//
195template <typename From, typename To>
196struct is_convertible_basic_impl
197{
198    static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(...);
199    static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(To);
200    static From _m_from;
201
202    BOOST_STATIC_CONSTANT(bool, value =
203        sizeof( _m_check(_m_from) ) == sizeof(::boost::type_traits::yes_type)
204        );
205};
206
207#endif // is_convertible_impl
208
209#if defined(__DMC__)
210// As before, a static constant sometimes causes errors on Digital Mars.
211template <typename From, typename To>
212struct is_convertible_impl
213{
214    typedef typename add_reference<From>::type ref_type;
215    enum { value =
216        ::boost::type_traits::ice_and<
217            ::boost::detail::is_convertible_basic_impl<ref_type, To>::value,
218            ::boost::type_traits::ice_not<
219                ::boost::is_array<To>::value
220            >::value,
221        >::value };
222};
223#elif !defined(__BORLANDC__) || __BORLANDC__ > 0x551
224template <typename From, typename To>
225struct is_convertible_impl
226{
227    typedef typename add_reference<From>::type ref_type;
228    BOOST_STATIC_CONSTANT(bool, value =
229        (::boost::type_traits::ice_and<
230            ::boost::detail::is_convertible_basic_impl<ref_type,To>::value,
231            ::boost::type_traits::ice_not<
232               ::boost::is_array<To>::value
233            >::value
234        >::value)
235        );
236};
237#endif
238
239template <bool trivial1, bool trivial2, bool abstract_target>
240struct is_convertible_impl_select
241{
242   template <class From, class To>
243   struct rebind
244   {
245      typedef is_convertible_impl<From, To> type;
246   };
247};
248
249template <>
250struct is_convertible_impl_select<true, true, false>
251{
252   template <class From, class To>
253   struct rebind
254   {
255      typedef true_type type;
256   };
257};
258
259template <>
260struct is_convertible_impl_select<false, false, true>
261{
262   template <class From, class To>
263   struct rebind
264   {
265      typedef false_type type;
266   };
267};
268
269template <>
270struct is_convertible_impl_select<true, false, true>
271{
272   template <class From, class To>
273   struct rebind
274   {
275      typedef false_type type;
276   };
277};
278
279template <typename From, typename To>
280struct is_convertible_impl_dispatch_base
281{
282#ifndef __HP_aCC
283   typedef is_convertible_impl_select<
284      ::boost::is_arithmetic<From>::value,
285      ::boost::is_arithmetic<To>::value,
286#ifndef BOOST_NO_IS_ABSTRACT
287      ::boost::is_abstract<To>::value
288#else
289      false
290#endif
291   > selector;
292#else
293   typedef is_convertible_impl_select<false, false, false> selector;
294#endif
295   typedef typename selector::template rebind<From, To> isc_binder;
296   typedef typename isc_binder::type type;
297};
298
299template <typename From, typename To>
300struct is_convertible_impl_dispatch
301   : public is_convertible_impl_dispatch_base<From, To>::type
302{};
303
304//
305// Now add the full and partial specialisations
306// for void types, these are common to all the
307// implementation above:
308//
309#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
310#   define TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2_PART1(trait,spec1,spec2,value) \
311    BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC2(trait,spec1,spec2,value) \
312    BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC2(trait,spec1,spec2 const,value) \
313    BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC2(trait,spec1,spec2 volatile,value) \
314    BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC2(trait,spec1,spec2 const volatile,value) \
315    /**/
316
317#   define TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2(trait,spec1,spec2,value) \
318    TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2_PART1(trait,spec1,spec2,value) \
319    TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2_PART1(trait,spec1 const,spec2,value) \
320    TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2_PART1(trait,spec1 volatile,spec2,value) \
321    TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2_PART1(trait,spec1 const volatile,spec2,value) \
322    /**/
323
324    TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2(is_convertible,void,void,true)
325
326#   undef TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2
327#   undef TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2_PART1
328
329#else
330    BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC2(is_convertible,void,void,true)
331#endif // BOOST_NO_CV_VOID_SPECIALIZATIONS
332
333#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
334BOOST_TT_AUX_BOOL_TRAIT_IMPL_PARTIAL_SPEC2_1(typename To,is_convertible,void,To,false)
335BOOST_TT_AUX_BOOL_TRAIT_IMPL_PARTIAL_SPEC2_1(typename From,is_convertible,From,void,false)
336#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
337BOOST_TT_AUX_BOOL_TRAIT_IMPL_PARTIAL_SPEC2_1(typename To,is_convertible,void const,To,false)
338BOOST_TT_AUX_BOOL_TRAIT_IMPL_PARTIAL_SPEC2_1(typename To,is_convertible,void volatile,To,false)
339BOOST_TT_AUX_BOOL_TRAIT_IMPL_PARTIAL_SPEC2_1(typename To,is_convertible,void const volatile,To,false)
340BOOST_TT_AUX_BOOL_TRAIT_IMPL_PARTIAL_SPEC2_1(typename From,is_convertible,From,void const,false)
341BOOST_TT_AUX_BOOL_TRAIT_IMPL_PARTIAL_SPEC2_1(typename From,is_convertible,From,void volatile,false)
342BOOST_TT_AUX_BOOL_TRAIT_IMPL_PARTIAL_SPEC2_1(typename From,is_convertible,From,void const volatile,false)
343#endif
344#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
345
346} // namespace detail
347
348BOOST_TT_AUX_BOOL_TRAIT_DEF2(is_convertible,From,To,(::boost::detail::is_convertible_impl_dispatch<From,To>::value))
349
350} // namespace boost
351
352#include "boost/type_traits/detail/bool_trait_undef.hpp"
353
354#endif // BOOST_TT_IS_CONVERTIBLE_HPP_INCLUDED
Note: See TracBrowser for help on using the repository browser.