<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 2153: Narrowing of the non-member swap contract</title>
<meta property="og:title" content="Issue 2153: Narrowing of the non-member swap contract">
<meta property="og:description" content="C++ library issue. Status: LEWG">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue2153.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#LEWG">LEWG</a> status.</em></p>
<h3 id="2153"><a href="lwg-active.html#2153">2153</a>. Narrowing of the non-member <code>swap</code> contract</h3>
<p><b>Section:</b> 22.2.2 <a href="https://wg21.link/utility.swap">[utility.swap]</a>, 16.4.4.3 <a href="https://wg21.link/swappable.requirements">[swappable.requirements]</a>, 23.2.2 <a href="https://wg21.link/container.requirements.general">[container.requirements.general]</a> <b>Status:</b> <a href="lwg-active.html#LEWG">LEWG</a>
 <b>Submitter:</b> Robert Shearer <b>Opened:</b> 2012-04-13 <b>Last modified:</b> 2020-10-02</p>
<p><b>Priority: </b>2
</p>
<p><b>View all other</b> <a href="lwg-index.html#utility.swap">issues</a> in [utility.swap].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#LEWG">LEWG</a> status.</p>
<p><b>Discussion:</b></p>
<p>
Sub-clause 22.2.2 <a href="https://wg21.link/utility.swap">[utility.swap]</a> defines a non-member 'swap' function with defined behavior for
all <code>MoveConstructible</code> and <code>MoveAssignable</code> types. It does not guarantee
constant-time complexity or <code>noexcept</code> in general, however this definition does
render all objects of <code>MoveConstructible</code> and <code>MoveAssignable</code> type swappable
(by the unary definition of sub-clause 16.4.4.3 <a href="https://wg21.link/swappable.requirements">[swappable.requirements]</a>) in the absence of 
specializations or overloads.
<p/>
The overload of the non-member <code>swap</code> function defined in Table 96, however,
defines semantics incompatible with the generic non-member <code>swap</code> function,
since it is defined to call a member <code>swap</code> function whose semantics are
undefined for some values of <code>MoveConstructible</code> and <code>MoveAssignable</code> types.
<p/>
The obvious (perhaps naive) interpretation of sub-clause 16.4.4.3 <a href="https://wg21.link/swappable.requirements">[swappable.requirements]</a> is as a guide to
the "right" semantics to provide for a non-member <code>swap</code> function (called in
the context defined by 16.4.4.3 <a href="https://wg21.link/swappable.requirements">[swappable.requirements]</a> p3) in order to provide interoperable
user-defined types for generic programming. The standard container types don't follow these guidelines.
<p/>
More generally, the design in the standard represents a classic example of "contract narrowing". It 
is entirely reasonable for the contract of a particular <code>swap</code> overload to provide <em>more</em> 
guarantees, such as constant-time execution and <code>noexcept</code>, than are provided by the <code>swap</code> 
that is provided for any <code>MoveConstructible</code> and <code>MoveAssignable</code> types, but it is <em>not</em> 
reasonable for such an overload to fail to live up to the guarantees it provides for general types when 
it is applied to more specific types. Such an overload or specialization in generic programming is akin 
to an override of an inherited virtual function in OO programming: violating a superclass contract in a
subclass may be legal from the point of view of the language, but it is poor design and can easily lead 
to errors. While we cannot prevent user code from providing overloads that violate the more general 
<code>swap</code> contract, we can avoid doing so within the library itself.
<p/>
My proposed resolution is to draw a sharp distinction between member <code>swap</code> functions, which provide 
optimal performance but idiosyncratic contracts, and non-member <code>swap</code> functions, which should always 
fulfill at least the contract of 22.2.2 <a href="https://wg21.link/utility.swap">[utility.swap]</a> and thus render objects swappable. The member 
<code>swap</code> for containers with non-propagating allocators, for example, would offer constant-time
guarantees and <code>noexcept</code> but would only offer defined behavior for values with allocators that compare 
equal; non-member <code>swap</code> would test allocator equality and then dispatch to either member <code>swap</code> or 
<code>std::swap</code> depending on the result, providing defined behavior for all values (and rendering the type
"swappable"), but offering neither the constant-time nor the <code>noexcept</code> guarantees.
</p>

<p><i>[2013-03-15 Issues Teleconference]</i></p>

<p>
Moved to Open.
</p>
<p>
This topic deserves more attention than can be given in the telecon, and there is no proposed resolution.
</p>

<p><i>[2016-03 Jacksonville]</i></p>

<p>
Alisdair says that his paper <a href="https://wg21.link/P0178">P0178</a> addresses this.
</p>

<p><i>[2016-08 Chicago]</i></p>

<p>Send to LEWG</p>

<p><i>[2016-06 Oulu]</i></p>

<p><a href="https://wg21.link/P0178">P0178</a> reviewed, and sent back to LEWG for confirmation.</p>
<p>Thursday Morning: A joint LWG/LEWG meeting declined to adopt <a href="https://wg21.link/P0178">P0178</a>.</p>


<p><i>[2020-10-02; remove P0178 as Proposed Resolution]</i></p>


<p id="res-2153"><b>Proposed resolution:</b></p>





</body>
</html>
