@@ -48,6 +48,11 @@ class shared_ptr
4848
4949 shared_ptr_wrapper (std::shared_ptr<T> &&ptr) noexcept : ptr_{std::move (ptr)} {}
5050
51+ shared_ptr_wrapper (const shared_ptr_wrapper &) = default ;
52+ shared_ptr_wrapper &operator =(const shared_ptr_wrapper &) = default ;
53+ shared_ptr_wrapper (shared_ptr_wrapper &&) = default ;
54+ shared_ptr_wrapper &operator =(shared_ptr_wrapper &&) = default ;
55+
5156 virtual ~shared_ptr_wrapper () {}
5257
5358 virtual void CopyTo (PlacementBuffer &buffer) const noexcept
@@ -99,20 +104,20 @@ class shared_ptr
99104 typename std::enable_if<std::is_convertible<U *, pointer>::value>::type * = nullptr >
100105 shared_ptr (shared_ptr<U> &&other) noexcept
101106 {
102- other.wrapper ().template MoveTo <T>(buffer_);
107+ std::move ( other) .wrapper ().template MoveTo <T>(buffer_);
103108 }
104109
105110 shared_ptr (const shared_ptr &other) noexcept { other.wrapper ().CopyTo (buffer_); }
106111
107112 shared_ptr (unique_ptr<T> &&other) noexcept
108113 {
109- std::shared_ptr<T> ptr_ (other.release ());
114+ std::shared_ptr<T> ptr_ (std::move ( other) .release ());
110115 new (buffer_.data ) shared_ptr_wrapper{std::move (ptr_)};
111116 }
112117
113118 shared_ptr (std::unique_ptr<T> &&other) noexcept
114119 {
115- std::shared_ptr<T> ptr_ (other.release ());
120+ std::shared_ptr<T> ptr_ (std::move ( other) .release ());
116121 new (buffer_.data ) shared_ptr_wrapper{std::move (ptr_)};
117122 }
118123
@@ -156,10 +161,15 @@ class shared_ptr
156161
157162 void swap (shared_ptr<T> &other) noexcept
158163 {
159- shared_ptr<T> tmp{std::move (other)};
164+ if (this == &other)
165+ {
166+ return ;
167+ }
160168
161- wrapper ().MoveTo (other.buffer_ );
162- tmp.wrapper ().MoveTo (buffer_);
169+ // Swap the live wrapper objects (object-level swap), not the raw
170+ // PlacementBuffer bytes. This preserves object lifetime correctness and
171+ // avoids moving `other` as an object.
172+ std::swap (wrapper (), other.wrapper ());
163173 }
164174
165175 template <typename U>
0 commit comments