This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of Resolved status.

### 983. `unique_ptr` reference deleters should not be moved from

Section: 20.3.1.3 [unique.ptr.single] Status: Resolved Submitter: Howard Hinnant Opened: 2009-02-10 Last modified: 2016-01-28

Priority: Not Prioritized

View other active issues in [unique.ptr.single].

View all other issues in [unique.ptr.single].

View all issues with Resolved status.

Discussion:

Dave brought to my attention that when a `unique_ptr` has a non-const reference type deleter, move constructing from it, even when the `unique_ptr` containing the reference is an rvalue, could have surprising results:

>     D d(some-state);
>     unique_ptr<A, D&> p(new A, d);
>     unique_ptr<A, D> p2 = std::move(p);
>     // has d's state changed here?

I agree with him. It is the `unique_ptr` that is the rvalue, not the deleter. When the deleter is a reference type, the `unique_ptr` should respect the "lvalueness" of the deleter.

Thanks Dave.

[ Batavia (2009-05): ]

> Seems correct, but complicated enough that we recommend moving to Review.

[ 2009-10 Santa Cruz: ]

> Move to Ready.

[ 2010-03-14 Howard adds: ]

> We moved N3073 to the formal motions page in Pittsburgh which should obsolete this issue. I've moved this issue to NAD Editorial, solved by N3073.

Rationale:

Solved by N3073.

Proposed resolution:

Change 20.3.1.3.2 [unique.ptr.single.ctor], p20-21

>     template <class U, class E> unique_ptr(unique_ptr<U, E>&& u);

> > -20- Requires: If `D E` is not a reference type, construction of the deleter `D` from an rvalue of type `E` shall be well formed and shall not throw an exception. Otherwise `E` is a reference type and construction of the deleter `D` from an lvalue of type `E` shall be well formed and shall not throw an exception. If `D` is a reference type, then `E` shall be the same type as `D` (diagnostic required). `unique_ptr<U, E>::pointer` shall be implicitly convertible to `pointer`. [`Note:` These requirements imply that `T` and `U` are complete types. — end note]

> > -21- Effects: Constructs a `unique_ptr` which owns the pointer which `u` owns (if any). If the deleter `E` is not a reference type, it this deleter is move constructed from `u`'s deleter, otherwise the reference this deleter is copy constructed from `u`.'s deleter. After the construction, `u` no longer owns a pointer. [Note: The deleter constructor can be implemented with `std::forward<DE>`. — end note]

Change 20.3.1.3.4 [unique.ptr.single.asgn], p1-3

>     unique_ptr& operator=(unique_ptr&& u);

> > -1- Requires: If the deleter `D` is not a reference type, A assignment of the deleter `D` from an rvalue `D` shall not throw an exception. Otherwise the deleter `D` is a reference type, and assignment of the deleter `D` from an lvalue `D` shall not throw an exception.

> > -2- Effects: reset(u.release()) followed by an move assignment from `u`'s deleter to this deleter `std::forward<D>(u.get_deleter())`.

> > -3- Postconditions: This `unique_ptr` now owns the pointer which `u` owned, and `u` no longer owns it. [Note: If `D` is a reference type, then the referenced lvalue deleters are move assigned. — end note]

Change 20.3.1.3.4 [unique.ptr.single.asgn], p6-7

>     template <class U, class E> unique_ptr& operator=(unique_ptr<U, E>&& u);

> > Requires: If the deleter `E` is not a reference type, A assignment of the deleter `D` from an rvalue `DE` shall not throw an exception. Otherwise the deleter `E` is a reference type, and assignment of the deleter `D` from an lvalue `E` shall not throw an exception. `unique_ptr<U, E>::pointer` shall be implicitly convertible to `pointer`. [Note: These requirements imply that `T` and `U>` are complete types. — end note]

> > Effects: `reset(u.release())` followed by an move assignment from `u`'s deleter to this deleter `std::forward<E>(u.get_deleter())`. If either `D` or `E` is a reference type, then the referenced lvalue deleter participates in the move assignment.