<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 594: Disadvantages of defining Swappable in terms of CopyConstructible and Assignable</title>
<meta property="og:title" content="Issue 594: Disadvantages of defining Swappable in terms of CopyConstructible and Assignable">
<meta property="og:description" content="C++ library issue. Status: Resolved">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue594.html">
<meta property="og:type" content="website">
<meta property="og:image" content="http://cplusplus.github.io/LWG/images/cpp_logo.png">
<meta property="og:image:alt" content="C++ logo">
<style>
  p {text-align:justify}
  li {text-align:justify}
  pre code.backtick::before { content: "`" }
  pre code.backtick::after { content: "`" }
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table.issues-index { border: 1px solid; border-collapse: collapse; }
  table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
  table.issues-index td { padding: 4px; border: 1px solid; }
  table.issues-index td:nth-child(1) { text-align: right; }
  table.issues-index td:nth-child(2) { text-align: left; }
  table.issues-index td:nth-child(3) { text-align: left; }
  table.issues-index td:nth-child(4) { text-align: left; }
  table.issues-index td:nth-child(5) { text-align: center; }
  table.issues-index td:nth-child(6) { text-align: center; }
  table.issues-index td:nth-child(7) { text-align: left; }
  table.issues-index td:nth-child(5) span.no-pr { color: red; }
  @media (prefers-color-scheme: dark) {
     html {
        color: #ddd;
        background-color: black;
     }
     ins {
        background-color: #225522
     }
     del {
        background-color: #662222
     }
     a {
        color: #6af
     }
     a:visited {
        color: #6af
     }
     blockquote.note
     {
        background-color: rgba(255, 255, 255, .10)
     }
  }
</style>
</head>
<body>
<hr>
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#Resolved">Resolved</a> status.</em></p>
<h3 id="594"><a href="lwg-defects.html#594">594</a>. Disadvantages of defining <code>Swappable</code> in terms of <code>CopyConstructible</code> and <code>Assignable</code></h3>
<p><b>Section:</b> 16.4.4.2 <a href="https://wg21.link/utility.arg.requirements">[utility.arg.requirements]</a> <b>Status:</b> <a href="lwg-active.html#Resolved">Resolved</a>
 <b>Submitter:</b> Niels Dekker <b>Opened:</b> 2006-11-02 <b>Last modified:</b> 2016-01-28</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View other</b> <a href="lwg-index-open.html#utility.arg.requirements">active issues</a> in [utility.arg.requirements].</p>
<p><b>View all other</b> <a href="lwg-index.html#utility.arg.requirements">issues</a> in [utility.arg.requirements].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#Resolved">Resolved</a> status.</p>
<p><b>Discussion:</b></p>

<p>
It seems undesirable to define the <code>Swappable</code> requirement in terms of
<code>CopyConstructible</code> and <code>Assignable</code> requirements. And likewise, once the
<code>MoveConstructible</code> and <code>MoveAssignable</code> requirements (N1860) have made it
into the Working Draft, it seems undesirable to define the <code>Swappable</code>
requirement in terms of those requirements. Instead, it appears
preferable to have the <code>Swappable</code> requirement defined exclusively in
terms of the existence of an appropriate swap function.
</p>

<p>
Section 20.1.4 [lib.swappable] of the current Working Draft (N2009)
says:
</p>

<blockquote><p>
The Swappable requirement is met by satisfying one or more of the
following conditions:</p>
<ul>
<li>
T is Swappable if T satisfies the CopyConstructible requirements
(20.1.3) and the Assignable requirements (23.1);
</li>
<li>
T is Swappable if a namespace scope function named swap exists in the
same namespace as the definition of T, such that the expression
swap(t,u) is valid and has the semantics described in Table 33.
</li>
</ul>
</blockquote>

<p>
I can think of three disadvantages of this definition:
</p>

