<!DOCTYPE html>
    <html>
    <head>
        <meta http-equiv="Content-type" content="text/html;charset=UTF-8">
        <title>Make stateful allocator propagation more consistent for `operator+(basic_string)`</title>
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.10.0-rc.1/dist/katex.min.css" integrity="sha384-D+9gmBxUQogRLqvARvNLmA9hS2x//eK1FhVb9PiU86gmcrBrJAQT8okdJ4LMp2uv" crossorigin="anonymous">
        <style>
/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ body { font-family: "Segoe WPC", "Segoe UI", "SFUIText-Light", "HelveticaNeue-Light", sans-serif, "Droid Sans Fallback"; font-size: 14px; padding: 0 26px; line-height: 22px; word-wrap: break-word; } #code-csp-warning { position: fixed; top: 0; right: 0; color: white; margin: 16px; text-align: center; font-size: 12px; font-family: sans-serif; background-color:#444444; cursor: pointer; padding: 6px; box-shadow: 1px 1px 1px rgba(0,0,0,.25); } #code-csp-warning:hover { text-decoration: none; background-color:#007acc; box-shadow: 2px 2px 2px rgba(0,0,0,.25); } body.scrollBeyondLastLine { margin-bottom: calc(100vh - 22px); } body.showEditorSelection .code-line { position: relative; } body.showEditorSelection .code-active-line:before, body.showEditorSelection .code-line:hover:before { content: ""; display: block; position: absolute; top: 0; left: -12px; height: 100%; } body.showEditorSelection li.code-active-line:before, body.showEditorSelection li.code-line:hover:before { left: -30px; } .vscode-light.showEditorSelection .code-active-line:before { border-left: 3px solid rgba(0, 0, 0, 0.15); } .vscode-light.showEditorSelection .code-line:hover:before { border-left: 3px solid rgba(0, 0, 0, 0.40); } .vscode-light.showEditorSelection .code-line .code-line:hover:before { border-left: none; } .vscode-dark.showEditorSelection .code-active-line:before { border-left: 3px solid rgba(255, 255, 255, 0.4); } .vscode-dark.showEditorSelection .code-line:hover:before { border-left: 3px solid rgba(255, 255, 255, 0.60); } .vscode-dark.showEditorSelection .code-line .code-line:hover:before { border-left: none; } .vscode-high-contrast.showEditorSelection .code-active-line:before { border-left: 3px solid rgba(255, 160, 0, 0.7); } .vscode-high-contrast.showEditorSelection .code-line:hover:before { border-left: 3px solid rgba(255, 160, 0, 1); } .vscode-high-contrast.showEditorSelection .code-line .code-line:hover:before { border-left: none; } img { max-width: 100%; max-height: 100%; } a { text-decoration: none; } a:hover { text-decoration: underline; } a:focus, input:focus, select:focus, textarea:focus { outline: 1px solid -webkit-focus-ring-color; outline-offset: -1px; } hr { border: 0; height: 2px; border-bottom: 2px solid; } h1 { padding-bottom: 0.3em; line-height: 1.2; border-bottom-width: 1px; border-bottom-style: solid; } h1, h2, h3 { font-weight: normal; } h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { font-size: inherit; line-height: auto; } table { border-collapse: collapse; } table > thead > tr > th { text-align: left; border-bottom: 1px solid; } table > thead > tr > th, table > thead > tr > td, table > tbody > tr > th, table > tbody > tr > td { padding: 5px 10px; } table > tbody > tr + tr > td { border-top: 1px solid; } blockquote { margin: 0 7px 0 5px; padding: 0 16px 0 10px; border-left-width: 5px; border-left-style: solid; } code { font-family: Menlo, Monaco, Consolas, "Droid Sans Mono", "Courier New", monospace, "Droid Sans Fallback"; font-size: 14px; line-height: 19px; } body.wordWrap pre { white-space: pre-wrap; } .mac code { font-size: 12px; line-height: 18px; } pre:not(.hljs), pre.hljs code > div { padding: 16px; border-radius: 3px; overflow: auto; } /** Theming */ pre code { color: var(--vscode-editor-foreground); } .vscode-light pre:not(.hljs), .vscode-light code > div { background-color: rgba(220, 220, 220, 0.4); } .vscode-dark pre:not(.hljs), .vscode-dark code > div { background-color: rgba(10, 10, 10, 0.4); } .vscode-high-contrast pre:not(.hljs), .vscode-high-contrast code > div { background-color: rgb(0, 0, 0); } .vscode-high-contrast h1 { border-color: rgb(0, 0, 0); } .vscode-light table > thead > tr > th { border-color: rgba(0, 0, 0, 0.69); } .vscode-dark table > thead > tr > th { border-color: rgba(255, 255, 255, 0.69); } .vscode-light h1, .vscode-light hr, .vscode-light table > tbody > tr + tr > td { border-color: rgba(0, 0, 0, 0.18); } .vscode-dark h1, .vscode-dark hr, .vscode-dark table > tbody > tr + tr > td { border-color: rgba(255, 255, 255, 0.18); } 
</style>
<style>
/* Tomorrow Theme */ /* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ /* Original theme - https://github.com/chriskempson/tomorrow-theme */ /* Tomorrow Comment */ .hljs-comment, .hljs-quote { color: #8e908c; } /* Tomorrow Red */ .hljs-variable, .hljs-template-variable, .hljs-tag, .hljs-name, .hljs-selector-id, .hljs-selector-class, .hljs-regexp, .hljs-deletion { color: #c82829; } /* Tomorrow Orange */ .hljs-number, .hljs-built_in, .hljs-builtin-name, .hljs-literal, .hljs-type, .hljs-params, .hljs-meta, .hljs-link { color: #f5871f; } /* Tomorrow Yellow */ .hljs-attribute { color: #eab700; } /* Tomorrow Green */ .hljs-string, .hljs-symbol, .hljs-bullet, .hljs-addition { color: #718c00; } /* Tomorrow Blue */ .hljs-title, .hljs-section { color: #4271ae; } /* Tomorrow Purple */ .hljs-keyword, .hljs-selector-tag { color: #8959a8; } .hljs { display: block; overflow-x: auto; color: #4d4d4c; padding: 0.5em; } .hljs-emphasis { font-style: italic; } .hljs-strong { font-weight: bold; }
</style>
<style>
.task-list-item { list-style-type: none; } .task-list-item-checkbox { margin-left: -20px; vertical-align: middle; }
</style>
        <style>
            body {
                font-family: -apple-system, BlinkMacSystemFont, 'Segoe WPC', 'Segoe UI', 'HelveticaNeue-Light', 'Ubuntu', 'Droid Sans', sans-serif;
                font-size: 14px;
                line-height: 1.6;
            }
        </style>
    </head>
    <body>
        <h1 id="make-stateful-allocator-propagation-more-consistent-for-operatorbasicstring">Make stateful allocator propagation more consistent for <code>operator+(basic_string)</code></h1>
<table>
<thead>
<tr>
<th><a href=""></a></th>
<th><a href=""></a></th>
</tr>
</thead>
<tbody>
<tr>
<td>Paper number</td>
<td>P1165R1</td>
</tr>
<tr>
<td>Reply-to</td>
<td>Tim Song &lt;<a href="mailto:rs2740@gmail.com">rs2740@gmail.com</a>&gt;</td>
</tr>
<tr>
<td>Audience</td>
<td>LWG</td>
</tr>
</tbody>
</table>
<h2 id="abstract">Abstract</h2>
<p>Allocator propagation for <code>basic_string</code>'s <code>operator+</code> is haphazard, inconsistent, and a source of implementation divergence. Let's make them consistent.</p>
<h2 id="revision-history">Revision history</h2>
<ul>
<li>R1: Implements LEWG's <a href="http://wiki.edg.com/bin/view/Wg21sandiego2018/P1165">desired outcome</a> (leave rvalue overloads unchanged, lvalue overloads use SOCCC on lhs if possible and rhs otherwise). Note reservation in appendix.</li>
<li>R0: Initial revision. Consistently default-constructs the allocator for the result.</li>
</ul>
<h2 id="introduction">Introduction</h2>
<p>Let <code>lhs</code> and <code>rhs</code> be two <code>basic_string</code> lvalues with a <code>char</code> <code>value_type</code>. The following table shows the allocator used for the result for each of the 12 <code>operator+</code> overloads, in the working paper and three major implementations, as well as LEWG's preferred direction:</p>
<table>
<thead>
<tr>
<th>Expression</th>
<th>WP</th>
<th>libstdc++ (trunk)</th>
<th>libc++ (trunk)</th>
<th>MSVC STL (19.00.23506)</th>
<th>LEWG direction</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>lhs + rhs</code></td>
<td><s>SOCCC on</s> SOCCC on <code>lhs</code></td>
<td>SOCCC on <code>lhs</code></td>
<td><code>lhs</code> (no SOCCC)</td>
<td>default-constructed</td>
<td>SOCCC on <code>lhs</code></td>
</tr>
<tr>
<td><code>lhs + std::move(rhs)</code></td>
<td><code>rhs</code></td>
<td><code>rhs</code></td>
<td><code>rhs</code></td>
<td><code>rhs</code></td>
<td><code>rhs</code></td>
</tr>
<tr>
<td><code>std::move(lhs) + rhs</code></td>
<td><code>lhs</code></td>
<td><code>lhs</code></td>
<td><code>lhs</code></td>
<td><code>lhs</code></td>
<td><code>lhs</code></td>
</tr>
<tr>
<td><code>std::move(lhs) + std::move(rhs)</code></td>
<td><code>lhs</code> <s>&quot;or equivalently&quot; <code>rhs</code></s></td>
<td><code>lhs</code></td>
<td><code>lhs</code></td>
<td><code>lhs</code></td>
<td><code>lhs</code></td>
</tr>
<tr>
<td><code>lhs + &quot;str&quot;</code></td>
<td>default-constructed</td>
<td>SOCCC on <code>lhs</code></td>
<td><code>lhs</code></td>
<td>default-constructed</td>
<td>SOCCC on <code>lhs</code></td>
</tr>
<tr>
<td><code>lhs + 'c'</code></td>
<td>default-constructed</td>
<td>SOCCC on <code>lhs</code></td>
<td><code>lhs</code></td>
<td>default-constructed</td>
<td>SOCCC on <code>lhs</code></td>
</tr>
<tr>
<td><code>std::move(lhs) + &quot;str&quot;</code></td>
<td><code>lhs</code></td>
<td><code>lhs</code></td>
<td><code>lhs</code></td>
<td><code>lhs</code></td>
<td><code>lhs</code></td>
</tr>
<tr>
<td><code>std::move(lhs) + 'c'</code></td>
<td><code>lhs</code></td>
<td><code>lhs</code></td>
<td><code>lhs</code></td>
<td><code>lhs</code></td>
<td><code>lhs</code></td>
</tr>
<tr>
<td><code>&quot;str&quot; + rhs</code></td>
<td>default-constructed</td>
<td>default-constructed</td>
<td><code>rhs</code></td>
<td>default-constructed</td>
<td>SOCCC on <code>rhs</code></td>
</tr>
<tr>
<td><code>'c' + rhs</code></td>
<td>default-constructed</td>
<td>default-constructed</td>
<td><code>rhs</code></td>
<td>default-constructed</td>
<td>SOCCC on <code>rhs</code></td>
</tr>
<tr>
<td><code>&quot;str&quot; + std::move(rhs)</code></td>
<td><code>rhs</code></td>
<td><code>rhs</code></td>
<td><code>rhs</code></td>
<td><code>rhs</code></td>
<td><code>rhs</code></td>
</tr>
<tr>
<td><code>'c' + std::move(rhs)</code></td>
<td><code>rhs</code></td>
<td><code>rhs</code></td>
<td><code>rhs</code></td>
<td><code>rhs</code></td>
<td><code>rhs</code></td>
</tr>
</tbody>
</table>
<p><small>(SOCCC == <code>select_on_container_copy_construction</code>. The <s>struckthrough</s> text is proposed to be removed by P1148R0.)</small></p>
<h2 id="discussion">Discussion</h2>
<p>The <a href="#proposed-wording">wording below</a> implements LEWG's <a href="http://wiki.edg.com/bin/view/Wg21sandiego2018/P1165">desired outcome</a>.
As the revision history makes clear, this is not the author's preferred direction. The <a href="#appendix">appendix</a> explains why.</p>
<h2 id="proposed-wording">Proposed wording</h2>
<p>This wording is relative to <a href="https://wg21.link/n4778">N4778</a>.</p>
<p>Replace <code>[string.op+]</code> in its entirety with the following:</p>
<pre><code class="language-c++"><div><span class="hljs-keyword">template</span>&lt;<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">charT</span>, <span class="hljs-title">class</span> <span class="hljs-title">traits</span>, <span class="hljs-title">class</span> <span class="hljs-title">Allocator</span>&gt;
  <span class="hljs-title">basic_string</span>&lt;charT, traits, Allocator&gt;
    <span class="hljs-title">operator</span>+(<span class="hljs-title">const</span> <span class="hljs-title">basic_string</span>&lt;charT, traits, Allocator&gt;&amp; <span class="hljs-title">lhs</span>,
              <span class="hljs-title">const</span> <span class="hljs-title">basic_string</span>&lt;charT, traits, Allocator&gt;&amp; <span class="hljs-title">rhs</span>);</span>

<span class="hljs-keyword">template</span>&lt;<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">charT</span>, <span class="hljs-title">class</span> <span class="hljs-title">traits</span>, <span class="hljs-title">class</span> <span class="hljs-title">Allocator</span>&gt;
  <span class="hljs-title">basic_string</span>&lt;charT, traits, Allocator&gt;
    <span class="hljs-title">operator</span>+(<span class="hljs-title">const</span> <span class="hljs-title">basic_string</span>&lt;charT, traits, Allocator&gt;&amp; <span class="hljs-title">lhs</span>, <span class="hljs-title">const</span> <span class="hljs-title">charT</span>* <span class="hljs-title">rhs</span>);</span>
</div></code></pre>
<p><sup>1</sup> <em>Effects</em>: Equivalent to:</p>
<pre><code class="language-c++"><div>    basic_string&lt;charT, traits, Allocator&gt; r = lhs;
    r.append(rhs);
    <span class="hljs-keyword">return</span> r;
</div></code></pre>
<pre><code class="language-c++"><div><span class="hljs-keyword">template</span>&lt;<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">charT</span>, <span class="hljs-title">class</span> <span class="hljs-title">traits</span>, <span class="hljs-title">class</span> <span class="hljs-title">Allocator</span>&gt;
  <span class="hljs-title">basic_string</span>&lt;charT, traits, Allocator&gt;
    <span class="hljs-title">operator</span>+(<span class="hljs-title">basic_string</span>&lt;charT, traits, Allocator&gt;&amp;&amp; <span class="hljs-title">lhs</span>,
              <span class="hljs-title">const</span> <span class="hljs-title">basic_string</span>&lt;charT, traits, Allocator&gt;&amp; <span class="hljs-title">rhs</span>);</span>
<span class="hljs-keyword">template</span>&lt;<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">charT</span>, <span class="hljs-title">class</span> <span class="hljs-title">traits</span>, <span class="hljs-title">class</span> <span class="hljs-title">Allocator</span>&gt;
  <span class="hljs-title">basic_string</span>&lt;charT, traits, Allocator&gt;
    <span class="hljs-title">operator</span>+(<span class="hljs-title">basic_string</span>&lt;charT, traits, Allocator&gt;&amp;&amp; <span class="hljs-title">lhs</span>, <span class="hljs-title">const</span> <span class="hljs-title">charT</span>* <span class="hljs-title">rhs</span>);</span>
</div></code></pre>
<p><sup>2</sup> <em>Effects</em>: Equivalent to:</p>
<pre><code class="language-c++"><div>    lhs.append(rhs);
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">std</span>::move(lhs);
</div></code></pre>
<pre><code class="language-c++"><div><span class="hljs-keyword">template</span>&lt;<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">charT</span>, <span class="hljs-title">class</span> <span class="hljs-title">traits</span>, <span class="hljs-title">class</span> <span class="hljs-title">Allocator</span>&gt;
  <span class="hljs-title">basic_string</span>&lt;charT, traits, Allocator&gt;
    <span class="hljs-title">operator</span>+(<span class="hljs-title">basic_string</span>&lt;charT, traits, Allocator&gt;&amp;&amp; <span class="hljs-title">lhs</span>,
              <span class="hljs-title">basic_string</span>&lt;charT, traits, Allocator&gt;&amp;&amp; <span class="hljs-title">rhs</span>);</span>
</div></code></pre>
<p><sup>3</sup> <em>Effects</em>: Equivalent to:</p>
<pre><code class="language-c++"><div>    lhs.append(rhs);
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">std</span>::move(lhs);
</div></code></pre>
<p>except that both  <code>lhs</code> and <code>rhs</code> are left in valid but unspecified states. [<em>Note:</em> If <code>lhs</code> and <code>rhs</code> have equal allocators, the implementation may move from either. — <em>end note</em>]</p>
<pre><code class="language-c++"><div><span class="hljs-keyword">template</span>&lt;<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">charT</span>, <span class="hljs-title">class</span> <span class="hljs-title">traits</span>, <span class="hljs-title">class</span> <span class="hljs-title">Allocator</span>&gt;
  <span class="hljs-title">basic_string</span>&lt;charT, traits, Allocator&gt;
    <span class="hljs-title">operator</span>+(<span class="hljs-title">const</span> <span class="hljs-title">basic_string</span>&lt;charT, traits, Allocator&gt;&amp; <span class="hljs-title">lhs</span>,
              <span class="hljs-title">basic_string</span>&lt;charT, traits, Allocator&gt;&amp;&amp; <span class="hljs-title">rhs</span>);</span>
<span class="hljs-keyword">template</span>&lt;<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">charT</span>, <span class="hljs-title">class</span> <span class="hljs-title">traits</span>, <span class="hljs-title">class</span> <span class="hljs-title">Allocator</span>&gt;
  <span class="hljs-title">basic_string</span>&lt;charT, traits, Allocator&gt;
    <span class="hljs-title">operator</span>+(<span class="hljs-title">const</span> <span class="hljs-title">charT</span>* <span class="hljs-title">lhs</span>, <span class="hljs-title">basic_string</span>&lt;charT, traits, Allocator&gt;&amp;&amp; <span class="hljs-title">rhs</span>);</span>
</div></code></pre>
<p><sup>4</sup> Effects: Equivalent to:</p>
<pre><code class="language-c++"><div>    rhs.insert(<span class="hljs-number">0</span>, lhs);
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">std</span>::move(rhs);
</div></code></pre>
<pre><code class="language-c++"><div><span class="hljs-keyword">template</span>&lt;<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">charT</span>, <span class="hljs-title">class</span> <span class="hljs-title">traits</span>, <span class="hljs-title">class</span> <span class="hljs-title">Allocator</span>&gt;
  <span class="hljs-title">basic_string</span>&lt;charT, traits, Allocator&gt;
    <span class="hljs-title">operator</span>+(<span class="hljs-title">const</span> <span class="hljs-title">charT</span>* <span class="hljs-title">lhs</span>, <span class="hljs-title">const</span> <span class="hljs-title">basic_string</span>&lt;charT, traits, Allocator&gt;&amp; <span class="hljs-title">rhs</span>);</span>
</div></code></pre>
<p><sup>5</sup> <em>Effects</em>: Equivalent to:</p>
<pre><code class="language-c++"><div>    basic_string&lt;charT, traits, Allocator&gt; r = rhs;
    r.insert(<span class="hljs-number">0</span>, lhs);
    <span class="hljs-keyword">return</span> r;
</div></code></pre>
<pre><code class="language-c++"><div><span class="hljs-keyword">template</span>&lt;<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">charT</span>, <span class="hljs-title">class</span> <span class="hljs-title">traits</span>, <span class="hljs-title">class</span> <span class="hljs-title">Allocator</span>&gt;
  <span class="hljs-title">basic_string</span>&lt;charT, traits, Allocator&gt;
    <span class="hljs-title">operator</span>+(<span class="hljs-title">charT</span> <span class="hljs-title">lhs</span>, <span class="hljs-title">const</span> <span class="hljs-title">basic_string</span>&lt;charT, traits, Allocator&gt;&amp; <span class="hljs-title">rhs</span>);</span>
</div></code></pre>
<p><sup>6</sup> <em>Effects</em>: Equivalent to:</p>
<pre><code class="language-c++"><div>    basic_string&lt;charT, traits, Allocator&gt; r = rhs;
    r.insert(r.begin(), lhs);
    <span class="hljs-keyword">return</span> r;
</div></code></pre>
<pre><code class="language-c++"><div><span class="hljs-keyword">template</span>&lt;<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">charT</span>, <span class="hljs-title">class</span> <span class="hljs-title">traits</span>, <span class="hljs-title">class</span> <span class="hljs-title">Allocator</span>&gt;
  <span class="hljs-title">basic_string</span>&lt;charT, traits, Allocator&gt;
    <span class="hljs-title">operator</span>+(<span class="hljs-title">charT</span> <span class="hljs-title">lhs</span>, <span class="hljs-title">basic_string</span>&lt;charT, traits, Allocator&gt;&amp;&amp; <span class="hljs-title">rhs</span>);</span>
</div></code></pre>
<p><sup>7</sup> <em>Effects</em>: Equivalent to:</p>
<pre><code class="language-c++"><div>    rhs.insert(rhs.begin(), lhs);
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">std</span>::move(rhs);
</div></code></pre>
<pre><code class="language-c++"><div><span class="hljs-keyword">template</span>&lt;<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">charT</span>, <span class="hljs-title">class</span> <span class="hljs-title">traits</span>, <span class="hljs-title">class</span> <span class="hljs-title">Allocator</span>&gt;
  <span class="hljs-title">basic_string</span>&lt;charT, traits, Allocator&gt;
    <span class="hljs-title">operator</span>+(<span class="hljs-title">const</span> <span class="hljs-title">basic_string</span>&lt;charT, traits, Allocator&gt;&amp; <span class="hljs-title">lhs</span>, <span class="hljs-title">charT</span> <span class="hljs-title">rhs</span>);</span>
</div></code></pre>
<p><sup>8</sup> <em>Effects</em>: Equivalent to:</p>
<pre><code class="language-c++"><div>    basic_string&lt;charT, traits, Allocator&gt; r = lhs;
    r.push_back(rhs);
    <span class="hljs-keyword">return</span> r;
</div></code></pre>
<pre><code class="language-c++"><div><span class="hljs-keyword">template</span>&lt;<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">charT</span>, <span class="hljs-title">class</span> <span class="hljs-title">traits</span>, <span class="hljs-title">class</span> <span class="hljs-title">Allocator</span>&gt;
  <span class="hljs-title">basic_string</span>&lt;charT, traits, Allocator&gt;
    <span class="hljs-title">operator</span>+(<span class="hljs-title">basic_string</span>&lt;charT, traits, Allocator&gt;&amp;&amp; <span class="hljs-title">lhs</span>, <span class="hljs-title">charT</span> <span class="hljs-title">rhs</span>);</span>
</div></code></pre>
<p><sup>9</sup> <em>Effects</em>: Equivalent to:</p>
<pre><code class="language-c++"><div>    lhs.push_back(rhs);
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">std</span>::move(lhs);
</div></code></pre>
<h2 id="appendix">Appendix</h2>
<p>The essence of the arguments below were made in a private discussion that was subsequently posted to the committee wiki prior to the San Diego meeting, to which LEWG has access.
However, the remainder of this section <em>has not been seen by LEWG in this form and reflects the author's opinion only</em>.</p>
<hr>
<p>Under LEWG's preferred approach, the result's allocator is sensitive to the value categories of the arguments, which may not be obvious from inspection of the code performing the concatenation:</p>
<pre><code class="language-c++"><div><span class="hljs-keyword">using</span> mystring = <span class="hljs-built_in">std</span>::basic_string&lt;<span class="hljs-keyword">char</span>, char_traits&lt;<span class="hljs-keyword">char</span>&gt;, my_allocator&lt;<span class="hljs-keyword">char</span>&gt;&gt;;
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">person</span> {</span>
  <span class="hljs-function"><span class="hljs-keyword">const</span> mystring&amp; <span class="hljs-title">name</span><span class="hljs-params">()</span> <span class="hljs-keyword">const</span></span>; <span class="hljs-comment">// maybe the name is stored directly</span>
  <span class="hljs-function">mystring <span class="hljs-title">address</span><span class="hljs-params">()</span> <span class="hljs-keyword">const</span></span>; <span class="hljs-comment">// but the full address is generated on request...</span>
} p;

