This page is a snapshot from the LWG issues list, see theLibrary Active Issues List for more information and the meaning ofResolved status.
unique_ptr reference deleters should not be moved fromSection: 20.3.1.3[unique.ptr.single]Status:ResolvedSubmitter: Howard HinnantOpened: 2009-02-10Last modified: 2016-01-28
Priority:Not Prioritized
View otheractive issues in [unique.ptr.single].
View all otherissues in [unique.ptr.single].
View all issues withResolved status.
Discussion:
Dave brought to my attention that when aunique_ptr has a non-const referencetype deleter, move constructing from it, even when theunique_ptr containingthe 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 theunique_ptr that is the rvalue, not thedeleter. When the deleter is a reference type, theunique_ptr shouldrespect 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 movedN3073to the formal motions page in Pittsburgh which should obsolete this issue. I'vemoved this issue to NAD Editorial, solved by N3073.
Rationale:
Solved byN3073.
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 deleterDEDfrom an rvalue of typeEshall be well formed and shall not throw an exception.OtherwiseEis a reference type and construction of the deleterDfrom an lvalue of typeEshall be well formed andshall not throw an exception.IfDisa reference type, thenEshall be the same type asD(diagnostic required).unique_ptr<U, E>::pointershall beimplicitly convertible topointer. [Note:Theserequirements imply thatTandUare complete types.—end note]-21-Effects: Constructs a
unique_ptrwhich owns thepointer whichuowns (if any). If the deleterEis not a reference type,itthisdeleter is move constructed fromu's deleter, otherwisethe referencethis deleter is copy constructedfromu.'s deleter. After the construction,uno longerowns a pointer. [Note: The deleter constructor can be implementedwithstd::forward<. —endnote]DE>
Change 20.3.1.3.4[unique.ptr.single.asgn], p1-3
unique_ptr& operator=(unique_ptr&& u);-1-Requires:If the deleter
Dis not a reference type,Aassignment of the deleterDfrom an rvalueDshall not throw an exception.Otherwise the deleterDis a reference type,and assignment of the deleterDfrom an lvalueDshall not throw an exception.-2-Effects: reset(u.release()) followed byan
moveassignment fromu's deleter to this deleterstd::forward<D>(u.get_deleter()).-3-Postconditions: This
unique_ptrnow owns the pointerwhichuowned, anduno longer owns it.[Note: IfDis a reference type, then the referenced lvalue deleters aremove 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
Eis not a reference type,Aassignment of the deleterDfrom an rvalueshall not throw an exception.Otherwise the deleterDEEis a reference type,and assignment of the deleterDfrom an lvalueEshall not throw an exception.unique_ptr<U, E>::pointershall be implicitly convertible topointer.[Note: These requirements imply thatTandU>are complete types. —end note]Effects:
reset(u.release())followed byanmoveassignment fromu's deleter to this deleterstd::forward<E>(u.get_deleter()).If eitherDorEis a reference type, then the referenced lvaluedeleter participates in the move assignment.