unique_ptr
reference deleters should not be moved fromSection: 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
is not a reference type, construction of the deleter
DED
from an rvalue of typeE
shall be well formed and shall not throw an exception. OtherwiseE
is a reference type and construction of the deleterD
from an lvalue of typeE
shall be well formed and shall not throw an exception. IfD
is a reference type, thenE
shall be the same type asD
(diagnostic required).unique_ptr<U, E>::pointer
shall be implicitly convertible topointer
. [Note:
These requirements imply thatT
andU
are complete types. — end note]-21- Effects: Constructs a
unique_ptr
which owns the pointer whichu
owns (if any). If the deleterE
is not a reference type,itthis deleter is move constructed fromu
's deleter, otherwisethe referencethis deleter is copy constructed fromu
.'s deleter. After the construction,u
no longer owns a pointer. [Note: The deleter constructor can be implemented withstd::forward<
. — end note]DE>
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,Aassignment of the deleterD
from an rvalueD
shall not throw an exception. Otherwise the deleterD
is a reference type, and assignment of the deleterD
from an lvalueD
shall not throw an exception.-2- Effects: reset(u.release()) followed by an
moveassignment fromu
's deleter to this deleterstd::forward<D>(u.get_deleter())
.-3- Postconditions: This
unique_ptr
now owns the pointer whichu
owned, andu
no longer owns it.[Note: IfD
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,Aassignment of the deleterD
from an rvalueshall not throw an exception. Otherwise the deleter
DEE
is a reference type, and assignment of the deleterD
from an lvalueE
shall not throw an exception.unique_ptr<U, E>::pointer
shall be implicitly convertible topointer
. [Note: These requirements imply thatT
andU>
are complete types. — end note]Effects:
reset(u.release())
followed by anmoveassignment fromu
's deleter to this deleterstd::forward<E>(u.get_deleter())
.If eitherD
orE
is a reference type, then the referenced lvalue deleter participates in the move assignment.