Skip to content

Commit 4c831ac

Browse files
committed
Adjust is_replaceable to disregard self-move
1 parent 4bca641 commit 4c831ac

File tree

5 files changed

+14
-20
lines changed

5 files changed

+14
-20
lines changed

libcxx/include/__exception/exception_ptr.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,9 @@ class _LIBCPP_EXPORTED_FROM_ABI exception_ptr {
6666

6767
public:
6868
// exception_ptr is basically a COW string so it is trivially relocatable.
69-
// However, it's not replaceable because destroying and move-constructing could cause
70-
// the underlying refcount to hit 0 if we're self-assigning.
69+
// It is also replaceable because assignment has normal value semantics.
7170
using __trivially_relocatable _LIBCPP_NODEBUG = exception_ptr;
72-
using __replaceable _LIBCPP_NODEBUG = void;
71+
using __replaceable _LIBCPP_NODEBUG = exception_ptr;
7372

7473
_LIBCPP_HIDE_FROM_ABI exception_ptr() _NOEXCEPT : __ptr_() {}
7574
_LIBCPP_HIDE_FROM_ABI exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {}

libcxx/include/__locale

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,9 @@ _LIBCPP_HIDE_FROM_ABI const _Facet& use_facet(const locale&);
5151
class _LIBCPP_EXPORTED_FROM_ABI locale {
5252
public:
5353
// locale is essentially a shared_ptr that doesn't support weak_ptrs and never got a move constructor,
54-
// so it is trivially relocatable. However, it is not replaceable because self-assignment must prevent
55-
// the refcount from hitting 0.
54+
// so it is trivially relocatable. Like shared_ptr, it is also replaceable.
5655
using __trivially_relocatable _LIBCPP_NODEBUG = locale;
57-
using __replaceable _LIBCPP_NODEBUG = void;
56+
using __replaceable _LIBCPP_NODEBUG = locale;
5857

5958
// types:
6059
class _LIBCPP_EXPORTED_FROM_ABI facet;

libcxx/include/__memory/shared_ptr.h

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -316,12 +316,10 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS shared_ptr {
316316
#endif
317317

318318
// A shared_ptr contains only two raw pointers which point to the heap and move constructing already doesn't require
319-
// any bookkeeping, so it's always trivially relocatable.
320-
//
321-
// However, it's not replaceable because of self-assignment, which must prevent the refcount from
322-
// hitting 0.
319+
// any bookkeeping, so it's always trivially relocatable. It is also replaceable because assignment just rebinds the
320+
// shared_ptr to manage a different object.
323321
using __trivially_relocatable _LIBCPP_NODEBUG = shared_ptr;
324-
using __replaceable _LIBCPP_NODEBUG = void;
322+
using __replaceable _LIBCPP_NODEBUG = shared_ptr;
325323

326324
private:
327325
element_type* __ptr_;
@@ -1215,11 +1213,9 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS weak_ptr {
12151213
#endif
12161214

12171215
// A weak_ptr contains only two raw pointers which point to the heap and move constructing already doesn't require
1218-
// any bookkeeping, so it's always trivially relocatable.
1219-
//
1220-
// However, it's not replaceable because we must preserve a non-zero refcount through self-assignment.
1216+
// any bookkeeping, so it's always trivially relocatable. It's also replaceable for the same reason.
12211217
using __trivially_relocatable _LIBCPP_NODEBUG = weak_ptr;
1222-
using __replaceable _LIBCPP_NODEBUG = void;
1218+
using __replaceable _LIBCPP_NODEBUG = weak_ptr;
12231219

12241220
private:
12251221
element_type* __ptr_;

libcxx/include/__type_traits/is_replaceable.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
_LIBCPP_BEGIN_NAMESPACE_STD
2323

24-
// A type is replaceable if `x = std::move(y)` is equivalent to:
24+
// A type is replaceable if, with `x` and `y` being different objects, `x = std::move(y)` is equivalent to:
2525
//
2626
// std::destroy_at(&x)
2727
// std::construct_at(&x, std::move(y))

libcxx/test/libcxx/type_traits/is_replaceable.compile.pass.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ static_assert(std::__is_replaceable<std::deque<int, NonPropagatingStatelessCopyA
191191
static_assert(std::__is_replaceable<std::deque<int, NonPropagatingStatelessMoveAssignAlloc<int> > >::value, "");
192192

193193
// exception_ptr
194-
static_assert(!std::__is_replaceable<std::exception_ptr>::value, "");
194+
static_assert(std::__is_replaceable<std::exception_ptr>::value, "");
195195

196196
// expected
197197
#if TEST_STD_VER >= 23
@@ -203,7 +203,7 @@ static_assert(!std::__is_replaceable<std::expected<CustomCopyAssignment, CustomC
203203

204204
// locale
205205
#ifndef TEST_HAS_NO_LOCALIZATION
206-
static_assert(!std::__is_replaceable<std::locale>::value, "");
206+
static_assert(std::__is_replaceable<std::locale>::value, "");
207207
#endif
208208

209209
// optional
@@ -219,7 +219,7 @@ static_assert(!std::__is_replaceable<std::pair<int, CustomCopyAssignment> >::val
219219
static_assert(!std::__is_replaceable<std::pair<CustomCopyAssignment, CustomCopyAssignment> >::value, "");
220220

221221
// shared_ptr
222-
static_assert(!std::__is_replaceable<std::shared_ptr<int> >::value, "");
222+
static_assert(std::__is_replaceable<std::shared_ptr<int> >::value, "");
223223

224224
// tuple
225225
#if TEST_STD_VER >= 11
@@ -284,6 +284,6 @@ static_assert(std::__is_replaceable<std::vector<int, NonPropagatingStatelessCopy
284284
static_assert(std::__is_replaceable<std::vector<int, NonPropagatingStatelessMoveAssignAlloc<int> > >::value, "");
285285

286286
// weak_ptr
287-
static_assert(!std::__is_replaceable<std::weak_ptr<CustomCopyAssignment> >::value, "");
287+
static_assert(std::__is_replaceable<std::weak_ptr<CustomCopyAssignment> >::value, "");
288288

289289
// TODO: Mark all the replaceable STL types as such

0 commit comments

Comments
 (0)