Move new test cases into the "tricky" section as many compilers can't handle them.

Revert previous change that used std::is_convertible on GCC as it breaks code prior to gcc-4.7.
Fix MSVC intrinsic to handle function types better.
Filter out rvalue-refs from is_function.
Partially apply patch from #7251 to make is_convertible behave more according to C++11.
Refs #7251.

[SVN r80234]
This commit is contained in:
John Maddock
2012-08-26 12:14:11 +00:00
parent c8294f4710
commit b95816426c
6 changed files with 66 additions and 32 deletions

View File

@ -82,6 +82,7 @@
#if (defined(BOOST_MSVC) && defined(BOOST_MSVC_FULL_VER) && (BOOST_MSVC_FULL_VER >=140050215))\
|| (defined(BOOST_INTEL) && defined(_MSC_VER) && (_MSC_VER >= 1500))
# include <boost/type_traits/is_same.hpp>
# include <boost/type_traits/is_function.hpp>
# define BOOST_IS_UNION(T) __is_union(T)
# define BOOST_IS_POD(T) (__is_pod(T) && __has_trivial_constructor(T))
@ -98,7 +99,7 @@
# define BOOST_IS_ABSTRACT(T) __is_abstract(T)
# define BOOST_IS_BASE_OF(T,U) (__is_base_of(T,U) && !is_same<T,U>::value)
# define BOOST_IS_CLASS(T) __is_class(T)
# define BOOST_IS_CONVERTIBLE(T,U) ((__is_convertible_to(T,U) || is_same<T,U>::value) && !__is_abstract(U))
# define BOOST_IS_CONVERTIBLE(T,U) ((__is_convertible_to(T,U) || (is_same<T,U>::value && !is_function<U>::value)) && !__is_abstract(U))
# define BOOST_IS_ENUM(T) __is_enum(T)
// This one doesn't quite always do the right thing:
// # define BOOST_IS_POLYMORPHIC(T) __is_polymorphic(T)
@ -222,11 +223,6 @@
# define BOOST_ALIGNMENT_OF(T) __alignof__(T)
# endif
#ifdef __GXX_EXPERIMENTAL_CXX0X__
# include <type_traits>
# define BOOST_IS_CONVERTIBLE(T,U) (std::is_convertible<T, U>::value)
#endif
# define BOOST_HAS_TYPE_TRAITS_INTRINSICS
#endif
@ -293,3 +289,4 @@

View File

