Boost logo

Boost :

Subject: Re: [boost] [type_traits][parameter] Inconsistent boost::is_convertible between gcc and clang
From: John Maddock (boost.regex_at_[hidden])
Date: 2012-08-12 14:06:11


> "Non-intrinsic version of `boost::is_convertible<int, int&>` returns
> true_type" is a BUG.

Yes it's a bug, but whether it's completely fixable is another matter (see
comments below).

> So, in Boost 1.47 and later versions, `boost::is_convertible<int, int&>`
> should return false_type.

Right.

> Below, I'll show the bug fix using the non-intrinsic version for gcc.
> The bug is caused by the following code (Line 132):
>
> template <typename From, typename To>
> struct is_convertible_basic_impl
> {
> static typename add_rvalue_reference<From>::type _m_from;
> static bool const value = sizeof(
> boost::detail::checker<To>::_m_check(_m_from, 0) )
> == sizeof(::boost::type_traits::yes_type);
> };
>
> Here, `_m_from` is not treated as an rvalue.
> The correct code is
>
> template <typename From, typename To>
> struct is_convertible_basic_impl
> {
> static bool const value = sizeof(
> boost::detail::checker<To>::_m_check(boost::declval<From>(),
> 0) )
> == sizeof(::boost::type_traits::yes_type);
> };

Yep. Fixed in Trunk.

> Also, `any_conversion` needs a constructor for an rvalue (Line 120):
>
> template <typename T> any_conversion(const T&);

Yep, fixed in Trunk.

> 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.

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.

It seems to me that these related issues are basically unfixable without
badly breaking something else,

Regards, John.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk