﻿<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta content="text/html;charset=UTF-8" http-equiv="Content-Type"/>
    <meta charset="UTF-8"/>
    <title>exchange() utility function, revision 2</title>
<style type="text/css">
body {color: #000000; background-color: #FFFFFF;}

del {text-decoration: line-through; color: #8B0040;}
ins {text-decoration: underline; color: #005100;}

pre code {display: inline-block; white-space: inherit}
code {white-space: nowrap}
code wbr {white-space: normal}

/*
.wording { max-width: 90ex; }
.wording .sectnum { margin-right: 1em; }
.wording .sectname { display: block; float: right;  }

section.numbered { counter-reset: par-num; }
.wording p:before, .wording dt:before {
    content: counter(par-num) " "; counter-increment: par-num;
    font-size: 80%; position: absolute; left: 2em}
*/
.wording td { border-top: thin solid black; border-bottom: thin solid black; }

section.function { clear: both; }
.attributes, .attribute {margin-left: 2em}

.docinfo {float: right}
.docinfo p {margin: 0; text-align:right; font-style: italic}

section {padding-left: 1em}
section header {margin-left: -1em}

h2, h3, h4, h5, h6 { margin-bottom: .75em }
h5, h6 { font-size: 1em; }
p {margin-top: .5em; margin-bottom: .5em}
p:first-child, ul, ol {margin-top: 0}
.todo dt:not(:first-child) {margin-top: .5em}
p, li, dd, table {max-width: 80ex}

table { border: double; margin: 1em; border-collapse: collapse; }
caption { white-space: pre; }
td { text-align: left; }


.example {display: inline-block; clear: both; margin-left: 1ex;
          border: thin solid #0e0; background-color: #f8f8f8; padding: 1ex}

.ednote {display: inline-block; clear: both; margin-left: 1ex;
         border: thin solid #0e0; background-color: #f8f8f8; padding: 1ex}

div.ednote > *:first-child::before {content: "Note: "; display: inline; font-weight: bold}
div.ednote {display: inline-block; margin-left: 1ex; border: thin solid #fb6;
            padding: 1ex; background-color: #fff4dd}

:target {background-color: #fed}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">//<![CDATA[
$(function() {
    var next_id = 0
    function find_id(node) {
        // Look down the first children of 'node' until we find one
        // with an id. If we don't find one, give 'node' an id and
        // return that.
        var cur = node[0];
        while (cur) {
            if (cur.id) return cur.id;
            if (cur.tagName == 'A' && cur.name)
                return cur.name;
            cur = cur.firstChild;
        };
        // No id.
        node.attr('id', 'gensection-' + next_id++);
        return node.attr('id');
    };

    // Put a table of contents in the #toc nav.

    // This is a list of <ol> elements, where toc[N] is the list for
    // the current sequence of <h(N+2)> tags. When a header of an
    // existing level is encountered, all higher levels are popped,
    // and an <li> is appended to the level
    var toc = [$("<ol/>")];
    $(':header').not('h1').each(function() {
        var header = $(this);
        // For each <hN> tag, add a link to the toc at the appropriate
        // level.  When toc is one element too short, start a new list
        var levels = {H2: 0, H3: 1, H4: 2, H5: 3, H6: 4};
        var level = levels[this.tagName];
        if (typeof level == 'undefined') {
            throw 'Unexpected tag: ' + this.tagName;
        }
        // Truncate to the new level.
        toc.splice(level + 1, toc.length);
        if (toc.length < level) {
            // Omit TOC entries for skipped header levels.
            return;
        }
        if (toc.length == level) {
            // Add a <ol> to the previous level's last <li> and push
            // it into the array.
            var ol = $('<ol/>')
            toc[toc.length - 1].children().last().append(ol);
            toc.push(ol);
        }
        var header_text = header.text();
        toc[toc.length - 1].append(
            $('<li/>').append($('<a href="#' + find_id(header) + '"/>')
                              .text(header_text)));
    });
    $('#toc').append(toc[0]);
})
//]]></script>
</head>
<body>
  <header>
    <div class="docinfo">
      <p>ISO/IEC JTC1 SC22 WG21 N3608</p>
      <p>Date: <time pubdate="">2013-03-15</time></p>
      <address>
        <p>Jeffrey Yasskin &lt;<a href="mailto:jyasskin@google.com">jyasskin@google.com</a>&gt;</p>
      </address>
    </div>
    <h1><code>exchange()</code> utility function, revision 2</h1>
  </header>
  <p><small><a href="#maincontent">Skip table of contents</a></small></p>
  <nav id="toc"></nav>
  <a id="maincontent"></a>
  <section>
    <header><h2 id="overview">Overview</h2></header>
    <p><small>Revises <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3511.html">N3511</a>
    by adding a default template argument.</small></p>

    <p>Atomic objects provide an <code>atomic_exchange</code> function
    ([atomics.types.operations.req]p18) that assigns a new value to the object
    and returns the old value.  This operation is also useful on non-atomic
    objects, and this paper proposes adding it to the library.  The benefit
    isn't huge, but neither is the specification cost.</p>

<pre><code>template&lt;typename T, typename U=T>
T exchange(T& obj, U&& new_val) {
  T old_val = std::move(obj);
  obj = std::forward&lt;U>(new_val);
  return old_val;
}
</code></pre>

    <p>For primitive types, this is equivalent to the obvious implementation,
    while for more complex types, this definition</p>
    <ul>
      <li>Avoids copying the old value when that type defines a move constructor</li>
      <li>Accepts any type as the new value, taking advantage of any converting assignment operator</li>
      <li>Avoids copying the new value if it's a temporary or moved.</li>
    </ul>

    <p>I chose the name for symmetry with <code>atomic_exchange</code>, since
    they behave the same except for this function not being atomic.</p>

    <p>We could consider defaulting <code>new_val</code> to <code>T{}</code>,
    which makes null'ing out a pointer even simpler, but I think that makes the
    name less good, so I'm not proposing it.</p>

    <header><h2 id="examples">Examples</h2></header>
    <p>c++std-ext-13750 mentions a use case for post-increment on
    <code>bool</code>, which this function would replace.  This proposal comes
    from my message c++std-lib-33183 on that thread.</p>

<pre class="example"><code>auto operator &lt;&lt; (std::ostream& os, section_num const & sn) -> std::ostream & {
   if (!sn.prefix.empty()) { os &lt;&lt; sn.prefix &lt;&lt; " "; }

   bool use_period{false};
   for (auto sub : sn.num ) {
      if(<strong>use_period++</strong>) {  // &lt;-- deprecated check to omit some code on the first time through the loop
         os &lt;&lt; '.';
      }

      if (sub >= 100) {
         os &lt;&lt; char(sub - 100 + 'A');
      }
      else {
         os &lt;&lt; sub;
      }
   }
   return os;
}</code></pre>

<p>becomes:</p>
<pre class="example"><code>auto operator &lt;&lt; (std::ostream& os, section_num const & sn) -> std::ostream & {
   if (!sn.prefix.empty()) { os &lt;&lt; sn.prefix &lt;&lt; " "; }

   bool use_period{false};
   for (auto sub : sn.num ) {
      if(<strong>std::exchange(use_period, true)</strong>) {
         os &lt;&lt; '.';
      }

      if (sub >= 100) {
         os &lt;&lt; char(sub - 100 + 'A');
      }
      else {
         os &lt;&lt; sub;
      }
   }
   return os;
}</code></pre>

    <p>Implementations of <code>std::unique_ptr</code> can also benefit:</p>

<pre class="example"><code>template&lt;typename T, typename D>
void unique_ptr&lt;T, D>::reset(pointer p = pointer()) {
  pointer old = ptr_;
  ptr_ = p;
  if (old)
    deleter_(old);
}</code></pre>

    <p>becomes:</p>

<pre class="example"><code>template&lt;typename T, typename D>
void unique_ptr&lt;T, D>::reset(pointer p = pointer()) {
  if (pointer old = <strong>std::exchange(ptr_, p)</strong>)
    deleter_(old);
}</code></pre>

    <p>Giving the second template argument a default value fixes the following two cases:</p>

    <ul>
      <li>
        <pre class="example"><code>DefaultConstructible x = ...;
if (exchange(x, {})) { ... }</code></pre>
      </li>
      <li>
        <pre class="example"><code>int (*fp)(int);
int f(int);
double f(double);
/*...*/ exchange(fp, &amp;f) /*...*/</code></pre>
      </li>
    </ul>
  </section>

  <hr/>

  <section class="wording">
    <header><h2 id="wording">Wording</h2></header>

    <p>Wording is relative to <a
    href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3485.pdf">N3485</a>.</p>


    <h3>In the "Header &lt;utility> synopsis" in [utility], add:</h3>

    <pre><code>// [utility.exchange] exchange:
template &lt;class T, class U=T> T exchange(T& obj, U&& new_val);</code></pre>

    <h3>Add a sub-section under [utility] named "exchange [utility.exchange]"</h3>

    <pre><code>template &lt;class T, class U=T> T exchange(T& obj, U&& new_val);</code></pre>
    <div class="attributes">
      <p><i>Effects:</i> Equivalent to:</p>
<pre><code>T old_val = move(obj);
obj = forward&lt;U>(new_val);
return old_val;</code></pre>
    </div>
  </section>
</body>
</html>
