Title
unique_ptr reference deleters should not be moved from
Status
resolved
Section
[unique.ptr.single]
Submitter
Howard Hinnant

Created on 2009-02-10.00:00:00 last changed 171 months ago

Messages

Date: 2010-10-21.18:28:33

Proposed resolution:

Change [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 [unique.ptr.single.asgn], p1-3

unique_ptr& operator=(unique_ptr&& u);

-1- Requires: If the deleter D is not a reference type, Aassignment 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 [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, Aassignment 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.

Date: 2010-10-21.18:28:33

Rationale:

Solved by N3073.

Date: 2010-03-14.00:00:00

[ 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.

Date: 2010-10-21.18:28:33

[ 2009-10 Santa Cruz: ]

Move to Ready.

Date: 2010-10-21.18:28:33

[ Batavia (2009-05): ]

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

Date: 2009-02-10.00:00:00

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.

History
Date User Action Args
2010-11-19 19:04:45adminsetstatus: nad editorial -> resolved
2010-10-21 18:28:33adminsetmessages: + msg4681
2010-10-21 18:28:33adminsetmessages: + msg4680
2010-10-21 18:28:33adminsetmessages: + msg4679
2010-10-21 18:28:33adminsetmessages: + msg4678
2010-10-21 18:28:33adminsetmessages: + msg4677
2009-02-10 00:00:00admincreate