<ol>
<li>
<p>
If a client's type T satisfies the first condition (T is both
CopyConstructible and Assignable), the client cannot stop T from
satisfying the Swappable requirement without stopping T from
satisfying the first condition.
</p>
<p>
A client might want to stop T from satisfying the Swappable
requirement, because swapping by means of copy construction and
assignment might throw an exception, and she might find a throwing
swap unacceptable for her type. On the other hand, she might not feel
the need to fully implement her own swap function for this type. In
this case she would want to be able to simply prevent algorithms that
would swap objects of type T from being used, e.g., by declaring a
swap function for T, and leaving this function purposely undefined.
This would trigger a link error, if an attempt would be made to use
such an algorithm for this type. For most standard library
implementations, this practice would indeed have the effect of
stopping T from satisfying the Swappable requirement.
</p>
</li>
<li>
<p>
A client's type T that does not satisfy the first condition can not be
made Swappable by providing a specialization of std::swap for T.
</p>
<p>
While I'm aware about the fact that people have mixed feelings about
providing a specialization of std::swap, it is well-defined to do so.
It sounds rather counter-intuitive to say that T is not Swappable, if
it has a valid and semantically correct specialization of std::swap.
Also in practice, providing such a specialization will have the same
effect as satisfying the Swappable requirement.
</p>
</li>
<li>
<p>
For a client's type T that satisfies both conditions of the Swappable
requirement, it is not specified which of the two conditions prevails.
After reading section 20.1.4 [lib.swappable], one might wonder whether
objects of T will be swapped by doing copy construction and
assignments, or by calling the swap function of T.
</p>
<p>
I'm aware that the intention of the Draft is to prefer calling the
swap function of T over doing copy construction and assignments. Still
in my opinion, it would be better to make this clear in the wording of
the definition of Swappable. 
</p>
</li>
</ol>

<p>
I would like to have the Swappable requirement defined in such a way
that the following code fragment will correctly swap two objects of a
type T, if and only if T is Swappable:
</p>

<pre>
   using std::swap;
   swap(t, u);  // t and u are of type T.
</pre>

<p>
This is also the way Scott Meyers recommends calling a swap function,
in Effective C++, Third Edition, item 25.
</p>

<p>
Most aspects of this issue have been dealt with in a discussion on
comp.std.c++ about the Swappable requirement, from 13 September to 4
October 2006, including valuable input by David Abrahams, Pete Becker,
Greg Herlihy, Howard Hinnant and others.
</p>

<p><i>[
San Francisco:
]</i></p>


<blockquote><p>
Recommend <del>NAD</del><ins>Resolved</ins>.  Solved by
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2774.pdf">N2774</a>.
</p></blockquote>

<p><i>[
2009-07 Frankfurt
]</i></p>


<blockquote><p>
Moved to Open.  Waiting for non-concepts draft.
</p></blockquote>

<p><i>[
2009-11-08 Howard adds:
]</i></p>


<blockquote><p>
This issue is very closely related to <a href="lwg-defects.html#742" title="Enabling swap for proxy iterators (Status: Resolved)">742</a><sup><a href="https://cplusplus.github.io/LWG/issue742" title="Latest snapshot">(i)</a></sup>.
</p></blockquote>

<p><i>[
2010-02-03 Sean Hunt adds:
]</i></p>


<blockquote>
<p>
While reading N3000, I independently came across Issue 594. Having seen that
it's an issue under discussion, I think the proposed wording needs fixing to
something more like "...function call swap(t,u) that includes std::swap in its
overload set is valid...", because "...is valid within the namespace std..."
does not allow other libraries to simply use the Swappable requirement by
referring to the standard's definition, since they cannot actually perform any
calls within std.
</p>

<p>
This wording I suggested would also make overloads visible in the same scope as
the <code class='backtick'>using std::swap</code> valid for Swappable requirements; a more complex wording
limiting the non-ADL overload set to std::swap might be required.
</p>
</blockquote>

<p><i>[
2010 Pittsburgh:
]</i></p>


<blockquote><p>
Moved to NAD Editorial.  Rationale added.
</p></blockquote>



<p><b>Rationale:</b></p>
<p>
Solved by N3048.
</p>


<p id="res-594"><b>Proposed resolution:</b></p>
<p>
Change section 20.1.4 [lib.swappable] as follows:
</p>
<blockquote><p>
The Swappable requirement is met by satisfying
<del>one or more of the following conditions:</del>
<ins>the following condition:</ins></p>
<ul>

<li>
<del>T is Swappable if T satisfies the CopyConstructible requirements
(20.1.3) and the Assignable requirements (23.1);</del>
</li>
<li>
<del>
T is Swappable if a namespace scope function named swap exists in the
same namespace as the definition of T, such that the expression
swap(t,u) is valid and has the semantics described in Table 33.
</del>
T is Swappable if an unqualified function call swap(t,u) is valid
within the namespace std, and has the semantics described in Table 33.
</li>
</ul>
</blockquote>





</body>
</html>
