
John Maddock wrote:
Finally, in `is_convertible_impl`, we shouldn't use `ref_type` in Line 299. Just using `From` is correct:
boost::detail::is_convertible_basic_impl<From,To>::value
With these changes, `boost::is_convertible<int, int&>` on gcc returns false_type.
It does, but it also terminally breaks C++03 compilers (not just gcc).
One note: The above code cannot deal with `boost::is_convertible<Func, Func&>`, where `Func` is a function type in a C++03 mode.
Not only that, it also breaks for abstract types, arrays, incomplete types, and anything else I've forgotten.
I've fixed the issue for GCC in C++11 mode by forwarding to std::is_convertible, but it remains for now in C++03 mode.
I don't think tweaking `intrinsics.hpp` is a good idea since gcc does not implement the intrinsic yet. The following code works well (incl. your mentioned cases) both in C++03 and C++11 on gcc. template <typename From, typename To> struct is_convertible_basic_impl { #ifdef BOOST_NO_RVALUE_REFERENCES static typename ::boost::add_reference<From>::type _m_from; static bool const rval_to_nonconst_lval_ref_conv = ::boost::type_traits::ice_and< !(::boost::is_function<From>::value) // Note: an rvalue ref to function type is an lvalue , !(::boost::is_reference<From>::value) , ::boost::is_reference<To>::value , !(::boost::is_const<typename ::boost::remove_reference<To>::type>::value) >::value; static bool const value = ::boost::type_traits::ice_and< sizeof( boost::detail::checker<To>::_m_check(_m_from, 0) ) == sizeof(::boost::type_traits::yes_type) , !rval_to_nonconst_lval_ref_conv >::value; #else static bool const value = sizeof( boost::detail::checker<To>::_m_check(boost::declval<From>(), 0) ) == sizeof(::boost::type_traits::yes_type); #endif }; template <typename From, typename To> struct is_convertible_impl { BOOST_STATIC_CONSTANT(bool, value = (::boost::type_traits::ice_and< ::boost::type_traits::ice_or< ::boost::detail::is_convertible_basic_impl<From,To>::value, ::boost::is_void<To>::value >::value, ::boost::type_traits::ice_not< ::boost::type_traits::ice_or< ::boost::is_array<To>::value, ::boost::is_function<To>::value >::value >::value >::value) ); }; * The C++03 code emulates C++11's behavior. For example, `is_convertible<Abst, Abst const&>` returns true_type for an abstract type `Abst`. * The code fixes the bug in the current code for function types. For example, `is_convertible<Func, Func>` should return false_type for a function type `Func`. But the current code returns true_type.
Note that other compilers are similarly effected *even when using a compiler intrinsic*, so for example given:
1) is_convertible<int&&, int&> 2) is_convertible<int, int&>
MSVC fails (1) even though it's using a compiler intrinsic (and no we can't stop using it, that breaks other stuff). Intel on Win32 fails both 1 & 2, again using it's __is_convertible intrinsic.
I just tried MSVC's `__is_convertible_to` intrinsic. It's too buggy... Did someone make a bug report to MS? Regards, Michel