Skip to content

Commit 34538db

Browse files
[libc++] Make shared_ptr move unique_ptr's deleter
Addresses LWG 3548 which mandates that when shared_ptr is being constructed from a unique_ptr, the unique_ptr's deleter should be moved and not copied. Reviewed By: #libc, philnik, EricWF Differential Revision: https://reviews.llvm.org/D119159
1 parent 8f108c3 commit 34538db

File tree

3 files changed

+46
-10
lines changed

3 files changed

+46
-10
lines changed

libcxx/docs/Status/Cxx2bIssues.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@
9090
`3543 <https://wg21.link/LWG3543>`__,"Definition of when ``counted_iterators`` refer to the same sequence isn't quite right","June 2021","|Nothing To Do|","","|ranges|"
9191
`3544 <https://wg21.link/LWG3544>`__,"``format-arg-store::args`` is unintentionally not exposition-only","June 2021","|Complete|","14.0","|format|"
9292
`3546 <https://wg21.link/LWG3546>`__,"``common_iterator``'s postfix-proxy is not quite right","June 2021","","","|ranges|"
93-
`3548 <https://wg21.link/LWG3548>`__,"``shared_ptr`` construction from ``unique_ptr`` should move (not copy) the deleter","June 2021","",""
93+
`3548 <https://wg21.link/LWG3548>`__,"``shared_ptr`` construction from ``unique_ptr`` should move (not copy) the deleter","June 2021","|Complete|","15.0"
9494
`3549 <https://wg21.link/LWG3549>`__,"``view_interface`` is overspecified to derive from ``view_base``","June 2021","|Complete|","14.0","|ranges|"
9595
`3551 <https://wg21.link/LWG3551>`__,"``borrowed_{iterator,subrange}_t`` are overspecified","June 2021","|Nothing To Do|","","|ranges|"
9696
`3552 <https://wg21.link/LWG3552>`__,"Parallel specialized memory algorithms should require forward iterators","June 2021","",""

libcxx/include/__memory/shared_ptr.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr
457457
explicit shared_ptr(_Yp* __p) : __ptr_(__p) {
458458
unique_ptr<_Yp> __hold(__p);
459459
typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT;
460-
typedef __shared_ptr_pointer<_Yp*, __shared_ptr_default_delete<_Tp, _Yp>, _AllocT > _CntrlBlk;
460+
typedef __shared_ptr_pointer<_Yp*, __shared_ptr_default_delete<_Tp, _Yp>, _AllocT> _CntrlBlk;
461461
__cntrl_ = new _CntrlBlk(__p, __shared_ptr_default_delete<_Tp, _Yp>(), _AllocT());
462462
__hold.release();
463463
__enable_weak_this(__p, __p);
@@ -473,7 +473,7 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr
473473
{
474474
#endif // _LIBCPP_NO_EXCEPTIONS
475475
typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT;
476-
typedef __shared_ptr_pointer<_Yp*, _Dp, _AllocT > _CntrlBlk;
476+
typedef __shared_ptr_pointer<_Yp*, _Dp, _AllocT> _CntrlBlk;
477477
#ifndef _LIBCPP_CXX03_LANG
478478
__cntrl_ = new _CntrlBlk(__p, _VSTD::move(__d), _AllocT());
479479
#else
@@ -532,7 +532,7 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr
532532
{
533533
#endif // _LIBCPP_NO_EXCEPTIONS
534534
typedef typename __shared_ptr_default_allocator<_Tp>::type _AllocT;
535-
typedef __shared_ptr_pointer<nullptr_t, _Dp, _AllocT > _CntrlBlk;
535+
typedef __shared_ptr_pointer<nullptr_t, _Dp, _AllocT> _CntrlBlk;
536536
#ifndef _LIBCPP_CXX03_LANG
537537
__cntrl_ = new _CntrlBlk(__p, _VSTD::move(__d), _AllocT());
538538
#else
@@ -665,8 +665,8 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr
665665
#endif
666666
{
667667
typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT;
668-
typedef __shared_ptr_pointer<typename unique_ptr<_Yp, _Dp>::pointer, _Dp, _AllocT > _CntrlBlk;
669-
__cntrl_ = new _CntrlBlk(__r.get(), __r.get_deleter(), _AllocT());
668+
typedef __shared_ptr_pointer<typename unique_ptr<_Yp, _Dp>::pointer, _Dp, _AllocT> _CntrlBlk;
669+
__cntrl_ = new _CntrlBlk(__r.get(), std::move(__r.get_deleter()), _AllocT());
670670
__enable_weak_this(__r.get(), __r.get());
671671
}
672672
__r.release();
@@ -689,7 +689,7 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr
689689
typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT;
690690
typedef __shared_ptr_pointer<typename unique_ptr<_Yp, _Dp>::pointer,
691691
reference_wrapper<typename remove_reference<_Dp>::type>,
692-
_AllocT > _CntrlBlk;
692+
_AllocT> _CntrlBlk;
693693
__cntrl_ = new _CntrlBlk(__r.get(), _VSTD::ref(__r.get_deleter()), _AllocT());
694694
__enable_weak_this(__r.get(), __r.get());
695695
}

libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.const/unique_ptr.pass.cpp

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,13 @@ struct StatefulArrayDeleter {
8282
}
8383
};
8484

85+
struct MovingDeleter {
86+
explicit MovingDeleter(int *moves) : moves_(moves) {}
87+
MovingDeleter(MovingDeleter&& rhs) : moves_(rhs.moves_) { *moves_ += 1; }
88+
void operator()(int*) const {}
89+
int *moves_;
90+
};
91+
8592
int main(int, char**)
8693
{
8794
{
@@ -230,10 +237,39 @@ int main(int, char**)
230237
assert(A::count == 0);
231238

232239
{
233-
std::unique_ptr<int[]> ptr(new int[8]);
234-
std::shared_ptr<int[]> p(std::move(ptr));
240+
int *p = new int[8];
241+
std::unique_ptr<int[]> u(p);
242+
std::shared_ptr<int[]> s(std::move(u));
243+
assert(u == nullptr);
244+
assert(s.get() == p);
245+
}
246+
#endif // TEST_STD_VER > 14
247+
248+
{ // LWG 3548
249+
{
250+
int moves = 0;
251+
int i = 42;
252+
std::unique_ptr<int, MovingDeleter> u(&i, MovingDeleter(&moves));
253+
assert(moves == 1);
254+
std::shared_ptr<int> s(std::move(u));
255+
assert(moves >= 2);
256+
assert(u == nullptr);
257+
assert(s.get() == &i);
258+
}
259+
260+
#if TEST_STD_VER > 14
261+
{
262+
int moves = 0;
263+
int a[8];
264+
std::unique_ptr<int[], MovingDeleter> u(a, MovingDeleter(&moves));
265+
assert(moves == 1);
266+
std::shared_ptr<int[]> s = std::move(u);
267+
assert(moves >= 2);
268+
assert(u == nullptr);
269+
assert(s.get() == a);
270+
}
271+
#endif // TEST_STD_VER > 14
235272
}
236-
#endif // TEST_STD_VER >= 14
237273

238274
return 0;
239275
}

0 commit comments

Comments
 (0)