|
Boost : |
Subject: Re: [boost] unique_ptr, was: Composing non copyable and movable classes
From: Howard Hinnant (hinnant_at_[hidden])
Date: 2008-12-10 16:27:58
On Dec 10, 2008, at 4:12 PM, Sebastian Redl wrote:
> Peter Dimov wrote:
>> Michael Marcin:
>>
>>> Speaking of unique_ptr is it possible to get a C++03 emulation of
>>> unique_ptr into boost?
>>>
>>> I've been using http://home.twcny.rr.com/hinnant/cpp_extensions/unique_ptr_03.html
>>> for months and it seems to work fine.
>>
>> To get it into Boost, someone needs to contribute the tests and
>> documentation and commit to maintaining it. :-)
>>
>> That said, I'm not fond of this property of the cited implementation:
>>
>> #
>>
>> This implementation will mistakenly move from const lvalues.
> Howard has an updated version that doesn't do this. The new version
> is really slick.
Here's a sketch of what Sebastian is referring to. It isn't a
complete unique_ptr. It is just a move-only-foundation to build off
of. I'm afraid I don't have the time to contribute the tests and
documentation and commit to maintaining a unique_ptr. So this is
offered in the same spirt as the code at http://home.twcny.rr.com/hinnant/cpp_extensions/unique_ptr_03.html
(anyone can do whatever they want with it). Also Sebastian deserves
credit for some of the details below.
template <class T>
class unique_ptr
{
T* ptr_;
unique_ptr(unique_ptr&);
unique_ptr& operator=(unique_ptr&);
class rv
{
unique_ptr& r_;
public:
explicit rv(unique_ptr& r) : r_(r) {}
unique_ptr* operator->() {return &r_;}
};
public:
operator rv() {return rv(*this);}
unique_ptr(rv r) : ptr_(r->release()) {}
unique_ptr& operator=(rv r) {reset(r->release()); return *this;}
friend unique_ptr move(unique_ptr& u) {return unique_ptr(rv(u));}
friend unique_ptr move(rv r) {return unique_ptr(r);}
explicit unique_ptr(T* p = 0) : ptr_(p) {}
template <class U>
unique_ptr(unique_ptr<U> u)
: ptr_(u.release()) {}
~unique_ptr() {reset();}
template <class U>
unique_ptr& operator=(unique_ptr<U> u) {reset(u.release());
return *this;}
T* release()
{
T* tmp = ptr_;
ptr_ = 0;
return tmp;
}
void reset(T* ptr = 0)
{
if (ptr_)
delete ptr_;
ptr_ = ptr;
}
};
It isn't a perfect emulation. But I think it is pretty close. And
where it fails, it is not a dangerous failure like moving from a const.
-Howard
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk