| |
| // Copyright (C) 2000 John Maddock (john_maddock@compuserve.com) |
| // Copyright (C) 2000 Jeremy Siek (jsiek@lsc.nd.edu) |
| // Copyright (C) 1999, 2000 Jaakko Jrvi (jaakko.jarvi@cs.utu.fi) |
| // |
| // Permission to copy and use this software is granted, |
| // provided this copyright notice appears in all copies. |
| // Permission to modify the code and to distribute modified code is granted, |
| // provided this copyright notice appears in all copies, and a notice |
| // that the code was modified is included with the copyright notice. |
| // |
| // This software is provided "as is" without express or implied warranty, |
| // and with no claim as to its suitability for any purpose. |
| // |
| |
| #ifndef BOOST_CONVERSION_TYPE_TRAITS_HPP |
| #define BOOST_CONVERSION_TYPE_TRAITS_HPP |
| |
| #ifndef BOOST_ICE_TYPE_TRAITS_HPP |
| #include <boost/type_traits/ice.hpp> |
| #endif |
| #ifndef BOOST_FWD_TYPE_TRAITS_HPP |
| #include <boost/type_traits/fwd.hpp> |
| #endif |
| #ifndef BOOST_ARITHMETIC_TYPE_TRAITS_HPP |
| #include <boost/type_traits/arithmetic_traits.hpp> |
| #endif |
| // |
| // is one type convertable 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 boost{ |
| |
| #ifdef BOOST_MSVC |
| |
| // |
| // MS specific version: |
| // |
| namespace detail{ |
| |
| // This workaround is necessary to handle when From is void |
| // which is normally taken care of by the partial specialization |
| // of the is_convertible class. |
| using ::boost::type_traits::yes_type; |
| using ::boost::type_traits::no_type; |
| |
| struct from_not_void_conversion { |
| template <class From, class To> |
| struct n_bind { |
| static no_type BOOST_TT_DECL _m_check(...); |
| static yes_type BOOST_TT_DECL _m_check(To); |
| public: |
| void foo(); // avoid warning about all members being private |
| static From _m_from; |
| enum { exists = sizeof( _m_check(_m_from) ) == sizeof(yes_type) }; |
| }; |
| }; |
| struct from_is_void_conversion { |
| template <class From, class To> |
| struct n_bind { |
| enum { exists = ::boost::is_void<To>::value }; |
| }; |
| }; |
| |
| template <class From> |
| struct conversion_helper { |
| typedef from_not_void_conversion type; |
| }; |
| template <> |
| struct conversion_helper<void> { |
| typedef from_is_void_conversion type; |
| }; |
| } // namespace detail |
| |
| template <class From, class To> |
| struct is_convertible |
| { |
| typedef typename detail::conversion_helper<From>::type Selector; |
| typedef typename Selector::template n_bind<From,To> Conversion; |
| public: |
| enum { value = Conversion::exists }; |
| }; |
| |
| #elif defined(__BORLANDC__) |
| // |
| // special version for Borland compilers |
| // this version breaks when used for some |
| // UDT conversions: |
| // |
| template <class From, class To> |
| struct is_convertible |
| { |
| private: |
| #pragma option push -w-8074 |
| // This workaround for Borland breaks the EDG C++ frontend, |
| // so we only use it for Borland. |
| template <class T> |
| struct checker |
| { |
| static type_traits::no_type BOOST_TT_DECL _m_check(...); |
| static type_traits::yes_type BOOST_TT_DECL _m_check(T); |
| }; |
| static From _m_from; |
| public: |
| static const bool value = sizeof( checker<To>::_m_check(_m_from) ) == sizeof(type_traits::yes_type); |
| |
| void foo(); // avoid warning about all members being private |
| #pragma option pop |
| }; |
| |
| #elif defined(__GNUC__) |
| // |
| // special version for gcc compiler |
| // |
| namespace detail{ |
| struct any_conversion |
| { |
| template <class T> |
| any_conversion(const T&); |
| template <class T> |
| any_conversion(T&); |
| }; |
| template <class T> |
| struct checker |
| { |
| static boost::type_traits::no_type _m_check(any_conversion ...); |
| static boost::type_traits::yes_type _m_check(T, int); |
| }; |
| } // namespace detail |
| template <class From, class To> |
| struct is_convertible |
| { |
| private: |
| static From _m_from; |
| public: |
| static const bool value = sizeof( detail::checker<To>::_m_check(_m_from, 0) ) == sizeof(type_traits::yes_type); |
| |
| void foo(); // avoid warning about all members being private |
| }; |
| |
| // Declare specializations of is_convertible for all of the floating |
| // types to all of the integral types. This suppresses some nasty |
| // warnings |
| |
| # define BOOST_IS_CONVERTIBLE(T1,T2) template<>struct is_convertible<T1,T2>{static const bool value=true;}; |
| # define BOOST_IS_CONVERTIBLE2(T1,T2) \ |
| BOOST_IS_CONVERTIBLE(T1,signed T2) \ |
| BOOST_IS_CONVERTIBLE(T1,unsigned T2) |
| |
| # define BOOST_FLOAT_IS_CONVERTIBLE(F) \ |
| BOOST_IS_CONVERTIBLE(F,char) \ |
| BOOST_IS_CONVERTIBLE2(F,char) \ |
| BOOST_IS_CONVERTIBLE2(F,short) \ |
| BOOST_IS_CONVERTIBLE2(F,int) \ |
| BOOST_IS_CONVERTIBLE2(F,long) \ |
| BOOST_IS_CONVERTIBLE2(F,long long) |
| |
| BOOST_FLOAT_IS_CONVERTIBLE(float) |
| BOOST_FLOAT_IS_CONVERTIBLE(double) |
| BOOST_FLOAT_IS_CONVERTIBLE(long double) |
| BOOST_FLOAT_IS_CONVERTIBLE(float const) |
| BOOST_FLOAT_IS_CONVERTIBLE(double const) |
| BOOST_FLOAT_IS_CONVERTIBLE(long double const) |
| BOOST_FLOAT_IS_CONVERTIBLE(float volatile) |
| BOOST_FLOAT_IS_CONVERTIBLE(double volatile) |
| BOOST_FLOAT_IS_CONVERTIBLE(long double volatile) |
| BOOST_FLOAT_IS_CONVERTIBLE(float const volatile) |
| BOOST_FLOAT_IS_CONVERTIBLE(double const volatile) |
| BOOST_FLOAT_IS_CONVERTIBLE(long double const volatile) |
| # undef BOOST_FLOAT_IS_CONVERTIBLE |
| # undef BOOST_IS_CONVERTIBLE2 |
| # undef BOOST_IS_CONVERTIBLE |
| #else |
| |
| template <class From, class To> |
| struct is_convertible |
| { |
| private: |
| static type_traits::no_type BOOST_TT_DECL _m_check(...); |
| static type_traits::yes_type BOOST_TT_DECL _m_check(To); |
| static From _m_from; |
| public: |
| BOOST_STATIC_CONSTANT(bool, value = sizeof( _m_check(_m_from) ) == sizeof(type_traits::yes_type)); |
| void foo(); // avoid warning about all members being private |
| }; |
| |
| #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION |
| // A definition is required even for integral static constants |
| template <class From, class To> |
| const bool is_convertible<From, To>::value; |
| #endif |
| |
| |
| #endif // is_convertible |
| |
| // |
| // Now add the full and partial specialisations |
| // for void types, these are common to all the |
| // implementation above: |
| // |
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
| template <class From> |
| struct is_convertible<From, void> |
| { |
| BOOST_STATIC_CONSTANT(bool, value = false); |
| }; |
| #ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS |
| template <class From> |
| struct is_convertible<From, const void> |
| { |
| BOOST_STATIC_CONSTANT(bool, value = false); |
| }; |
| template <class From> |
| struct is_convertible<From, volatile void> |
| { |
| BOOST_STATIC_CONSTANT(bool, value = false); |
| }; |
| template <class From> |
| struct is_convertible<From, const volatile void> |
| { |
| BOOST_STATIC_CONSTANT(bool, value = false); |
| }; |
| #endif // BOOST_NO_CV_VOID_SPECIALIZATIONS |
| |
| template <class To> |
| struct is_convertible<void, To> |
| { |
| BOOST_STATIC_CONSTANT(bool, value = false); |
| }; |
| #ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS |
| template <class To> |
| struct is_convertible<const void, To> |
| { |
| BOOST_STATIC_CONSTANT(bool, value = false); |
| }; |
| template <class To> |
| struct is_convertible<volatile void, To> |
| { |
| BOOST_STATIC_CONSTANT(bool, value = false); |
| }; |
| template <class To> |
| struct is_convertible<const volatile void, To> |
| { |
| BOOST_STATIC_CONSTANT(bool, value = false); |
| }; |
| #endif |
| #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
| |
| template <> |
| struct is_convertible<void, void> |
| { |
| BOOST_STATIC_CONSTANT(bool, value = true); |
| }; |
| #ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS |
| template <> |
| struct is_convertible<void, const void> |
| { |
| BOOST_STATIC_CONSTANT(bool, value = true); |
| }; |
| template <> |
| struct is_convertible<void, volatile void> |
| { |
| BOOST_STATIC_CONSTANT(bool, value = true); |
| }; |
| template <> |
| struct is_convertible<void, const volatile void> |
| { |
| BOOST_STATIC_CONSTANT(bool, value = true); |
| }; |
| template <> |
| struct is_convertible<const void, const void> |
| { |
| BOOST_STATIC_CONSTANT(bool, value = true); |
| }; |
| template <> |
| struct is_convertible<const void, volatile void> |
| { |
| BOOST_STATIC_CONSTANT(bool, value = true); |
| }; |
| template <> |
| struct is_convertible<const void, const volatile void> |
| { |
| BOOST_STATIC_CONSTANT(bool, value = true); |
| }; |
| template <> |
| struct is_convertible<volatile void, const void> |
| { |
| BOOST_STATIC_CONSTANT(bool, value = true); |
| }; |
| template <> |
| struct is_convertible<volatile void, volatile void> |
| { |
| BOOST_STATIC_CONSTANT(bool, value = true); |
| }; |
| template <> |
| struct is_convertible<volatile void, const volatile void> |
| { |
| BOOST_STATIC_CONSTANT(bool, value = true); |
| }; |
| template <> |
| struct is_convertible<const volatile void, const void> |
| { |
| BOOST_STATIC_CONSTANT(bool, value = true); |
| }; |
| template <> |
| struct is_convertible<const volatile void, volatile void> |
| { |
| BOOST_STATIC_CONSTANT(bool, value = true); |
| }; |
| template <> |
| struct is_convertible<const volatile void, const volatile void> |
| { |
| BOOST_STATIC_CONSTANT(bool, value = true); |
| }; |
| #endif |
| |
| } // namespace boost |
| |
| #endif // include guard |
| |
| |