123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506 |
- // 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>
- #include <boost/type_traits/is_complete.hpp>
- #include <boost/type_traits/is_void.hpp>
- #include <boost/type_traits/is_array.hpp>
- #include <boost/static_assert.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>
- {
- BOOST_STATIC_ASSERT_MSG(boost::is_complete<To>::value || boost::is_void<To>::value || boost::is_array<To>::value, "Destination argument type to is_convertible must be a complete type");
- BOOST_STATIC_ASSERT_MSG(boost::is_complete<From>::value || boost::is_void<From>::value || boost::is_array<From>::value, "From argument type to is_convertible must be a complete type");
- };
- #else
- template <class From, class To>
- struct is_convertible : public integral_constant<bool, BOOST_IS_CONVERTIBLE(From, To)>
- {
- #if BOOST_WORKAROUND(BOOST_MSVC, <= 1900)
- BOOST_STATIC_ASSERT_MSG(boost::is_complete<From>::value || boost::is_void<From>::value || boost::is_array<From>::value || boost::is_reference<From>::value, "From argument type to is_convertible must be a complete type");
- #endif
- #if defined(__clang__)
- // clang's intrinsic doesn't assert on incomplete types:
- BOOST_STATIC_ASSERT_MSG(boost::is_complete<To>::value || boost::is_void<To>::value || boost::is_array<To>::value, "Destination argument type to is_convertible must be a complete type");
- BOOST_STATIC_ASSERT_MSG(boost::is_complete<From>::value || boost::is_void<From>::value || boost::is_array<From>::value, "From argument type to is_convertible must be a complete type");
- #endif
- };
- #endif
- } // namespace boost
- #endif // BOOST_TT_IS_CONVERTIBLE_HPP_INCLUDED
|