Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 10:10:26

0001 
0002 // Copyright 2000 John Maddock (john@johnmaddock.co.uk)
0003 // Copyright 2000 Jeremy Siek (jsiek@lsc.nd.edu)
0004 // Copyright 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
0005 //
0006 //  Use, modification and distribution are subject to the Boost Software License,
0007 //  Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0008 //  http://www.boost.org/LICENSE_1_0.txt).
0009 //
0010 //  See http://www.boost.org/libs/type_traits for most recent version including documentation.
0011 
0012 #ifndef BOOST_TT_IS_CONVERTIBLE_HPP_INCLUDED
0013 #define BOOST_TT_IS_CONVERTIBLE_HPP_INCLUDED
0014 
0015 #include <boost/type_traits/intrinsics.hpp>
0016 #include <boost/type_traits/integral_constant.hpp>
0017 #include <boost/type_traits/is_complete.hpp>
0018 #include <boost/type_traits/is_void.hpp>
0019 #include <boost/type_traits/is_array.hpp>
0020 #include <boost/static_assert.hpp>
0021 #ifndef BOOST_IS_CONVERTIBLE
0022 #include <boost/type_traits/detail/yes_no_type.hpp>
0023 #include <boost/type_traits/detail/config.hpp>
0024 #include <boost/type_traits/is_array.hpp>
0025 #include <boost/type_traits/is_arithmetic.hpp>
0026 #include <boost/type_traits/is_void.hpp>
0027 #if !defined(BOOST_NO_IS_ABSTRACT)
0028 #include <boost/type_traits/is_abstract.hpp>
0029 #endif
0030 #include <boost/type_traits/add_lvalue_reference.hpp>
0031 #include <boost/type_traits/add_rvalue_reference.hpp>
0032 #include <boost/type_traits/is_function.hpp>
0033 
0034 #if defined(__MWERKS__)
0035 #include <boost/type_traits/remove_reference.hpp>
0036 #endif
0037 #if !defined(BOOST_NO_SFINAE_EXPR) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0038 #  include <boost/type_traits/declval.hpp>
0039 #endif
0040 #elif defined(BOOST_MSVC) || defined(BOOST_INTEL)
0041 #include <boost/type_traits/is_function.hpp>
0042 #include <boost/type_traits/is_same.hpp>
0043 #endif // BOOST_IS_CONVERTIBLE
0044 
0045 namespace boost {
0046 
0047 #ifndef BOOST_IS_CONVERTIBLE
0048 
0049 // is one type convertible to another?
0050 //
0051 // there are multiple versions of the is_convertible
0052 // template, almost every compiler seems to require its
0053 // own version.
0054 //
0055 // Thanks to Andrei Alexandrescu for the original version of the
0056 // conversion detection technique!
0057 //
0058 
0059 namespace detail {
0060 
0061 #if !defined(BOOST_NO_SFINAE_EXPR) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !(defined(BOOST_GCC) && (BOOST_GCC < 40700))
0062 
0063    // This is a C++11 conforming version, place this first and use it wherever possible:
0064 
0065 #  define BOOST_TT_CXX11_IS_CONVERTIBLE
0066 
0067    template <class A, class B, class C>
0068    struct or_helper
0069    {
0070       static const bool value = (A::value || B::value || C::value);
0071    };
0072 
0073    template<typename From, typename To, bool b = or_helper<boost::is_void<From>, boost::is_function<To>, boost::is_array<To> >::value>
0074    struct is_convertible_basic_impl
0075    {
0076       // Nothing converts to function or array, but void converts to void:
0077       static const bool value = is_void<To>::value; 
0078    };
0079 
0080    template<typename From, typename To>
0081    class is_convertible_basic_impl<From, To, false>
0082    {
0083       typedef char one;
0084       typedef int  two;
0085 
0086       template<typename To1>
0087       static void test_aux(To1);
0088 
0089       template<typename From1, typename To1>
0090       static decltype(test_aux<To1>(boost::declval<From1>()), one()) test(int);
0091 
0092       template<typename, typename>
0093       static two test(...);
0094 
0095    public:
0096       static const bool value = sizeof(test<From, To>(0)) == 1;
0097    };
0098 
0099 #elif defined(BOOST_BORLANDC) && (BOOST_BORLANDC < 0x560)
0100 //
0101 // special version for Borland compilers
0102 // this version breaks when used for some
0103 // UDT conversions:
0104 //
0105 template <typename From, typename To>
0106 struct is_convertible_impl
0107 {
0108 #pragma option push -w-8074
0109     // This workaround for Borland breaks the EDG C++ frontend,
0110     // so we only use it for Borland.
0111     template <typename T> struct checker
0112     {
0113         static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(...);
0114         static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(T);
0115     };
0116 
0117     static typename add_lvalue_reference<From>::type  _m_from;
0118     static bool const value = sizeof( checker<To>::_m_check(_m_from) )
0119         == sizeof(::boost::type_traits::yes_type);
0120 #pragma option pop
0121 };
0122 
0123 #elif defined(__GNUC__) || defined(BOOST_BORLANDC) && (BOOST_BORLANDC < 0x600)
0124 // special version for gcc compiler + recent Borland versions
0125 // note that this does not pass UDT's through (...)
0126 
0127 struct any_conversion
0128 {
0129     template <typename T> any_conversion(const volatile T&);
0130     template <typename T> any_conversion(const T&);
0131     template <typename T> any_conversion(volatile T&);
0132     template <typename T> any_conversion(T&);
0133 };
0134 
0135 template <typename T> struct checker
0136 {
0137     static boost::type_traits::no_type _m_check(any_conversion ...);
0138     static boost::type_traits::yes_type _m_check(T, int);
0139 };
0140 
0141 template <typename From, typename To>
0142 struct is_convertible_basic_impl
0143 {
0144     typedef typename add_lvalue_reference<From>::type lvalue_type;
0145     typedef typename add_rvalue_reference<From>::type rvalue_type;
0146     static lvalue_type _m_from;
0147 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 6)))
0148     static bool const value =
0149         sizeof( boost::detail::checker<To>::_m_check(static_cast<rvalue_type>(_m_from), 0) )
0150         == sizeof(::boost::type_traits::yes_type);
0151 #else
0152     static bool const value =
0153         sizeof( boost::detail::checker<To>::_m_check(_m_from, 0) )
0154         == sizeof(::boost::type_traits::yes_type);
0155 #endif
0156 };
0157 
0158 #elif (defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 245) && !defined(__ICL)) \
0159       || defined(__IBMCPP__) || defined(__HP_aCC)
0160 //
0161 // This is *almost* an ideal world implementation as it doesn't rely
0162 // on undefined behaviour by passing UDT's through (...).
0163 // Unfortunately it doesn't quite pass all the tests for most compilers (sigh...)
0164 // Enable this for your compiler if is_convertible_test.cpp will compile it...
0165 //
0166 // Note we do not enable this for VC7.1, because even though it passes all the
0167 // type_traits tests it is known to cause problems when instantiation occurs
0168 // deep within the instantiation tree :-(
0169 //
0170 struct any_conversion
0171 {
0172     template <typename T> any_conversion(const volatile T&);
0173     template <typename T> any_conversion(const T&);
0174     template <typename T> any_conversion(volatile T&);
0175     // we need this constructor to catch references to functions
0176     // (which can not be cv-qualified):
0177     template <typename T> any_conversion(T&);
0178 };
0179 
0180 template <typename From, typename To>
0181 struct is_convertible_basic_impl
0182 {
0183     static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(any_conversion ...);
0184     static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(To, int);
0185     typedef typename add_lvalue_reference<From>::type lvalue_type;
0186     typedef typename add_rvalue_reference<From>::type rvalue_type; 
0187     static lvalue_type _m_from;
0188 
0189 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
0190     BOOST_STATIC_CONSTANT(bool, value =
0191         sizeof( _m_check(static_cast<rvalue_type>(_m_from), 0) ) == sizeof(::boost::type_traits::yes_type)
0192         );
0193 #else
0194     BOOST_STATIC_CONSTANT(bool, value =
0195         sizeof( _m_check(_m_from, 0) ) == sizeof(::boost::type_traits::yes_type)
0196         );
0197 #endif
0198 };
0199 
0200 #elif defined(__DMC__)
0201 
0202 struct any_conversion
0203 {
0204     template <typename T> any_conversion(const volatile T&);
0205     template <typename T> any_conversion(const T&);
0206     template <typename T> any_conversion(volatile T&);
0207     // we need this constructor to catch references to functions
0208     // (which can not be cv-qualified):
0209     template <typename T> any_conversion(T&);
0210 };
0211 
0212 template <typename From, typename To>
0213 struct is_convertible_basic_impl
0214 {
0215     // Using '...' doesn't always work on Digital Mars. This version seems to.
0216     template <class T>
0217     static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(any_conversion,  float, T);
0218     static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(To, int, int);
0219     typedef typename add_lvalue_reference<From>::type lvalue_type;
0220     typedef typename add_rvalue_reference<From>::type rvalue_type;
0221     static lvalue_type _m_from;
0222 
0223     // Static constants sometime cause the conversion of _m_from to To to be
0224     // called. This doesn't happen with an enum.
0225 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
0226     enum { value =
0227         sizeof( _m_check(static_cast<rvalue_type>(_m_from), 0, 0) ) == sizeof(::boost::type_traits::yes_type)
0228         };
0229 #else
0230     enum { value =
0231         sizeof( _m_check(_m_from, 0, 0) ) == sizeof(::boost::type_traits::yes_type)
0232         };
0233 #endif
0234 };
0235 
0236 #elif defined(__MWERKS__)
0237 // 
0238 // CW works with the technique implemented above for EDG, except when From
0239 // is a function type (or a reference to such a type), in which case
0240 // any_conversion won't be accepted as a valid conversion. We detect this
0241 // exceptional situation and channel it through an alternative algorithm.
0242 //
0243 
0244 template <typename From, typename To,bool FromIsFunctionRef>
0245 struct is_convertible_basic_impl_aux;
0246 
0247 struct any_conversion
0248 {
0249     template <typename T> any_conversion(const volatile T&);
0250     template <typename T> any_conversion(const T&);
0251     template <typename T> any_conversion(volatile T&);
0252     template <typename T> any_conversion(T&);
0253 };
0254 
0255 template <typename From, typename To>
0256 struct is_convertible_basic_impl_aux<From,To,false /*FromIsFunctionRef*/>
0257 {
0258     static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(any_conversion ...);
0259     static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(To, int);
0260     typedef typename add_lvalue_reference<From>::type lvalue_type;
0261     typedef typename add_rvalue_reference<From>::type rvalue_type; 
0262     static lvalue_type _m_from;
0263 
0264 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
0265     BOOST_STATIC_CONSTANT(bool, value =
0266         sizeof( _m_check(static_cast<rvalue_type>(_m_from), 0) ) == sizeof(::boost::type_traits::yes_type)
0267         );
0268 #else
0269     BOOST_STATIC_CONSTANT(bool, value =
0270         sizeof( _m_check(_m_from, 0) ) == sizeof(::boost::type_traits::yes_type)
0271         );
0272 #endif
0273 };
0274 
0275 template <typename From, typename To>
0276 struct is_convertible_basic_impl_aux<From,To,true /*FromIsFunctionRef*/>
0277 {
0278     static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(...);
0279     static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(To);
0280     typedef typename add_lvalue_reference<From>::type lvalue_type;
0281     typedef typename add_rvalue_reference<From>::type rvalue_type;
0282     static lvalue_type _m_from;
0283 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
0284     BOOST_STATIC_CONSTANT(bool, value =
0285         sizeof( _m_check(static_cast<rvalue_type>(_m_from)) ) == sizeof(::boost::type_traits::yes_type)
0286         );
0287 #else
0288     BOOST_STATIC_CONSTANT(bool, value =
0289         sizeof( _m_check(_m_from) ) == sizeof(::boost::type_traits::yes_type)
0290         );
0291 #endif
0292 };
0293 
0294 template <typename From, typename To>
0295 struct is_convertible_basic_impl:
0296   is_convertible_basic_impl_aux<
0297     From,To,
0298     ::boost::is_function<typename ::boost::remove_reference<From>::type>::value
0299   >
0300 {};
0301 
0302 #else
0303 //
0304 // This version seems to work pretty well for a wide spectrum of compilers,
0305 // however it does rely on undefined behaviour by passing UDT's through (...).
0306 //
0307 
0308 //Workaround for old compilers like MSVC 7.1 to avoid
0309 //forming a reference to an array of unknown bound
0310 template <typename From>
0311 struct is_convertible_basic_impl_add_lvalue_reference
0312    : add_lvalue_reference<From>
0313 {};
0314 
0315 template <typename From>
0316 struct is_convertible_basic_impl_add_lvalue_reference<From[]>
0317 {
0318     typedef From type [];
0319 };
0320 
0321 template <typename From, typename To>
0322 struct is_convertible_basic_impl
0323 {
0324     static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(...);
0325     static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(To);
0326     typedef typename is_convertible_basic_impl_add_lvalue_reference<From>::type lvalue_type;
0327     static lvalue_type _m_from;
0328 #ifdef BOOST_MSVC
0329 #pragma warning(push)
0330 #pragma warning(disable:4244)
0331 #if BOOST_WORKAROUND(BOOST_MSVC_FULL_VER, >= 140050000)
0332 #pragma warning(disable:6334)
0333 #endif
0334 #endif
0335 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
0336     typedef typename add_rvalue_reference<From>::type rvalue_type; 
0337     BOOST_STATIC_CONSTANT(bool, value =
0338         sizeof( _m_check(static_cast<rvalue_type>(_m_from)) ) == sizeof(::boost::type_traits::yes_type)
0339         );
0340 #else
0341     BOOST_STATIC_CONSTANT(bool, value =
0342         sizeof( _m_check(_m_from) ) == sizeof(::boost::type_traits::yes_type)
0343         );
0344 #endif
0345 #ifdef BOOST_MSVC
0346 #pragma warning(pop)
0347 #endif
0348 };
0349 
0350 #endif // is_convertible_impl
0351 
0352 #if defined(__DMC__)
0353 // As before, a static constant sometimes causes errors on Digital Mars.
0354 template <typename From, typename To>
0355 struct is_convertible_impl
0356 {
0357     enum { 
0358        value = ( ::boost::detail::is_convertible_basic_impl<From,To>::value && ! ::boost::is_array<To>::value && ! ::boost::is_function<To>::value) 
0359     };
0360 };
0361 #elif !defined(BOOST_BORLANDC) || BOOST_BORLANDC > 0x551
0362 template <typename From, typename To>
0363 struct is_convertible_impl
0364 {
0365    BOOST_STATIC_CONSTANT(bool, value = ( ::boost::detail::is_convertible_basic_impl<From, To>::value && !::boost::is_array<To>::value && !::boost::is_function<To>::value));
0366 };
0367 #endif
0368 
0369 template <bool trivial1, bool trivial2, bool abstract_target>
0370 struct is_convertible_impl_select
0371 {
0372    template <class From, class To>
0373    struct rebind
0374    {
0375       typedef is_convertible_impl<From, To> type;
0376    };
0377 };
0378 
0379 template <>
0380 struct is_convertible_impl_select<true, true, false>
0381 {
0382    template <class From, class To>
0383    struct rebind
0384    {
0385       typedef true_type type;
0386    };
0387 };
0388 
0389 template <>
0390 struct is_convertible_impl_select<false, false, true>
0391 {
0392    template <class From, class To>
0393    struct rebind
0394    {
0395       typedef false_type type;
0396    };
0397 };
0398 
0399 template <>
0400 struct is_convertible_impl_select<true, false, true>
0401 {
0402    template <class From, class To>
0403    struct rebind
0404    {
0405       typedef false_type type;
0406    };
0407 };
0408 
0409 template <typename From, typename To>
0410 struct is_convertible_impl_dispatch_base
0411 {
0412 #if !BOOST_WORKAROUND(__HP_aCC, < 60700)
0413    typedef is_convertible_impl_select< 
0414       ::boost::is_arithmetic<From>::value, 
0415       ::boost::is_arithmetic<To>::value,
0416 #if !defined(BOOST_NO_IS_ABSTRACT) && !defined(BOOST_TT_CXX11_IS_CONVERTIBLE)
0417       // We need to filter out abstract types, only if we don't have a strictly conforming C++11 version:
0418       ::boost::is_abstract<To>::value
0419 #else
0420       false
0421 #endif
0422    > selector;
0423 #else
0424    typedef is_convertible_impl_select<false, false, false> selector;
0425 #endif
0426    typedef typename selector::template rebind<From, To> isc_binder;
0427    typedef typename isc_binder::type type;
0428 };
0429 
0430 template <typename From, typename To>
0431 struct is_convertible_impl_dispatch 
0432    : public is_convertible_impl_dispatch_base<From, To>::type
0433 {};
0434 
0435 //
0436 // Now add the full and partial specialisations
0437 // for void types, these are common to all the
0438 // implementation above:
0439 //
0440 #ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
0441 
0442 template <> struct is_convertible_impl_dispatch<void, void> : public true_type{};
0443 template <> struct is_convertible_impl_dispatch<void, void const> : public true_type{};
0444 template <> struct is_convertible_impl_dispatch<void, void const volatile> : public true_type{};
0445 template <> struct is_convertible_impl_dispatch<void, void volatile> : public true_type{};
0446 
0447 template <> struct is_convertible_impl_dispatch<void const, void> : public true_type{};
0448 template <> struct is_convertible_impl_dispatch<void const, void const> : public true_type{};
0449 template <> struct is_convertible_impl_dispatch<void const, void const volatile> : public true_type{};
0450 template <> struct is_convertible_impl_dispatch<void const, void volatile> : public true_type{};
0451 
0452 template <> struct is_convertible_impl_dispatch<void const volatile, void> : public true_type{};
0453 template <> struct is_convertible_impl_dispatch<void const volatile, void const> : public true_type{};
0454 template <> struct is_convertible_impl_dispatch<void const volatile, void const volatile> : public true_type{};
0455 template <> struct is_convertible_impl_dispatch<void const volatile, void volatile> : public true_type{};
0456 
0457 template <> struct is_convertible_impl_dispatch<void volatile, void> : public true_type{};
0458 template <> struct is_convertible_impl_dispatch<void volatile, void const> : public true_type{};
0459 template <> struct is_convertible_impl_dispatch<void volatile, void const volatile> : public true_type{};
0460 template <> struct is_convertible_impl_dispatch<void volatile, void volatile> : public true_type{};
0461 
0462 #else
0463 template <> struct is_convertible_impl_dispatch<void, void> : public true_type{};
0464 #endif // BOOST_NO_CV_VOID_SPECIALIZATIONS
0465 
0466 template <class To> struct is_convertible_impl_dispatch<void, To> : public false_type{};
0467 template <class From> struct is_convertible_impl_dispatch<From, void> : public false_type{};
0468 
0469 #ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
0470 template <class To> struct is_convertible_impl_dispatch<void const, To> : public false_type{};
0471 template <class From> struct is_convertible_impl_dispatch<From, void const> : public false_type{};
0472 template <class To> struct is_convertible_impl_dispatch<void const volatile, To> : public false_type{};
0473 template <class From> struct is_convertible_impl_dispatch<From, void const volatile> : public false_type{};
0474 template <class To> struct is_convertible_impl_dispatch<void volatile, To> : public false_type{};
0475 template <class From> struct is_convertible_impl_dispatch<From, void volatile> : public false_type{};
0476 #endif
0477 
0478 } // namespace detail
0479 
0480 template <class From, class To> 
0481 struct is_convertible : public integral_constant<bool, ::boost::detail::is_convertible_impl_dispatch<From, To>::value> 
0482 {
0483    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");
0484    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");
0485 };
0486 
0487 #else
0488 
0489 template <class From, class To>
0490 struct is_convertible : public integral_constant<bool, BOOST_IS_CONVERTIBLE(From, To)> 
0491 {
0492 #if defined(BOOST_MSVC)
0493    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");
0494 #endif
0495 #if defined(__clang__)
0496    // clang's intrinsic doesn't assert on incomplete types:
0497    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");
0498    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");
0499 #endif
0500 };
0501 
0502 #endif
0503 
0504 } // namespace boost
0505 
0506 #endif // BOOST_TT_IS_CONVERTIBLE_HPP_INCLUDED