Boost logo

Boost :

Subject: Re: [boost] is_convertible problems associated with move-only types
From: David Abrahams (dave_at_[hidden])
Date: 2009-01-06 10:45:53


on Mon Jan 05 2009, Howard Hinnant <hinnant-AT-twcny.rr.com> wrote:

> I'm continuing to refine a boost::unique_ptr emulation and testsuite.

Howard, can you put this in the sandbox? I know there are a number of
us who would like very much to collaborate on it.

> One thing I've just uncovered is that I'm hitting a brick wall with
> is_convertible and move-only deleters used within the unique_ptr move
> constructor. The problem is that boost::is_convertible<From, To>
> assumes From is an lvalue.

Sorry to be nitpicky, but that's not making sense to me. IIUC the terms
lvalue and rvalue can only apply to expressions, not types. Are you
saying that From has to be a reference type? Surely not.

> is_convertible<Deleter, Deleter> gets instantiated and it is all over.

Specifically, how?

> I've modified my copy of is_convertible (without really knowing what I'm doing) like
> so:
>
> Index: is_convertible.hpp
> ===================================================================
> --- is_convertible.hpp (revision 50433)
> +++ is_convertible.hpp (working copy)
> @@ -119,6 +119,8 @@
> struct any_conversion
> {
> template <typename T> any_conversion(const volatile T&);
> + template <typename T> any_conversion(volatile T&);
> + template <typename T> any_conversion(const T&);
> template <typename T> any_conversion(T&);
> };
>
> @@ -131,8 +133,8 @@
> template <typename From, typename To>
> struct is_convertible_basic_impl
> {
> - static From _m_from;
> - static bool const value = sizeof( detail::checker<To>::_m_check(_m_from, 0) )
> + static From _m_from();
> + static bool const value = sizeof( detail::checker<To>::_m_check(_m_from(), 0) )
> == sizeof(::boost::type_traits::yes_type);
> };

Note the From above is not the same as the one below at least in the
current code.

> @@ -291,7 +293,8 @@
> template <typename From, typename To>
> struct is_convertible_impl
> {
> - typedef typename add_reference<From>::type ref_type;
> +// typedef typename add_reference<From>::type ref_type;
> + typedef From ref_type;
> BOOST_STATIC_CONSTANT(bool, value =
> (::boost::type_traits::ice_and<
> ::boost::type_traits::ice_or<

So it used to pass an lvalue of type _m_from, and after your change it
passes an rvalue. Of course, your change now assumes that From can be
returned from a function. I think you'll have a problem if you try this
with From being a noncopyable non-movable type.

> This hits just the part targeting gcc.

(and old Borland compilers).

> The intent is that in boost::is_convertible<From, To> From is now
> considered an rvalue (unless From is a (lvalue) reference type). This
> makes my test case happy. I can now move construct a unique_ptr with
> a move-only deleter.
>
> Fwiw, this definition of is_convertible is consistent with std::is_convertible in
> N2800:

I was just going to ask that.

-- 
Dave Abrahams
BoostPro Computing
http://www.boostpro.com

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