Boost logo

Boost :

Subject: Re: [boost] [type_traits][parameter] Inconsistent boost::is_convertible between gcc and clang
From: Michel Morin (mimomorin_at_[hidden])
Date: 2012-08-12 00:32:00


(CC'ing John Maddock)

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

In Boost 1.46 and prior versions, the doc of is_convertible says

    If an imaginary lvalue of type From is convertible to type To
    then inherits from true_type,

So the behavior is correct in these versions.
But, in later versions, the doc says

    If an imaginary rvalue of type From is convertible to type To
    then inherits from true_type,

Also, here is the "History" section of the doc

    Boost 1.47.0
    * Breaking change: changed is_convertible to C++0x behaviour when possible.

(TR1's is_convertible is equivalent to the old Boost one.
C++11's is_convertible is different from them; see N2255.)

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

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);
    };

Also, `any_conversion` needs a constructor for an rvalue (Line 120):

    template <typename T> any_conversion(const T&);

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.

One note:
The above code cannot deal with `boost::is_convertible<Func, Func&>`,
where `Func` is a function type in a C++03 mode.
This results in a compiler error. (In a C++11 mode, it returns true_type.)
`boost::is_convertible<void, void>` results in a compiler error in both
C++03 and C++11 modes. If these needs to be supported, we have to
add special treatment codes.

Regards,
Michel


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