489 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			489 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
 | |
| // Copyright 2000 John Maddock (john@johnmaddock.co.uk)
 | |
| // Copyright 2000 Jeremy Siek (jsiek@lsc.nd.edu)
 | |
| // Copyright 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
 | |
| //
 | |
| //  Use, modification and distribution are subject to the Boost Software License,
 | |
| //  Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
 | |
| //  http://www.boost.org/LICENSE_1_0.txt).
 | |
| //
 | |
| //  See http://www.boost.org/libs/type_traits for most recent version including documentation.
 | |
| 
 | |
| #ifndef BOOST_TT_IS_CONVERTIBLE_HPP_INCLUDED
 | |
| #define BOOST_TT_IS_CONVERTIBLE_HPP_INCLUDED
 | |
| 
 | |
| #include <boost/type_traits/intrinsics.hpp>
 | |
| #include <boost/type_traits/integral_constant.hpp>
 | |
| #ifndef BOOST_IS_CONVERTIBLE
 | |
| #include <boost/type_traits/detail/yes_no_type.hpp>
 | |
| #include <boost/type_traits/detail/config.hpp>
 | |
| #include <boost/type_traits/is_array.hpp>
 | |
| #include <boost/type_traits/is_arithmetic.hpp>
 | |
| #include <boost/type_traits/is_void.hpp>
 | |
| #if !defined(BOOST_NO_IS_ABSTRACT)
 | |
| #include <boost/type_traits/is_abstract.hpp>
 | |
| #endif
 | |
| #include <boost/type_traits/add_lvalue_reference.hpp>
 | |
| #include <boost/type_traits/add_rvalue_reference.hpp>
 | |
| #include <boost/type_traits/is_function.hpp>
 | |
| 
 | |
| #if defined(__MWERKS__)
 | |
| #include <boost/type_traits/remove_reference.hpp>
 | |
| #endif
 | |
| #if !defined(BOOST_NO_SFINAE_EXPR) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
 | |
| #  include <boost/type_traits/declval.hpp>
 | |
| #endif
 | |
| #elif defined(BOOST_MSVC) || defined(BOOST_INTEL)
 | |
| #include <boost/type_traits/is_function.hpp>
 | |
| #include <boost/type_traits/is_same.hpp>
 | |
| #endif // BOOST_IS_CONVERTIBLE
 | |
| 
 | |
| namespace boost {
 | |
| 
 | |
| #ifndef BOOST_IS_CONVERTIBLE
 | |
| 
 | |
| // is one type convertible to another?
 | |
| //
 | |
| // there are multiple versions of the is_convertible
 | |
| // template, almost every compiler seems to require its
 | |
| // own version.
 | |
| //
 | |
| // Thanks to Andrei Alexandrescu for the original version of the
 | |
| // conversion detection technique!
 | |
| //
 | |
| 
 | |
| namespace detail {
 | |
| 
 | |
| #if !defined(BOOST_NO_SFINAE_EXPR) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !(defined(BOOST_GCC) && (BOOST_GCC < 40700))
 | |
| 
 | |
|    // This is a C++11 conforming version, place this first and use it wherever possible:
 | |
| 
 | |
| #  define BOOST_TT_CXX11_IS_CONVERTIBLE
 | |
| 
 | |
|    template <class A, class B, class C>
 | |
|    struct or_helper
 | |
|    {
 | |
|       static const bool value = (A::value || B::value || C::value);
 | |
|    };
 | |
| 
 | |
|    template<typename From, typename To, bool b = or_helper<boost::is_void<From>, boost::is_function<To>, boost::is_array<To> >::value>
 | |
|    struct is_convertible_basic_impl
 | |
|    {
 | |
|       // Nothing converts to function or array, but void converts to void:
 | |
|       static const bool value = is_void<To>::value; 
 | |
|    };
 | |
| 
 | |
|    template<typename From, typename To>
 | |
|    class is_convertible_basic_impl<From, To, false>
 | |
|    {
 | |
|       typedef char one;
 | |
|       typedef int  two;
 | |
| 
 | |
|       template<typename To1>
 | |
|       static void test_aux(To1);
 | |
| 
 | |
|       template<typename From1, typename To1>
 | |
|       static decltype(test_aux<To1>(boost::declval<From1>()), one()) test(int);
 | |
| 
 | |
|       template<typename, typename>
 | |
|       static two test(...);
 | |
| 
 | |
|    public:
 | |
|       static const bool value = sizeof(test<From, To>(0)) == 1;
 | |
|    };
 | |
| 
 | |
| #elif defined(__BORLANDC__) && (__BORLANDC__ < 0x560)
 | |
| //
 | |
| // special version for Borland compilers
 | |
| // this version breaks when used for some
 | |
| // UDT conversions:
 | |
| //
 | |
| template <typename From, typename To>
 | |
| struct is_convertible_impl
 | |
| {
 | |
| #pragma option push -w-8074
 | |
|     // This workaround for Borland breaks the EDG C++ frontend,
 | |
|     // so we only use it for Borland.
 | |
|     template <typename T> struct checker
 | |
|     {
 | |
|         static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(...);
 | |
|         static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(T);
 | |
|     };
 | |
| 
 | |
|     static typename add_lvalue_reference<From>::type  _m_from;
 | |
|     static bool const value = sizeof( checker<To>::_m_check(_m_from) )
 | |
|         == sizeof(::boost::type_traits::yes_type);
 | |
| #pragma option pop
 | |
| };
 | |
| 
 | |
| #elif defined(__GNUC__) || defined(__BORLANDC__) && (__BORLANDC__ < 0x600)
 | |
| // special version for gcc compiler + recent Borland versions
 | |
| // note that this does not pass UDT's through (...)
 | |
| 
 | |
| struct any_conversion
 | |
| {
 | |
|     template <typename T> any_conversion(const volatile T&);
 | |
|     template <typename T> any_conversion(const T&);
 | |
|     template <typename T> any_conversion(volatile T&);
 | |
|     template <typename T> any_conversion(T&);
 | |
| };
 | |
| 
 | |
| template <typename T> struct checker
 | |
| {
 | |
|     static boost::type_traits::no_type _m_check(any_conversion ...);
 | |
|     static boost::type_traits::yes_type _m_check(T, int);
 | |
| };
 | |
| 
 | |
| template <typename From, typename To>
 | |
| struct is_convertible_basic_impl
 | |
| {
 | |
|     typedef typename add_lvalue_reference<From>::type lvalue_type;
 | |
|     typedef typename add_rvalue_reference<From>::type rvalue_type;
 | |
|     static lvalue_type _m_from;
 | |
| #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 6)))
 | |
|     static bool const value =
 | |
|         sizeof( boost::detail::checker<To>::_m_check(static_cast<rvalue_type>(_m_from), 0) )
 | |
|         == sizeof(::boost::type_traits::yes_type);
 | |
| #else
 | |
|     static bool const value =
 | |
|         sizeof( boost::detail::checker<To>::_m_check(_m_from, 0) )
 | |
|         == sizeof(::boost::type_traits::yes_type);
 | |
| #endif
 | |
| };
 | |
| 
 | |
| #elif (defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 245) && !defined(__ICL)) \
 | |
|       || defined(__IBMCPP__) || defined(__HP_aCC)
 | |
| //
 | |
| // This is *almost* an ideal world implementation as it doesn't rely
 | |
| // on undefined behaviour by passing UDT's through (...).
 | |
| // Unfortunately it doesn't quite pass all the tests for most compilers (sigh...)
 | |
| // Enable this for your compiler if is_convertible_test.cpp will compile it...
 | |
| //
 | |
| // Note we do not enable this for VC7.1, because even though it passes all the
 | |
| // type_traits tests it is known to cause problems when instantiation occurs
 | |
| // deep within the instantiation tree :-(
 | |
| //
 | |
| struct any_conversion
 | |
| {
 | |
|     template <typename T> any_conversion(const volatile T&);
 | |
|     template <typename T> any_conversion(const T&);
 | |
|     template <typename T> any_conversion(volatile T&);
 | |
|     // we need this constructor to catch references to functions
 | |
|     // (which can not be cv-qualified):
 | |
|     template <typename T> any_conversion(T&);
 | |
| };
 | |
| 
 | |
| template <typename From, typename To>
 | |
| struct is_convertible_basic_impl
 | |
| {
 | |
|     static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(any_conversion ...);
 | |
|     static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(To, int);
 | |
|     typedef typename add_lvalue_reference<From>::type lvalue_type;
 | |
|     typedef typename add_rvalue_reference<From>::type rvalue_type; 
 | |
|     static lvalue_type _m_from;
 | |
| 
 | |
| #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
 | |
|     BOOST_STATIC_CONSTANT(bool, value =
 | |
|         sizeof( _m_check(static_cast<rvalue_type>(_m_from), 0) ) == sizeof(::boost::type_traits::yes_type)
 | |
|         );
 | |
| #else
 | |
|     BOOST_STATIC_CONSTANT(bool, value =
 | |
|         sizeof( _m_check(_m_from, 0) ) == sizeof(::boost::type_traits::yes_type)
 | |
|         );
 | |
| #endif
 | |
| };
 | |
| 
 | |
| #elif defined(__DMC__)
 | |
| 
 | |
| struct any_conversion
 | |
| {
 | |
|     template <typename T> any_conversion(const volatile T&);
 | |
|     template <typename T> any_conversion(const T&);
 | |
|     template <typename T> any_conversion(volatile T&);
 | |
|     // we need this constructor to catch references to functions
 | |
|     // (which can not be cv-qualified):
 | |
|     template <typename T> any_conversion(T&);
 | |
| };
 | |
| 
 | |
| template <typename From, typename To>
 | |
| struct is_convertible_basic_impl
 | |
| {
 | |
|     // Using '...' doesn't always work on Digital Mars. This version seems to.
 | |
|     template <class T>
 | |
|     static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(any_conversion,  float, T);
 | |
|     static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(To, int, int);
 | |
|     typedef typename add_lvalue_reference<From>::type lvalue_type;
 | |
|     typedef typename add_rvalue_reference<From>::type rvalue_type;
 | |
|     static lvalue_type _m_from;
 | |
| 
 | |
|     // Static constants sometime cause the conversion of _m_from to To to be
 | |
|     // called. This doesn't happen with an enum.
 | |
| #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
 | |
|     enum { value =
 | |
|         sizeof( _m_check(static_cast<rvalue_type>(_m_from), 0, 0) ) == sizeof(::boost::type_traits::yes_type)
 | |
|         };
 | |
| #else
 | |
|     enum { value =
 | |
|         sizeof( _m_check(_m_from, 0, 0) ) == sizeof(::boost::type_traits::yes_type)
 | |
|         };
 | |
| #endif
 | |
| };
 | |
| 
 | |
| #elif defined(__MWERKS__)
 | |
| // 
 | |
| // CW works with the technique implemented above for EDG, except when From
 | |
| // is a function type (or a reference to such a type), in which case
 | |
| // any_conversion won't be accepted as a valid conversion. We detect this
 | |
| // exceptional situation and channel it through an alternative algorithm.
 | |
| //
 | |
| 
 | |
| template <typename From, typename To,bool FromIsFunctionRef>
 | |
| struct is_convertible_basic_impl_aux;
 | |
| 
 | |
| struct any_conversion
 | |
| {
 | |
|     template <typename T> any_conversion(const volatile T&);
 | |
|     template <typename T> any_conversion(const T&);
 | |
|     template <typename T> any_conversion(volatile T&);
 | |
|     template <typename T> any_conversion(T&);
 | |
| };
 | |
| 
 | |
| template <typename From, typename To>
 | |
| struct is_convertible_basic_impl_aux<From,To,false /*FromIsFunctionRef*/>
 | |
| {
 | |
|     static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(any_conversion ...);
 | |
|     static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(To, int);
 | |
|     typedef typename add_lvalue_reference<From>::type lvalue_type;
 | |
|     typedef typename add_rvalue_reference<From>::type rvalue_type; 
 | |
|     static lvalue_type _m_from;
 | |
| 
 | |
| #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
 | |
|     BOOST_STATIC_CONSTANT(bool, value =
 | |
|         sizeof( _m_check(static_cast<rvalue_type>(_m_from), 0) ) == sizeof(::boost::type_traits::yes_type)
 | |
|         );
 | |
| #else
 | |
|     BOOST_STATIC_CONSTANT(bool, value =
 | |
|         sizeof( _m_check(_m_from, 0) ) == sizeof(::boost::type_traits::yes_type)
 | |
|         );
 | |
| #endif
 | |
| };
 | |
| 
 | |
| template <typename From, typename To>
 | |
| struct is_convertible_basic_impl_aux<From,To,true /*FromIsFunctionRef*/>
 | |
| {
 | |
|     static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(...);
 | |
|     static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(To);
 | |
|     typedef typename add_lvalue_reference<From>::type lvalue_type;
 | |
|     typedef typename add_rvalue_reference<From>::type rvalue_type;
 | |
|     static lvalue_type _m_from;
 | |
| #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
 | |
|     BOOST_STATIC_CONSTANT(bool, value =
 | |
|         sizeof( _m_check(static_cast<rvalue_type>(_m_from)) ) == sizeof(::boost::type_traits::yes_type)
 | |
|         );
 | |
| #else
 | |
|     BOOST_STATIC_CONSTANT(bool, value =
 | |
|         sizeof( _m_check(_m_from) ) == sizeof(::boost::type_traits::yes_type)
 | |
|         );
 | |
| #endif
 | |
| };
 | |
| 
 | |
| template <typename From, typename To>
 | |
| struct is_convertible_basic_impl:
 | |
|   is_convertible_basic_impl_aux<
 | |
|     From,To,
 | |
|     ::boost::is_function<typename ::boost::remove_reference<From>::type>::value
 | |
|   >
 | |
| {};
 | |
| 
 | |
| #else
 | |
| //
 | |
| // This version seems to work pretty well for a wide spectrum of compilers,
 | |
| // however it does rely on undefined behaviour by passing UDT's through (...).
 | |
| //
 | |
| 
 | |
| //Workaround for old compilers like MSVC 7.1 to avoid
 | |
| //forming a reference to an array of unknown bound
 | |
| template <typename From>
 | |
| struct is_convertible_basic_impl_add_lvalue_reference
 | |
|    : add_lvalue_reference<From>
 | |
| {};
 | |
| 
 | |
| template <typename From>
 | |
| struct is_convertible_basic_impl_add_lvalue_reference<From[]>
 | |
| {
 | |
|     typedef From type [];
 | |
| };
 | |
| 
 | |
| template <typename From, typename To>
 | |
| struct is_convertible_basic_impl
 | |
| {
 | |
|     static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(...);
 | |
|     static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(To);
 | |
|     typedef typename is_convertible_basic_impl_add_lvalue_reference<From>::type lvalue_type;
 | |
|     static lvalue_type _m_from;
 | |
| #ifdef BOOST_MSVC
 | |
| #pragma warning(push)
 | |
| #pragma warning(disable:4244)
 | |
| #if BOOST_WORKAROUND(BOOST_MSVC_FULL_VER, >= 140050000)
 | |
| #pragma warning(disable:6334)
 | |
| #endif
 | |
| #endif
 | |
| #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
 | |
|     typedef typename add_rvalue_reference<From>::type rvalue_type; 
 | |
|     BOOST_STATIC_CONSTANT(bool, value =
 | |
|         sizeof( _m_check(static_cast<rvalue_type>(_m_from)) ) == sizeof(::boost::type_traits::yes_type)
 | |
|         );
 | |
| #else
 | |
|     BOOST_STATIC_CONSTANT(bool, value =
 | |
|         sizeof( _m_check(_m_from) ) == sizeof(::boost::type_traits::yes_type)
 | |
|         );
 | |
| #endif
 | |
| #ifdef BOOST_MSVC
 | |
| #pragma warning(pop)
 | |
| #endif
 | |
| };
 | |
| 
 | |
| #endif // is_convertible_impl
 | |
| 
 | |
| #if defined(__DMC__)
 | |
| // As before, a static constant sometimes causes errors on Digital Mars.
 | |
| template <typename From, typename To>
 | |
| struct is_convertible_impl
 | |
| {
 | |
|     enum { 
 | |
|        value = ( ::boost::detail::is_convertible_basic_impl<From,To>::value && ! ::boost::is_array<To>::value && ! ::boost::is_function<To>::value) 
 | |
|     };
 | |
| };
 | |
| #elif !defined(__BORLANDC__) || __BORLANDC__ > 0x551
 | |
| template <typename From, typename To>
 | |
| struct is_convertible_impl
 | |
| {
 | |
|    BOOST_STATIC_CONSTANT(bool, value = ( ::boost::detail::is_convertible_basic_impl<From, To>::value && !::boost::is_array<To>::value && !::boost::is_function<To>::value));
 | |
| };
 | |
| #endif
 | |
| 
 | |
| template <bool trivial1, bool trivial2, bool abstract_target>
 | |
| struct is_convertible_impl_select
 | |
| {
 | |
|    template <class From, class To>
 | |
|    struct rebind
 | |
|    {
 | |
|       typedef is_convertible_impl<From, To> type;
 | |
|    };
 | |
| };
 | |
| 
 | |
| template <>
 | |
| struct is_convertible_impl_select<true, true, false>
 | |
| {
 | |
|    template <class From, class To>
 | |
|    struct rebind
 | |
|    {
 | |
|       typedef true_type type;
 | |
|    };
 | |
| };
 | |
| 
 | |
| template <>
 | |
| struct is_convertible_impl_select<false, false, true>
 | |
| {
 | |
|    template <class From, class To>
 | |
|    struct rebind
 | |
|    {
 | |
|       typedef false_type type;
 | |
|    };
 | |
| };
 | |
| 
 | |
| template <>
 | |
| struct is_convertible_impl_select<true, false, true>
 | |
| {
 | |
|    template <class From, class To>
 | |
|    struct rebind
 | |
|    {
 | |
|       typedef false_type type;
 | |
|    };
 | |
| };
 | |
| 
 | |
| template <typename From, typename To>
 | |
| struct is_convertible_impl_dispatch_base
 | |
| {
 | |
| #if !BOOST_WORKAROUND(__HP_aCC, < 60700)
 | |
|    typedef is_convertible_impl_select< 
 | |
|       ::boost::is_arithmetic<From>::value, 
 | |
|       ::boost::is_arithmetic<To>::value,
 | |
| #if !defined(BOOST_NO_IS_ABSTRACT) && !defined(BOOST_TT_CXX11_IS_CONVERTIBLE)
 | |
|       // We need to filter out abstract types, only if we don't have a strictly conforming C++11 version:
 | |
|       ::boost::is_abstract<To>::value
 | |
| #else
 | |
|       false
 | |
| #endif
 | |
|    > selector;
 | |
| #else
 | |
|    typedef is_convertible_impl_select<false, false, false> selector;
 | |
| #endif
 | |
|    typedef typename selector::template rebind<From, To> isc_binder;
 | |
|    typedef typename isc_binder::type type;
 | |
| };
 | |
| 
 | |
| template <typename From, typename To>
 | |
| struct is_convertible_impl_dispatch 
 | |
|    : public is_convertible_impl_dispatch_base<From, To>::type
 | |
| {};
 | |
| 
 | |
| //
 | |
| // Now add the full and partial specialisations
 | |
| // for void types, these are common to all the
 | |
| // implementation above:
 | |
| //
 | |
| #ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
 | |
| 
 | |
| template <> struct is_convertible_impl_dispatch<void, void> : public true_type{};
 | |
| template <> struct is_convertible_impl_dispatch<void, void const> : public true_type{};
 | |
| template <> struct is_convertible_impl_dispatch<void, void const volatile> : public true_type{};
 | |
| template <> struct is_convertible_impl_dispatch<void, void volatile> : public true_type{};
 | |
| 
 | |
| template <> struct is_convertible_impl_dispatch<void const, void> : public true_type{};
 | |
| template <> struct is_convertible_impl_dispatch<void const, void const> : public true_type{};
 | |
| template <> struct is_convertible_impl_dispatch<void const, void const volatile> : public true_type{};
 | |
| template <> struct is_convertible_impl_dispatch<void const, void volatile> : public true_type{};
 | |
| 
 | |
| template <> struct is_convertible_impl_dispatch<void const volatile, void> : public true_type{};
 | |
| template <> struct is_convertible_impl_dispatch<void const volatile, void const> : public true_type{};
 | |
| template <> struct is_convertible_impl_dispatch<void const volatile, void const volatile> : public true_type{};
 | |
| template <> struct is_convertible_impl_dispatch<void const volatile, void volatile> : public true_type{};
 | |
| 
 | |
| template <> struct is_convertible_impl_dispatch<void volatile, void> : public true_type{};
 | |
| template <> struct is_convertible_impl_dispatch<void volatile, void const> : public true_type{};
 | |
| template <> struct is_convertible_impl_dispatch<void volatile, void const volatile> : public true_type{};
 | |
| template <> struct is_convertible_impl_dispatch<void volatile, void volatile> : public true_type{};
 | |
| 
 | |
| #else
 | |
| template <> struct is_convertible_impl_dispatch<void, void> : public true_type{};
 | |
| #endif // BOOST_NO_CV_VOID_SPECIALIZATIONS
 | |
| 
 | |
| template <class To> struct is_convertible_impl_dispatch<void, To> : public false_type{};
 | |
| template <class From> struct is_convertible_impl_dispatch<From, void> : public false_type{};
 | |
| 
 | |
| #ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
 | |
| template <class To> struct is_convertible_impl_dispatch<void const, To> : public false_type{};
 | |
| template <class From> struct is_convertible_impl_dispatch<From, void const> : public false_type{};
 | |
| template <class To> struct is_convertible_impl_dispatch<void const volatile, To> : public false_type{};
 | |
| template <class From> struct is_convertible_impl_dispatch<From, void const volatile> : public false_type{};
 | |
| template <class To> struct is_convertible_impl_dispatch<void volatile, To> : public false_type{};
 | |
| template <class From> struct is_convertible_impl_dispatch<From, void volatile> : public false_type{};
 | |
| #endif
 | |
| 
 | |
| } // namespace detail
 | |
| 
 | |
| template <class From, class To> 
 | |
| struct is_convertible : public integral_constant<bool, ::boost::detail::is_convertible_impl_dispatch<From, To>::value> {};
 | |
| 
 | |
| #else
 | |
| 
 | |
| template <class From, class To>
 | |
| struct is_convertible : public integral_constant<bool, BOOST_IS_CONVERTIBLE(From, To)> {};
 | |
| 
 | |
| #endif
 | |
| 
 | |
| } // namespace boost
 | |
| 
 | |
| #endif // BOOST_TT_IS_CONVERTIBLE_HPP_INCLUDED
 | 
