|
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