mystring foo = <span class="hljs-comment">/* ... */</span>, bar = <span class="hljs-comment">/* ... */</span>, baz = <span class="hljs-comment">/* ... */</span>;
foo + p.name() + ...; <span class="hljs-comment">// uses SOCCC on foo's allocator</span>
bar + p.address() + ...; <span class="hljs-comment">// uses allocator of address()'s return value instead</span>
</div></code></pre>
<p>and, because it breaks associativity with respect to allocator state, the result's allocator is also sensitive to simple refactoring:</p>
<pre><code class="language-c++"><div>baz + foo + bar; <span class="hljs-comment">// SOCCC on baz's allocator</span>

baz + (foo + bar); <span class="hljs-comment">// SOCCC on foo's allocator instead</span>

<span class="hljs-keyword">auto</span> format_bar = [&amp;](<span class="hljs-keyword">const</span> mystring&amp; b) { <span class="hljs-keyword">return</span> foo + b; };
baz + format_bar(bar); <span class="hljs-comment">// also SOCCC on foo's allocator</span>
</div></code></pre>
<p>Additionally, it's not clear that unconditional propagation of allocator state for rvalues is desirable, since it may result in leakage of locally-scoped resources.
<code>a + &quot;str&quot;</code> is also no longer merely a performance shortcut for <code>a + basic_string&lt;...&gt;(&quot;str&quot;)</code>, which may break the mental model of some people.</p>
<p>Nonetheless, it should be acknowledged that LEWG's preferred approach has benefits as well:</p>
<ul>
<li>it avoids breaking any existing code that depends on implementation convergence for the rvalue overloads;</li>
<li>it permits using non-default-constructible allocators with <code>operator+</code>;</li>
<li>it maintains the equivalence of <code>x += y</code> and <code>x = x + y</code> ;</li>
<li>it permits a hack to control the allocator to be used for the result, by supplying an rvalue <code>basic_string</code> with the desired allocator as the first operand;</li>
</ul>
<p>It appeared unlikely to the author that there are much existing code relying on the rvalue overloads, considering the implementation divergence on the lvalue overloads. Under those circumstances,
the author preferred a &quot;break loudly and obviously&quot; approach to the approach taken above, which in his view is prone to causing more subtle breakages.</p>

    </body>
    </html>