<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css">
  p {text-align:justify}
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  blockquote.note
  {
   background-color:#E0E0E0;
   padding-left: 15px;
   padding-right: 15px;
   padding-top: 1px;
   padding-bottom: 1px;
  }
  div#refs p { padding-left: 32px; text-indent: -32px; }
</style>

<title>Introduce Cpp17Swappable as additional convenience requirements</title>

</head>
<body>
<address style="text-align: left;">
Document number: P2696R0<br>
Date: 2022-11-07<br>
Audience: Library Working Group<br>
Author: Daniel Kr&uuml;gler<br>
Reply-to: <a href="mailto:daniel.kruegler@gmail.com">Daniel Kr&uuml;gler</a>
</address>
<hr>
<h1 style="text-align: center;">Introduce <i>Cpp17Swappable</i> as additional convenience requirements</h1>

<ul>
<li><a href="#Intro">Introduction</a></li>
<li><a href="#RevisionHistory">Revision History</a></li>
<li><a href="#Discussion">Discussion</a></li>
<li><a href="#Rationale">Rationale</a></li>
<li><a href="#Proposed_resolution">Proposed Resolution</a></li>
<li><a href="#Akn">Acknowledgements</a></li>
<li><a href="#Bibliography">Bibliography</a></li>
</ul>

<h2><a name="Intro"></a>Introduction</h2>
<p>
This proposal suggests to introduce an additional requirements set to simplify, clarify, and harmonize various swappable specifications
in the Standard Library.
</p>

<h2><a name="RevisionHistory"></a>Revision History</h2>
<ul>
<li><p>
Following LWG review recommendations, <i>Cpp17Swappable</i> requirements have been withdrawn from <tt>unique_ptr::delete_type</tt>, 
<tt>pair</tt>, and <tt>tuple</tt> <tt>swap</tt>s.
</p></li>
</ul>

<h2><a name="Discussion"></a>Discussion</h2>
<p>
<a href="https://wg21.link/n3048">N3048</a> introduced requirements sets for various swappable requirements because at that
point we had eradicated the initial C++11 concepts from the working draft and had no corresponding substitute by the core 
language to express them. Nonetheless they had been introduced attempting to get similar specification advantages. At that time,
we introduced specific swappable requirements for those situations that seemed most prominently occurring in the working draft,
namely:
</p>
<ol>
<li><p>An rvalue or lvalue <tt>t</tt> is <i>swappable</i> if and only if <tt>t</tt> is swappable with any rvalue or lvalue, respectively, of
type <tt>T</tt>.</p></li>
<li><p>A type <tt>X</tt> meeting any of the iterator requirements (25.3 [iterator.requirements]) meets the 
<i>Cpp17ValueSwappable</i> requirements if, for any dereferenceable object <tt>x</tt> of type <tt>X</tt>, <tt>*x</tt> is swappable.</p></li>
</ol>
<p>
At that time it seemed especially useful to introduce the term <i>Cpp17ValueSwappable</i> because the specification of various 
algorithms could be considerably simplified that way.
</p>

<h2><a name="Rationale"></a>Rationale</h2>
<p>
The <a href="https://wg21.link/n3048">N3048</a> paper did attempt to keep the changes to the working draft rather small,
but with its future evolvement one could say that we underestimated the special case of "swappable lvalues", because we didn't introduce
a specific name for them. The effect of the current situation is that various places in the specification of types uses a mixture of
requirement set names such as <i>Cpp17MoveAssignable</i> and <i>Cpp17MoveConstructible</i> together with "lvalues of type <tt>X</tt> 
are swappable", leading to unnecessary paragraph splitting and often unnecessary long wording.
<p/>
This paper attempts to improve the specification state by introducing a new named requirement set, <i>Cpp17Swappable</i>, as a new
shortcut when we attempt to specify swappable lvalues of a specific (homogeneous) type and to use this new shortcut throughout the
library specification. In most cases, this leads to a shorter and clearer specification. 
<p/>
In an earlier draft version of this proposal we decided to apply this new set to additional places ([unique.ptr.single.modifiers], 
[pairs.pair], [tuple.swap]) where the involved types could have reference types. 
But feedback from the LWG review group showed that requirement sets are not well-suited here because we cannot 
simply apply reference collapsing rules as we would do in templates. This basically means that we are affected by the 
long existing LWG issue <a href="https://wg21.link/lwg2146">LWG2146</a> here. An alternative solution could have been
to use <tt>remove_reference_t&lt;<i>Type</i>&gt;</tt> to cope for the reference cases, but that seemed less appealing
because it would in some places make the requirement too general, which was not wanted.
In all such situations we have therefore kept the preexisting style or improved the current wording for other reasons. 
<p/>
It should be emphasized that the intention of this paper is just a simplification of existing specification, but <em>not</em>
a change of semantics. In theory, this request could have been handled as a plain editorial change request, but the author thinks
that the amount of wording changes is sufficiently high to approve them like an ordinary proposal.
</p>

<h2><a name="Proposed_resolution"></a>Proposed resolution</h2>

<p>
The proposed wording changes refer to <a href="https://wg21.link/n4917">N4917</a>.
</p>

<ol>

<li><p>Modify in 16.4.4.3 [swappable.requirements] Swappable requirements as indicated:</p>

<blockquote>
<p>
-4- An rvalue or lvalue <tt>t</tt> is <i>swappable</i> if and only if <tt>t</tt> is swappable with any rvalue or lvalue, respectively, of
type <tt>T</tt>.
<p/>
<ins>-?- A type <tt>X</tt> meets the <i>Cpp17Swappable</i> requirements if lvalues of type <tt>X</tt> are swappable.</ins>
<p/>
-5- A type <tt>X</tt> meeting any of the iterator requirements (25.3 [iterator.requirements]) meets the <i>Cpp17ValueSwappable</i> 
requirements if, for any dereferenceable object <tt>x</tt> of type <tt>X</tt>, <tt>*x</tt> is swappable.
<p/>
-6- [<i>Example 1</i>: User code can ensure that the evaluation of <tt>swap</tt> calls is performed in an appropriate context under the
various conditions as follows:
</p>
<blockquote><pre>
#include &lt;cassert&gt;
#include &lt;utility&gt;

<i>// Preconditions: std::forward&lt;T&gt;(t) is swappable with std::forward&lt;U&gt;(u).</i>
template&lt;class T, class U&gt;
void value_swap(T&amp;&amp; t, U&amp;&amp; u) {
  using std::swap;
  swap(std::forward&lt;T&gt;(t), std::forward&lt;U&gt;(u)); <i>// OK, uses "swappable with" conditions</i>
                                                <i>// for rvalues and lvalues</i>
}

<i>// Preconditions: <del>lvalues of</del> T <ins>meets the <i>Cpp17Swappable</i> requirements</ins><del>are swappable</del>.</i>
template&lt;class T&gt;
void lv_swap(T&amp; t1, T&amp; t2) {
  using std::swap;
  swap(t1, t2); <i>// OK, uses swappable conditions for lvalues of type T</i>
}

[&hellip;]
</pre></blockquote>
</blockquote>
</li>

<li><p>Modify 16.4.4.4 [nullablepointer.requirements] <i>Cpp17NullablePointer</i> requirements as indicated:</p>

<blockquote>
<p>
-1- A <i>Cpp17NullablePointer</i> type is a pointer-like type that supports null values. A type <tt>P</tt> meets the 
<i>Cpp17NullablePointer</i> requirements if:
</p>
<ol style="list-style-type: none">
<li><p>(1.1) &mdash; <tt>P</tt> meets the <i>Cpp17EqualityComparable</i>, <i>Cpp17DefaultConstructible</i>, 
<i>Cpp17CopyConstructible</i>, <i>Cpp17CopyAssignable</i><ins>, <i>Cpp17Swappable</i></ins>, and 
<i>Cpp17Destructible</i> requirements,</p></li>
<li><p><del>(1.2) &mdash; lvalues of type <tt>P</tt> are swappable (16.4.4.3 [swappable.requirements]),</del></p></li>
<li><p>(1.3) &mdash; [&hellip;]</p></li>
<li><p>(1.4) &mdash; [&hellip;]</p></li>
</ol>
</blockquote>
</li>

<li><p>Modify 16.4.4.6.1 [allocator.requirements.general] as indicated:</p>

<blockquote>
<pre>
typename X::propagate_on_container_swap
</pre>
<blockquote>
<p>
-86- <i>Result</i>: Identical to or derived from <tt>true_type</tt> or <tt>false_type</tt>.
<p/>
-87- <i>Returns</i>: <tt>true_type</tt> only if an allocator of type <tt>X</tt> should be swapped 
when the client container is swapped; if so, <del>lvalues of type</del> <tt>X</tt> shall <ins>meet the <i>Cpp17Swappable</i>
requirements</ins> <del>be swappable</del> (16.4.4.3 [swappable.requirements]) and the <tt>swap</tt> 
operation shall not throw exceptions.
</p>
</blockquote>
</blockquote>
</li>

<li><p>Modify 17.9.2.1 [support.srcloc.class.general] as indicated:</p>

<blockquote>
<p>
-1- The type <tt>source_location</tt> meets the <i>Cpp17DefaultConstructible</i>, <i>Cpp17CopyConstructible</i>, 
<i>Cpp17CopyAssignable</i><ins>, <i>Cpp17Swappable</i></ins>, and <i>Cpp17Destructible</i> requirements 
(16.4.4.2 [utility.arg.requirements]<ins>, 16.4.4.3 [swappable.requirements]</ins>). 
<del>Lvalues of type <tt>source_location</tt> are swappable (16.4.4.3 [swappable.requirements])</del>. 
All of the following conditions are <tt>true</tt>:
</p>
</blockquote>
</li>

<li><p>Keep 20.3.1.3.6 [unique.ptr.single.modifiers] unchanged:</p>

<blockquote class="note">
<p>
[<i>Drafting note:</i> <tt>deleter_type</tt> is allowed to be of reference type, therefore we don't use <i>Cpp17Swappable</i> here.]
</p>
</blockquote>

<blockquote>
<pre>
constexpr void swap(unique_ptr&amp; u) noexcept;
</pre>
<blockquote>
<p>
-6- <i>Preconditions</i>: <tt>get_deleter()</tt> is swappable (16.4.4.3 [swappable.requirements]) and does not throw an exception under <tt>swap</tt>.
<p/>
-7- <i>Effects</i>: Invokes <tt>swap</tt> on the stored pointers and on the stored deleters of <tt>*this</tt> and <tt>u</tt>.
</p>
</blockquote>
</blockquote>
</li>

<li><p>Keep 22.3.2 [pairs.pair] unchanged:</p>

<blockquote class="note">
<p>
[<i>Drafting note:</i> Both <tt>T1</tt> and <tt>T2</tt> are allowed to be of reference type, 
therefore we don't use <i>Cpp17Swappable</i> here.]
</p>
</blockquote>

<blockquote>
<pre>
constexpr void swap(pair&amp; p) noexcept(<i>see below</i>);
constexpr void swap(const pair&amp; p) const noexcept(<i>see below</i>);
</pre>
<blockquote>
<p>
-51- <i>Mandates</i>:
</p>
<ol style="list-style-type: none">
<li><p>(51.1) &mdash; For the first overload, <tt>is_swappable_v&lt;T1&gt;</tt> is <tt>true</tt> and 
<tt>is_swappable_v&lt;T2&gt;</tt> is <tt>true</tt>.</p></li>
<li><p>(51.2) &mdash; For the second overload, <tt>is_swappable_v&lt;const T1&gt;</tt> is <tt>true</tt> 
and <tt>is_swappable_v&lt;const T2&gt;</tt> is <tt>true</tt>.</p></li>
</ol>
<p>
-52- <i>Preconditions</i>: <tt>first</tt> is swappable with (16.4.4.3 [swappable.requirements]) <tt>p.first</tt> and 
<tt>second</tt> is swappable with <tt>p.second</tt>.
</p>
<p>
-53- <i>Effects</i>: Swaps <tt>first</tt> with <tt>p.first</tt> and <tt>second</tt> with <tt>p.second</tt>.
<p/>
-54- <i>Remarks</i>: [&hellip;]
</p>
</blockquote>
</blockquote>
</li>

<li><p>Modify 22.4.4.3 [tuple.swap] as indicated:</p>

<blockquote class="note">
<p>
[<i>Drafting note:</i> Any of the types in <tt>Types</tt> are allowed to be of reference type, 
therefore we don't use <i>Cpp17Swappable</i> here. But feedback from the review group 
improves the existing specification to clarify that we always apply <tt>swap</tt> on lvalues due to
the direct usage of <tt>*this</tt> and <tt>rhs</tt> as arguments of <tt>get</tt>. Another side-effect
of the new wording is the ensured ordering of element-wise swap which corresponds to the ensured
ordering of assignments in all assignment operations. This clarification shouldn't have impact
on existing implementations, which all seem to use the element-wise order already.]
</p>
</blockquote>

<blockquote>
<pre>
constexpr void swap(tuple&amp; rhs) noexcept(<i>see below</i>);
constexpr void swap(const tuple&amp; rhs) const noexcept(<i>see below</i>);
</pre>
<blockquote>
<p>
<ins>-?- Let <tt><i>i</i></tt> be in the range <tt>[0, sizeof...(Types))</tt> in order.</ins>
<p/>
-1- <i>Mandates</i>:
</p>
<ol style="list-style-type: none">
<li><p>(1.1) &mdash; For the first overload, <tt>(is_swappable_v&lt;Types&gt; &amp;&amp; ...)</tt> is <tt>true</tt>.</p></li>
<li><p>(1.2) &mdash; For the second overload, <tt>(is_swappable_v&lt;const Types&gt; &amp;&amp; ...)</tt> is <tt>true</tt>.</p></li>
</ol>
<p>
-2- <i>Preconditions</i>: <ins>For all <tt><i>i</i></tt>, <tt>get&lt;<i>i</i>&gt;(*this)</tt></ins><del>Each 
element in <tt>*this</tt></del> is swappable with (16.4.4.3 [swappable.requirements]) 
<ins><tt>get&lt;<i>i</i>&gt;(rhs)</tt></ins><del>the corresponding element in <tt>rhs</tt></del>.
</p>
<p>
-3- <i>Effects</i>: <del>Calls <tt>swap</tt> f</del><ins>F</ins>or each <ins><tt><i>i</i></tt>, calls <tt>swap</tt> for 
<tt>get&lt;<i>i</i>&gt;(*this)</tt></ins><del>element 
in <tt>*this</tt> and</del><ins>with <tt>get&lt;<i>i</i>&gt;(rhs)</tt></ins><del>its corresponding element in <tt>rhs</tt></del>.
<p/>
-4- <i>Throws</i>: Nothing unless one of the element-wise <tt>swap</tt> calls throws an exception.
<p/>
-5- <i>Remarks</i>: The exception specification is equivalent to [&hellip;]
</p>
</blockquote>
</blockquote>
</li>

<li><p>Modify 22.5.3.5 [optional.swap] as indicated:</p>

<blockquote>
<pre>
constexpr void swap(optional&amp; rhs) noexcept(<i>see below</i>);
</pre>
<blockquote>
<p>
-1- <i>Mandates</i>: <tt>is_move_constructible_v&lt;T&gt;</tt> is <tt>true</tt>.
<p/>
-2- <i>Preconditions</i>: <ins><tt>T</tt> meets the <i>Cpp17Swappable</i> requirements</ins><del>Lvalues of type <tt>T</tt> are swappable</del>.
</p>
</blockquote>
</blockquote>
</li>

<li><p>Modify 22.6.3.7 [variant.swap] as indicated:</p>

<blockquote>
<pre>
constexpr void swap(variant&amp; rhs) noexcept(<i>see below</i>);
</pre>
<blockquote>
<p>
-1- <i>Mandates</i>: <tt>is_move_constructible_v&lt;T<sub><i>i</i></sub>&gt;</tt> is <tt>true</tt> for all <tt><i>i</i></tt>.
<p/>
-2- <i>Preconditions</i>: <ins>Each <tt>T<sub><i>i</i></sub></tt> meets the <i>Cpp17Swappable</i> 
requirements</ins><del>Lvalues of type <tt>T<sub><i>i</i></sub></tt> are swappable</del> (16.4.4.3 [swappable.requirements]).
</p>
</blockquote>
</blockquote>
</li>

<li><p>Modify 22.10.19 [unord.hash] as indicated:</p>

<blockquote>
<p>
-5- An enabled specialization <tt>hash&lt;Key&gt;</tt> will:
</p>
<ol style="list-style-type: none">
<li><p>(5.1) &mdash; meet the <i>Cpp17Hash</i> requirements (Table 38 [tab:cpp17.hash]), with <tt>Key</tt> as the 
function call argument type, the <i>Cpp17DefaultConstructible</i> requirements (Table 31 [tab:cpp17.defaultconstructible]), 
the <i>Cpp17CopyAssignable</i> requirements (Table 35 [tab:cpp17.copyassignable])<ins>, the <i>Cpp17Swappable</i> 
requirements (16.4.4.3 [swappable.requirements])</ins>,</p></li>
<li><p><del>(5.2) &mdash; be swappable (16.4.4.3 [swappable.requirements]) for lvalues,</del></p></li>
<li><p>(5.3) &mdash; [&hellip;]</p></li>
<li><p>(5.4) &mdash; [&hellip;]</p></li>
</ol>

</blockquote>
</li>

<li><p>Modify 22.14.6.1 [formatter.requirements] as indicated:</p>

<blockquote>
<p>
-1- A type <tt>F</tt> meets the <i>BasicFormatter</i> requirements if:
</p>
<ol style="list-style-type: none">
<li><p>(1.1) &mdash; it meets the</p>
<ol style="list-style-type: none">
<li><p>(1.1.1) &mdash; <i>Cpp17DefaultConstructible</i> (Table 31),</p></li>
<li><p>(1.1.2) &mdash; <i>Cpp17CopyConstructible</i> (Table 33),</p></li>
<li><p>(1.1.3) &mdash; <i>Cpp17CopyAssignable</i> (Table 35), <del>and</del></p></li>
<li><p><ins>(1.1.?) &mdash; <i>Cpp17Swappable</i> (16.4.4.3 [swappable.requirements]), and</ins></p></li>
<li><p>(1.1.4) &mdash; <i>Cpp17Destructible</i> (Table 36)</p></li>
</ol>
<p>
requirements, <ins>and</ins>
</p>
</li>
<li><p><del>(1.2) &mdash; it is swappable (16.4.4.3 [swappable.requirements]) for lvalues, and</del></p></li>
<li><p>(1.3) &mdash; the expressions shown in Table 74 are valid and have the indicated semantics.</p></li>
</ol>

</blockquote>
</li>

<li><p>Modify 24.2.2.2 [container.reqmts] as indicated:</p>

<blockquote class="note">
<p>
[<i>Drafting note:</i> The suggested changes for p37 and p41 provide an alternative resolution for 
<a href="https://github.com/cplusplus/draft/issues/5627">editorial issue 5627</a>]
</p>
</blockquote>

<blockquote>
<pre>
a.insert(p, i, j)
</pre>
<blockquote>
<p>
-36- <i>Result</i>: <tt>iterator</tt>.
<p/>
-37- <i>Preconditions</i>: <tt>T</tt> is <i>Cpp17EmplaceConstructible</i> into <tt>X</tt> from <tt>*i</tt>. 
For <tt>vector</tt> and <tt>deque</tt>, <tt>T</tt> is also <i>Cpp17MoveInsertable</i> into <tt>X</tt>, <ins>and
<tt>T</tt> meets the</ins> <i>Cpp17MoveConstructible</i>, <i>Cpp17MoveAssignable</i>, and 
<ins><i>Cpp17Swappable</i></ins><del>swappable</del> (16.4.4.3 [swappable.requirements]) <ins>requirements</ins>.
Neither <tt>i</tt> nor <tt>j</tt> are iterators into <tt>a</tt>.
<p/>
-38- [&hellip;]
<p/>
-39- [&hellip;]
</p>
</blockquote>
<pre>
a.insert_range(p, rg)
</pre>
<blockquote>
<p>
-40- <i>Result</i>: <tt>iterator</tt>.
<p/>
-41- <i>Preconditions</i>: <tt>T</tt> is <i>Cpp17EmplaceConstructible</i> into <tt>X</tt> from <tt>*ranges::begin(rg)</tt>. 
For <tt>vector</tt> and <tt>deque</tt>, <tt>T</tt> is also <i>Cpp17MoveInsertable</i> into <tt>X</tt>, <ins>and
<tt>T</tt> meets the</ins> <i>Cpp17MoveConstructible</i>, <i>Cpp17MoveAssignable</i>, and 
<ins><i>Cpp17Swappable</i></ins><del>swappable</del> (16.4.4.3 [swappable.requirements]) <ins>requirements</ins>.
<tt>rg</tt> and <tt>a</tt> do not overlap..
<p/>
-42- [&hellip;]
<p/>
-43- [&hellip;]
</p>
</blockquote>
<p>
[&hellip;]
<p/>
-65- The expression <tt>a.swap(b)</tt>, for containers <tt>a</tt> and <tt>b</tt> of a standard container 
type other than <tt>array</tt>, shall exchange the values of <tt>a</tt> and <tt>b</tt> without invoking 
any move, copy, or swap operations on the individual container elements. <del>Lvalues of a</del><ins>A</ins>ny 
<tt>Compare</tt>, <tt>Pred</tt>, or <tt>Hash</tt> types belonging to <tt>a</tt> and <tt>b</tt> shall 
<ins>meet the <i>Cpp17Swappable</i> requirements</ins> <del>be swappable</del> and shall be exchanged by 
calling <tt>swap</tt> as described in 16.4.4.3 [swappable.requirements]. If 
<tt>allocator_traits&lt;allocator_type&gt;::propagate_on_container_swap::value</tt> is <tt>true</tt>, then 
<del>lvalues of type</del> <tt>allocator_type</tt> shall <ins>meet the <i>Cpp17Swappable</i> requirements</ins><del>be 
swappable</del> and the allocators of <tt>a</tt> and <tt>b</tt> shall also be exchanged by calling <tt>swap</tt> 
as described in 16.4.4.3 [swappable.requirements].
</p>
</blockquote>
</li>

<li><p>Modify 25.3.5.2 [iterator.iterators] as indicated:</p>

<blockquote>
<p>
-2- A type <tt>X</tt> meets the <i>Cpp17Iterator</i> requirements if:
</p>
<ol style="list-style-type: none">
<li><p>(2.1) &mdash; <tt>X</tt> meets the <i>Cpp17CopyConstructible</i>, <i>Cpp17CopyAssignable</i><ins>,
<i>Cpp17Swappable</i></ins>, and <i>Cpp17Destructible</i> requirements (16.4.4.2 [utility.arg.requirements]<ins>, 
16.4.4.3 [swappable.requirements]</ins>) <del>and lvalues of type <tt>X</tt> 
are swappable (16.4.4.3 [swappable.requirements])</del>, and</p></li>
<li><p>(2.2) &mdash; [&hellip;]</p></li>
<li><p>(2.3) &mdash; [&hellip;]</p></li>
</ol>

</blockquote>
</li>


<li><p>Modify 29.3 [time.clock.req] as indicated:</p>

<blockquote>
<p>
-4- A type <tt>TC</tt> meets the <i>Cpp17TrivialClock</i> requirements if:
</p>
<ol style="list-style-type: none">
<li><p>(4.1) &mdash; <tt>TC</tt> meets the <i>Cpp17Clock</i> requirements,</p></li>
<li><p>(4.2) &mdash; the types <tt>TC::rep</tt>, <tt>TC::duration</tt>, and <tt>TC::time_point</tt> meet the 
<i>Cpp17EqualityComparable</i> (Table 29) and <i>Cpp17LessThanComparable</i> (Table 30) <ins>and 
<i>Cpp17Swappable</i> (16.4.4.3 [swappable.requirements])</ins> requirements and the 
requirements of numeric types (28.2 [numeric.requirements]).
[<i>Note 3</i>: This means, in particular, that operations on these types will not throw exceptions. &mdash; <i>end note</i>]</p></li>
<li><p><del>(4.3) &mdash; lvalues of the types <tt>TC::rep</tt>, <tt>TC::duration</tt>, and <tt>TC::time_point</tt> 
are swappable (16.4.4.3 [swappable.requirements]),</del></p></li>
<li><p>(4.4) &mdash; the function <tt>TC::now()</tt> does not throw exceptions, and</p></li>
<li><p>(4.5) &mdash; the type <tt>TC::time_point::clock</tt> meets the <i>Cpp17TrivialClock</i> requirements, recursively.</p></li>
</ol>

</blockquote>
</li>

</ol>

<h2><a name="Akn"></a>Acknowledgements</h2>
<p>
Thanks to the <a href="https://wiki.edg.com/bin/view/Wg21telecons2022/D2696-20221102">LWG group that reviewed</a> this proposal 
and provided helpful improvement suggestions.
</p>

<h2><a name="Bibliography"></a>Bibliography</h2>

<div id="refs">
<div id="ref-N4910">
<p>
[N4917] Thomas K&ouml;ppe: "Working Draft, Standard for Programming Language C++", 2022<br/>
<a href="https://wg21.link/n4917">https://wg21.link/n4917</a>
</p>
</div>

<div id="ref-N3048">
<p>
[N3048] Daniel Krgler, Mike Spertus, Stefanus Du Toit, Walter E. Brown: "Defining Swappable Requirements", 2010<br/>
<a href="https://wg21.link/n3048">https://wg21.link/n3048</a>
</p>
</div>

<div id="ref-LWG-2146">
<p>
[LWG2146] Nikolay Ivchenkov: "Are reference types <tt>Copy</tt>&#47;<tt>Move-Constructible</tt>&#47;<tt>Assignable</tt> or <tt>Destructible</tt>?", 
2012<br/>
<a href="https://wg21.link/lwg2146">https://wg21.link/lwg2146</a>
</p>
</div>
</div>

</body></html>