|
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