|
Boost : |
Subject: Re: [boost] [type_traits][parameter] Inconsistent boost::is_convertible between gcc and clang
From: Michel Morin (mimomorin_at_[hidden])
Date: 2012-08-13 11:14:22
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
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk