Boost logo

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