@ -17,13 +17,13 @@
#include <boost/type_traits/detail/yes_no_type.hpp>
#include <boost/type_traits/config.hpp>
#include <boost/type_traits/is_array.hpp>
#include <boost/type_traits/add_reference.hpp>
#include <boost/type_traits/ice.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
#include <boost/type_traits/is_void.hpp>
#ifndef 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>
@ -69,7 +69,7 @@ struct does_conversion_exist
{
static no_type BOOST_TT_DECL _m_check(...);
static yes_type BOOST_TT_DECL _m_check(To);
static typename add_rvalue_reference<From>::type _m_from;
static typename add_lvalue_reference<From>::type _m_from;
enum { value = sizeof( _m_check(_m_from) ) == sizeof(yes_type) };
};
};
@ -107,7 +107,7 @@ struct is_convertible_impl
static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(T);
};
static typename add_rvalue_reference<From>::type _m_from;
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
@ -134,10 +134,17 @@ template <typename T> struct checker
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 From _m_from;
static bool const value = sizeof( boost::detail::checker<To>::_m_check(static_cast<rvalue_type>(_m_from), 0) )
static lvalue_type _m_from;
static bool const value =
#if !defined(BOOST_NO_RVALUE_REFERENCES) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 6)))
sizeof( boost::detail::checker<To>::_m_check(static_cast<rvalue_type>(_m_from), 0) )
== sizeof(::boost::type_traits::yes_type);
#else
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)) \
@ -167,11 +174,16 @@ 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 From _m_from;
static lvalue_type _m_from;
BOOST_STATIC_CONSTANT(bool, value =
#ifndef BOOST_NO_RVALUE_REFERENCES
sizeof( _m_check(static_cast<rvalue_type>(_m_from), 0) ) == sizeof(::boost::type_traits::yes_type)
#else
sizeof( _m_check(_m_from, 0) ) == sizeof(::boost::type_traits::yes_type)
#endif
);
};
@ -194,13 +206,18 @@ struct is_convertible_basic_impl
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_rvalue_reference<From>::type rvalue_type;
static From _m_from;
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.
enum { value =
#ifndef BOOST_NO_RVALUE_REFERENCES
sizeof( _m_check(static_cast<rvalue_type>(_m_from), 0, 0) ) == sizeof(::boost::type_traits::yes_type)
#else
sizeof( _m_check(_m_from, 0, 0) ) == sizeof(::boost::type_traits::yes_type)
#endif
};
};
@ -228,11 +245,16 @@ 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 From _m_from;
static lvalue_type _m_from;
BOOST_STATIC_CONSTANT(bool, value =
#ifndef BOOST_NO_RVALUE_REFERENCES
sizeof( _m_check(static_cast<rvalue_type>(_m_from), 0) ) == sizeof(::boost::type_traits::yes_type)
#else
sizeof( _m_check(_m_from, 0) ) == sizeof(::boost::type_traits::yes_type)
#endif
);
};
@ -241,10 +263,15 @@ 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_rvalue_reference<From>::type rvalue_type;
static From _m_from;
typedef typename add_lvalue_reference<From>::type lvalue_type;
typedef typename add_rvalue_reference<From>::type rvalue_type;
static lvalue_type _m_from;
BOOST_STATIC_CONSTANT(bool, value =
#ifndef BOOST_NO_RVALUE_REFERENCES
sizeof( _m_check(static_cast<rvalue_type>(_m_from)) ) == sizeof(::boost::type_traits::yes_type)
#else
sizeof( _m_check(_m_from) ) == sizeof(::boost::type_traits::yes_type)
#endif
);
};
@ -266,8 +293,9 @@ 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 add_lvalue_reference<From>::type lvalue_type;
typedef typename add_rvalue_reference<From>::type rvalue_type;
static From _m_from;
static lvalue_type _m_from;
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable:4244)
@ -276,7 +304,11 @@ struct is_convertible_basic_impl
#endif
#endif
BOOST_STATIC_CONSTANT(bool, value =
#ifndef BOOST_NO_RVALUE_REFERENCES
sizeof( _m_check(static_cast<rvalue_type>(_m_from)) ) == sizeof(::boost::type_traits::yes_type)
#else
sizeof( _m_check(_m_from) ) == sizeof(::boost::type_traits::yes_type)
#endif
);
#ifdef BOOST_MSVC
#pragma warning(pop)
@ -290,11 +322,10 @@ struct is_convertible_basic_impl
template <typename From, typename To>
struct is_convertible_impl
{
typedef typename add_reference<From>::type ref_type;
enum { value =
(::boost::type_traits::ice_and<
::boost::type_traits::ice_or<
::boost::detail::is_convertible_basic_impl<ref_type,To>::value,
::boost::detail::is_convertible_basic_impl<From,To>::value,
::boost::is_void<To>::value
>::value,
::boost::type_traits::ice_not<
@ -309,11 +340,10 @@ struct is_convertible_impl
template <typename From, typename To>
struct is_convertible_impl
{
typedef typename add_reference<From>::type ref_type;
BOOST_STATIC_CONSTANT(bool, value =
(::boost::type_traits::ice_and<
::boost::type_traits::ice_or<
::boost::detail::is_convertible_basic_impl<ref_type,To>::value,
::boost::detail::is_convertible_basic_impl<From,To>::value,
::boost::is_void<To>::value
>::value,
::boost::type_traits::ice_not<

View File

@ -83,6 +83,11 @@ struct is_function_impl
template <typename T>
struct is_function_impl<T&> : public false_type
{};
#ifndef BOOST_NO_RVALUE_REFERENCES
template <typename T>
struct is_function_impl<T&&> : public false_type
{};
#endif
#endif
#endif

View File

@ -103,8 +103,11 @@ BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_convertible<const int&, int>::value), tr
#ifndef BOOST_NO_RVALUE_REFERENCES
BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_convertible<const int&&, int>::value), true);
BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_convertible<int&&, const int&>::value), true);
#if !defined(__GNUC__) || ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 6)))
// Machinary required to support this, not available prior to gcc-4.7.0:
BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_convertible<int, int&>::value), false);
#endif
#endif
BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_convertible<int(&)[4], const int*>::value), true);
BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_convertible<int(&)(int), int(*)(int)>::value), true);
BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_convertible<int *, const int*>::value), true);
@ -115,16 +118,6 @@ BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_convertible<const int[2], int*>::value),
BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_convertible<int*, int[3]>::value), false);
BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_convertible<test_abc3, const test_abc1&>::value), true);
BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_convertible<int(), int()>::value), false);
BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_convertible<int(), int(*)()>::value), true);
BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_convertible<int(), int(* const)()>::value), true);
BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_convertible<int(), int(* volatile)()>::value), true);
BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_convertible<int(), int(* const volatile)()>::value), true);
BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_convertible<int(), int(&)()>::value), true);
#ifndef BOOST_NO_RVALUE_REFERENCES
BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_convertible<int(), int(&&)()>::value), true);
#endif
BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_convertible<non_pointer, void*>::value), true);
BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_convertible<non_pointer, int*>::value), false);
BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_convertible<non_int_pointer, int*>::value), true);

View File

@ -97,6 +97,13 @@ BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_member_function_pointer<vproc2>::value, t
typedef void (test_abc1::*vproc3)(int, char, long, long, ...)const;
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_member_function_pointer<vproc3>::value, true);
BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_convertible<int(), int()>::value), false);
BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_convertible<int(), int(*)()>::value), true);
BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_convertible<int(), int(* const)()>::value), true);
BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_convertible<int(), int(* volatile)()>::value), true);
BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_convertible<int(), int(* const volatile)()>::value), true);
BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_convertible<int(), int(&)()>::value), true);
TT_TEST_END

View File

@ -13,6 +13,7 @@
# include <boost/type_traits/is_lvalue_reference.hpp>
# include <boost/type_traits/is_rvalue_reference.hpp>
# include <boost/type_traits/is_reference.hpp>
# include <boost/type_traits/is_function.hpp>
#endif
TT_TEST_BEGIN(rvalue_reference_test)
@ -22,6 +23,7 @@ BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_reference<int (&&)(int)>::value, true);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_rvalue_reference<int (&)(int)>::value, false);
BOOST_CHECK_INTEGRAL_CONSTANT(::tt::is_rvalue_reference<int (&&)(int)>::value, true);
BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_convertible<int&&, int&>::value), false);
BOOST_CHECK_INTEGRAL_CONSTANT((::tt::is_convertible<int(), int(&&)()>::value), true);
#endif
TT_TEST_END