Skip to content

Commit aaa76fc

Browse files
committed
Updates P/R for 4251, covering polymorphic
1 parent f122fa9 commit aaa76fc

File tree

1 file changed

+153
-4
lines changed

1 file changed

+153
-4
lines changed

xml/issue4251.xml

Lines changed: 153 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33

44
<issue num="4251" status="New">
55
<title>Move assignment for `indirect` unnecessarily requires copy construction</title>
6-
<section><sref ref="[indirect.asgn]"/></section>
6+
<section>
7+
<sref ref="[indirect.assign]"/>
8+
<sref ref="[polymorphic.assign]"/>
9+
</section>
710
<submitter>Jonathan Wakely</submitter>
811
<date>01 May 2025</date>
912
<priority>1</priority>
@@ -46,15 +49,14 @@ Set priority to 1 after reflector poll.
4649
Similar change needed for `std::polymorphic`.
4750
</p>
4851

49-
</discussion>
5052

51-
<resolution>
53+
<superseded>
5254
<p>
5355
This wording is relative to <paper num="N5008"/>.
5456
</p>
5557
<ol>
5658

57-
<li><p>Modify <sref ref="[indirect.asgn]"/> as indicated:</p>
59+
<li><p>Modify <sref ref="[indirect.assign]"/> as indicated:</p>
5860
<blockquote>
5961
<pre><code>
6062
constexpr indirect&amp; operator=(indirect&amp;&amp; other)
@@ -122,6 +124,153 @@ the allocator in `*this` is replaced with a copy of the allocator in `other`.
122124
</blockquote>
123125
</blockquote>
124126
</li>
127+
</ol>
128+
</superseded>
129+
130+
<note>2025-11-03; Tomasz provides wording.</note>
131+
</discussion>
132+
133+
<resolution>
134+
<p>
135+
This wording is relative to <paper num="N5008"/>.
136+
</p>
137+
<ol>
138+
139+
<li><p>Modify <sref ref="[indirect.assign]"/> as indicated:</p>
140+
<blockquote>
141+
<pre><code>
142+
constexpr indirect&amp; operator=(indirect&amp;&amp; other)
143+
noexcept(allocator_traits&lt;Allocator&gt;::propagate_on_container_move_assignment::value ||
144+
allocator_traits&lt;Allocator&gt;::is_always_equal::value);
145+
</code></pre>
146+
<blockquote>
147+
<p>
148+
-5- <i>Mandates</i>:
149+
<ins>
150+
If
151+
<code>allocator_traits&lt;Allocator&gt;::propagate_on_container_move_assignment::value</code>
152+
is `false`
153+
and
154+
<code>allocator_traits&lt;Allocator&gt;::is_always_equal::value</code>
155+
is `false`,
156+
</ins>
157+
<code>is_<del>copy</del><ins>move</ins>_constructible_t&lt;T&gt;</code> is `true`.
158+
</p>
159+
<p>
160+
-6- <i>Effects</i>:
161+
If `addressof(other) == this` is `true`, there are no effects.
162+
Otherwise:
163+
<ol style="list-style-type:none">
164+
<li>(6.1) &mdash;
165+
The allocator needs updating if
166+
<code>allocator_traits&lt;Allocator&gt;::propagate_on_container_move_assignment::value</code>
167+
is `true`.
168+
</li>
169+
<li>(6.2) &mdash;
170+
If `other` is valueless, `*this` becomes valueless<del> and the owned object
171+
in `*this`, if any, is destroyed using
172+
<code>allocator_traits&lt;Allocator&gt;::destroy</code>
173+
and then the storage is deallocated</del>.
174+
</li>
175+
<li>(6.3) &mdash;
176+
Otherwise,
177+
<ins>if the allocator needs updating or</ins>
178+
if <code><i>alloc</i> == other.<i>alloc</i></code> is `true`,
179+
<del>
180+
swaps the owned objects in `*this` and `other`;
181+
the owned object in `other`, if any, is then destroyed using
182+
<code>allocator_traits&lt;Allocator&gt;::destroy</code>
183+
and then the storage is deallocated
184+
</del>
185+
<ins>`*this` takes ownership of the owned object of `other`</ins>.
186+
</li>
187+
<li>(6.4) &mdash;
188+
Otherwise, constructs a new owned object with the owned object of `other`
189+
as the argument as an rvalue, using <del>either</del> the allocator in `*this`
190+
<del>or the allocator in `other` if the allocator needs updating</del>.
191+
</li>
192+
<li>(6.5) &mdash;
193+
The previously owned object in `*this`, if any, is destroyed using
194+
<code>allocator_traits&lt;Allocator&gt;::destroy</code>
195+
and then the storage is deallocated.
196+
</li>
197+
<li>(6.6) &mdash;
198+
If the allocator needs updating,
199+
the allocator in `*this` is replaced with a copy of the allocator in `other`.
200+
</li>
201+
</ol>
202+
</p>
203+
<p>-7- <i>Postcondition</i>: `other` is valueless.</p>
204+
</blockquote>
205+
</blockquote>
206+
</li>
207+
208+
<li><p>Modify <sref ref="[polymorphic.assign]"/> as indicated:</p>
209+
<blockquote>
210+
<pre><code>
211+
constexpr polymorphic&amp; operator=(polymorphic&amp;&amp; other)
212+
noexcept(allocator_traits&lt;Allocator&gt;::propagate_on_container_move_assignment::value ||
213+
allocator_traits&lt;Allocator&gt;::is_always_equal::value);
214+
</code></pre>
215+
<blockquote>
216+
<p>
217+
-5- <i>Mandates</i>:
218+
If
219+
<ins>
220+
<code>allocator_traits&lt;Allocator&gt;::propagate_on_container_move_assignment::value</code>
221+
is `false`
222+
and
223+
</ins>
224+
<code>allocator_traits&lt;Allocator&gt;::is_always_equal::value</code>
225+
is `false`,
226+
`T` is complete type.
227+
</p>
228+
<p>
229+
-6- <i>Effects</i>:
230+
If `addressof(other) == this` is `true`, there are no effects.
231+
Otherwise:
232+
<ol style="list-style-type:none">
233+
<li>(6.1) &mdash;
234+
The allocator needs updating if
235+
<code>allocator_traits&lt;Allocator&gt;::propagate_on_container_move_assignment::value</code>
236+
is `true`.
237+
</li>
238+
<li><ins>(6.?) &mdash; If `other` is valueless, `*this` becomes valueless.</ins></li>
239+
<li>(6.2) &mdash;
240+
<ins>Otherwise, if the allocator needs updating or</ins><del>If</del>
241+
<code><i>alloc</i> == other.<i>alloc</i></code> is `true`,
242+
<del>
243+
swaps the owned objects in `*this` and `other`;
244+
the owned object in `other`, if any, is then destroyed using
245+
<code>allocator_traits&lt;Allocator&gt;::destroy</code>
246+
and then the storage is deallocated
247+
</del>
248+
<ins>`*this` takes ownership of the owned object of `other`</ins>.
249+
</li>
250+
<li>(6.3) &mdash;
251+
<del>Otherwise, if `alloc != other.alloc` is `true`; if `other` is not valueless,
252+
a new owned object is constructed in `*this` using <tt>allocator_traits::construct</tt>
253+
with the owned object from</del>
254+
<ins>Otherwise, constructs a new owned object with the owned object of</ins>
255+
`other` as the argument as an rvalue, using <del>either</del> the allocator in `*this`
256+
<del>or the allocator in `other` if the allocator needs updating</del>.
257+
</li>
258+
<li>(6.4) &mdash;
259+
The previously owned object in `*this`, if any, is destroyed using
260+
<code>allocator_traits&lt;Allocator&gt;::destroy</code>
261+
and then the storage is deallocated.
262+
</li>
263+
<li>(6.5) &mdash;
264+
If the allocator needs updating,
265+
the allocator in `*this` is replaced with a copy of the allocator in `other`.
266+
</li>
267+
</ol>
268+
</p>
269+
[&hellip;]
270+
</blockquote>
271+
</blockquote>
272+
</li>
273+
125274
</ol>
126275
</resolution>
127276

0 commit comments

Comments
 (0)