Boost logo

Boost :

Subject: Re: [boost] is_convertible problems associated with move-only types
From: Howard Hinnant (hinnant_at_[hidden])
Date: 2009-01-06 10:24:17


On Jan 6, 2009, at 4:53 AM, John Maddock wrote:

>> 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:
>>
>>> In order to instantiate the template is_convertible<From, To>, the
>>> following code shall be well formed:
>>>
>>> template <class T>
>>> typename add_rvalue_reference<T>::type create();
>>> To test() {
>>> return create<From>();
>>> }
>>>
>>> [ Note: This requirement gives well defined results for reference
>>> types,
>>> void types, array types, and function types. -- end note ]
>>
>>
>> I've got a much more refined unique_ptr testsuite on the way which
>> will contain the unique_ptr header and test case for this (not
>> there yet, I'll post when it is).
>
> Howard, have you checked that this doesn't break any of the existing
> type_traits tests? If not can you let me have one (or more!) test
> cases for the problem so I can work on patching is_convertible here?

Hi John,

I haven't tested is_convertible at all, much less developed fixes for
all the different #else branches. Here's a simplified test case:

#include <boost/type_traits.hpp>
#include <boost/static_assert.hpp>

class move_only
{
     int data_;

     move_only(move_only& u);
     move_only& operator=(volatile move_only&);

     class rv
     {
         move_only& r_;
     public:
         explicit rv(move_only& r) : r_(r) {}
         move_only* operator->() {return &r_;}
     };

public:

     operator rv() {return rv(*this);}
     move_only(rv r) : data_(r->data_) {}
     move_only& operator=(rv r) {data_ = r->data_; return *this;}

     friend move_only move(move_only& p) {return move_only(rv(p));}
     friend move_only move(rv r) {return move_only(r);}

     move_only() : data_(0) {}
};

move_only source() {return move_only();}

int main()
{
     move_only x = source();
     BOOST_STATIC_ASSERT((boost::is_convertible<move_only,
move_only>::value));
}

If it compiles, it is good. My best guess is that it will be DOA on VC
++ unless the /Za option is used.

A VC++-no-/Za workaround for the move_only type is:

#if !BROKEN
     move_only(move_only& u);
     move_only& operator=(volatile move_only&);
#else
public:
     move_only(move_only& u) : data_(u.data_) {}
     move_only& operator=(volatile move_only& u) {data_ = u.data_;
return *this;}
private:
#endif

Various people here at boost probably already have better VC++-no-/Za
solutions. I don't have this compiler to experiment with.

-Howard


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