Topic: Preferring operator=(T&& rhs) over operator(T


Author: Nicolas Lesser <blitzrakete@gmail.com>
Date: Fri, 13 Apr 2018 08:33:15 +0200
Raw View
--000000000000193e760569b50c91
Content-Type: text/plain; charset="UTF-8"

You can have the copy-swap idiom with an `operator=(const C&), I don't know
why you think so otherwise.

C& operator=(const C& rhs) {
    C copy(rhs);
    swap(copy, *this);
    return *this;
}

This is essentially what your operator=(C) is doing, but just that the copy
is now explicit instead of the compiler doing it for you.

On Fri, Apr 13, 2018 at 8:11 AM, <oguzakyuz@gmail.com> wrote:

> Let me know if this is a stupid idea or something that is already
> considered. But to my knowledge, if we have the following operator
> overloads for a class, compilers will generate an ambiguity error (probably
> enforced by the standard):
>
> C& C::operator=(C rhs);
> C& C::operator=(C&& rhs);
>
> However, if the compilers could choose the rvalue reference version over the pass-by-value version for rvalue arguments (i.e. c2 = c1 + c1), it could lead to an efficient copy-swap idiom implementation.
>
> Below is a sample code that demonstrates the problem. The issue is explained by the long comment block inside the main function:
>
>
> #include <algorithm>
>
> class C
> {
>     int* data;
>
>      public:
>
>      C() : data(nullptr) { }
>
>      C(int data) : data(new int)
>      {
>          *(this->data) = data;
>      }
>
>      C(const C& rhs) : data(new int)
>      {
>          *data = *(rhs.data);
>      }
>
>      C(C&& rhs) : C()
>      {
>          // Move constructor is first creating a default
>          // object and swapping it with the rvalue reference.
>          swap(*this, rhs);
>      }
>
>      C& operator=(C rhs)
>      {
>          // We let the compiler copy into rhs and we swap the
>          // current object with this copy. Together with the
>          // move constructor above, this implements the copy-swap
>          // idiom. Thanks to the move-constructor above, the
>          // copy to rhs is not a deep copy if the input is an rvalue
>          // reference.
>          swap(*this, rhs);
>          return *this;
>      }
>
>      // The function below is commented out because it fails compilation
>      // due to ambiguity with the above function. However, if it worked
>      // it could have saved us an extra call to the move constructor when
>      // we make calls such as c2 = c1 + c1 (see operator+ below). If it had
>      // worked, the temporary created from c1 + c1 would have been
> directly
>      // taken by rvalue reference instead of its copy  (albeit shallow)
> being
>      // created.
>
>      /*
>      C& operator=(C&& rhs)
>      {
>          swap(*this, rhs);
>          return *this;
>      }
>      */
>
>      C operator+(const C& rhs)
>      {
>          C result(*data + *(rhs.data));
>          return result;
>      }
>
>      friend void swap(C& lhs, C& rhs);
>
>      ~C()
>      {
>          delete data;
>      }
> };
>
> void swap(C& lhs, C& rhs)
> {
>     std::swap(lhs.data, rhs.data);
> }
>
> int main()
> {
>     C c1(7);
>     C c2;
>
>     // The following will first create the "result" inside operator+.
>     // The return value will then get move-constructed from the result
>     // (I'm assuming that -fno-elide-constructors option is used). Then
>     // the "rhs" parameter of operator= will get move-constructed from
>     // this return temporary.
>     //
>     // But if we could overload operator=(C&&), this second
> move-construction
>     // could have been avoided as the return temporary could have been
> directly
>     // captured by rvalue reference.
>     //
>     // Granted that we can implement operator=(const C&) and operator=(C&&)
>     // to make assignment as efficient as possible for both lvalue and
> rvalue
>     // inputs. However, to my knowledge, having operator=(const C&) would
>     // essentially prevent us from having the copy-swap idiom.
>
>     c2 = c1 + c1;
>
>     return 0;
> }
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> To view this discussion on the web visit https://groups.google.com/a/
> isocpp.org/d/msgid/std-proposals/62809333-fd1a-4bde-
> 8805-ccc0578a4284%40isocpp.org
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/62809333-fd1a-4bde-8805-ccc0578a4284%40isocpp.org?utm_medium=email&utm_source=footer>
> .
>

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CALmDwq1BmvjJWdqiQOn8GJUrFKqtO6tGtTHN7NBqAOX8vVspog%40mail.gmail.com.

--000000000000193e760569b50c91
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">You can have the copy-swap idiom with an `operator=3D(cons=
t C&amp;), I don&#39;t know why you think so otherwise.<div><br></div><div>=
C&amp; operator=3D(const C&amp; rhs) {<br>=C2=A0 =C2=A0 C copy(rhs);</div><=
div>=C2=A0 =C2=A0 swap(copy, *this);</div><div>=C2=A0 =C2=A0 return *this;<=
/div><div>}</div><div><br></div><div>This is essentially what your operator=
=3D(C) is doing, but just that the copy is now explicit instead of the comp=
iler doing it for you.</div></div><div class=3D"gmail_extra"><br><div class=
=3D"gmail_quote">On Fri, Apr 13, 2018 at 8:11 AM,  <span dir=3D"ltr">&lt;<a=
 href=3D"mailto:oguzakyuz@gmail.com" target=3D"_blank">oguzakyuz@gmail.com<=
/a>&gt;</span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:=
0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">Le=
t me know if this is a stupid idea or something that is already considered.=
 But to my knowledge, if we have the following operator overloads for a cla=
ss, compilers will generate an ambiguity error (probably enforced by the st=
andard):<br><br><pre class=3D"m_3382430202751094859lang-cpp m_3382430202751=
094859prettyprint m_3382430202751094859prettyprinted"><code><span class=3D"=
m_3382430202751094859pln">C</span><span class=3D"m_3382430202751094859pun">=
&amp;</span><span class=3D"m_3382430202751094859pln"> C::</span><span class=
=3D"m_3382430202751094859kwd">operator</span><span class=3D"m_3382430202751=
094859pun">=3D(</span><span class=3D"m_3382430202751094859pln">C rhs</span>=
<span class=3D"m_3382430202751094859pun">);<br></span></code><code><span cl=
ass=3D"m_3382430202751094859pln">C</span><span class=3D"m_33824302027510948=
59pun">&amp;</span><span class=3D"m_3382430202751094859pln"> C::</span><spa=
n class=3D"m_3382430202751094859kwd">operator</span><span class=3D"m_338243=
0202751094859pun">=3D(</span><span class=3D"m_3382430202751094859pln">C&amp=
;&amp; rhs</span><span class=3D"m_3382430202751094859pun">);</span></code><=
br><br>However, if the compilers could choose the rvalue reference version =
over the pass-by-value version for rvalue arguments (i.e. c2 =3D c1 + c1), =
it could lead to an efficient copy-swap idiom implementation.<br><br>Below =
is a sample code that demonstrates the problem. The issue is explained by t=
he long comment block inside the main function:<br><code><span class=3D"m_3=
382430202751094859pun"></span></code></pre><br><div style=3D"background-col=
or:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;border=
-width:1px" class=3D"m_3382430202751094859prettyprint"><code class=3D"m_338=
2430202751094859prettyprint"><div class=3D"m_3382430202751094859subprettypr=
int"><span style=3D"color:#000" class=3D"m_3382430202751094859styled-by-pre=
ttify">#include &lt;algorithm&gt;<br><br></span><span style=3D"color:#008" =
class=3D"m_3382430202751094859styled-by-prettify">class</span><span style=
=3D"color:#000" class=3D"m_3382430202751094859styled-by-prettify"> C<br></s=
pan><span style=3D"color:#660" class=3D"m_3382430202751094859styled-by-pret=
tify">{</span><span style=3D"color:#000" class=3D"m_3382430202751094859styl=
ed-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008" class=
=3D"m_3382430202751094859styled-by-prettify">int</span><span style=3D"color=
:#660" class=3D"m_3382430202751094859styled-by-prettify">*</span><span styl=
e=3D"color:#000" class=3D"m_3382430202751094859styled-by-prettify"> data</s=
pan><span style=3D"color:#660" class=3D"m_3382430202751094859styled-by-pret=
tify">;</span><span style=3D"color:#000" class=3D"m_3382430202751094859styl=
ed-by-prettify"><br><br>=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#00=
8" class=3D"m_3382430202751094859styled-by-prettify">public</span><span sty=
le=3D"color:#660" class=3D"m_3382430202751094859styled-by-prettify">:</span=
><span style=3D"color:#000" class=3D"m_3382430202751094859styled-by-prettif=
y"><br><br>=C2=A0 =C2=A0 =C2=A0C</span><span style=3D"color:#660" class=3D"=
m_3382430202751094859styled-by-prettify">()</span><span style=3D"color:#000=
" class=3D"m_3382430202751094859styled-by-prettify"> </span><span style=3D"=
color:#660" class=3D"m_3382430202751094859styled-by-prettify">:</span><span=
 style=3D"color:#000" class=3D"m_3382430202751094859styled-by-prettify"> da=
ta</span><span style=3D"color:#660" class=3D"m_3382430202751094859styled-by=
-prettify">(</span><span style=3D"color:#008" class=3D"m_338243020275109485=
9styled-by-prettify">nullptr</span><span style=3D"color:#660" class=3D"m_33=
82430202751094859styled-by-prettify">)</span><span style=3D"color:#000" cla=
ss=3D"m_3382430202751094859styled-by-prettify"> </span><span style=3D"color=
:#660" class=3D"m_3382430202751094859styled-by-prettify">{</span><span styl=
e=3D"color:#000" class=3D"m_3382430202751094859styled-by-prettify"> </span>=
<span style=3D"color:#660" class=3D"m_3382430202751094859styled-by-prettify=
">}</span><span style=3D"color:#000" class=3D"m_3382430202751094859styled-b=
y-prettify"><br><br>=C2=A0 =C2=A0 =C2=A0C</span><span style=3D"color:#660" =
class=3D"m_3382430202751094859styled-by-prettify">(</span><span style=3D"co=
lor:#008" class=3D"m_3382430202751094859styled-by-prettify">int</span><span=
 style=3D"color:#000" class=3D"m_3382430202751094859styled-by-prettify"> da=
ta</span><span style=3D"color:#660" class=3D"m_3382430202751094859styled-by=
-prettify">)</span><span style=3D"color:#000" class=3D"m_338243020275109485=
9styled-by-prettify"> </span><span style=3D"color:#660" class=3D"m_33824302=
02751094859styled-by-prettify">:</span><span style=3D"color:#000" class=3D"=
m_3382430202751094859styled-by-prettify"> data</span><span style=3D"color:#=
660" class=3D"m_3382430202751094859styled-by-prettify">(</span><span style=
=3D"color:#008" class=3D"m_3382430202751094859styled-by-prettify">new</span=
><span style=3D"color:#000" class=3D"m_3382430202751094859styled-by-prettif=
y"> </span><span style=3D"color:#008" class=3D"m_3382430202751094859styled-=
by-prettify">int</span><span style=3D"color:#660" class=3D"m_33824302027510=
94859styled-by-prettify">)</span><span style=3D"color:#000" class=3D"m_3382=
430202751094859styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0</span><span sty=
le=3D"color:#660" class=3D"m_3382430202751094859styled-by-prettify">{</span=
><span style=3D"color:#000" class=3D"m_3382430202751094859styled-by-prettif=
y"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660" =
class=3D"m_3382430202751094859styled-by-prettify">*(</span><span style=3D"c=
olor:#008" class=3D"m_3382430202751094859styled-by-prettify">this</span><sp=
an style=3D"color:#660" class=3D"m_3382430202751094859styled-by-prettify">-=
&gt;</span><span style=3D"color:#000" class=3D"m_3382430202751094859styled-=
by-prettify">data</span><span style=3D"color:#660" class=3D"m_3382430202751=
094859styled-by-prettify">)</span><span style=3D"color:#000" class=3D"m_338=
2430202751094859styled-by-prettify"> </span><span style=3D"color:#660" clas=
s=3D"m_3382430202751094859styled-by-prettify">=3D</span><span style=3D"colo=
r:#000" class=3D"m_3382430202751094859styled-by-prettify"> data</span><span=
 style=3D"color:#660" class=3D"m_3382430202751094859styled-by-prettify">;</=
span><span style=3D"color:#000" class=3D"m_3382430202751094859styled-by-pre=
ttify"><br>=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660" class=3D"m=
_3382430202751094859styled-by-prettify">}</span><span style=3D"color:#000" =
class=3D"m_3382430202751094859styled-by-prettify"><br><br>=C2=A0 =C2=A0 =C2=
=A0C</span><span style=3D"color:#660" class=3D"m_3382430202751094859styled-=
by-prettify">(</span><span style=3D"color:#008" class=3D"m_3382430202751094=
859styled-by-prettify">const</span><span style=3D"color:#000" class=3D"m_33=
82430202751094859styled-by-prettify"> C</span><span style=3D"color:#660" cl=
ass=3D"m_3382430202751094859styled-by-prettify">&amp;</span><span style=3D"=
color:#000" class=3D"m_3382430202751094859styled-by-prettify"> rhs</span><s=
pan style=3D"color:#660" class=3D"m_3382430202751094859styled-by-prettify">=
)</span><span style=3D"color:#000" class=3D"m_3382430202751094859styled-by-=
prettify"> </span><span style=3D"color:#660" class=3D"m_3382430202751094859=
styled-by-prettify">:</span><span style=3D"color:#000" class=3D"m_338243020=
2751094859styled-by-prettify"> data</span><span style=3D"color:#660" class=
=3D"m_3382430202751094859styled-by-prettify">(</span><span style=3D"color:#=
008" class=3D"m_3382430202751094859styled-by-prettify">new</span><span styl=
e=3D"color:#000" class=3D"m_3382430202751094859styled-by-prettify"> </span>=
<span style=3D"color:#008" class=3D"m_3382430202751094859styled-by-prettify=
">int</span><span style=3D"color:#660" class=3D"m_3382430202751094859styled=
-by-prettify">)</span><span style=3D"color:#000" class=3D"m_338243020275109=
4859styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color=
:#660" class=3D"m_3382430202751094859styled-by-prettify">{</span><span styl=
e=3D"color:#000" class=3D"m_3382430202751094859styled-by-prettify"><br>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660" class=3D"m=
_3382430202751094859styled-by-prettify">*</span><span style=3D"color:#000" =
class=3D"m_3382430202751094859styled-by-prettify">data </span><span style=
=3D"color:#660" class=3D"m_3382430202751094859styled-by-prettify">=3D</span=
><span style=3D"color:#000" class=3D"m_3382430202751094859styled-by-prettif=
y"> </span><span style=3D"color:#660" class=3D"m_3382430202751094859styled-=
by-prettify">*(</span><span style=3D"color:#000" class=3D"m_338243020275109=
4859styled-by-prettify">rhs</span><span style=3D"color:#660" class=3D"m_338=
2430202751094859styled-by-prettify">.</span><span style=3D"color:#000" clas=
s=3D"m_3382430202751094859styled-by-prettify">data</span><span style=3D"col=
or:#660" class=3D"m_3382430202751094859styled-by-prettify">);</span><span s=
tyle=3D"color:#000" class=3D"m_3382430202751094859styled-by-prettify"><br>=
=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660" class=3D"m_3382430202=
751094859styled-by-prettify">}</span><span style=3D"color:#000" class=3D"m_=
3382430202751094859styled-by-prettify"><br><br>=C2=A0 =C2=A0 =C2=A0C</span>=
<span style=3D"color:#660" class=3D"m_3382430202751094859styled-by-prettify=
">(</span><span style=3D"color:#000" class=3D"m_3382430202751094859styled-b=
y-prettify">C</span><span style=3D"color:#660" class=3D"m_33824302027510948=
59styled-by-prettify">&amp;&amp;</span><span style=3D"color:#000" class=3D"=
m_3382430202751094859styled-by-prettify"> rhs</span><span style=3D"color:#6=
60" class=3D"m_3382430202751094859styled-by-prettify">)</span><span style=
=3D"color:#000" class=3D"m_3382430202751094859styled-by-prettify"> </span><=
span style=3D"color:#660" class=3D"m_3382430202751094859styled-by-prettify"=
>:</span><span style=3D"color:#000" class=3D"m_3382430202751094859styled-by=
-prettify"> C</span><span style=3D"color:#660" class=3D"m_33824302027510948=
59styled-by-prettify">()</span><span style=3D"color:#000" class=3D"m_338243=
0202751094859styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0</span><span style=
=3D"color:#660" class=3D"m_3382430202751094859styled-by-prettify">{</span><=
span style=3D"color:#000" class=3D"m_3382430202751094859styled-by-prettify"=
><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#800" cl=
ass=3D"m_3382430202751094859styled-by-prettify">// Move constructor is firs=
t creating a default</span><span style=3D"color:#000" class=3D"m_3382430202=
751094859styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><=
span style=3D"color:#800" class=3D"m_3382430202751094859styled-by-prettify"=
>// object and swapping it with the rvalue reference.</span><span style=3D"=
color:#000" class=3D"m_3382430202751094859styled-by-prettify"><br>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0swap</span><span style=3D"color:#660" class=3D"m=
_3382430202751094859styled-by-prettify">(*</span><span style=3D"color:#008"=
 class=3D"m_3382430202751094859styled-by-prettify">this</span><span style=
=3D"color:#660" class=3D"m_3382430202751094859styled-by-prettify">,</span><=
span style=3D"color:#000" class=3D"m_3382430202751094859styled-by-prettify"=
> rhs</span><span style=3D"color:#660" class=3D"m_3382430202751094859styled=
-by-prettify">);</span><span style=3D"color:#000" class=3D"m_33824302027510=
94859styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0</span><span style=3D"colo=
r:#660" class=3D"m_3382430202751094859styled-by-prettify">}</span><span sty=
le=3D"color:#000" class=3D"m_3382430202751094859styled-by-prettify"><br><br=
>=C2=A0 =C2=A0 =C2=A0C</span><span style=3D"color:#660" class=3D"m_33824302=
02751094859styled-by-prettify">&amp;</span><span style=3D"color:#000" class=
=3D"m_3382430202751094859styled-by-prettify"> </span><span style=3D"color:#=
008" class=3D"m_3382430202751094859styled-by-prettify">operator</span><span=
 style=3D"color:#660" class=3D"m_3382430202751094859styled-by-prettify">=3D=
(</span><span style=3D"color:#000" class=3D"m_3382430202751094859styled-by-=
prettify">C rhs</span><span style=3D"color:#660" class=3D"m_338243020275109=
4859styled-by-prettify">)</span><span style=3D"color:#000" class=3D"m_33824=
30202751094859styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0</span><span styl=
e=3D"color:#660" class=3D"m_3382430202751094859styled-by-prettify">{</span>=
<span style=3D"color:#000" class=3D"m_3382430202751094859styled-by-prettify=
"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#800" c=
lass=3D"m_3382430202751094859styled-by-prettify">// We let the compiler cop=
y into rhs and we swap the</span><span style=3D"color:#000" class=3D"m_3382=
430202751094859styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</=
span><span style=3D"color:#800" class=3D"m_3382430202751094859styled-by-pre=
ttify">// current object with this copy. Together with the</span><span styl=
e=3D"color:#000" class=3D"m_3382430202751094859styled-by-prettify"><br>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#800" class=3D"m=
_3382430202751094859styled-by-prettify">// move constructor above, this imp=
lements the copy-swap</span><span style=3D"color:#000" class=3D"m_338243020=
2751094859styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span>=
<span style=3D"color:#800" class=3D"m_3382430202751094859styled-by-prettify=
">// idiom. Thanks to the move-constructor above, the</span><span style=3D"=
color:#000" class=3D"m_3382430202751094859styled-by-prettify"><br>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#800" class=3D"m_338=
2430202751094859styled-by-prettify">// copy to rhs is not a deep copy if th=
e input is an rvalue<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 //=
 reference.</span><span style=3D"color:#000" class=3D"m_3382430202751094859=
styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0swap</span><span =
style=3D"color:#660" class=3D"m_3382430202751094859styled-by-prettify">(*</=
span><span style=3D"color:#008" class=3D"m_3382430202751094859styled-by-pre=
ttify">this</span><span style=3D"color:#660" class=3D"m_3382430202751094859=
styled-by-prettify">,</span><span style=3D"color:#000" class=3D"m_338243020=
2751094859styled-by-prettify"> rhs</span><span style=3D"color:#660" class=
=3D"m_3382430202751094859styled-by-prettify">);</span><span style=3D"color:=
#000" class=3D"m_3382430202751094859styled-by-prettify"><br>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#008" class=3D"m_3382430202=
751094859styled-by-prettify">return</span><span style=3D"color:#000" class=
=3D"m_3382430202751094859styled-by-prettify"> </span><span style=3D"color:#=
660" class=3D"m_3382430202751094859styled-by-prettify">*</span><span style=
=3D"color:#008" class=3D"m_3382430202751094859styled-by-prettify">this</spa=
n><span style=3D"color:#660" class=3D"m_3382430202751094859styled-by-pretti=
fy">;</span><span style=3D"color:#000" class=3D"m_3382430202751094859styled=
-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660" cla=
ss=3D"m_3382430202751094859styled-by-prettify">}</span><span style=3D"color=
:#000" class=3D"m_3382430202751094859styled-by-prettify"><br><br></span>=C2=
=A0=C2=A0=C2=A0=C2=A0 // The function below is commented out because it fai=
ls compilation<br>=C2=A0=C2=A0=C2=A0=C2=A0 // due to ambiguity with the abo=
ve function. However, if it worked<br>=C2=A0=C2=A0=C2=A0=C2=A0 // it could =
have saved us an extra call to the move constructor when<br>=C2=A0=C2=A0=C2=
=A0=C2=A0 // we make calls such as c2 =3D c1 + c1 (see operator+ below). If=
 it had<br>=C2=A0=C2=A0=C2=A0=C2=A0 // worked, the temporary created from c=
1 + c1 would have been directly <br>=C2=A0=C2=A0=C2=A0=C2=A0 // taken by rv=
alue reference instead of its copy=C2=A0 (albeit shallow) being<br>=C2=A0=
=C2=A0=C2=A0=C2=A0 // created. <br>=C2=A0=C2=A0=C2=A0=C2=A0 <br>=C2=A0=C2=
=A0=C2=A0=C2=A0 /*<br><span style=3D"color:#000" class=3D"m_338243020275109=
4859styled-by-prettify"><code class=3D"m_3382430202751094859prettyprint"><s=
pan style=3D"color:#000" class=3D"m_3382430202751094859styled-by-prettify">=
=C2=A0=C2=A0=C2=A0=C2=A0 C</span><span style=3D"color:#660" class=3D"m_3382=
430202751094859styled-by-prettify">&amp;</span><span style=3D"color:#000" c=
lass=3D"m_3382430202751094859styled-by-prettify"> </span><span style=3D"col=
or:#008" class=3D"m_3382430202751094859styled-by-prettify">operator</span><=
span style=3D"color:#660" class=3D"m_3382430202751094859styled-by-prettify"=
>=3D(</span><span style=3D"color:#000" class=3D"m_3382430202751094859styled=
-by-prettify">C&amp;&amp; rhs</span><span style=3D"color:#660" class=3D"m_3=
382430202751094859styled-by-prettify">)</span><span style=3D"color:#000" cl=
ass=3D"m_3382430202751094859styled-by-prettify"><br>=C2=A0 =C2=A0=C2=A0 </s=
pan><span style=3D"color:#660" class=3D"m_3382430202751094859styled-by-pret=
tify">{</span><span style=3D"color:#000" class=3D"m_3382430202751094859styl=
ed-by-prettify"></span><span style=3D"color:#000" class=3D"m_33824302027510=
94859styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0swap</span><=
span style=3D"color:#660" class=3D"m_3382430202751094859styled-by-prettify"=
>(*</span><span style=3D"color:#008" class=3D"m_3382430202751094859styled-b=
y-prettify">this</span><span style=3D"color:#660" class=3D"m_33824302027510=
94859styled-by-prettify">,</span><span style=3D"color:#000" class=3D"m_3382=
430202751094859styled-by-prettify"> rhs</span><span style=3D"color:#660" cl=
ass=3D"m_3382430202751094859styled-by-prettify">);</span><span style=3D"col=
or:#000" class=3D"m_3382430202751094859styled-by-prettify"><br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#008" class=3D"m_338243=
0202751094859styled-by-prettify">return</span><span style=3D"color:#000" cl=
ass=3D"m_3382430202751094859styled-by-prettify"> </span><span style=3D"colo=
r:#660" class=3D"m_3382430202751094859styled-by-prettify">*</span><span sty=
le=3D"color:#008" class=3D"m_3382430202751094859styled-by-prettify">this</s=
pan><span style=3D"color:#660" class=3D"m_3382430202751094859styled-by-pret=
tify">;</span><span style=3D"color:#000" class=3D"m_3382430202751094859styl=
ed-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660" c=
lass=3D"m_3382430202751094859styled-by-prettify">}</span><span style=3D"col=
or:#000" class=3D"m_3382430202751094859styled-by-prettify"><br>=C2=A0=C2=A0=
=C2=A0=C2=A0 */<br></span></code><br>=C2=A0 =C2=A0 =C2=A0C </span><span sty=
le=3D"color:#008" class=3D"m_3382430202751094859styled-by-prettify">operato=
r</span><span style=3D"color:#660" class=3D"m_3382430202751094859styled-by-=
prettify">+(</span><span style=3D"color:#008" class=3D"m_338243020275109485=
9styled-by-prettify">const</span><span style=3D"color:#000" class=3D"m_3382=
430202751094859styled-by-prettify"> C</span><span style=3D"color:#660" clas=
s=3D"m_3382430202751094859styled-by-prettify">&amp;</span><span style=3D"co=
lor:#000" class=3D"m_3382430202751094859styled-by-prettify"> rhs</span><spa=
n style=3D"color:#660" class=3D"m_3382430202751094859styled-by-prettify">)<=
/span><span style=3D"color:#000" class=3D"m_3382430202751094859styled-by-pr=
ettify"><br>=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660" class=3D"=
m_3382430202751094859styled-by-prettify">{</span><span style=3D"color:#000"=
 class=3D"m_3382430202751094859styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0=
 =C2=A0 =C2=A0C result</span><span style=3D"color:#660" class=3D"m_33824302=
02751094859styled-by-prettify">(*</span><span style=3D"color:#000" class=3D=
"m_3382430202751094859styled-by-prettify">data </span><span style=3D"color:=
#660" class=3D"m_3382430202751094859styled-by-prettify">+</span><span style=
=3D"color:#000" class=3D"m_3382430202751094859styled-by-prettify"> </span><=
span style=3D"color:#660" class=3D"m_3382430202751094859styled-by-prettify"=
>*(</span><span style=3D"color:#000" class=3D"m_3382430202751094859styled-b=
y-prettify">rhs</span><span style=3D"color:#660" class=3D"m_338243020275109=
4859styled-by-prettify">.</span><span style=3D"color:#000" class=3D"m_33824=
30202751094859styled-by-prettify">data</span><span style=3D"color:#660" cla=
ss=3D"m_3382430202751094859styled-by-prettify">));</span><span style=3D"col=
or:#000" class=3D"m_3382430202751094859styled-by-prettify"><br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#008" class=3D"m_338243=
0202751094859styled-by-prettify">return</span><span style=3D"color:#000" cl=
ass=3D"m_3382430202751094859styled-by-prettify"> result</span><span style=
=3D"color:#660" class=3D"m_3382430202751094859styled-by-prettify">;</span><=
span style=3D"color:#000" class=3D"m_3382430202751094859styled-by-prettify"=
><br>=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660" class=3D"m_33824=
30202751094859styled-by-prettify">}</span><span style=3D"color:#000" class=
=3D"m_3382430202751094859styled-by-prettify"><br><br>=C2=A0</span><span sty=
le=3D"color:#008" class=3D"m_3382430202751094859styled-by-prettify">=C2=A0=
=C2=A0=C2=A0 friend</span><span style=3D"color:#000" class=3D"m_33824302027=
51094859styled-by-prettify"> </span><span style=3D"color:#008" class=3D"m_3=
382430202751094859styled-by-prettify">void</span><span style=3D"color:#000"=
 class=3D"m_3382430202751094859styled-by-prettify"> swap</span><span style=
=3D"color:#660" class=3D"m_3382430202751094859styled-by-prettify">(</span><=
span style=3D"color:#000" class=3D"m_3382430202751094859styled-by-prettify"=
>C</span><span style=3D"color:#660" class=3D"m_3382430202751094859styled-by=
-prettify">&amp;</span><span style=3D"color:#000" class=3D"m_33824302027510=
94859styled-by-prettify"> lhs</span><span style=3D"color:#660" class=3D"m_3=
382430202751094859styled-by-prettify">,</span><span style=3D"color:#000" cl=
ass=3D"m_3382430202751094859styled-by-prettify"> C</span><span style=3D"col=
or:#660" class=3D"m_3382430202751094859styled-by-prettify">&amp;</span><spa=
n style=3D"color:#000" class=3D"m_3382430202751094859styled-by-prettify"> r=
hs</span><span style=3D"color:#660" class=3D"m_3382430202751094859styled-by=
-prettify">);</span><span style=3D"color:#000" class=3D"m_33824302027510948=
59styled-by-prettify"><br><br>=C2=A0=C2=A0=C2=A0=C2=A0 </span><span style=
=3D"color:#660" class=3D"m_3382430202751094859styled-by-prettify">~</span><=
span style=3D"color:#000" class=3D"m_3382430202751094859styled-by-prettify"=
>C</span><span style=3D"color:#660" class=3D"m_3382430202751094859styled-by=
-prettify">()</span><span style=3D"color:#000" class=3D"m_33824302027510948=
59styled-by-prettify"><br>=C2=A0</span><span style=3D"color:#660" class=3D"=
m_3382430202751094859styled-by-prettify">=C2=A0=C2=A0=C2=A0 {</span><span s=
tyle=3D"color:#000" class=3D"m_3382430202751094859styled-by-prettify"><br>=
=C2=A0</span><span style=3D"color:#008" class=3D"m_3382430202751094859style=
d-by-prettify">=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 delete</span><spa=
n style=3D"color:#000" class=3D"m_3382430202751094859styled-by-prettify"> d=
ata</span><span style=3D"color:#660" class=3D"m_3382430202751094859styled-b=
y-prettify">;</span><span style=3D"color:#000" class=3D"m_33824302027510948=
59styled-by-prettify"><br>=C2=A0=C2=A0=C2=A0=C2=A0 </span><span style=3D"co=
lor:#660" class=3D"m_3382430202751094859styled-by-prettify">}</span><span s=
tyle=3D"color:#000" class=3D"m_3382430202751094859styled-by-prettify"><br><=
/span><span style=3D"color:#660" class=3D"m_3382430202751094859styled-by-pr=
ettify">};</span><span style=3D"color:#000" class=3D"m_3382430202751094859s=
tyled-by-prettify"><br><br></span><span style=3D"color:#008" class=3D"m_338=
2430202751094859styled-by-prettify">void</span><span style=3D"color:#000" c=
lass=3D"m_3382430202751094859styled-by-prettify"> swap</span><span style=3D=
"color:#660" class=3D"m_3382430202751094859styled-by-prettify">(</span><spa=
n style=3D"color:#000" class=3D"m_3382430202751094859styled-by-prettify">C<=
/span><span style=3D"color:#660" class=3D"m_3382430202751094859styled-by-pr=
ettify">&amp;</span><span style=3D"color:#000" class=3D"m_33824302027510948=
59styled-by-prettify"> lhs</span><span style=3D"color:#660" class=3D"m_3382=
430202751094859styled-by-prettify">,</span><span style=3D"color:#000" class=
=3D"m_3382430202751094859styled-by-prettify"> C</span><span style=3D"color:=
#660" class=3D"m_3382430202751094859styled-by-prettify">&amp;</span><span s=
tyle=3D"color:#000" class=3D"m_3382430202751094859styled-by-prettify"> rhs<=
/span><span style=3D"color:#660" class=3D"m_3382430202751094859styled-by-pr=
ettify">)</span><span style=3D"color:#000" class=3D"m_3382430202751094859st=
yled-by-prettify"><br></span><span style=3D"color:#660" class=3D"m_33824302=
02751094859styled-by-prettify">{</span><span style=3D"color:#000" class=3D"=
m_3382430202751094859styled-by-prettify"><br>=C2=A0=C2=A0=C2=A0 std</span><=
span style=3D"color:#660" class=3D"m_3382430202751094859styled-by-prettify"=
>::</span><span style=3D"color:#000" class=3D"m_3382430202751094859styled-b=
y-prettify">swap</span><span style=3D"color:#660" class=3D"m_33824302027510=
94859styled-by-prettify">(</span><span style=3D"color:#000" class=3D"m_3382=
430202751094859styled-by-prettify">lhs</span><span style=3D"color:#660" cla=
ss=3D"m_3382430202751094859styled-by-prettify">.</span><span style=3D"color=
:#000" class=3D"m_3382430202751094859styled-by-prettify">data</span><span s=
tyle=3D"color:#660" class=3D"m_3382430202751094859styled-by-prettify">,</sp=
an><span style=3D"color:#000" class=3D"m_3382430202751094859styled-by-prett=
ify"> rhs</span><span style=3D"color:#660" class=3D"m_3382430202751094859st=
yled-by-prettify">.</span><span style=3D"color:#000" class=3D"m_33824302027=
51094859styled-by-prettify">data</span><span style=3D"color:#660" class=3D"=
m_3382430202751094859styled-by-prettify">);</span><span style=3D"color:#000=
" class=3D"m_3382430202751094859styled-by-prettify"><br></span><span style=
=3D"color:#660" class=3D"m_3382430202751094859styled-by-prettify">}</span><=
span style=3D"color:#000" class=3D"m_3382430202751094859styled-by-prettify"=
><br><br></span><span style=3D"color:#008" class=3D"m_3382430202751094859st=
yled-by-prettify">int</span><span style=3D"color:#000" class=3D"m_338243020=
2751094859styled-by-prettify"> main</span><span style=3D"color:#660" class=
=3D"m_3382430202751094859styled-by-prettify">()</span><span style=3D"color:=
#000" class=3D"m_3382430202751094859styled-by-prettify"><br></span><span st=
yle=3D"color:#660" class=3D"m_3382430202751094859styled-by-prettify">{</spa=
n><span style=3D"color:#000" class=3D"m_3382430202751094859styled-by-pretti=
fy"><br>=C2=A0=C2=A0=C2=A0 C c1</span><span style=3D"color:#660" class=3D"m=
_3382430202751094859styled-by-prettify">(</span><span style=3D"color:#066" =
class=3D"m_3382430202751094859styled-by-prettify">7</span><span style=3D"co=
lor:#660" class=3D"m_3382430202751094859styled-by-prettify">);</span><span =
style=3D"color:#000" class=3D"m_3382430202751094859styled-by-prettify"><br>=
=C2=A0=C2=A0=C2=A0 C c2</span><span style=3D"color:#660" class=3D"m_3382430=
202751094859styled-by-prettify">;</span><span style=3D"color:#000" class=3D=
"m_3382430202751094859styled-by-prettify"></span><span style=3D"color:#000"=
 class=3D"m_3382430202751094859styled-by-prettify"><br><br>=C2=A0=C2=A0=C2=
=A0 // The following will first create the &quot;result&quot; inside operat=
or+.<br>=C2=A0 =C2=A0 // The return value will then get move-constructed fr=
om the result<br>=C2=A0=C2=A0=C2=A0 // (I&#39;m assuming that -fno-elide-co=
nstructors option is used). Then<br>=C2=A0=C2=A0=C2=A0 // the &quot;rhs&quo=
t; parameter of operator=3D will get move-constructed from<br>=C2=A0=C2=A0=
=C2=A0 // this return temporary.<br>=C2=A0=C2=A0=C2=A0 //<br>=C2=A0=C2=A0=
=C2=A0 // But if we could overload operator=3D(C&amp;&amp;), this second mo=
ve-construction<br>=C2=A0=C2=A0=C2=A0 // could have been avoided as the ret=
urn temporary could have been directly<br>=C2=A0=C2=A0=C2=A0 // captured by=
 rvalue reference.<br>=C2=A0=C2=A0=C2=A0 //<br>=C2=A0=C2=A0=C2=A0 // Grante=
d that we can implement operator=3D(const C&amp;) and operator=3D(C&amp;&am=
p;)<br>=C2=A0=C2=A0=C2=A0 // to make assignment as efficient as possible fo=
r both lvalue and rvalue<br>=C2=A0=C2=A0=C2=A0 // inputs. However, to my kn=
owledge, having operator=3D(const C&amp;) would<br>=C2=A0=C2=A0=C2=A0 // es=
sentially prevent us from having the copy-swap idiom.<br><br>=C2=A0=C2=A0=
=C2=A0 c2 </span><span style=3D"color:#660" class=3D"m_3382430202751094859s=
tyled-by-prettify">=3D</span><span style=3D"color:#000" class=3D"m_33824302=
02751094859styled-by-prettify"> c1 </span><span style=3D"color:#660" class=
=3D"m_3382430202751094859styled-by-prettify">+</span><span style=3D"color:#=
000" class=3D"m_3382430202751094859styled-by-prettify"> c1</span><span styl=
e=3D"color:#660" class=3D"m_3382430202751094859styled-by-prettify">;</span>=
<span style=3D"color:#000" class=3D"m_3382430202751094859styled-by-prettify=
"><br><br>=C2=A0</span><span style=3D"color:#008" class=3D"m_33824302027510=
94859styled-by-prettify">=C2=A0=C2=A0 return</span><span style=3D"color:#00=
0" class=3D"m_3382430202751094859styled-by-prettify"> </span><span style=3D=
"color:#066" class=3D"m_3382430202751094859styled-by-prettify">0</span><spa=
n style=3D"color:#660" class=3D"m_3382430202751094859styled-by-prettify">;<=
/span><span style=3D"color:#000" class=3D"m_3382430202751094859styled-by-pr=
ettify"><br></span><span style=3D"color:#660" class=3D"m_338243020275109485=
9styled-by-prettify">}</span><span class=3D"HOEnZb"><font color=3D"#888888"=
><span style=3D"color:#000" class=3D"m_3382430202751094859styled-by-prettif=
y"><br></span></font></span></div></code></div><span class=3D"HOEnZb"><font=
 color=3D"#888888"><br><br></font></span></div><span class=3D"HOEnZb"><font=
 color=3D"#888888">

<p></p>

-- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_=
blank">std-proposals+unsubscribe@<wbr>isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br>
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/62809333-fd1a-4bde-8805-ccc0578a4284%=
40isocpp.org?utm_medium=3Demail&amp;utm_source=3Dfooter" target=3D"_blank">=
https://groups.google.com/a/<wbr>isocpp.org/d/msgid/std-<wbr>proposals/6280=
9333-fd1a-4bde-<wbr>8805-ccc0578a4284%40isocpp.org</a><wbr>.<br>
</font></span></blockquote></div><br></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CALmDwq1BmvjJWdqiQOn8GJUrFKqtO6tGtTHN=
7NBqAOX8vVspog%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">htt=
ps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CALmDwq1BmvjJWdqi=
QOn8GJUrFKqtO6tGtTHN7NBqAOX8vVspog%40mail.gmail.com</a>.<br />

--000000000000193e760569b50c91--

.


Author: oguzakyuz@gmail.com
Date: Fri, 13 Apr 2018 00:24:32 -0700 (PDT)
Raw View
------=_Part_8050_1039716041.1523604272447
Content-Type: multipart/alternative;
 boundary="----=_Part_8051_799474595.1523604272449"

------=_Part_8051_799474595.1523604272449
Content-Type: text/plain; charset="UTF-8"

I remember reading in SO forums that letting the compiler take care of the
copy may allow for a more efficient implementation in certain cases. See
the following links:

  --
https://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa
  --
https://web.archive.org/web/20140113221447/http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/

What they say is that if you let the compiler do the copy, rather than
doing it yourself, the compiler may accomplish copy-elision instead of
pass-by-value. But now thinking about this more carefully, given that we
have a move-assignment operator, in a case where copy elision could have
happened (due to the actual parameter being an rvalue object), our
move-assignment operator would kick in avoiding the copy. So in the
presence of a move-assignment operator, doing the copy yourself or letting
the compiler do it for us would be equally efficient. Please correct me if
this reasoning is wrong.

Oguz

On Friday, April 13, 2018 at 9:33:18 AM UTC+3, Nicolas Lesser wrote:
>
> You can have the copy-swap idiom with an `operator=(const C&), I don't
> know why you think so otherwise.
>
> C& operator=(const C& rhs) {
>     C copy(rhs);
>     swap(copy, *this);
>     return *this;
> }
>
> This is essentially what your operator=(C) is doing, but just that the
> copy is now explicit instead of the compiler doing it for you.
>
> On Fri, Apr 13, 2018 at 8:11 AM, <oguz...@gmail.com <javascript:>> wrote:
>
>> Let me know if this is a stupid idea or something that is already
>> considered. But to my knowledge, if we have the following operator
>> overloads for a class, compilers will generate an ambiguity error (probably
>> enforced by the standard):
>>
>> C& C::operator=(C rhs);
>> C& C::operator=(C&& rhs);
>>
>> However, if the compilers could choose the rvalue reference version over the pass-by-value version for rvalue arguments (i.e. c2 = c1 + c1), it could lead to an efficient copy-swap idiom implementation.
>>
>> Below is a sample code that demonstrates the problem. The issue is explained by the long comment block inside the main function:
>>
>>
>> #include <algorithm>
>>
>> class C
>> {
>>     int* data;
>>
>>      public:
>>
>>      C() : data(nullptr) { }
>>
>>      C(int data) : data(new int)
>>      {
>>          *(this->data) = data;
>>      }
>>
>>      C(const C& rhs) : data(new int)
>>      {
>>          *data = *(rhs.data);
>>      }
>>
>>      C(C&& rhs) : C()
>>      {
>>          // Move constructor is first creating a default
>>          // object and swapping it with the rvalue reference.
>>          swap(*this, rhs);
>>      }
>>
>>      C& operator=(C rhs)
>>      {
>>          // We let the compiler copy into rhs and we swap the
>>          // current object with this copy. Together with the
>>          // move constructor above, this implements the copy-swap
>>          // idiom. Thanks to the move-constructor above, the
>>          // copy to rhs is not a deep copy if the input is an rvalue
>>          // reference.
>>          swap(*this, rhs);
>>          return *this;
>>      }
>>
>>      // The function below is commented out because it fails compilation
>>      // due to ambiguity with the above function. However, if it worked
>>      // it could have saved us an extra call to the move constructor when
>>      // we make calls such as c2 = c1 + c1 (see operator+ below). If it
>> had
>>      // worked, the temporary created from c1 + c1 would have been
>> directly
>>      // taken by rvalue reference instead of its copy  (albeit shallow)
>> being
>>      // created.
>>
>>      /*
>>      C& operator=(C&& rhs)
>>      {
>>          swap(*this, rhs);
>>          return *this;
>>      }
>>      */
>>
>>      C operator+(const C& rhs)
>>      {
>>          C result(*data + *(rhs.data));
>>          return result;
>>      }
>>
>>      friend void swap(C& lhs, C& rhs);
>>
>>      ~C()
>>      {
>>          delete data;
>>      }
>> };
>>
>> void swap(C& lhs, C& rhs)
>> {
>>     std::swap(lhs.data, rhs.data);
>> }
>>
>> int main()
>> {
>>     C c1(7);
>>     C c2;
>>
>>     // The following will first create the "result" inside operator+.
>>     // The return value will then get move-constructed from the result
>>     // (I'm assuming that -fno-elide-constructors option is used). Then
>>     // the "rhs" parameter of operator= will get move-constructed from
>>     // this return temporary.
>>     //
>>     // But if we could overload operator=(C&&), this second
>> move-construction
>>     // could have been avoided as the return temporary could have been
>> directly
>>     // captured by rvalue reference.
>>     //
>>     // Granted that we can implement operator=(const C&) and
>> operator=(C&&)
>>     // to make assignment as efficient as possible for both lvalue and
>> rvalue
>>     // inputs. However, to my knowledge, having operator=(const C&) would
>>     // essentially prevent us from having the copy-swap idiom.
>>
>>     c2 = c1 + c1;
>>
>>     return 0;
>> }
>>
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "ISO C++ Standard - Future Proposals" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to std-proposal...@isocpp.org <javascript:>.
>> To post to this group, send email to std-pr...@isocpp.org <javascript:>.
>> To view this discussion on the web visit
>> https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/62809333-fd1a-4bde-8805-ccc0578a4284%40isocpp.org
>> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/62809333-fd1a-4bde-8805-ccc0578a4284%40isocpp.org?utm_medium=email&utm_source=footer>
>> .
>>
>
>

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/0b576a51-27e6-49eb-851c-1d64bece5f64%40isocpp.org.

------=_Part_8051_799474595.1523604272449
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">I remember reading in SO forums that letting the compiler =
take care of the copy may allow for a more efficient implementation in cert=
ain cases. See the following links:<br><br>=C2=A0 --=C2=A0 https://stackove=
rflow.com/questions/3279543/what-is-the-copy-and-swap-idiom?utm_medium=3Dor=
ganic&amp;utm_source=3Dgoogle_rich_qa&amp;utm_campaign=3Dgoogle_rich_qa<br>=
=C2=A0 -- https://web.archive.org/web/20140113221447/http://cpp-next.com/ar=
chive/2009/08/want-speed-pass-by-value/<br><br>What they say is that if you=
 let the compiler do the copy, rather than doing it yourself, the compiler =
may accomplish copy-elision instead of pass-by-value. But now thinking abou=
t this more carefully, given that we have a move-assignment operator, in a =
case where copy elision could have happened (due to the actual parameter be=
ing an rvalue object), our move-assignment operator would kick in avoiding =
the copy. So in the presence of a move-assignment operator, doing the copy =
yourself or letting the compiler do it for us would be equally efficient. P=
lease correct me if this reasoning is wrong.<br><br>Oguz<br><br>On Friday, =
April 13, 2018 at 9:33:18 AM UTC+3, Nicolas Lesser wrote:<blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div dir=3D"ltr">You can have the copy-swap idi=
om with an `operator=3D(const C&amp;), I don&#39;t know why you think so ot=
herwise.<div><br></div><div>C&amp; operator=3D(const C&amp; rhs) {<br>=C2=
=A0 =C2=A0 C copy(rhs);</div><div>=C2=A0 =C2=A0 swap(copy, *this);</div><di=
v>=C2=A0 =C2=A0 return *this;</div><div>}</div><div><br></div><div>This is =
essentially what your operator=3D(C) is doing, but just that the copy is no=
w explicit instead of the compiler doing it for you.</div></div><div><br><d=
iv class=3D"gmail_quote">On Fri, Apr 13, 2018 at 8:11 AM,  <span dir=3D"ltr=
">&lt;<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"Gk=
TXtCqGCAAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D&#39;javascript:&#3=
9;;return true;" onclick=3D"this.href=3D&#39;javascript:&#39;;return true;"=
>oguz...@gmail.com</a>&gt;</span> wrote:<br><blockquote class=3D"gmail_quot=
e" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">=
<div dir=3D"ltr">Let me know if this is a stupid idea or something that is =
already considered. But to my knowledge, if we have the following operator =
overloads for a class, compilers will generate an ambiguity error (probably=
 enforced by the standard):<br><br><pre><code><span>C</span><span>&amp;</sp=
an><span> C::</span><span>operator</span><span>=3D(</span><span>C rhs</span=
><span>);<br></span></code><code><span>C</span><span>&amp;</span><span> C::=
</span><span>operator</span><span>=3D(</span><span>C&amp;&amp; rhs</span><s=
pan>);</span></code><br><br>However, if the compilers could choose the rval=
ue reference version over the pass-by-value version for rvalue arguments (i=
..e. c2 =3D c1 + c1), it could lead to an efficient copy-swap idiom implemen=
tation.<br><br>Below is a sample code that demonstrates the problem. The is=
sue is explained by the long comment block inside the main function:<br><co=
de><span></span></code></pre><br><div style=3D"background-color:rgb(250,250=
,250);border-color:rgb(187,187,187);border-style:solid;border-width:1px"><c=
ode><div><span style=3D"color:#000">#include &lt;algorithm&gt;<br><br></spa=
n><span style=3D"color:#008">class</span><span style=3D"color:#000"> C<br><=
/span><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=
=A0 =C2=A0 </span><span style=3D"color:#008">int</span><span style=3D"color=
:#660">*</span><span style=3D"color:#000"> data</span><span style=3D"color:=
#660">;</span><span style=3D"color:#000"><br><br>=C2=A0 =C2=A0 =C2=A0</span=
><span style=3D"color:#008">public</span><span style=3D"color:#660">:</span=
><span style=3D"color:#000"><br><br>=C2=A0 =C2=A0 =C2=A0C</span><span style=
=3D"color:#660">()</span><span style=3D"color:#000"> </span><span style=3D"=
color:#660">:</span><span style=3D"color:#000"> data</span><span style=3D"c=
olor:#660">(</span><span style=3D"color:#008">nullptr</span><span style=3D"=
color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"color=
:#660">{</span><span style=3D"color:#000"> </span><span style=3D"color:#660=
">}</span><span style=3D"color:#000"><br><br>=C2=A0 =C2=A0 =C2=A0C</span><s=
pan style=3D"color:#660">(</span><span style=3D"color:#008">int</span><span=
 style=3D"color:#000"> data</span><span style=3D"color:#660">)</span><span =
style=3D"color:#000"> </span><span style=3D"color:#660">:</span><span style=
=3D"color:#000"> data</span><span style=3D"color:#660">(</span><span style=
=3D"color:#008">new</span><span style=3D"color:#000"> </span><span style=3D=
"color:#008">int</span><span style=3D"color:#660">)</span><span style=3D"co=
lor:#000"><br>=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660">{</span=
><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><s=
pan style=3D"color:#660">*(</span><span style=3D"color:#008">this</span><sp=
an style=3D"color:#660">-&gt;</span><span style=3D"color:#000">data</span><=
span style=3D"color:#660">)</span><span style=3D"color:#000"> </span><span =
style=3D"color:#660">=3D</span><span style=3D"color:#000"> data</span><span=
 style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =
=C2=A0</span><span style=3D"color:#660">}</span><span style=3D"color:#000">=
<br><br>=C2=A0 =C2=A0 =C2=A0C</span><span style=3D"color:#660">(</span><spa=
n style=3D"color:#008">const</span><span style=3D"color:#000"> C</span><spa=
n style=3D"color:#660">&amp;</span><span style=3D"color:#000"> rhs</span><s=
pan style=3D"color:#660">)</span><span style=3D"color:#000"> </span><span s=
tyle=3D"color:#660">:</span><span style=3D"color:#000"> data</span><span st=
yle=3D"color:#660">(</span><span style=3D"color:#008">new</span><span style=
=3D"color:#000"> </span><span style=3D"color:#008">int</span><span style=3D=
"color:#660">)</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0</s=
pan><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660">*</span><s=
pan style=3D"color:#000">data </span><span style=3D"color:#660">=3D</span><=
span style=3D"color:#000"> </span><span style=3D"color:#660">*(</span><span=
 style=3D"color:#000">rhs</span><span style=3D"color:#660">.</span><span st=
yle=3D"color:#000">data</span><span style=3D"color:#660">);</span><span sty=
le=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660"=
>}</span><span style=3D"color:#000"><br><br>=C2=A0 =C2=A0 =C2=A0C</span><sp=
an style=3D"color:#660">(</span><span style=3D"color:#000">C</span><span st=
yle=3D"color:#660">&amp;&amp;</span><span style=3D"color:#000"> rhs</span><=
span style=3D"color:#660">)</span><span style=3D"color:#000"> </span><span =
style=3D"color:#660">:</span><span style=3D"color:#000"> C</span><span styl=
e=3D"color:#660">()</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=
=A0</span><span style=3D"color:#660">{</span><span style=3D"color:#000"><br=
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#800">// Mov=
e constructor is first creating a default</span><span style=3D"color:#000">=
<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#800">// =
object and swapping it with the rvalue reference.</span><span style=3D"colo=
r:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0swap</span><span style=3D"col=
or:#660">(*</span><span style=3D"color:#008">this</span><span style=3D"colo=
r:#660">,</span><span style=3D"color:#000"> rhs</span><span style=3D"color:=
#660">);</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0</span><s=
pan style=3D"color:#660">}</span><span style=3D"color:#000"><br><br>=C2=A0 =
=C2=A0 =C2=A0C</span><span style=3D"color:#660">&amp;</span><span style=3D"=
color:#000"> </span><span style=3D"color:#008">operator</span><span style=
=3D"color:#660">=3D(</span><span style=3D"color:#000">C rhs</span><span sty=
le=3D"color:#660">)</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=
=A0</span><span style=3D"color:#660">{</span><span style=3D"color:#000"><br=
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#800">// We =
let the compiler copy into rhs and we swap the</span><span style=3D"color:#=
000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#800=
">// current object with this copy. Together with the</span><span style=3D"=
color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"col=
or:#800">// move constructor above, this implements the copy-swap</span><sp=
an style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span =
style=3D"color:#800">// idiom. Thanks to the move-constructor above, the</s=
pan><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span=
><span style=3D"color:#800">// copy to rhs is not a deep copy if the input =
is an rvalue<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 // referen=
ce.</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=
swap</span><span style=3D"color:#660">(*</span><span style=3D"color:#008">t=
his</span><span style=3D"color:#660">,</span><span style=3D"color:#000"> rh=
s</span><span style=3D"color:#660">);</span><span style=3D"color:#000"><br>=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#008">return<=
/span><span style=3D"color:#000"> </span><span style=3D"color:#660">*</span=
><span style=3D"color:#008">this</span><span style=3D"color:#660">;</span><=
span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0</span><span style=3D"col=
or:#660">}</span><span style=3D"color:#000"><br><br></span>=C2=A0=C2=A0=C2=
=A0=C2=A0 // The function below is commented out because it fails compilati=
on<br>=C2=A0=C2=A0=C2=A0=C2=A0 // due to ambiguity with the above function.=
 However, if it worked<br>=C2=A0=C2=A0=C2=A0=C2=A0 // it could have saved u=
s an extra call to the move constructor when<br>=C2=A0=C2=A0=C2=A0=C2=A0 //=
 we make calls such as c2 =3D c1 + c1 (see operator+ below). If it had<br>=
=C2=A0=C2=A0=C2=A0=C2=A0 // worked, the temporary created from c1 + c1 woul=
d have been directly <br>=C2=A0=C2=A0=C2=A0=C2=A0 // taken by rvalue refere=
nce instead of its copy=C2=A0 (albeit shallow) being<br>=C2=A0=C2=A0=C2=A0=
=C2=A0 // created. <br>=C2=A0=C2=A0=C2=A0=C2=A0 <br>=C2=A0=C2=A0=C2=A0=C2=
=A0 /*<br><span style=3D"color:#000"><code><span style=3D"color:#000">=C2=
=A0=C2=A0=C2=A0=C2=A0 C</span><span style=3D"color:#660">&amp;</span><span =
style=3D"color:#000"> </span><span style=3D"color:#008">operator</span><spa=
n style=3D"color:#660">=3D(</span><span style=3D"color:#000">C&amp;&amp; rh=
s</span><span style=3D"color:#660">)</span><span style=3D"color:#000"><br>=
=C2=A0 =C2=A0=C2=A0 </span><span style=3D"color:#660">{</span><span style=
=3D"color:#000"></span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0swap</span><span style=3D"color:#660">(*</span><span style=3D"=
color:#008">this</span><span style=3D"color:#660">,</span><span style=3D"co=
lor:#000"> rhs</span><span style=3D"color:#660">);</span><span style=3D"col=
or:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:=
#008">return</span><span style=3D"color:#000"> </span><span style=3D"color:=
#660">*</span><span style=3D"color:#008">this</span><span style=3D"color:#6=
60">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0</span><span=
 style=3D"color:#660">}</span><span style=3D"color:#000"><br>=C2=A0=C2=A0=
=C2=A0=C2=A0 */<br></span></code><br>=C2=A0 =C2=A0 =C2=A0C </span><span sty=
le=3D"color:#008">operator</span><span style=3D"color:#660">+(</span><span =
style=3D"color:#008">const</span><span style=3D"color:#000"> C</span><span =
style=3D"color:#660">&amp;</span><span style=3D"color:#000"> rhs</span><spa=
n style=3D"color:#660">)</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0=
 =C2=A0</span><span style=3D"color:#660">{</span><span style=3D"color:#000"=
><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0C result</span><span style=3D"color:=
#660">(*</span><span style=3D"color:#000">data </span><span style=3D"color:=
#660">+</span><span style=3D"color:#000"> </span><span style=3D"color:#660"=
>*(</span><span style=3D"color:#000">rhs</span><span style=3D"color:#660">.=
</span><span style=3D"color:#000">data</span><span style=3D"color:#660">));=
</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</s=
pan><span style=3D"color:#008">return</span><span style=3D"color:#000"> res=
ult</span><span style=3D"color:#660">;</span><span style=3D"color:#000"><br=
>=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660">}</span><span style=
=3D"color:#000"><br><br>=C2=A0</span><span style=3D"color:#008">=C2=A0=C2=
=A0=C2=A0 friend</span><span style=3D"color:#000"> </span><span style=3D"co=
lor:#008">void</span><span style=3D"color:#000"> swap</span><span style=3D"=
color:#660">(</span><span style=3D"color:#000">C</span><span style=3D"color=
:#660">&amp;</span><span style=3D"color:#000"> lhs</span><span style=3D"col=
or:#660">,</span><span style=3D"color:#000"> C</span><span style=3D"color:#=
660">&amp;</span><span style=3D"color:#000"> rhs</span><span style=3D"color=
:#660">);</span><span style=3D"color:#000"><br><br>=C2=A0=C2=A0=C2=A0=C2=A0=
 </span><span style=3D"color:#660">~</span><span style=3D"color:#000">C</sp=
an><span style=3D"color:#660">()</span><span style=3D"color:#000"><br>=C2=
=A0</span><span style=3D"color:#660">=C2=A0=C2=A0=C2=A0 {</span><span style=
=3D"color:#000"><br>=C2=A0</span><span style=3D"color:#008">=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0 delete</span><span style=3D"color:#000"> data</=
span><span style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=
=A0=C2=A0=C2=A0=C2=A0 </span><span style=3D"color:#660">}</span><span style=
=3D"color:#000"><br></span><span style=3D"color:#660">};</span><span style=
=3D"color:#000"><br><br></span><span style=3D"color:#008">void</span><span =
style=3D"color:#000"> swap</span><span style=3D"color:#660">(</span><span s=
tyle=3D"color:#000">C</span><span style=3D"color:#660">&amp;</span><span st=
yle=3D"color:#000"> lhs</span><span style=3D"color:#660">,</span><span styl=
e=3D"color:#000"> C</span><span style=3D"color:#660">&amp;</span><span styl=
e=3D"color:#000"> rhs</span><span style=3D"color:#660">)</span><span style=
=3D"color:#000"><br></span><span style=3D"color:#660">{</span><span style=
=3D"color:#000"><br>=C2=A0=C2=A0=C2=A0 std</span><span style=3D"color:#660"=
>::</span><span style=3D"color:#000">swap</span><span style=3D"color:#660">=
(</span><span style=3D"color:#000">lhs</span><span style=3D"color:#660">.</=
span><span style=3D"color:#000">data</span><span style=3D"color:#660">,</sp=
an><span style=3D"color:#000"> rhs</span><span style=3D"color:#660">.</span=
><span style=3D"color:#000">data</span><span style=3D"color:#660">);</span>=
<span style=3D"color:#000"><br></span><span style=3D"color:#660">}</span><s=
pan style=3D"color:#000"><br><br></span><span style=3D"color:#008">int</spa=
n><span style=3D"color:#000"> main</span><span style=3D"color:#660">()</spa=
n><span style=3D"color:#000"><br></span><span style=3D"color:#660">{</span>=
<span style=3D"color:#000"><br>=C2=A0=C2=A0=C2=A0 C c1</span><span style=3D=
"color:#660">(</span><span style=3D"color:#066">7</span><span style=3D"colo=
r:#660">);</span><span style=3D"color:#000"><br>=C2=A0=C2=A0=C2=A0 C c2</sp=
an><span style=3D"color:#660">;</span><span style=3D"color:#000"></span><sp=
an style=3D"color:#000"><br><br>=C2=A0=C2=A0=C2=A0 // The following will fi=
rst create the &quot;result&quot; inside operator+.<br>=C2=A0 =C2=A0 // The=
 return value will then get move-constructed from the result<br>=C2=A0=C2=
=A0=C2=A0 // (I&#39;m assuming that -fno-elide-constructors option is used)=
.. Then<br>=C2=A0=C2=A0=C2=A0 // the &quot;rhs&quot; parameter of operator=
=3D will get move-constructed from<br>=C2=A0=C2=A0=C2=A0 // this return tem=
porary.<br>=C2=A0=C2=A0=C2=A0 //<br>=C2=A0=C2=A0=C2=A0 // But if we could o=
verload operator=3D(C&amp;&amp;), this second move-construction<br>=C2=A0=
=C2=A0=C2=A0 // could have been avoided as the return temporary could have =
been directly<br>=C2=A0=C2=A0=C2=A0 // captured by rvalue reference.<br>=C2=
=A0=C2=A0=C2=A0 //<br>=C2=A0=C2=A0=C2=A0 // Granted that we can implement o=
perator=3D(const C&amp;) and operator=3D(C&amp;&amp;)<br>=C2=A0=C2=A0=C2=A0=
 // to make assignment as efficient as possible for both lvalue and rvalue<=
br>=C2=A0=C2=A0=C2=A0 // inputs. However, to my knowledge, having operator=
=3D(const C&amp;) would<br>=C2=A0=C2=A0=C2=A0 // essentially prevent us fro=
m having the copy-swap idiom.<br><br>=C2=A0=C2=A0=C2=A0 c2 </span><span sty=
le=3D"color:#660">=3D</span><span style=3D"color:#000"> c1 </span><span sty=
le=3D"color:#660">+</span><span style=3D"color:#000"> c1</span><span style=
=3D"color:#660">;</span><span style=3D"color:#000"><br><br>=C2=A0</span><sp=
an style=3D"color:#008">=C2=A0=C2=A0 return</span><span style=3D"color:#000=
"> </span><span style=3D"color:#066">0</span><span style=3D"color:#660">;</=
span><span style=3D"color:#000"><br></span><span style=3D"color:#660">}</sp=
an><span><font color=3D"#888888"><span style=3D"color:#000"><br></span></fo=
nt></span></div></code></div><span><font color=3D"#888888"><br><br></font><=
/span></div><span><font color=3D"#888888">

<p></p>

-- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"=
GkTXtCqGCAAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D&#39;javascript:&=
#39;;return true;" onclick=3D"this.href=3D&#39;javascript:&#39;;return true=
;">std-proposal...@<wbr>isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"javascript:" target=3D"_bla=
nk" gdf-obfuscated-mailto=3D"GkTXtCqGCAAJ" rel=3D"nofollow" onmousedown=3D"=
this.href=3D&#39;javascript:&#39;;return true;" onclick=3D"this.href=3D&#39=
;javascript:&#39;;return true;">std-pr...@isocpp.org</a>.<br>
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/62809333-fd1a-4bde-8805-ccc0578a4284%=
40isocpp.org?utm_medium=3Demail&amp;utm_source=3Dfooter" target=3D"_blank" =
rel=3D"nofollow" onmousedown=3D"this.href=3D&#39;https://groups.google.com/=
a/isocpp.org/d/msgid/std-proposals/62809333-fd1a-4bde-8805-ccc0578a4284%40i=
socpp.org?utm_medium\x3demail\x26utm_source\x3dfooter&#39;;return true;" on=
click=3D"this.href=3D&#39;https://groups.google.com/a/isocpp.org/d/msgid/st=
d-proposals/62809333-fd1a-4bde-8805-ccc0578a4284%40isocpp.org?utm_medium\x3=
demail\x26utm_source\x3dfooter&#39;;return true;">https://groups.google.com=
/a/<wbr>isocpp.org/d/msgid/std-<wbr>proposals/62809333-fd1a-4bde-<wbr>8805-=
ccc0578a4284%40isocpp.org</a><wbr>.<br>
</font></span></blockquote></div><br></div>
</blockquote></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/0b576a51-27e6-49eb-851c-1d64bece5f64%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/0b576a51-27e6-49eb-851c-1d64bece5f64=
%40isocpp.org</a>.<br />

------=_Part_8051_799474595.1523604272449--

------=_Part_8050_1039716041.1523604272447--

.


Author: Nicolas Lesser <blitzrakete@gmail.com>
Date: Fri, 13 Apr 2018 11:11:39 +0200
Raw View
--0000000000008879b70569b7422e
Content-Type: text/plain; charset="UTF-8"

On Fri, Apr 13, 2018 at 9:24 AM, <oguzakyuz@gmail.com> wrote:

> I remember reading in SO forums that letting the compiler take care of the
> copy may allow for a more efficient implementation in certain cases. See
> the following links:
>
>   --  https://stackoverflow.com/questions/3279543/what-is-the-
> copy-and-swap-idiom?utm_medium=organic&utm_source=
> google_rich_qa&utm_campaign=google_rich_qa
>   -- https://web.archive.org/web/20140113221447/http://cpp-
> next.com/archive/2009/08/want-speed-pass-by-value/
>
> What they say is that if you let the compiler do the copy, rather than
> doing it yourself, the compiler may accomplish copy-elision instead of
> pass-by-value.
>
Jup, or a move. It'd do a copy in the worst copy.


> But now thinking about this more carefully, given that we have a
> move-assignment operator, in a case where copy elision could have happened
> (due to the actual parameter being an rvalue object), our move-assignment
> operator would kick in avoiding the copy.
>
Exactly.


> So in the presence of a move-assignment operator, doing the copy yourself
> or letting the compiler do it for us would be equally efficient. Please
> correct me if this reasoning is wrong.
>

Yes, as for rvalues your move assignment operator would get chosen instead
(that's the whole: avoiding copies for rvalues). Using pass-by-value gets
you the most efficient code possible if you don't want to write two
overloads of your operator=. (lvalue -> copy; xvalue -> move; prvalue ->
nothing).
But if you are using two overloads, there is no need to use pass-by-value,
because then you want to pass-by-ref which would be even better, but
because moves are generally cheap, the above pass-by-value is usually
sufficient. (lvalue -> copy; xvalue -> nothing; prvalue -> nothing).

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CALmDwq1657rC1d-0L-A9khGVhafOkpx99MVHxU%2BVcP8yswf%2B6w%40mail.gmail.com.

--0000000000008879b70569b7422e
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On F=
ri, Apr 13, 2018 at 9:24 AM,  <span dir=3D"ltr">&lt;<a href=3D"mailto:oguza=
kyuz@gmail.com" target=3D"_blank">oguzakyuz@gmail.com</a>&gt;</span> wrote:=
<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-lef=
t:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">I remember reading in S=
O forums that letting the compiler take care of the copy may allow for a mo=
re efficient implementation in certain cases. See the following links:<br><=
br>=C2=A0 --=C2=A0 <a href=3D"https://stackoverflow.com/questions/3279543/w=
hat-is-the-copy-and-swap-idiom?utm_medium=3Dorganic&amp;utm_source=3Dgoogle=
_rich_qa&amp;utm_campaign=3Dgoogle_rich_qa" target=3D"_blank">https://stack=
overflow.com/<wbr>questions/3279543/what-is-the-<wbr>copy-and-swap-idiom?ut=
m_<wbr>medium=3Dorganic&amp;utm_source=3D<wbr>google_rich_qa&amp;utm_campai=
gn=3D<wbr>google_rich_qa</a><br>=C2=A0 -- <a href=3D"https://web.archive.or=
g/web/20140113221447/http://cpp-next.com/archive/2009/08/want-speed-pass-by=
-value/" target=3D"_blank">https://web.archive.org/web/<wbr>20140113221447/=
http://cpp-<wbr>next.com/archive/2009/08/want-<wbr>speed-pass-by-value/</a>=
<br><br>What they say is that if you let the compiler do the copy, rather t=
han doing it yourself, the compiler may accomplish copy-elision instead of =
pass-by-value.</div></blockquote><div>Jup, or a move. It&#39;d do a copy in=
 the worst copy.</div><div>=C2=A0</div><blockquote class=3D"gmail_quote" st=
yle=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div =
dir=3D"ltr"> But now thinking about this more carefully, given that we have=
 a move-assignment operator, in a case where copy elision could have happen=
ed (due to the actual parameter being an rvalue object), our move-assignmen=
t operator would kick in avoiding the copy.</div></blockquote><div>Exactly.=
</div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0 =
0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">So i=
n the presence of a move-assignment operator, doing the copy yourself or le=
tting the compiler do it for us would be equally efficient. Please correct =
me if this reasoning is wrong.<br></div></blockquote><div><br></div><div>Ye=
s, as for rvalues your move assignment operator would get chosen instead (t=
hat&#39;s the whole: avoiding copies for rvalues). Using pass-by-value gets=
 you the most efficient code possible if you don&#39;t want to write two ov=
erloads of your operator=3D. (lvalue -&gt; copy; xvalue -&gt; move; prvalue=
 -&gt; nothing).</div><div>But if you are using two overloads, there is no =
need to use pass-by-value, because then you want to pass-by-ref which would=
 be even better, but because moves are generally cheap, the above pass-by-v=
alue is usually sufficient. (lvalue -&gt; copy; xvalue -&gt; nothing; prval=
ue -&gt; nothing).</div></div></div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CALmDwq1657rC1d-0L-A9khGVhafOkpx99MVH=
xU%2BVcP8yswf%2B6w%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter"=
>https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CALmDwq1657rC=
1d-0L-A9khGVhafOkpx99MVHxU%2BVcP8yswf%2B6w%40mail.gmail.com</a>.<br />

--0000000000008879b70569b7422e--

.


Author: Richard Hodges <hodges.r@gmail.com>
Date: Fri, 13 Apr 2018 12:04:44 +0100
Raw View
--000000000000f6d1820569b8d6eb
Content-Type: text/plain; charset="UTF-8"

On 13 April 2018 at 07:11, <oguzakyuz@gmail.com> wrote:

> Let me know if this is a stupid idea or something that is already
> considered. But to my knowledge, if we have the following operator
> overloads for a class, compilers will generate an ambiguity error (probably
> enforced by the standard):
>

Imagine an external function, foo:

extern void foo(Bar b);

*where foo is defined in an another compilation unit*.

That function is not expecting a reference, it is expecting a fully formed
Bar to exist in its arguments (i.e. for all intents and purposes 'on the
stack')

assume at the call site:

foo(Bar(arguments, of, bar));

A well behaved compiler will:
1. allocate space on the stack, in foo's argument stack frame
2. construct b right there on the stack.
3. assume that foo will destroy b.

In other words, copy elision will take place. The b belongs to foo. The
caller constructed it on foo's behalf.

Now consider:

extern void foo(Bar&& b);

The same compiler will:
1. allocate space on the stack, in the *caller's* stack frame
2. construct b right there on the stack.
3. pass the address of b to foo
4. call b's destructor upon foo's return

Now consider

extern void foo(Bar const& b);

The same compiler will:
1. allocate space on the stack, in the caller's stack frame
2. construct b right there on the stack.
3. pass the address of b to foo
4. call b's destructor upon foo's return

In the pass-by-reference cases the code incurs a cost of one extra
operation on the stack - pushing the address of b. The only difference in
the implementations is when the work of destruction is done. The same
amount of work is actually done.

The question is, do we mind about this minuscule extra cost?

If we absolutely do, then it's worth thinking about allowing the 3
overloads to coexist (this may be a can of worms?).

If we don't mind about the push, probably best to leave it alone.

That's my 2c.

Does that seem reasonable?



>
> C& C::operator=(C rhs);
> C& C::operator=(C&& rhs);
>
> However, if the compilers could choose the rvalue reference version over the pass-by-value version for rvalue arguments (i.e. c2 = c1 + c1), it could lead to an efficient copy-swap idiom implementation.
>
> Below is a sample code that demonstrates the problem. The issue is explained by the long comment block inside the main function:
>
>
> #include <algorithm>
>
> class C
> {
>     int* data;
>
>      public:
>
>      C() : data(nullptr) { }
>
>      C(int data) : data(new int)
>      {
>          *(this->data) = data;
>      }
>
>      C(const C& rhs) : data(new int)
>      {
>          *data = *(rhs.data);
>      }
>
>      C(C&& rhs) : C()
>      {
>          // Move constructor is first creating a default
>          // object and swapping it with the rvalue reference.
>          swap(*this, rhs);
>      }
>
>      C& operator=(C rhs)
>      {
>          // We let the compiler copy into rhs and we swap the
>          // current object with this copy. Together with the
>          // move constructor above, this implements the copy-swap
>          // idiom. Thanks to the move-constructor above, the
>          // copy to rhs is not a deep copy if the input is an rvalue
>          // reference.
>          swap(*this, rhs);
>          return *this;
>      }
>
>      // The function below is commented out because it fails compilation
>      // due to ambiguity with the above function. However, if it worked
>      // it could have saved us an extra call to the move constructor when
>      // we make calls such as c2 = c1 + c1 (see operator+ below). If it had
>      // worked, the temporary created from c1 + c1 would have been
> directly
>      // taken by rvalue reference instead of its copy  (albeit shallow)
> being
>      // created.
>
>      /*
>      C& operator=(C&& rhs)
>      {
>          swap(*this, rhs);
>          return *this;
>      }
>      */
>
>      C operator+(const C& rhs)
>      {
>          C result(*data + *(rhs.data));
>          return result;
>      }
>
>      friend void swap(C& lhs, C& rhs);
>
>      ~C()
>      {
>          delete data;
>      }
> };
>
> void swap(C& lhs, C& rhs)
> {
>     std::swap(lhs.data, rhs.data);
> }
>
> int main()
> {
>     C c1(7);
>     C c2;
>
>     // The following will first create the "result" inside operator+.
>     // The return value will then get move-constructed from the result
>     // (I'm assuming that -fno-elide-constructors option is used). Then
>     // the "rhs" parameter of operator= will get move-constructed from
>     // this return temporary.
>     //
>     // But if we could overload operator=(C&&), this second
> move-construction
>     // could have been avoided as the return temporary could have been
> directly
>     // captured by rvalue reference.
>     //
>     // Granted that we can implement operator=(const C&) and operator=(C&&)
>     // to make assignment as efficient as possible for both lvalue and
> rvalue
>     // inputs. However, to my knowledge, having operator=(const C&) would
>     // essentially prevent us from having the copy-swap idiom.
>
>     c2 = c1 + c1;
>
>     return 0;
> }
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> To view this discussion on the web visit https://groups.google.com/a/
> isocpp.org/d/msgid/std-proposals/62809333-fd1a-4bde-
> 8805-ccc0578a4284%40isocpp.org
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/62809333-fd1a-4bde-8805-ccc0578a4284%40isocpp.org?utm_medium=email&utm_source=footer>
> .
>

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CALvx3hak9T5xCsGQALwgw5dUq%2BE4SkcHfOJeWqJDfAML8PM1pA%40mail.gmail.com.

--000000000000f6d1820569b8d6eb
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On 13 April 2018 at 07:11,  <span dir=3D"ltr">&lt;<a href=3D"mailto:ogu=
zakyuz@gmail.com" target=3D"_blank">oguzakyuz@gmail.com</a>&gt;</span> wrot=
e:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-l=
eft:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">Let me know if this i=
s a stupid idea or something that is already considered. But to my knowledg=
e, if we have the following operator overloads for a class, compilers will =
generate an ambiguity error (probably enforced by the standard):<br></div><=
/blockquote><div><br></div><div>Imagine an external function, foo:<br></div=
><div><br></div><div><font face=3D"monospace, monospace">extern void foo(Ba=
r b);</font></div><div><br></div><div><b>where foo is defined in an another=
 compilation unit</b>.=C2=A0</div><div><br></div><div>That function is not =
expecting a reference, it is expecting a fully formed Bar to exist in its a=
rguments (i.e. for all intents and purposes &#39;on the stack&#39;)</div><d=
iv><br></div><div>assume at the call site:=C2=A0</div><div><br></div><div><=
font face=3D"monospace, monospace">foo(Bar(arguments, of, bar));</font></di=
v><div><br></div><div>A well behaved compiler will:</div><div>1. allocate s=
pace on the stack, in foo&#39;s argument stack frame</div><div>2. construct=
 b right there on the stack.</div><div>3. assume that foo will destroy b.</=
div><div><br></div><div>In other words, copy elision will take place. The b=
 belongs to foo. The caller constructed it on foo&#39;s behalf.</div><div><=
br></div><div>Now consider:</div><div><br></div><div><font face=3D"monospac=
e, monospace">extern void foo(Bar&amp;&amp; b);</font></div><div><br></div>=
<div>The same compiler will:</div><div><div style=3D"color:rgb(34,34,34);fo=
nt-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-l=
igatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:nor=
mal;text-align:start;text-indent:0px;text-transform:none;white-space:normal=
;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:i=
nitial;text-decoration-color:initial">1. allocate space on the stack, in th=
e <u>caller&#39;s</u> stack frame</div><div style=3D"color:rgb(34,34,34);fo=
nt-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-l=
igatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:nor=
mal;text-align:start;text-indent:0px;text-transform:none;white-space:normal=
;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:i=
nitial;text-decoration-color:initial">2. construct b right there on the sta=
ck.</div><div style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;fon=
t-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-c=
aps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-inde=
nt:0px;text-transform:none;white-space:normal;word-spacing:0px;background-c=
olor:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:i=
nitial">3. pass the address of b to foo</div><div style=3D"color:rgb(34,34,=
34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-var=
iant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spaci=
ng:normal;text-align:start;text-indent:0px;text-transform:none;white-space:=
normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-s=
tyle:initial;text-decoration-color:initial">4. call b&#39;s destructor upon=
 foo&#39;s return</div><div style=3D"color:rgb(34,34,34);font-family:arial,=
sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;=
font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:s=
tart;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0p=
x;background-color:rgb(255,255,255);text-decoration-style:initial;text-deco=
ration-color:initial"><br></div><div style=3D"color:rgb(34,34,34);font-size=
:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:no=
rmal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px=
;text-transform:none;white-space:normal;word-spacing:0px;background-color:r=
gb(255,255,255);text-decoration-style:initial;text-decoration-color:initial=
"><div style=3D"font-family:arial,sans-serif">Now consider</div><div style=
=3D"font-family:arial,sans-serif"><br></div><div style=3D""><font face=3D"m=
onospace, monospace">extern void foo(Bar const&amp; b);</font></div><div st=
yle=3D"font-family:arial,sans-serif"><br></div><div style=3D"font-family:ar=
ial,sans-serif">The same compiler will:</div><div style=3D"font-family:aria=
l,sans-serif"><div style=3D"color:rgb(34,34,34);font-family:arial,sans-seri=
f;font-size:small;font-style:normal;font-variant-ligatures:normal;font-vari=
ant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text=
-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-de=
coration-style:initial;text-decoration-color:initial;background-color:rgb(2=
55,255,255)">1. allocate space on the stack, in the caller&#39;s stack fram=
e</div><div style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-=
size:small;font-style:normal;font-variant-ligatures:normal;font-variant-cap=
s:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent=
:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoratio=
n-style:initial;text-decoration-color:initial;background-color:rgb(255,255,=
255)">2. construct b right there on the stack.</div><div style=3D"color:rgb=
(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;f=
ont-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;lette=
r-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white=
-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoratio=
n-color:initial;background-color:rgb(255,255,255)">3. pass the address of b=
 to foo</div><div style=3D"color:rgb(34,34,34);font-family:arial,sans-serif=
;font-size:small;font-style:normal;font-variant-ligatures:normal;font-varia=
nt-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-=
indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-dec=
oration-style:initial;text-decoration-color:initial;background-color:rgb(25=
5,255,255)">4. call b&#39;s destructor upon foo&#39;s return</div><br class=
=3D"gmail-Apple-interchange-newline"></div>In the pass-by-reference cases t=
he code incurs a cost of one extra operation on the stack - pushing the add=
ress of b. The only difference in the implementations is when the work of d=
estruction is done. The same amount of work is actually done.</div><div sty=
le=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font=
-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-w=
eight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-trans=
form:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,=
255);text-decoration-style:initial;text-decoration-color:initial"><br></div=
><div style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:s=
mall;font-style:normal;font-variant-ligatures:normal;font-variant-caps:norm=
al;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;t=
ext-transform:none;white-space:normal;word-spacing:0px;background-color:rgb=
(255,255,255);text-decoration-style:initial;text-decoration-color:initial">=
The question is, do we mind about this minuscule extra cost?</div><div styl=
e=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-=
style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-we=
ight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transf=
orm:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,2=
55);text-decoration-style:initial;text-decoration-color:initial"><br></div>=
<div style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:sm=
all;font-style:normal;font-variant-ligatures:normal;font-variant-caps:norma=
l;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;te=
xt-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(=
255,255,255);text-decoration-style:initial;text-decoration-color:initial">I=
f we absolutely do, then it&#39;s worth thinking about allowing the 3 overl=
oads to coexist (this may be a can of worms?).</div><div style=3D"color:rgb=
(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;f=
ont-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;lette=
r-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white=
-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decor=
ation-style:initial;text-decoration-color:initial"><br></div><div style=3D"=
color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style=
:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:=
400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:n=
one;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);t=
ext-decoration-style:initial;text-decoration-color:initial">If we don&#39;t=
 mind about the push, probably best to leave it alone.</div><div style=3D"c=
olor:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:=
normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:4=
00;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:no=
ne;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);te=
xt-decoration-style:initial;text-decoration-color:initial"><br></div><div s=
tyle=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;fo=
nt-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font=
-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-tra=
nsform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,25=
5,255);text-decoration-style:initial;text-decoration-color:initial">That&#3=
9;s my 2c.</div><br></div><div>Does that seem reasonable?</div><div><br></d=
iv><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0=
 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><br><pr=
e class=3D"m_-8606062210350549036lang-cpp m_-8606062210350549036prettyprint=
 m_-8606062210350549036prettyprinted"><code><span class=3D"m_-8606062210350=
549036pln">C</span><span class=3D"m_-8606062210350549036pun">&amp;</span><s=
pan class=3D"m_-8606062210350549036pln"> C::</span><span class=3D"m_-860606=
2210350549036kwd">operator</span><span class=3D"m_-8606062210350549036pun">=
=3D(</span><span class=3D"m_-8606062210350549036pln">C rhs</span><span clas=
s=3D"m_-8606062210350549036pun">);<br></span></code><code><span class=3D"m_=
-8606062210350549036pln">C</span><span class=3D"m_-8606062210350549036pun">=
&amp;</span><span class=3D"m_-8606062210350549036pln"> C::</span><span clas=
s=3D"m_-8606062210350549036kwd">operator</span><span class=3D"m_-8606062210=
350549036pun">=3D(</span><span class=3D"m_-8606062210350549036pln">C&amp;&a=
mp; rhs</span><span class=3D"m_-8606062210350549036pun">);</span></code><br=
><br>However, if the compilers could choose the rvalue reference version ov=
er the pass-by-value version for rvalue arguments (i.e. c2 =3D c1 + c1), it=
 could lead to an efficient copy-swap idiom implementation.<br><br>Below is=
 a sample code that demonstrates the problem. The issue is explained by the=
 long comment block inside the main function:<br><code><span class=3D"m_-86=
06062210350549036pun"></span></code></pre><br><div style=3D"background-colo=
r:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;border-=
width:1px" class=3D"m_-8606062210350549036prettyprint"><code class=3D"m_-86=
06062210350549036prettyprint"><div class=3D"m_-8606062210350549036subpretty=
print"><span style=3D"color:#000" class=3D"m_-8606062210350549036styled-by-=
prettify">#include &lt;algorithm&gt;<br><br></span><span style=3D"color:#00=
8" class=3D"m_-8606062210350549036styled-by-prettify">class</span><span sty=
le=3D"color:#000" class=3D"m_-8606062210350549036styled-by-prettify"> C<br>=
</span><span style=3D"color:#660" class=3D"m_-8606062210350549036styled-by-=
prettify">{</span><span style=3D"color:#000" class=3D"m_-860606221035054903=
6styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008" cl=
ass=3D"m_-8606062210350549036styled-by-prettify">int</span><span style=3D"c=
olor:#660" class=3D"m_-8606062210350549036styled-by-prettify">*</span><span=
 style=3D"color:#000" class=3D"m_-8606062210350549036styled-by-prettify"> d=
ata</span><span style=3D"color:#660" class=3D"m_-8606062210350549036styled-=
by-prettify">;</span><span style=3D"color:#000" class=3D"m_-860606221035054=
9036styled-by-prettify"><br><br>=C2=A0 =C2=A0 =C2=A0</span><span style=3D"c=
olor:#008" class=3D"m_-8606062210350549036styled-by-prettify">public</span>=
<span style=3D"color:#660" class=3D"m_-8606062210350549036styled-by-prettif=
y">:</span><span style=3D"color:#000" class=3D"m_-8606062210350549036styled=
-by-prettify"><br><br>=C2=A0 =C2=A0 =C2=A0C</span><span style=3D"color:#660=
" class=3D"m_-8606062210350549036styled-by-prettify">()</span><span style=
=3D"color:#000" class=3D"m_-8606062210350549036styled-by-prettify"> </span>=
<span style=3D"color:#660" class=3D"m_-8606062210350549036styled-by-prettif=
y">:</span><span style=3D"color:#000" class=3D"m_-8606062210350549036styled=
-by-prettify"> data</span><span style=3D"color:#660" class=3D"m_-8606062210=
350549036styled-by-prettify">(</span><span style=3D"color:#008" class=3D"m_=
-8606062210350549036styled-by-prettify">nullptr</span><span style=3D"color:=
#660" class=3D"m_-8606062210350549036styled-by-prettify">)</span><span styl=
e=3D"color:#000" class=3D"m_-8606062210350549036styled-by-prettify"> </span=
><span style=3D"color:#660" class=3D"m_-8606062210350549036styled-by-pretti=
fy">{</span><span style=3D"color:#000" class=3D"m_-8606062210350549036style=
d-by-prettify"> </span><span style=3D"color:#660" class=3D"m_-8606062210350=
549036styled-by-prettify">}</span><span style=3D"color:#000" class=3D"m_-86=
06062210350549036styled-by-prettify"><br><br>=C2=A0 =C2=A0 =C2=A0C</span><s=
pan style=3D"color:#660" class=3D"m_-8606062210350549036styled-by-prettify"=
>(</span><span style=3D"color:#008" class=3D"m_-8606062210350549036styled-b=
y-prettify">int</span><span style=3D"color:#000" class=3D"m_-86060622103505=
49036styled-by-prettify"> data</span><span style=3D"color:#660" class=3D"m_=
-8606062210350549036styled-by-prettify">)</span><span style=3D"color:#000" =
class=3D"m_-8606062210350549036styled-by-prettify"> </span><span style=3D"c=
olor:#660" class=3D"m_-8606062210350549036styled-by-prettify">:</span><span=
 style=3D"color:#000" class=3D"m_-8606062210350549036styled-by-prettify"> d=
ata</span><span style=3D"color:#660" class=3D"m_-8606062210350549036styled-=
by-prettify">(</span><span style=3D"color:#008" class=3D"m_-860606221035054=
9036styled-by-prettify">new</span><span style=3D"color:#000" class=3D"m_-86=
06062210350549036styled-by-prettify"> </span><span style=3D"color:#008" cla=
ss=3D"m_-8606062210350549036styled-by-prettify">int</span><span style=3D"co=
lor:#660" class=3D"m_-8606062210350549036styled-by-prettify">)</span><span =
style=3D"color:#000" class=3D"m_-8606062210350549036styled-by-prettify"><br=
>=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660" class=3D"m_-86060622=
10350549036styled-by-prettify">{</span><span style=3D"color:#000" class=3D"=
m_-8606062210350549036styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0</span><span style=3D"color:#660" class=3D"m_-8606062210350549036styl=
ed-by-prettify">*(</span><span style=3D"color:#008" class=3D"m_-86060622103=
50549036styled-by-prettify">this</span><span style=3D"color:#660" class=3D"=
m_-8606062210350549036styled-by-prettify">-&gt;</span><span style=3D"color:=
#000" class=3D"m_-8606062210350549036styled-by-prettify">data</span><span s=
tyle=3D"color:#660" class=3D"m_-8606062210350549036styled-by-prettify">)</s=
pan><span style=3D"color:#000" class=3D"m_-8606062210350549036styled-by-pre=
ttify"> </span><span style=3D"color:#660" class=3D"m_-8606062210350549036st=
yled-by-prettify">=3D</span><span style=3D"color:#000" class=3D"m_-86060622=
10350549036styled-by-prettify"> data</span><span style=3D"color:#660" class=
=3D"m_-8606062210350549036styled-by-prettify">;</span><span style=3D"color:=
#000" class=3D"m_-8606062210350549036styled-by-prettify"><br>=C2=A0 =C2=A0 =
=C2=A0</span><span style=3D"color:#660" class=3D"m_-8606062210350549036styl=
ed-by-prettify">}</span><span style=3D"color:#000" class=3D"m_-860606221035=
0549036styled-by-prettify"><br><br>=C2=A0 =C2=A0 =C2=A0C</span><span style=
=3D"color:#660" class=3D"m_-8606062210350549036styled-by-prettify">(</span>=
<span style=3D"color:#008" class=3D"m_-8606062210350549036styled-by-prettif=
y">const</span><span style=3D"color:#000" class=3D"m_-8606062210350549036st=
yled-by-prettify"> C</span><span style=3D"color:#660" class=3D"m_-860606221=
0350549036styled-by-prettify">&amp;</span><span style=3D"color:#000" class=
=3D"m_-8606062210350549036styled-by-prettify"> rhs</span><span style=3D"col=
or:#660" class=3D"m_-8606062210350549036styled-by-prettify">)</span><span s=
tyle=3D"color:#000" class=3D"m_-8606062210350549036styled-by-prettify"> </s=
pan><span style=3D"color:#660" class=3D"m_-8606062210350549036styled-by-pre=
ttify">:</span><span style=3D"color:#000" class=3D"m_-8606062210350549036st=
yled-by-prettify"> data</span><span style=3D"color:#660" class=3D"m_-860606=
2210350549036styled-by-prettify">(</span><span style=3D"color:#008" class=
=3D"m_-8606062210350549036styled-by-prettify">new</span><span style=3D"colo=
r:#000" class=3D"m_-8606062210350549036styled-by-prettify"> </span><span st=
yle=3D"color:#008" class=3D"m_-8606062210350549036styled-by-prettify">int</=
span><span style=3D"color:#660" class=3D"m_-8606062210350549036styled-by-pr=
ettify">)</span><span style=3D"color:#000" class=3D"m_-8606062210350549036s=
tyled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660=
" class=3D"m_-8606062210350549036styled-by-prettify">{</span><span style=3D=
"color:#000" class=3D"m_-8606062210350549036styled-by-prettify"><br>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660" class=3D"m_-86=
06062210350549036styled-by-prettify">*</span><span style=3D"color:#000" cla=
ss=3D"m_-8606062210350549036styled-by-prettify">data </span><span style=3D"=
color:#660" class=3D"m_-8606062210350549036styled-by-prettify">=3D</span><s=
pan style=3D"color:#000" class=3D"m_-8606062210350549036styled-by-prettify"=
> </span><span style=3D"color:#660" class=3D"m_-8606062210350549036styled-b=
y-prettify">*(</span><span style=3D"color:#000" class=3D"m_-860606221035054=
9036styled-by-prettify">rhs</span><span style=3D"color:#660" class=3D"m_-86=
06062210350549036styled-by-prettify">.</span><span style=3D"color:#000" cla=
ss=3D"m_-8606062210350549036styled-by-prettify">data</span><span style=3D"c=
olor:#660" class=3D"m_-8606062210350549036styled-by-prettify">);</span><spa=
n style=3D"color:#000" class=3D"m_-8606062210350549036styled-by-prettify"><=
br>=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660" class=3D"m_-860606=
2210350549036styled-by-prettify">}</span><span style=3D"color:#000" class=
=3D"m_-8606062210350549036styled-by-prettify"><br><br>=C2=A0 =C2=A0 =C2=A0C=
</span><span style=3D"color:#660" class=3D"m_-8606062210350549036styled-by-=
prettify">(</span><span style=3D"color:#000" class=3D"m_-860606221035054903=
6styled-by-prettify">C</span><span style=3D"color:#660" class=3D"m_-8606062=
210350549036styled-by-prettify">&amp;&amp;</span><span style=3D"color:#000"=
 class=3D"m_-8606062210350549036styled-by-prettify"> rhs</span><span style=
=3D"color:#660" class=3D"m_-8606062210350549036styled-by-prettify">)</span>=
<span style=3D"color:#000" class=3D"m_-8606062210350549036styled-by-prettif=
y"> </span><span style=3D"color:#660" class=3D"m_-8606062210350549036styled=
-by-prettify">:</span><span style=3D"color:#000" class=3D"m_-86060622103505=
49036styled-by-prettify"> C</span><span style=3D"color:#660" class=3D"m_-86=
06062210350549036styled-by-prettify">()</span><span style=3D"color:#000" cl=
ass=3D"m_-8606062210350549036styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0</=
span><span style=3D"color:#660" class=3D"m_-8606062210350549036styled-by-pr=
ettify">{</span><span style=3D"color:#000" class=3D"m_-8606062210350549036s=
tyled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=
=3D"color:#800" class=3D"m_-8606062210350549036styled-by-prettify">// Move =
constructor is first creating a default</span><span style=3D"color:#000" cl=
ass=3D"m_-8606062210350549036styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0</span><span style=3D"color:#800" class=3D"m_-8606062210350549=
036styled-by-prettify">// object and swapping it with the rvalue reference.=
</span><span style=3D"color:#000" class=3D"m_-8606062210350549036styled-by-=
prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0swap</span><span style=3D"c=
olor:#660" class=3D"m_-8606062210350549036styled-by-prettify">(*</span><spa=
n style=3D"color:#008" class=3D"m_-8606062210350549036styled-by-prettify">t=
his</span><span style=3D"color:#660" class=3D"m_-8606062210350549036styled-=
by-prettify">,</span><span style=3D"color:#000" class=3D"m_-860606221035054=
9036styled-by-prettify"> rhs</span><span style=3D"color:#660" class=3D"m_-8=
606062210350549036styled-by-prettify">);</span><span style=3D"color:#000" c=
lass=3D"m_-8606062210350549036styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0<=
/span><span style=3D"color:#660" class=3D"m_-8606062210350549036styled-by-p=
rettify">}</span><span style=3D"color:#000" class=3D"m_-8606062210350549036=
styled-by-prettify"><br><br>=C2=A0 =C2=A0 =C2=A0C</span><span style=3D"colo=
r:#660" class=3D"m_-8606062210350549036styled-by-prettify">&amp;</span><spa=
n style=3D"color:#000" class=3D"m_-8606062210350549036styled-by-prettify"> =
</span><span style=3D"color:#008" class=3D"m_-8606062210350549036styled-by-=
prettify">operator</span><span style=3D"color:#660" class=3D"m_-86060622103=
50549036styled-by-prettify">=3D(</span><span style=3D"color:#000" class=3D"=
m_-8606062210350549036styled-by-prettify">C rhs</span><span style=3D"color:=
#660" class=3D"m_-8606062210350549036styled-by-prettify">)</span><span styl=
e=3D"color:#000" class=3D"m_-8606062210350549036styled-by-prettify"><br>=C2=
=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660" class=3D"m_-860606221035=
0549036styled-by-prettify">{</span><span style=3D"color:#000" class=3D"m_-8=
606062210350549036styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0</span><span style=3D"color:#800" class=3D"m_-8606062210350549036styled-=
by-prettify">// We let the compiler copy into rhs and we swap the</span><sp=
an style=3D"color:#000" class=3D"m_-8606062210350549036styled-by-prettify">=
<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#800" cla=
ss=3D"m_-8606062210350549036styled-by-prettify">// current object with this=
 copy. Together with the</span><span style=3D"color:#000" class=3D"m_-86060=
62210350549036styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</s=
pan><span style=3D"color:#800" class=3D"m_-8606062210350549036styled-by-pre=
ttify">// move constructor above, this implements the copy-swap</span><span=
 style=3D"color:#000" class=3D"m_-8606062210350549036styled-by-prettify"><b=
r>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#800" class=
=3D"m_-8606062210350549036styled-by-prettify">// idiom. Thanks to the move-=
constructor above, the</span><span style=3D"color:#000" class=3D"m_-8606062=
210350549036styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</spa=
n><span style=3D"color:#800" class=3D"m_-8606062210350549036styled-by-prett=
ify">// copy to rhs is not a deep copy if the input is an rvalue<br>=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 // reference.</span><span style=
=3D"color:#000" class=3D"m_-8606062210350549036styled-by-prettify"><br>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0swap</span><span style=3D"color:#660" class=
=3D"m_-8606062210350549036styled-by-prettify">(*</span><span style=3D"color=
:#008" class=3D"m_-8606062210350549036styled-by-prettify">this</span><span =
style=3D"color:#660" class=3D"m_-8606062210350549036styled-by-prettify">,</=
span><span style=3D"color:#000" class=3D"m_-8606062210350549036styled-by-pr=
ettify"> rhs</span><span style=3D"color:#660" class=3D"m_-86060622103505490=
36styled-by-prettify">);</span><span style=3D"color:#000" class=3D"m_-86060=
62210350549036styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</s=
pan><span style=3D"color:#008" class=3D"m_-8606062210350549036styled-by-pre=
ttify">return</span><span style=3D"color:#000" class=3D"m_-8606062210350549=
036styled-by-prettify"> </span><span style=3D"color:#660" class=3D"m_-86060=
62210350549036styled-by-prettify">*</span><span style=3D"color:#008" class=
=3D"m_-8606062210350549036styled-by-prettify">this</span><span style=3D"col=
or:#660" class=3D"m_-8606062210350549036styled-by-prettify">;</span><span s=
tyle=3D"color:#000" class=3D"m_-8606062210350549036styled-by-prettify"><br>=
=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660" class=3D"m_-860606221=
0350549036styled-by-prettify">}</span><span style=3D"color:#000" class=3D"m=
_-8606062210350549036styled-by-prettify"><br><br></span>=C2=A0=C2=A0=C2=A0=
=C2=A0 // The function below is commented out because it fails compilation<=
br>=C2=A0=C2=A0=C2=A0=C2=A0 // due to ambiguity with the above function. Ho=
wever, if it worked<br>=C2=A0=C2=A0=C2=A0=C2=A0 // it could have saved us a=
n extra call to the move constructor when<br>=C2=A0=C2=A0=C2=A0=C2=A0 // we=
 make calls such as c2 =3D c1 + c1 (see operator+ below). If it had<br>=C2=
=A0=C2=A0=C2=A0=C2=A0 // worked, the temporary created from c1 + c1 would h=
ave been directly <br>=C2=A0=C2=A0=C2=A0=C2=A0 // taken by rvalue reference=
 instead of its copy=C2=A0 (albeit shallow) being<br>=C2=A0=C2=A0=C2=A0=C2=
=A0 // created. <br>=C2=A0=C2=A0=C2=A0=C2=A0 <br>=C2=A0=C2=A0=C2=A0=C2=A0 /=
*<br><span style=3D"color:#000" class=3D"m_-8606062210350549036styled-by-pr=
ettify"><code class=3D"m_-8606062210350549036prettyprint"><span style=3D"co=
lor:#000" class=3D"m_-8606062210350549036styled-by-prettify">=C2=A0=C2=A0=
=C2=A0=C2=A0 C</span><span style=3D"color:#660" class=3D"m_-860606221035054=
9036styled-by-prettify">&amp;</span><span style=3D"color:#000" class=3D"m_-=
8606062210350549036styled-by-prettify"> </span><span style=3D"color:#008" c=
lass=3D"m_-8606062210350549036styled-by-prettify">operator</span><span styl=
e=3D"color:#660" class=3D"m_-8606062210350549036styled-by-prettify">=3D(</s=
pan><span style=3D"color:#000" class=3D"m_-8606062210350549036styled-by-pre=
ttify">C&amp;&amp; rhs</span><span style=3D"color:#660" class=3D"m_-8606062=
210350549036styled-by-prettify">)</span><span style=3D"color:#000" class=3D=
"m_-8606062210350549036styled-by-prettify"><br>=C2=A0 =C2=A0=C2=A0 </span><=
span style=3D"color:#660" class=3D"m_-8606062210350549036styled-by-prettify=
">{</span><span style=3D"color:#000" class=3D"m_-8606062210350549036styled-=
by-prettify"></span><span style=3D"color:#000" class=3D"m_-8606062210350549=
036styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0swap</span><sp=
an style=3D"color:#660" class=3D"m_-8606062210350549036styled-by-prettify">=
(*</span><span style=3D"color:#008" class=3D"m_-8606062210350549036styled-b=
y-prettify">this</span><span style=3D"color:#660" class=3D"m_-8606062210350=
549036styled-by-prettify">,</span><span style=3D"color:#000" class=3D"m_-86=
06062210350549036styled-by-prettify"> rhs</span><span style=3D"color:#660" =
class=3D"m_-8606062210350549036styled-by-prettify">);</span><span style=3D"=
color:#000" class=3D"m_-8606062210350549036styled-by-prettify"><br>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#008" class=3D"m_-86=
06062210350549036styled-by-prettify">return</span><span style=3D"color:#000=
" class=3D"m_-8606062210350549036styled-by-prettify"> </span><span style=3D=
"color:#660" class=3D"m_-8606062210350549036styled-by-prettify">*</span><sp=
an style=3D"color:#008" class=3D"m_-8606062210350549036styled-by-prettify">=
this</span><span style=3D"color:#660" class=3D"m_-8606062210350549036styled=
-by-prettify">;</span><span style=3D"color:#000" class=3D"m_-86060622103505=
49036styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0</span><span style=3D"colo=
r:#660" class=3D"m_-8606062210350549036styled-by-prettify">}</span><span st=
yle=3D"color:#000" class=3D"m_-8606062210350549036styled-by-prettify"><br>=
=C2=A0=C2=A0=C2=A0=C2=A0 */<br></span></code><br>=C2=A0 =C2=A0 =C2=A0C </sp=
an><span style=3D"color:#008" class=3D"m_-8606062210350549036styled-by-pret=
tify">operator</span><span style=3D"color:#660" class=3D"m_-860606221035054=
9036styled-by-prettify">+(</span><span style=3D"color:#008" class=3D"m_-860=
6062210350549036styled-by-prettify">const</span><span style=3D"color:#000" =
class=3D"m_-8606062210350549036styled-by-prettify"> C</span><span style=3D"=
color:#660" class=3D"m_-8606062210350549036styled-by-prettify">&amp;</span>=
<span style=3D"color:#000" class=3D"m_-8606062210350549036styled-by-prettif=
y"> rhs</span><span style=3D"color:#660" class=3D"m_-8606062210350549036sty=
led-by-prettify">)</span><span style=3D"color:#000" class=3D"m_-86060622103=
50549036styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0</span><span style=3D"c=
olor:#660" class=3D"m_-8606062210350549036styled-by-prettify">{</span><span=
 style=3D"color:#000" class=3D"m_-8606062210350549036styled-by-prettify"><b=
r>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0C result</span><span style=3D"color:#66=
0" class=3D"m_-8606062210350549036styled-by-prettify">(*</span><span style=
=3D"color:#000" class=3D"m_-8606062210350549036styled-by-prettify">data </s=
pan><span style=3D"color:#660" class=3D"m_-8606062210350549036styled-by-pre=
ttify">+</span><span style=3D"color:#000" class=3D"m_-8606062210350549036st=
yled-by-prettify"> </span><span style=3D"color:#660" class=3D"m_-8606062210=
350549036styled-by-prettify">*(</span><span style=3D"color:#000" class=3D"m=
_-8606062210350549036styled-by-prettify">rhs</span><span style=3D"color:#66=
0" class=3D"m_-8606062210350549036styled-by-prettify">.</span><span style=
=3D"color:#000" class=3D"m_-8606062210350549036styled-by-prettify">data</sp=
an><span style=3D"color:#660" class=3D"m_-8606062210350549036styled-by-pret=
tify">));</span><span style=3D"color:#000" class=3D"m_-8606062210350549036s=
tyled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=
=3D"color:#008" class=3D"m_-8606062210350549036styled-by-prettify">return</=
span><span style=3D"color:#000" class=3D"m_-8606062210350549036styled-by-pr=
ettify"> result</span><span style=3D"color:#660" class=3D"m_-86060622103505=
49036styled-by-prettify">;</span><span style=3D"color:#000" class=3D"m_-860=
6062210350549036styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0</span><span st=
yle=3D"color:#660" class=3D"m_-8606062210350549036styled-by-prettify">}</sp=
an><span style=3D"color:#000" class=3D"m_-8606062210350549036styled-by-pret=
tify"><br><br>=C2=A0</span><span style=3D"color:#008" class=3D"m_-860606221=
0350549036styled-by-prettify">=C2=A0=C2=A0=C2=A0 friend</span><span style=
=3D"color:#000" class=3D"m_-8606062210350549036styled-by-prettify"> </span>=
<span style=3D"color:#008" class=3D"m_-8606062210350549036styled-by-prettif=
y">void</span><span style=3D"color:#000" class=3D"m_-8606062210350549036sty=
led-by-prettify"> swap</span><span style=3D"color:#660" class=3D"m_-8606062=
210350549036styled-by-prettify">(</span><span style=3D"color:#000" class=3D=
"m_-8606062210350549036styled-by-prettify">C</span><span style=3D"color:#66=
0" class=3D"m_-8606062210350549036styled-by-prettify">&amp;</span><span sty=
le=3D"color:#000" class=3D"m_-8606062210350549036styled-by-prettify"> lhs</=
span><span style=3D"color:#660" class=3D"m_-8606062210350549036styled-by-pr=
ettify">,</span><span style=3D"color:#000" class=3D"m_-8606062210350549036s=
tyled-by-prettify"> C</span><span style=3D"color:#660" class=3D"m_-86060622=
10350549036styled-by-prettify">&amp;</span><span style=3D"color:#000" class=
=3D"m_-8606062210350549036styled-by-prettify"> rhs</span><span style=3D"col=
or:#660" class=3D"m_-8606062210350549036styled-by-prettify">);</span><span =
style=3D"color:#000" class=3D"m_-8606062210350549036styled-by-prettify"><br=
><br>=C2=A0=C2=A0=C2=A0=C2=A0 </span><span style=3D"color:#660" class=3D"m_=
-8606062210350549036styled-by-prettify">~</span><span style=3D"color:#000" =
class=3D"m_-8606062210350549036styled-by-prettify">C</span><span style=3D"c=
olor:#660" class=3D"m_-8606062210350549036styled-by-prettify">()</span><spa=
n style=3D"color:#000" class=3D"m_-8606062210350549036styled-by-prettify"><=
br>=C2=A0</span><span style=3D"color:#660" class=3D"m_-8606062210350549036s=
tyled-by-prettify">=C2=A0=C2=A0=C2=A0 {</span><span style=3D"color:#000" cl=
ass=3D"m_-8606062210350549036styled-by-prettify"><br>=C2=A0</span><span sty=
le=3D"color:#008" class=3D"m_-8606062210350549036styled-by-prettify">=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 delete</span><span style=3D"color:#000=
" class=3D"m_-8606062210350549036styled-by-prettify"> data</span><span styl=
e=3D"color:#660" class=3D"m_-8606062210350549036styled-by-prettify">;</span=
><span style=3D"color:#000" class=3D"m_-8606062210350549036styled-by-pretti=
fy"><br>=C2=A0=C2=A0=C2=A0=C2=A0 </span><span style=3D"color:#660" class=3D=
"m_-8606062210350549036styled-by-prettify">}</span><span style=3D"color:#00=
0" class=3D"m_-8606062210350549036styled-by-prettify"><br></span><span styl=
e=3D"color:#660" class=3D"m_-8606062210350549036styled-by-prettify">};</spa=
n><span style=3D"color:#000" class=3D"m_-8606062210350549036styled-by-prett=
ify"><br><br></span><span style=3D"color:#008" class=3D"m_-8606062210350549=
036styled-by-prettify">void</span><span style=3D"color:#000" class=3D"m_-86=
06062210350549036styled-by-prettify"> swap</span><span style=3D"color:#660"=
 class=3D"m_-8606062210350549036styled-by-prettify">(</span><span style=3D"=
color:#000" class=3D"m_-8606062210350549036styled-by-prettify">C</span><spa=
n style=3D"color:#660" class=3D"m_-8606062210350549036styled-by-prettify">&=
amp;</span><span style=3D"color:#000" class=3D"m_-8606062210350549036styled=
-by-prettify"> lhs</span><span style=3D"color:#660" class=3D"m_-86060622103=
50549036styled-by-prettify">,</span><span style=3D"color:#000" class=3D"m_-=
8606062210350549036styled-by-prettify"> C</span><span style=3D"color:#660" =
class=3D"m_-8606062210350549036styled-by-prettify">&amp;</span><span style=
=3D"color:#000" class=3D"m_-8606062210350549036styled-by-prettify"> rhs</sp=
an><span style=3D"color:#660" class=3D"m_-8606062210350549036styled-by-pret=
tify">)</span><span style=3D"color:#000" class=3D"m_-8606062210350549036sty=
led-by-prettify"><br></span><span style=3D"color:#660" class=3D"m_-86060622=
10350549036styled-by-prettify">{</span><span style=3D"color:#000" class=3D"=
m_-8606062210350549036styled-by-prettify"><br>=C2=A0=C2=A0=C2=A0 std</span>=
<span style=3D"color:#660" class=3D"m_-8606062210350549036styled-by-prettif=
y">::</span><span style=3D"color:#000" class=3D"m_-8606062210350549036style=
d-by-prettify">swap</span><span style=3D"color:#660" class=3D"m_-8606062210=
350549036styled-by-prettify">(</span><span style=3D"color:#000" class=3D"m_=
-8606062210350549036styled-by-prettify">lhs</span><span style=3D"color:#660=
" class=3D"m_-8606062210350549036styled-by-prettify">.</span><span style=3D=
"color:#000" class=3D"m_-8606062210350549036styled-by-prettify">data</span>=
<span style=3D"color:#660" class=3D"m_-8606062210350549036styled-by-prettif=
y">,</span><span style=3D"color:#000" class=3D"m_-8606062210350549036styled=
-by-prettify"> rhs</span><span style=3D"color:#660" class=3D"m_-86060622103=
50549036styled-by-prettify">.</span><span style=3D"color:#000" class=3D"m_-=
8606062210350549036styled-by-prettify">data</span><span style=3D"color:#660=
" class=3D"m_-8606062210350549036styled-by-prettify">);</span><span style=
=3D"color:#000" class=3D"m_-8606062210350549036styled-by-prettify"><br></sp=
an><span style=3D"color:#660" class=3D"m_-8606062210350549036styled-by-pret=
tify">}</span><span style=3D"color:#000" class=3D"m_-8606062210350549036sty=
led-by-prettify"><br><br></span><span style=3D"color:#008" class=3D"m_-8606=
062210350549036styled-by-prettify">int</span><span style=3D"color:#000" cla=
ss=3D"m_-8606062210350549036styled-by-prettify"> main</span><span style=3D"=
color:#660" class=3D"m_-8606062210350549036styled-by-prettify">()</span><sp=
an style=3D"color:#000" class=3D"m_-8606062210350549036styled-by-prettify">=
<br></span><span style=3D"color:#660" class=3D"m_-8606062210350549036styled=
-by-prettify">{</span><span style=3D"color:#000" class=3D"m_-86060622103505=
49036styled-by-prettify"><br>=C2=A0=C2=A0=C2=A0 C c1</span><span style=3D"c=
olor:#660" class=3D"m_-8606062210350549036styled-by-prettify">(</span><span=
 style=3D"color:#066" class=3D"m_-8606062210350549036styled-by-prettify">7<=
/span><span style=3D"color:#660" class=3D"m_-8606062210350549036styled-by-p=
rettify">);</span><span style=3D"color:#000" class=3D"m_-860606221035054903=
6styled-by-prettify"><br>=C2=A0=C2=A0=C2=A0 C c2</span><span style=3D"color=
:#660" class=3D"m_-8606062210350549036styled-by-prettify">;</span><span sty=
le=3D"color:#000" class=3D"m_-8606062210350549036styled-by-prettify"></span=
><span style=3D"color:#000" class=3D"m_-8606062210350549036styled-by-pretti=
fy"><br><br>=C2=A0=C2=A0=C2=A0 // The following will first create the &quot=
;result&quot; inside operator+.<br>=C2=A0 =C2=A0 // The return value will t=
hen get move-constructed from the result<br>=C2=A0=C2=A0=C2=A0 // (I&#39;m =
assuming that -fno-elide-constructors option is used). Then<br>=C2=A0=C2=A0=
=C2=A0 // the &quot;rhs&quot; parameter of operator=3D will get move-constr=
ucted from<br>=C2=A0=C2=A0=C2=A0 // this return temporary.<br>=C2=A0=C2=A0=
=C2=A0 //<br>=C2=A0=C2=A0=C2=A0 // But if we could overload operator=3D(C&a=
mp;&amp;), this second move-construction<br>=C2=A0=C2=A0=C2=A0 // could hav=
e been avoided as the return temporary could have been directly<br>=C2=A0=
=C2=A0=C2=A0 // captured by rvalue reference.<br>=C2=A0=C2=A0=C2=A0 //<br>=
=C2=A0=C2=A0=C2=A0 // Granted that we can implement operator=3D(const C&amp=
;) and operator=3D(C&amp;&amp;)<br>=C2=A0=C2=A0=C2=A0 // to make assignment=
 as efficient as possible for both lvalue and rvalue<br>=C2=A0=C2=A0=C2=A0 =
// inputs. However, to my knowledge, having operator=3D(const C&amp;) would=
<br>=C2=A0=C2=A0=C2=A0 // essentially prevent us from having the copy-swap =
idiom.<br><br>=C2=A0=C2=A0=C2=A0 c2 </span><span style=3D"color:#660" class=
=3D"m_-8606062210350549036styled-by-prettify">=3D</span><span style=3D"colo=
r:#000" class=3D"m_-8606062210350549036styled-by-prettify"> c1 </span><span=
 style=3D"color:#660" class=3D"m_-8606062210350549036styled-by-prettify">+<=
/span><span style=3D"color:#000" class=3D"m_-8606062210350549036styled-by-p=
rettify"> c1</span><span style=3D"color:#660" class=3D"m_-86060622103505490=
36styled-by-prettify">;</span><span style=3D"color:#000" class=3D"m_-860606=
2210350549036styled-by-prettify"><br><br>=C2=A0</span><span style=3D"color:=
#008" class=3D"m_-8606062210350549036styled-by-prettify">=C2=A0=C2=A0 retur=
n</span><span style=3D"color:#000" class=3D"m_-8606062210350549036styled-by=
-prettify"> </span><span style=3D"color:#066" class=3D"m_-86060622103505490=
36styled-by-prettify">0</span><span style=3D"color:#660" class=3D"m_-860606=
2210350549036styled-by-prettify">;</span><span style=3D"color:#000" class=
=3D"m_-8606062210350549036styled-by-prettify"><br></span><span style=3D"col=
or:#660" class=3D"m_-8606062210350549036styled-by-prettify">}</span><span c=
lass=3D"HOEnZb"><font color=3D"#888888"><span style=3D"color:#000" class=3D=
"m_-8606062210350549036styled-by-prettify"><br></span></font></span></div><=
/code></div><span class=3D"HOEnZb"><font color=3D"#888888"><br><br></font><=
/span></div><span class=3D"HOEnZb"><font color=3D"#888888">

<p></p>

-- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_=
blank">std-proposals+unsubscribe@<wbr>isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br>
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/62809333-fd1a-4bde-8805-ccc0578a4284%=
40isocpp.org?utm_medium=3Demail&amp;utm_source=3Dfooter" target=3D"_blank">=
https://groups.google.com/a/<wbr>isocpp.org/d/msgid/std-<wbr>proposals/6280=
9333-fd1a-4bde-<wbr>8805-ccc0578a4284%40isocpp.org</a><wbr>.<br>
</font></span></blockquote></div><br></div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/CALvx3hak9T5xCsGQALwgw5dUq%2BE4SkcHfO=
JeWqJDfAML8PM1pA%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">h=
ttps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CALvx3hak9T5xCs=
GQALwgw5dUq%2BE4SkcHfOJeWqJDfAML8PM1pA%40mail.gmail.com</a>.<br />

--000000000000f6d1820569b8d6eb--

.


Author: florian.csdt@gmail.com
Date: Fri, 13 Apr 2018 04:49:50 -0700 (PDT)
Raw View
------=_Part_8515_1758379965.1523620190255
Content-Type: multipart/alternative;
 boundary="----=_Part_8516_1646849856.1523620190256"

------=_Part_8516_1646849856.1523620190256
Content-Type: text/plain; charset="UTF-8"

In my experience, values are much easier to deal with, especially when you
want to return them.
Consider a simple operator+

If you want to use references and optimize for rvalues, you do:
struct Foo {
  Foo& operator+=(const Foo&);
};
Foo operator+(const Foo& a, const Foo& b) { Foo R; R += a ; return R; }
Foo&& operator+(Foo&& a, const Foo& b) { a += b; return std::move(a); }
Foo&& operator+(const Foo& a, Foo&& b) { return std::move(b) + a; }
Foo&& operator+(Foo&& a, Foo&& b) { return std::move(a) + b; }
And if you do that, you might end up with dangling references in few cases.

If you do the same with passing by value:
struct Foo {
  Foo& operator+=(const Foo&); // unchanged
};
Foo operator+(Foo a, Foo b) { a += b; return a; }
The code here is much simpler, you cannot have dangling references, and in
most cases it is at least as optimized as the reference implementation (but
no guarantee by the language, I think).
(maybe you still need to take the second argument as a reference though...)

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/d68aa110-1d00-48ac-89a8-03f0079079d1%40isocpp.org.

------=_Part_8516_1646849856.1523620190256
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">In my experience, values are much easier to deal with, esp=
ecially when you want to return them.<br>Consider a simple operator+<br><br=
>If you want to use references and optimize for rvalues, you do:<br><div st=
yle=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 187, 18=
7); border-style: solid; border-width: 1px; overflow-wrap: break-word;" cla=
ss=3D"prettyprint"><code class=3D"prettyprint"><div class=3D"subprettyprint=
"><span style=3D"color: #008;" class=3D"styled-by-prettify">struct</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #606;" class=3D"styled-by-prettify">Foo</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #606;" clas=
s=3D"styled-by-prettify">Foo</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">&amp;</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pretti=
fy">operator</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">+=3D(</span><span style=3D"color: #008;" class=3D"styled-by-prettify">con=
st</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span>=
<span style=3D"color: #606;" class=3D"styled-by-prettify">Foo</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">&amp;);</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">};</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #606;" c=
lass=3D"styled-by-prettify">Foo</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">operator</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">+(</span><span style=3D"color: #008;" class=3D"styled-by-prettify=
">const</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </=
span><span style=3D"color: #606;" class=3D"styled-by-prettify">Foo</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">&amp;</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> a</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">const</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by=
-prettify">Foo</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">&amp;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
b</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #606;"=
 class=3D"styled-by-prettify">Foo</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> R</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> R </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
+=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> a </s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D=
"color: #008;" class=3D"styled-by-prettify">return</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> R</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br></span><span style=3D"color: #606;" class=3D"styled-by-prettify">=
Foo</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&amp;&a=
mp;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">operator</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">+(</span><span sty=
le=3D"color: #606;" class=3D"styled-by-prettify">Foo</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">&amp;&amp;</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> a</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">const</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify=
">Foo</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&amp;=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> b</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"> a </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">+=3D</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> b</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">return</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> std</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify">move</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify">a</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">);</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><=
br></span><span style=3D"color: #606;" class=3D"styled-by-prettify">Foo</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">&amp;&amp;</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span =
style=3D"color: #008;" class=3D"styled-by-prettify">operator</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">+(</span><span style=3D"c=
olor: #008;" class=3D"styled-by-prettify">const</span><span style=3D"color:=
 #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #606;" c=
lass=3D"styled-by-prettify">Foo</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">&amp;</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> a</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span><span style=3D"color: #606;" class=3D"styled-by-prettify">Foo</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">&amp;&amp;</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> b</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">return</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> std</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">mov=
e</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify">b</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;"=
 class=3D"styled-by-prettify">+</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> a</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><sp=
an style=3D"color: #606;" class=3D"styled-by-prettify">Foo</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">&amp;&amp;</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">operator</span><span style=3D"color:=
 #660;" class=3D"styled-by-prettify">+(</span><span style=3D"color: #606;" =
class=3D"styled-by-prettify">Foo</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">&amp;&amp;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> a</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">Fo=
o</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&amp;&amp=
;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> b</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">return</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> std</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify">move</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">a</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">+</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"> b</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br=
></span></div></code></div>And if you do that, you might end up with dangli=
ng references in few cases.<br><br>If you do the same with passing by value=
:<br><div style=3D"background-color: rgb(250, 250, 250); border-color: rgb(=
187, 187, 187); border-style: solid; border-width: 1px; overflow-wrap: brea=
k-word;" class=3D"prettyprint"><code class=3D"prettyprint"><div class=3D"su=
bprettyprint"><span style=3D"color: #008;" class=3D"styled-by-prettify">str=
uct</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #606;" class=3D"styled-by-prettify">Foo</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #=
606;" class=3D"styled-by-prettify">Foo</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">&amp;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">operator</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">+=3D(</span><span style=3D"color: #008;" class=3D"styled-by-pr=
ettify">const</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">Foo</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">&amp;);</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #800;" class=3D"styled-by-prettify">// unchanged</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">};</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #60=
6;" class=3D"styled-by-prettify">Foo</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">operator</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">+(</span><span style=3D"color: #606;" class=3D"styled-by-pre=
ttify">Foo</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
 a</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #606;" class=3D"styled-by-prettify">Foo</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> b</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> a </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
+=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> b</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"=
color: #008;" class=3D"styled-by-prettify">return</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> a</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br></span></div></code></div>The code here is much simpler, you cann=
ot have dangling references, and in most cases it is at least as optimized =
as the reference implementation (but no guarantee by the language, I think)=
..<br>(maybe you still need to take the second argument as a reference thoug=
h...)<br></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/d68aa110-1d00-48ac-89a8-03f0079079d1%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/d68aa110-1d00-48ac-89a8-03f0079079d1=
%40isocpp.org</a>.<br />

------=_Part_8516_1646849856.1523620190256--

------=_Part_8515_1758379965.1523620190255--

.


Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
Date: Fri, 13 Apr 2018 16:40:55 -0700 (PDT)
Raw View
------=_Part_11142_260065937.1523662855889
Content-Type: multipart/alternative;
 boundary="----=_Part_11143_945081778.1523662855890"

------=_Part_11143_945081778.1523662855890
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

On Friday, April 13, 2018 at 4:49:50 AM UTC-7, floria...@gmail.com wrote:
>
> In my experience, values are much easier to deal with, especially when yo=
u=20
> want to return them.
> Consider a simple operator+
>
> If you want to use references and optimize for rvalues, you do:
> struct Foo {
>   Foo& operator+=3D(const Foo&);
> };
> Foo operator+(const Foo& a, const Foo& b) { Foo R; R +=3D a ; return R; }
> Foo&& operator+(Foo&& a, const Foo& b) { a +=3D b; return std::move(a); }
> Foo&& operator+(const Foo& a, Foo&& b) { return std::move(b) + a; }
> Foo&& operator+(Foo&& a, Foo&& b) { return std::move(a) + b; }
> And if you do that, you might end up with dangling references in few case=
s.
>

Right; and also I believe you silently break lifetime-extension, for people=
=20
who care about that kind of thing.
    Foo a, b, c;
    const auto& d =3D (a + b) + c;  // oops

I think (with about 90% confidence) that a sufficient and maximally=20
optimizable version can look like this:

struct Foo {
    Foo& operator+=3D(const Foo&);
};
Foo operator+(Foo a, const Foo& b) { a +=3D b; return a; }
Foo operator+(const Foo& a, Foo&& b) { b +=3D a; return b; }

Notice that
- we always return by value (which will move, not copy, in cases where it=
=20
cannot be elided)
- we always take by-const-ref as a general rule, if we do not need to make=
=20
a copy
- we always take by-value as a general rule, if we do need to make a copy
- we have one special overload (const T&, T&&) that breaks the general=20
rules for performance's sake

Notice that "Foo e =3D a + b + c + d" does exactly one more "move" than we'=
d=20
like it to, but I think that is unavoidable as of C++17.
https://wandbox.org/permlink/gc61gvtGTwy24Mby
I have a blog post on the subject of unavoidable moves.
https://quuxplusone.github.io/blog/2018/03/29/the-superconstructing-super-e=
lider/

Thoughts?
=E2=80=93Arthur

--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/ddf07046-aa7f-4ff0-aca8-29e34398e55b%40isocpp.or=
g.

------=_Part_11143_945081778.1523662855890
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">On Friday, April 13, 2018 at 4:49:50 AM UTC-7, floria...@g=
mail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-=
left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr=
">In my experience, values are much easier to deal with, especially when yo=
u want to return them.<br>Consider a simple operator+<br><br>If you want to=
 use references and optimize for rvalues, you do:<br><div style=3D"backgrou=
nd-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;=
border-width:1px"><code><div><span style=3D"color:#008">struct</span><span =
style=3D"color:#000"> </span><span style=3D"color:#606">Foo</span><span sty=
le=3D"color:#000"> </span><span style=3D"color:#660">{</span><span style=3D=
"color:#000"><br>=C2=A0 </span><span style=3D"color:#606">Foo</span><span s=
tyle=3D"color:#660">&amp;</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#008">operator</span><span style=3D"color:#660">+=3D(</span><s=
pan style=3D"color:#008">const</span><span style=3D"color:#000"> </span><sp=
an style=3D"color:#606">Foo</span><span style=3D"color:#660">&amp;);</span>=
<span style=3D"color:#000"><br></span><span style=3D"color:#660">};</span><=
span style=3D"color:#000"><br></span><span style=3D"color:#606">Foo</span><=
span style=3D"color:#000"> </span><span style=3D"color:#008">operator</span=
><span style=3D"color:#660">+(</span><span style=3D"color:#008">const</span=
><span style=3D"color:#000"> </span><span style=3D"color:#606">Foo</span><s=
pan style=3D"color:#660">&amp;</span><span style=3D"color:#000"> a</span><s=
pan style=3D"color:#660">,</span><span style=3D"color:#000"> </span><span s=
tyle=3D"color:#008">const</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#606">Foo</span><span style=3D"color:#660">&amp;</span><span s=
tyle=3D"color:#000"> b</span><span style=3D"color:#660">)</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">{</span><span style=3D"c=
olor:#000"> </span><span style=3D"color:#606">Foo</span><span style=3D"colo=
r:#000"> R</span><span style=3D"color:#660">;</span><span style=3D"color:#0=
00"> R </span><span style=3D"color:#660">+=3D</span><span style=3D"color:#0=
00"> a </span><span style=3D"color:#660">;</span><span style=3D"color:#000"=
> </span><span style=3D"color:#008">return</span><span style=3D"color:#000"=
> R</span><span style=3D"color:#660">;</span><span style=3D"color:#000"> </=
span><span style=3D"color:#660">}</span><span style=3D"color:#000"><br></sp=
an><span style=3D"color:#606">Foo</span><span style=3D"color:#660">&amp;&am=
p;</span><span style=3D"color:#000"> </span><span style=3D"color:#008">oper=
ator</span><span style=3D"color:#660">+(</span><span style=3D"color:#606">F=
oo</span><span style=3D"color:#660">&amp;&amp;</span><span style=3D"color:#=
000"> a</span><span style=3D"color:#660">,</span><span style=3D"color:#000"=
> </span><span style=3D"color:#008">const</span><span style=3D"color:#000">=
 </span><span style=3D"color:#606">Foo</span><span style=3D"color:#660">&am=
p;</span><span style=3D"color:#000"> b</span><span style=3D"color:#660">)</=
span><span style=3D"color:#000"> </span><span style=3D"color:#660">{</span>=
<span style=3D"color:#000"> a </span><span style=3D"color:#660">+=3D</span>=
<span style=3D"color:#000"> b</span><span style=3D"color:#660">;</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#008">return</span><spa=
n style=3D"color:#000"> std</span><span style=3D"color:#660">::</span><span=
 style=3D"color:#000">move</span><span style=3D"color:#660">(</span><span s=
tyle=3D"color:#000">a</span><span style=3D"color:#660">);</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">}</span><span style=3D"c=
olor:#000"><br></span><span style=3D"color:#606">Foo</span><span style=3D"c=
olor:#660">&amp;&amp;</span><span style=3D"color:#000"> </span><span style=
=3D"color:#008">operator</span><span style=3D"color:#660">+(</span><span st=
yle=3D"color:#008">const</span><span style=3D"color:#000"> </span><span sty=
le=3D"color:#606">Foo</span><span style=3D"color:#660">&amp;</span><span st=
yle=3D"color:#000"> a</span><span style=3D"color:#660">,</span><span style=
=3D"color:#000"> </span><span style=3D"color:#606">Foo</span><span style=3D=
"color:#660">&amp;&amp;</span><span style=3D"color:#000"> b</span><span sty=
le=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D=
"color:#660">{</span><span style=3D"color:#000"> </span><span style=3D"colo=
r:#008">return</span><span style=3D"color:#000"> std</span><span style=3D"c=
olor:#660">::</span><span style=3D"color:#000">move</span><span style=3D"co=
lor:#660">(</span><span style=3D"color:#000">b</span><span style=3D"color:#=
660">)</span><span style=3D"color:#000"> </span><span style=3D"color:#660">=
+</span><span style=3D"color:#000"> a</span><span style=3D"color:#660">;</s=
pan><span style=3D"color:#000"> </span><span style=3D"color:#660">}</span><=
span style=3D"color:#000"><br></span><span style=3D"color:#606">Foo</span><=
span style=3D"color:#660">&amp;&amp;</span><span style=3D"color:#000"> </sp=
an><span style=3D"color:#008">operator</span><span style=3D"color:#660">+(<=
/span><span style=3D"color:#606">Foo</span><span style=3D"color:#660">&amp;=
&amp;</span><span style=3D"color:#000"> a</span><span style=3D"color:#660">=
,</span><span style=3D"color:#000"> </span><span style=3D"color:#606">Foo</=
span><span style=3D"color:#660">&amp;&amp;</span><span style=3D"color:#000"=
> b</span><span style=3D"color:#660">)</span><span style=3D"color:#000"> </=
span><span style=3D"color:#660">{</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#008">return</span><span style=3D"color:#000"> std</sp=
an><span style=3D"color:#660">::</span><span style=3D"color:#000">move</spa=
n><span style=3D"color:#660">(</span><span style=3D"color:#000">a</span><sp=
an style=3D"color:#660">)</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#660">+</span><span style=3D"color:#000"> b</span><span style=
=3D"color:#660">;</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#660">}</span><span style=3D"color:#000"><br></span></div></code></div=
>And if you do that, you might end up with dangling references in few cases=
..<br></div></blockquote><div><br></div><div>Right; and also I believe you s=
ilently break lifetime-extension, for people who care about that kind of th=
ing.</div><div>=C2=A0 =C2=A0 Foo a, b, c;</div><div>=C2=A0 =C2=A0 const aut=
o&amp; d =3D (a + b) + c; =C2=A0// oops</div><div><br></div><div>I think (w=
ith about 90% confidence) that a sufficient and maximally optimizable versi=
on can look like this:</div><div><br></div><div class=3D"prettyprint" style=
=3D"background-color: rgb(250, 250, 250); border: 1px solid rgb(187, 187, 1=
87); word-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"subp=
rettyprint"><span style=3D"color: #008;" class=3D"styled-by-prettify">struc=
t</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><=
span style=3D"color: #606;" class=3D"styled-by-prettify">Foo</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"col=
or: #606;" class=3D"styled-by-prettify">Foo</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">&amp;</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"s=
tyled-by-prettify">operator</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">+=3D(</span><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">const</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">Fo=
o</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&amp;);</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">};</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"=
color: #606;" class=3D"styled-by-prettify">Foo</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" cl=
ass=3D"styled-by-prettify">operator</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">+(</span><span style=3D"color: #606;" class=3D"sty=
led-by-prettify">Foo</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> a</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">const</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #606;" class=3D"styled-by-prettify">Foo</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">&amp;</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> b</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
 a </span><span style=3D"color: #660;" class=3D"styled-by-prettify">+=3D</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> b</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">return</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> a</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><=
br></span><span style=3D"color: #606;" class=3D"styled-by-prettify">Foo</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span =
style=3D"color: #008;" class=3D"styled-by-prettify">operator</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">+(</span><span style=3D"c=
olor: #008;" class=3D"styled-by-prettify">const</span><span style=3D"color:=
 #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #606;" c=
lass=3D"styled-by-prettify">Foo</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">&amp;</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> a</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span><span style=3D"color: #606;" class=3D"styled-by-prettify">Foo</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">&amp;&amp;</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> b</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> b </span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">+=3D</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> a</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </spa=
n><span style=3D"color: #008;" class=3D"styled-by-prettify">return</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> b</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;"=
 class=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"><br></span></div></code></div><div><br><div>Notice tha=
t</div><div>- we always return by value (which will move, not copy, in case=
s where it cannot be elided)</div><div>- we always take by-const-ref as a g=
eneral rule, if we do not need to make a copy</div><div>- we always take by=
-value as a general rule, if we do need to make a copy</div><div>- we have =
one special overload (const T&amp;, T&amp;&amp;) that breaks the general ru=
les for performance&#39;s sake</div><div><br></div><div>Notice that &quot;F=
oo e =3D a + b + c + d&quot; does exactly one more &quot;move&quot; than we=
&#39;d like it to, but I think that is unavoidable as of C++17.</div><div><=
a href=3D"https://wandbox.org/permlink/gc61gvtGTwy24Mby">https://wandbox.or=
g/permlink/gc61gvtGTwy24Mby</a><br></div><div>I have a blog post on the sub=
ject of unavoidable moves.</div><div><a href=3D"https://quuxplusone.github.=
io/blog/2018/03/29/the-superconstructing-super-elider/">https://quuxplusone=
..github.io/blog/2018/03/29/the-superconstructing-super-elider/</a></div><di=
v><br></div><div>Thoughts?</div><div>=E2=80=93Arthur</div></div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/ddf07046-aa7f-4ff0-aca8-29e34398e55b%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/ddf07046-aa7f-4ff0-aca8-29e34398e55b=
%40isocpp.org</a>.<br />

------=_Part_11143_945081778.1523662855890--

------=_Part_11142_260065937.1523662855889--

.


Author: oguzakyuz@gmail.com
Date: Sat, 14 Apr 2018 02:43:27 -0700 (PDT)
Raw View
------=_Part_9278_241452772.1523699007449
Content-Type: multipart/alternative;
 boundary="----=_Part_9279_1637493190.1523699007450"

------=_Part_9279_1637493190.1523699007450
Content-Type: text/plain; charset="UTF-8"

I think this is very reasonable. My original question was regarding the
case when copy-elision was turned off. However, you are right that in a
real world setting copy elision will take place and the maximum efficiency
can be gained by implementing all three versions. Whether this minimal gain
in efficiency is worth the effort of adding an extra function is something
that everybody should consider for their own application.

In my original question I also wanted to find out if rules could not be set
up to choose an rvalue reference over value parameter in overloading
resolution. rvalue reference is chosen over lvalue reference, so why not
rvalue reference is not chosen over value parameter? Is there a case when a
programmer would prefer the pass-by-value for a temporary object?

Thanks,
Oguz

On Friday, April 13, 2018 at 2:04:47 PM UTC+3, Richard Hodges wrote:
>
>
>
> On 13 April 2018 at 07:11, <oguz...@gmail.com <javascript:>> wrote:
>
>> Let me know if this is a stupid idea or something that is already
>> considered. But to my knowledge, if we have the following operator
>> overloads for a class, compilers will generate an ambiguity error (probably
>> enforced by the standard):
>>
>
> Imagine an external function, foo:
>
> extern void foo(Bar b);
>
> *where foo is defined in an another compilation unit*.
>
> That function is not expecting a reference, it is expecting a fully formed
> Bar to exist in its arguments (i.e. for all intents and purposes 'on the
> stack')
>
> assume at the call site:
>
> foo(Bar(arguments, of, bar));
>
> A well behaved compiler will:
> 1. allocate space on the stack, in foo's argument stack frame
> 2. construct b right there on the stack.
> 3. assume that foo will destroy b.
>
> In other words, copy elision will take place. The b belongs to foo. The
> caller constructed it on foo's behalf.
>
> Now consider:
>
> extern void foo(Bar&& b);
>
> The same compiler will:
> 1. allocate space on the stack, in the *caller's* stack frame
> 2. construct b right there on the stack.
> 3. pass the address of b to foo
> 4. call b's destructor upon foo's return
>
> Now consider
>
> extern void foo(Bar const& b);
>
> The same compiler will:
> 1. allocate space on the stack, in the caller's stack frame
> 2. construct b right there on the stack.
> 3. pass the address of b to foo
> 4. call b's destructor upon foo's return
>
> In the pass-by-reference cases the code incurs a cost of one extra
> operation on the stack - pushing the address of b. The only difference in
> the implementations is when the work of destruction is done. The same
> amount of work is actually done.
>
> The question is, do we mind about this minuscule extra cost?
>
> If we absolutely do, then it's worth thinking about allowing the 3
> overloads to coexist (this may be a can of worms?).
>
> If we don't mind about the push, probably best to leave it alone.
>
> That's my 2c.
>
> Does that seem reasonable?
>
>
>
>>
>> C& C::operator=(C rhs);
>> C& C::operator=(C&& rhs);
>>
>> However, if the compilers could choose the rvalue reference version over the pass-by-value version for rvalue arguments (i.e. c2 = c1 + c1), it could lead to an efficient copy-swap idiom implementation.
>>
>> Below is a sample code that demonstrates the problem. The issue is explained by the long comment block inside the main function:
>>
>>
>> #include <algorithm>
>>
>> class C
>> {
>>     int* data;
>>
>>      public:
>>
>>      C() : data(nullptr) { }
>>
>>      C(int data) : data(new int)
>>      {
>>          *(this->data) = data;
>>      }
>>
>>      C(const C& rhs) : data(new int)
>>      {
>>          *data = *(rhs.data);
>>      }
>>
>>      C(C&& rhs) : C()
>>      {
>>          // Move constructor is first creating a default
>>          // object and swapping it with the rvalue reference.
>>          swap(*this, rhs);
>>      }
>>
>>      C& operator=(C rhs)
>>      {
>>          // We let the compiler copy into rhs and we swap the
>>          // current object with this copy. Together with the
>>          // move constructor above, this implements the copy-swap
>>          // idiom. Thanks to the move-constructor above, the
>>          // copy to rhs is not a deep copy if the input is an rvalue
>>          // reference.
>>          swap(*this, rhs);
>>          return *this;
>>      }
>>
>>      // The function below is commented out because it fails compilation
>>      // due to ambiguity with the above function. However, if it worked
>>      // it could have saved us an extra call to the move constructor when
>>      // we make calls such as c2 = c1 + c1 (see operator+ below). If it
>> had
>>      // worked, the temporary created from c1 + c1 would have been
>> directly
>>      // taken by rvalue reference instead of its copy  (albeit shallow)
>> being
>>      // created.
>>
>>      /*
>>      C& operator=(C&& rhs)
>>      {
>>          swap(*this, rhs);
>>          return *this;
>>      }
>>      */
>>
>>      C operator+(const C& rhs)
>>      {
>>          C result(*data + *(rhs.data));
>>          return result;
>>      }
>>
>>      friend void swap(C& lhs, C& rhs);
>>
>>      ~C()
>>      {
>>          delete data;
>>      }
>> };
>>
>> void swap(C& lhs, C& rhs)
>> {
>>     std::swap(lhs.data, rhs.data);
>> }
>>
>> int main()
>> {
>>     C c1(7);
>>     C c2;
>>
>>     // The following will first create the "result" inside operator+.
>>     // The return value will then get move-constructed from the result
>>     // (I'm assuming that -fno-elide-constructors option is used). Then
>>     // the "rhs" parameter of operator= will get move-constructed from
>>     // this return temporary.
>>     //
>>     // But if we could overload operator=(C&&), this second
>> move-construction
>>     // could have been avoided as the return temporary could have been
>> directly
>>     // captured by rvalue reference.
>>     //
>>     // Granted that we can implement operator=(const C&) and
>> operator=(C&&)
>>     // to make assignment as efficient as possible for both lvalue and
>> rvalue
>>     // inputs. However, to my knowledge, having operator=(const C&) would
>>     // essentially prevent us from having the copy-swap idiom.
>>
>>     c2 = c1 + c1;
>>
>>     return 0;
>> }
>>
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "ISO C++ Standard - Future Proposals" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to std-proposal...@isocpp.org <javascript:>.
>> To post to this group, send email to std-pr...@isocpp.org <javascript:>.
>> To view this discussion on the web visit
>> https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/62809333-fd1a-4bde-8805-ccc0578a4284%40isocpp.org
>> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/62809333-fd1a-4bde-8805-ccc0578a4284%40isocpp.org?utm_medium=email&utm_source=footer>
>> .
>>
>
>

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/a062d2a9-7805-4184-adf3-32a2986baab4%40isocpp.org.

------=_Part_9279_1637493190.1523699007450
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">I think this is very reasonable. My original question was =
regarding the case when copy-elision was turned off. However, you are right=
 that in a real world setting copy elision will take place and the maximum =
efficiency can be gained by implementing all three versions. Whether this m=
inimal gain in efficiency is worth the effort of adding an extra function i=
s something that everybody should consider for their own application.<div><=
br></div><div>In my original question I also wanted to find out if rules co=
uld not be set up to choose an rvalue reference over value parameter in ove=
rloading resolution. rvalue reference is chosen over lvalue reference, so w=
hy not rvalue reference is not chosen over value parameter? Is there a case=
 when a programmer would prefer the pass-by-value for a temporary object?<b=
r><div><br></div><div>Thanks,</div><div>Oguz<br><br>On Friday, April 13, 20=
18 at 2:04:47 PM UTC+3, Richard Hodges wrote:<blockquote class=3D"gmail_quo=
te" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddi=
ng-left: 1ex;"><div dir=3D"ltr"><br><div><br><div class=3D"gmail_quote">On =
13 April 2018 at 07:11,  <span dir=3D"ltr">&lt;<a href=3D"javascript:" targ=
et=3D"_blank" gdf-obfuscated-mailto=3D"rL4IJPuUCAAJ" rel=3D"nofollow" onmou=
sedown=3D"this.href=3D&#39;javascript:&#39;;return true;" onclick=3D"this.h=
ref=3D&#39;javascript:&#39;;return true;">oguz...@gmail.com</a>&gt;</span> =
wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bord=
er-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">Let me know if th=
is is a stupid idea or something that is already considered. But to my know=
ledge, if we have the following operator overloads for a class, compilers w=
ill generate an ambiguity error (probably enforced by the standard):<br></d=
iv></blockquote><div><br></div><div>Imagine an external function, foo:<br><=
/div><div><br></div><div><font face=3D"monospace, monospace">extern void fo=
o(Bar b);</font></div><div><br></div><div><b>where foo is defined in an ano=
ther compilation unit</b>.=C2=A0</div><div><br></div><div>That function is =
not expecting a reference, it is expecting a fully formed Bar to exist in i=
ts arguments (i.e. for all intents and purposes &#39;on the stack&#39;)</di=
v><div><br></div><div>assume at the call site:=C2=A0</div><div><br></div><d=
iv><font face=3D"monospace, monospace">foo(Bar(arguments, of, bar));</font>=
</div><div><br></div><div>A well behaved compiler will:</div><div>1. alloca=
te space on the stack, in foo&#39;s argument stack frame</div><div>2. const=
ruct b right there on the stack.</div><div>3. assume that foo will destroy =
b.</div><div><br></div><div>In other words, copy elision will take place. T=
he b belongs to foo. The caller constructed it on foo&#39;s behalf.</div><d=
iv><br></div><div>Now consider:</div><div><br></div><div><font face=3D"mono=
space, monospace">extern void foo(Bar&amp;&amp; b);</font></div><div><br></=
div><div>The same compiler will:</div><div><div style=3D"color:rgb(34,34,34=
);font-family:arial,sans-serif;font-size:small;font-style:normal;font-weigh=
t:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform=
:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255)=
">1. allocate space on the stack, in the <u>caller&#39;s</u> stack frame</d=
iv><div style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size=
:small;font-style:normal;font-weight:400;letter-spacing:normal;text-align:s=
tart;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0p=
x;background-color:rgb(255,255,255)">2. construct b right there on the stac=
k.</div><div style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font=
-size:small;font-style:normal;font-weight:400;letter-spacing:normal;text-al=
ign:start;text-indent:0px;text-transform:none;white-space:normal;word-spaci=
ng:0px;background-color:rgb(255,255,255)">3. pass the address of b to foo</=
div><div style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-siz=
e:small;font-style:normal;font-weight:400;letter-spacing:normal;text-align:=
start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0=
px;background-color:rgb(255,255,255)">4. call b&#39;s destructor upon foo&#=
39;s return</div><div style=3D"color:rgb(34,34,34);font-family:arial,sans-s=
erif;font-size:small;font-style:normal;font-weight:400;letter-spacing:norma=
l;text-align:start;text-indent:0px;text-transform:none;white-space:normal;w=
ord-spacing:0px;background-color:rgb(255,255,255)"><br></div><div style=3D"=
color:rgb(34,34,34);font-size:small;font-style:normal;font-weight:400;lette=
r-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white=
-space:normal;word-spacing:0px;background-color:rgb(255,255,255)"><div styl=
e=3D"font-family:arial,sans-serif">Now consider</div><div style=3D"font-fam=
ily:arial,sans-serif"><br></div><div><font face=3D"monospace, monospace">ex=
tern void foo(Bar const&amp; b);</font></div><div style=3D"font-family:aria=
l,sans-serif"><br></div><div style=3D"font-family:arial,sans-serif">The sam=
e compiler will:</div><div style=3D"font-family:arial,sans-serif"><div styl=
e=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-=
style:normal;font-weight:400;letter-spacing:normal;text-align:start;text-in=
dent:0px;text-transform:none;white-space:normal;word-spacing:0px;background=
-color:rgb(255,255,255)">1. allocate space on the stack, in the caller&#39;=
s stack frame</div><div style=3D"color:rgb(34,34,34);font-family:arial,sans=
-serif;font-size:small;font-style:normal;font-weight:400;letter-spacing:nor=
mal;text-align:start;text-indent:0px;text-transform:none;white-space:normal=
;word-spacing:0px;background-color:rgb(255,255,255)">2. construct b right t=
here on the stack.</div><div style=3D"color:rgb(34,34,34);font-family:arial=
,sans-serif;font-size:small;font-style:normal;font-weight:400;letter-spacin=
g:normal;text-align:start;text-indent:0px;text-transform:none;white-space:n=
ormal;word-spacing:0px;background-color:rgb(255,255,255)">3. pass the addre=
ss of b to foo</div><div style=3D"color:rgb(34,34,34);font-family:arial,san=
s-serif;font-size:small;font-style:normal;font-weight:400;letter-spacing:no=
rmal;text-align:start;text-indent:0px;text-transform:none;white-space:norma=
l;word-spacing:0px;background-color:rgb(255,255,255)">4. call b&#39;s destr=
uctor upon foo&#39;s return</div><br></div>In the pass-by-reference cases t=
he code incurs a cost of one extra operation on the stack - pushing the add=
ress of b. The only difference in the implementations is when the work of d=
estruction is done. The same amount of work is actually done.</div><div sty=
le=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font=
-style:normal;font-weight:400;letter-spacing:normal;text-align:start;text-i=
ndent:0px;text-transform:none;white-space:normal;word-spacing:0px;backgroun=
d-color:rgb(255,255,255)"><br></div><div style=3D"color:rgb(34,34,34);font-=
family:arial,sans-serif;font-size:small;font-style:normal;font-weight:400;l=
etter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;w=
hite-space:normal;word-spacing:0px;background-color:rgb(255,255,255)">The q=
uestion is, do we mind about this minuscule extra cost?</div><div style=3D"=
color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style=
:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:=
0px;text-transform:none;white-space:normal;word-spacing:0px;background-colo=
r:rgb(255,255,255)"><br></div><div style=3D"color:rgb(34,34,34);font-family=
:arial,sans-serif;font-size:small;font-style:normal;font-weight:400;letter-=
spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-s=
pace:normal;word-spacing:0px;background-color:rgb(255,255,255)">If we absol=
utely do, then it&#39;s worth thinking about allowing the 3 overloads to co=
exist (this may be a can of worms?).</div><div style=3D"color:rgb(34,34,34)=
;font-family:arial,sans-serif;font-size:small;font-style:normal;font-weight=
:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:=
none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255)"=
><br></div><div style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;f=
ont-size:small;font-style:normal;font-weight:400;letter-spacing:normal;text=
-align:start;text-indent:0px;text-transform:none;white-space:normal;word-sp=
acing:0px;background-color:rgb(255,255,255)">If we don&#39;t mind about the=
 push, probably best to leave it alone.</div><div style=3D"color:rgb(34,34,=
34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-wei=
ght:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transfo=
rm:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,25=
5)"><br></div><div style=3D"color:rgb(34,34,34);font-family:arial,sans-seri=
f;font-size:small;font-style:normal;font-weight:400;letter-spacing:normal;t=
ext-align:start;text-indent:0px;text-transform:none;white-space:normal;word=
-spacing:0px;background-color:rgb(255,255,255)">That&#39;s my 2c.</div><br>=
</div><div>Does that seem reasonable?</div><div><br></div><div>=C2=A0</div>=
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div dir=3D"ltr"><br><pre><code><span>C</spa=
n><span>&amp;</span><span> C::</span><span>operator</span><span>=3D(</span>=
<span>C rhs</span><span>);<br></span></code><code><span>C</span><span>&amp;=
</span><span> C::</span><span>operator</span><span>=3D(</span><span>C&amp;&=
amp; rhs</span><span>);</span></code><br><br>However, if the compilers coul=
d choose the rvalue reference version over the pass-by-value version for rv=
alue arguments (i.e. c2 =3D c1 + c1), it could lead to an efficient copy-sw=
ap idiom implementation.<br><br>Below is a sample code that demonstrates th=
e problem. The issue is explained by the long comment block inside the main=
 function:<br><code><span></span></code></pre><br><div style=3D"background-=
color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;bor=
der-width:1px"><code><div><span style=3D"color:#000">#include &lt;algorithm=
&gt;<br><br></span><span style=3D"color:#008">class</span><span style=3D"co=
lor:#000"> C<br></span><span style=3D"color:#660">{</span><span style=3D"co=
lor:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008">int</span><sp=
an style=3D"color:#660">*</span><span style=3D"color:#000"> data</span><spa=
n style=3D"color:#660">;</span><span style=3D"color:#000"><br><br>=C2=A0 =
=C2=A0 =C2=A0</span><span style=3D"color:#008">public</span><span style=3D"=
color:#660">:</span><span style=3D"color:#000"><br><br>=C2=A0 =C2=A0 =C2=A0=
C</span><span style=3D"color:#660">()</span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#660">:</span><span style=3D"color:#000"> data</sp=
an><span style=3D"color:#660">(</span><span style=3D"color:#008">nullptr</s=
pan><span style=3D"color:#660">)</span><span style=3D"color:#000"> </span><=
span style=3D"color:#660">{</span><span style=3D"color:#000"> </span><span =
style=3D"color:#660">}</span><span style=3D"color:#000"><br><br>=C2=A0 =C2=
=A0 =C2=A0C</span><span style=3D"color:#660">(</span><span style=3D"color:#=
008">int</span><span style=3D"color:#000"> data</span><span style=3D"color:=
#660">)</span><span style=3D"color:#000"> </span><span style=3D"color:#660"=
>:</span><span style=3D"color:#000"> data</span><span style=3D"color:#660">=
(</span><span style=3D"color:#008">new</span><span style=3D"color:#000"> </=
span><span style=3D"color:#008">int</span><span style=3D"color:#660">)</spa=
n><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0</span><span style=3D"=
color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0</span><span style=3D"color:#660">*(</span><span style=3D"color:#=
008">this</span><span style=3D"color:#660">-&gt;</span><span style=3D"color=
:#000">data</span><span style=3D"color:#660">)</span><span style=3D"color:#=
000"> </span><span style=3D"color:#660">=3D</span><span style=3D"color:#000=
"> data</span><span style=3D"color:#660">;</span><span style=3D"color:#000"=
><br>=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660">}</span><span st=
yle=3D"color:#000"><br><br>=C2=A0 =C2=A0 =C2=A0C</span><span style=3D"color=
:#660">(</span><span style=3D"color:#008">const</span><span style=3D"color:=
#000"> C</span><span style=3D"color:#660">&amp;</span><span style=3D"color:=
#000"> rhs</span><span style=3D"color:#660">)</span><span style=3D"color:#0=
00"> </span><span style=3D"color:#660">:</span><span style=3D"color:#000"> =
data</span><span style=3D"color:#660">(</span><span style=3D"color:#008">ne=
w</span><span style=3D"color:#000"> </span><span style=3D"color:#008">int</=
span><span style=3D"color:#660">)</span><span style=3D"color:#000"><br>=C2=
=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660">{</span><span style=3D"c=
olor:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"colo=
r:#660">*</span><span style=3D"color:#000">data </span><span style=3D"color=
:#660">=3D</span><span style=3D"color:#000"> </span><span style=3D"color:#6=
60">*(</span><span style=3D"color:#000">rhs</span><span style=3D"color:#660=
">.</span><span style=3D"color:#000">data</span><span style=3D"color:#660">=
);</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0</span><span st=
yle=3D"color:#660">}</span><span style=3D"color:#000"><br><br>=C2=A0 =C2=A0=
 =C2=A0C</span><span style=3D"color:#660">(</span><span style=3D"color:#000=
">C</span><span style=3D"color:#660">&amp;&amp;</span><span style=3D"color:=
#000"> rhs</span><span style=3D"color:#660">)</span><span style=3D"color:#0=
00"> </span><span style=3D"color:#660">:</span><span style=3D"color:#000"> =
C</span><span style=3D"color:#660">()</span><span style=3D"color:#000"><br>=
=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660">{</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D=
"color:#800">// Move constructor is first creating a default</span><span st=
yle=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=
=3D"color:#800">// object and swapping it with the rvalue reference.</span>=
<span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0swap</span=
><span style=3D"color:#660">(*</span><span style=3D"color:#008">this</span>=
<span style=3D"color:#660">,</span><span style=3D"color:#000"> rhs</span><s=
pan style=3D"color:#660">);</span><span style=3D"color:#000"><br>=C2=A0 =C2=
=A0 =C2=A0</span><span style=3D"color:#660">}</span><span style=3D"color:#0=
00"><br><br>=C2=A0 =C2=A0 =C2=A0C</span><span style=3D"color:#660">&amp;</s=
pan><span style=3D"color:#000"> </span><span style=3D"color:#008">operator<=
/span><span style=3D"color:#660">=3D(</span><span style=3D"color:#000">C rh=
s</span><span style=3D"color:#660">)</span><span style=3D"color:#000"><br>=
=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660">{</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D=
"color:#800">// We let the compiler copy into rhs and we swap the</span><sp=
an style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span =
style=3D"color:#800">// current object with this copy. Together with the</s=
pan><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span=
><span style=3D"color:#800">// move constructor above, this implements the =
copy-swap</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0</span><span style=3D"color:#800">// idiom. Thanks to the move-constr=
uctor above, the</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0</span><span style=3D"color:#800">// copy to rhs is not a deep=
 copy if the input is an rvalue<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0 // reference.</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0swap</span><span style=3D"color:#660">(*</span><span st=
yle=3D"color:#008">this</span><span style=3D"color:#660">,</span><span styl=
e=3D"color:#000"> rhs</span><span style=3D"color:#660">);</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D=
"color:#008">return</span><span style=3D"color:#000"> </span><span style=3D=
"color:#660">*</span><span style=3D"color:#008">this</span><span style=3D"c=
olor:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0</spa=
n><span style=3D"color:#660">}</span><span style=3D"color:#000"><br><br></s=
pan>=C2=A0=C2=A0=C2=A0=C2=A0 // The function below is commented out because=
 it fails compilation<br>=C2=A0=C2=A0=C2=A0=C2=A0 // due to ambiguity with =
the above function. However, if it worked<br>=C2=A0=C2=A0=C2=A0=C2=A0 // it=
 could have saved us an extra call to the move constructor when<br>=C2=A0=
=C2=A0=C2=A0=C2=A0 // we make calls such as c2 =3D c1 + c1 (see operator+ b=
elow). If it had<br>=C2=A0=C2=A0=C2=A0=C2=A0 // worked, the temporary creat=
ed from c1 + c1 would have been directly <br>=C2=A0=C2=A0=C2=A0=C2=A0 // ta=
ken by rvalue reference instead of its copy=C2=A0 (albeit shallow) being<br=
>=C2=A0=C2=A0=C2=A0=C2=A0 // created. <br>=C2=A0=C2=A0=C2=A0=C2=A0 <br>=C2=
=A0=C2=A0=C2=A0=C2=A0 /*<br><span style=3D"color:#000"><code><span style=3D=
"color:#000">=C2=A0=C2=A0=C2=A0=C2=A0 C</span><span style=3D"color:#660">&a=
mp;</span><span style=3D"color:#000"> </span><span style=3D"color:#008">ope=
rator</span><span style=3D"color:#660">=3D(</span><span style=3D"color:#000=
">C&amp;&amp; rhs</span><span style=3D"color:#660">)</span><span style=3D"c=
olor:#000"><br>=C2=A0 =C2=A0=C2=A0 </span><span style=3D"color:#660">{</spa=
n><span style=3D"color:#000"></span><span style=3D"color:#000"><br>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0swap</span><span style=3D"color:#660">(*</span><=
span style=3D"color:#008">this</span><span style=3D"color:#660">,</span><sp=
an style=3D"color:#000"> rhs</span><span style=3D"color:#660">);</span><spa=
n style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span s=
tyle=3D"color:#008">return</span><span style=3D"color:#000"> </span><span s=
tyle=3D"color:#660">*</span><span style=3D"color:#008">this</span><span sty=
le=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=
=A0</span><span style=3D"color:#660">}</span><span style=3D"color:#000"><br=
>=C2=A0=C2=A0=C2=A0=C2=A0 */<br></span></code><br>=C2=A0 =C2=A0 =C2=A0C </s=
pan><span style=3D"color:#008">operator</span><span style=3D"color:#660">+(=
</span><span style=3D"color:#008">const</span><span style=3D"color:#000"> C=
</span><span style=3D"color:#660">&amp;</span><span style=3D"color:#000"> r=
hs</span><span style=3D"color:#660">)</span><span style=3D"color:#000"><br>=
=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660">{</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0C result</span><span =
style=3D"color:#660">(*</span><span style=3D"color:#000">data </span><span =
style=3D"color:#660">+</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">*(</span><span style=3D"color:#000">rhs</span><span style=
=3D"color:#660">.</span><span style=3D"color:#000">data</span><span style=
=3D"color:#660">));</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0</span><span style=3D"color:#008">return</span><span style=
=3D"color:#000"> result</span><span style=3D"color:#660">;</span><span styl=
e=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660">=
}</span><span style=3D"color:#000"><br><br>=C2=A0</span><span style=3D"colo=
r:#008">=C2=A0=C2=A0=C2=A0 friend</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#008">void</span><span style=3D"color:#000"> swap</spa=
n><span style=3D"color:#660">(</span><span style=3D"color:#000">C</span><sp=
an style=3D"color:#660">&amp;</span><span style=3D"color:#000"> lhs</span><=
span style=3D"color:#660">,</span><span style=3D"color:#000"> C</span><span=
 style=3D"color:#660">&amp;</span><span style=3D"color:#000"> rhs</span><sp=
an style=3D"color:#660">);</span><span style=3D"color:#000"><br><br>=C2=A0=
=C2=A0=C2=A0=C2=A0 </span><span style=3D"color:#660">~</span><span style=3D=
"color:#000">C</span><span style=3D"color:#660">()</span><span style=3D"col=
or:#000"><br>=C2=A0</span><span style=3D"color:#660">=C2=A0=C2=A0=C2=A0 {</=
span><span style=3D"color:#000"><br>=C2=A0</span><span style=3D"color:#008"=
>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 delete</span><span style=3D"col=
or:#000"> data</span><span style=3D"color:#660">;</span><span style=3D"colo=
r:#000"><br>=C2=A0=C2=A0=C2=A0=C2=A0 </span><span style=3D"color:#660">}</s=
pan><span style=3D"color:#000"><br></span><span style=3D"color:#660">};</sp=
an><span style=3D"color:#000"><br><br></span><span style=3D"color:#008">voi=
d</span><span style=3D"color:#000"> swap</span><span style=3D"color:#660">(=
</span><span style=3D"color:#000">C</span><span style=3D"color:#660">&amp;<=
/span><span style=3D"color:#000"> lhs</span><span style=3D"color:#660">,</s=
pan><span style=3D"color:#000"> C</span><span style=3D"color:#660">&amp;</s=
pan><span style=3D"color:#000"> rhs</span><span style=3D"color:#660">)</spa=
n><span style=3D"color:#000"><br></span><span style=3D"color:#660">{</span>=
<span style=3D"color:#000"><br>=C2=A0=C2=A0=C2=A0 std</span><span style=3D"=
color:#660">::</span><span style=3D"color:#000">swap</span><span style=3D"c=
olor:#660">(</span><span style=3D"color:#000">lhs</span><span style=3D"colo=
r:#660">.</span><span style=3D"color:#000">data</span><span style=3D"color:=
#660">,</span><span style=3D"color:#000"> rhs</span><span style=3D"color:#6=
60">.</span><span style=3D"color:#000">data</span><span style=3D"color:#660=
">);</span><span style=3D"color:#000"><br></span><span style=3D"color:#660"=
>}</span><span style=3D"color:#000"><br><br></span><span style=3D"color:#00=
8">int</span><span style=3D"color:#000"> main</span><span style=3D"color:#6=
60">()</span><span style=3D"color:#000"><br></span><span style=3D"color:#66=
0">{</span><span style=3D"color:#000"><br>=C2=A0=C2=A0=C2=A0 C c1</span><sp=
an style=3D"color:#660">(</span><span style=3D"color:#066">7</span><span st=
yle=3D"color:#660">);</span><span style=3D"color:#000"><br>=C2=A0=C2=A0=C2=
=A0 C c2</span><span style=3D"color:#660">;</span><span style=3D"color:#000=
"></span><span style=3D"color:#000"><br><br>=C2=A0=C2=A0=C2=A0 // The follo=
wing will first create the &quot;result&quot; inside operator+.<br>=C2=A0 =
=C2=A0 // The return value will then get move-constructed from the result<b=
r>=C2=A0=C2=A0=C2=A0 // (I&#39;m assuming that -fno-elide-constructors opti=
on is used). Then<br>=C2=A0=C2=A0=C2=A0 // the &quot;rhs&quot; parameter of=
 operator=3D will get move-constructed from<br>=C2=A0=C2=A0=C2=A0 // this r=
eturn temporary.<br>=C2=A0=C2=A0=C2=A0 //<br>=C2=A0=C2=A0=C2=A0 // But if w=
e could overload operator=3D(C&amp;&amp;), this second move-construction<br=
>=C2=A0=C2=A0=C2=A0 // could have been avoided as the return temporary coul=
d have been directly<br>=C2=A0=C2=A0=C2=A0 // captured by rvalue reference.=
<br>=C2=A0=C2=A0=C2=A0 //<br>=C2=A0=C2=A0=C2=A0 // Granted that we can impl=
ement operator=3D(const C&amp;) and operator=3D(C&amp;&amp;)<br>=C2=A0=C2=
=A0=C2=A0 // to make assignment as efficient as possible for both lvalue an=
d rvalue<br>=C2=A0=C2=A0=C2=A0 // inputs. However, to my knowledge, having =
operator=3D(const C&amp;) would<br>=C2=A0=C2=A0=C2=A0 // essentially preven=
t us from having the copy-swap idiom.<br><br>=C2=A0=C2=A0=C2=A0 c2 </span><=
span style=3D"color:#660">=3D</span><span style=3D"color:#000"> c1 </span><=
span style=3D"color:#660">+</span><span style=3D"color:#000"> c1</span><spa=
n style=3D"color:#660">;</span><span style=3D"color:#000"><br><br>=C2=A0</s=
pan><span style=3D"color:#008">=C2=A0=C2=A0 return</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#066">0</span><span style=3D"color:#6=
60">;</span><span style=3D"color:#000"><br></span><span style=3D"color:#660=
">}</span><span><font color=3D"#888888"><span style=3D"color:#000"><br></sp=
an></font></span></div></code></div><span><font color=3D"#888888"><br><br><=
/font></span></div><span><font color=3D"#888888">

<p></p>

-- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"=
rL4IJPuUCAAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D&#39;javascript:&=
#39;;return true;" onclick=3D"this.href=3D&#39;javascript:&#39;;return true=
;">std-proposal...@<wbr>isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"javascript:" target=3D"_bla=
nk" gdf-obfuscated-mailto=3D"rL4IJPuUCAAJ" rel=3D"nofollow" onmousedown=3D"=
this.href=3D&#39;javascript:&#39;;return true;" onclick=3D"this.href=3D&#39=
;javascript:&#39;;return true;">std-pr...@isocpp.org</a>.<br>
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/62809333-fd1a-4bde-8805-ccc0578a4284%=
40isocpp.org?utm_medium=3Demail&amp;utm_source=3Dfooter" target=3D"_blank" =
rel=3D"nofollow" onmousedown=3D"this.href=3D&#39;https://groups.google.com/=
a/isocpp.org/d/msgid/std-proposals/62809333-fd1a-4bde-8805-ccc0578a4284%40i=
socpp.org?utm_medium\x3demail\x26utm_source\x3dfooter&#39;;return true;" on=
click=3D"this.href=3D&#39;https://groups.google.com/a/isocpp.org/d/msgid/st=
d-proposals/62809333-fd1a-4bde-8805-ccc0578a4284%40isocpp.org?utm_medium\x3=
demail\x26utm_source\x3dfooter&#39;;return true;">https://groups.google.com=
/a/<wbr>isocpp.org/d/msgid/std-<wbr>proposals/62809333-fd1a-4bde-<wbr>8805-=
ccc0578a4284%40isocpp.org</a><wbr>.<br>
</font></span></blockquote></div><br></div></div>
</blockquote></div></div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/a062d2a9-7805-4184-adf3-32a2986baab4%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/a062d2a9-7805-4184-adf3-32a2986baab4=
%40isocpp.org</a>.<br />

------=_Part_9279_1637493190.1523699007450--

------=_Part_9278_241452772.1523699007449--

.


Author: oguzakyuz@gmail.com
Date: Sat, 14 Apr 2018 02:47:53 -0700 (PDT)
Raw View
------=_Part_12470_1064850336.1523699273498
Content-Type: multipart/alternative;
 boundary="----=_Part_12471_405560012.1523699273499"

------=_Part_12471_405560012.1523699273499
Content-Type: text/plain; charset="UTF-8"

Oops, never mind. You've actually answered this question. In the case of
copy-elision, value parameter can be faster than r-value reference (or
l-value reference for that matter)!

Cheers,
Oguz

On Saturday, April 14, 2018 at 12:43:27 PM UTC+3, oguz...@gmail.com wrote:
>
> I think this is very reasonable. My original question was regarding the
> case when copy-elision was turned off. However, you are right that in a
> real world setting copy elision will take place and the maximum efficiency
> can be gained by implementing all three versions. Whether this minimal gain
> in efficiency is worth the effort of adding an extra function is something
> that everybody should consider for their own application.
>
> In my original question I also wanted to find out if rules could not be
> set up to choose an rvalue reference over value parameter in overloading
> resolution. rvalue reference is chosen over lvalue reference, so why not
> rvalue reference is not chosen over value parameter? Is there a case when a
> programmer would prefer the pass-by-value for a temporary object?
>
> Thanks,
> Oguz
>
> On Friday, April 13, 2018 at 2:04:47 PM UTC+3, Richard Hodges wrote:
>>
>>
>>
>> On 13 April 2018 at 07:11, <oguz...@gmail.com> wrote:
>>
>>> Let me know if this is a stupid idea or something that is already
>>> considered. But to my knowledge, if we have the following operator
>>> overloads for a class, compilers will generate an ambiguity error (probably
>>> enforced by the standard):
>>>
>>
>> Imagine an external function, foo:
>>
>> extern void foo(Bar b);
>>
>> *where foo is defined in an another compilation unit*.
>>
>> That function is not expecting a reference, it is expecting a fully
>> formed Bar to exist in its arguments (i.e. for all intents and purposes 'on
>> the stack')
>>
>> assume at the call site:
>>
>> foo(Bar(arguments, of, bar));
>>
>> A well behaved compiler will:
>> 1. allocate space on the stack, in foo's argument stack frame
>> 2. construct b right there on the stack.
>> 3. assume that foo will destroy b.
>>
>> In other words, copy elision will take place. The b belongs to foo. The
>> caller constructed it on foo's behalf.
>>
>> Now consider:
>>
>> extern void foo(Bar&& b);
>>
>> The same compiler will:
>> 1. allocate space on the stack, in the *caller's* stack frame
>> 2. construct b right there on the stack.
>> 3. pass the address of b to foo
>> 4. call b's destructor upon foo's return
>>
>> Now consider
>>
>> extern void foo(Bar const& b);
>>
>> The same compiler will:
>> 1. allocate space on the stack, in the caller's stack frame
>> 2. construct b right there on the stack.
>> 3. pass the address of b to foo
>> 4. call b's destructor upon foo's return
>>
>> In the pass-by-reference cases the code incurs a cost of one extra
>> operation on the stack - pushing the address of b. The only difference in
>> the implementations is when the work of destruction is done. The same
>> amount of work is actually done.
>>
>> The question is, do we mind about this minuscule extra cost?
>>
>> If we absolutely do, then it's worth thinking about allowing the 3
>> overloads to coexist (this may be a can of worms?).
>>
>> If we don't mind about the push, probably best to leave it alone.
>>
>> That's my 2c.
>>
>> Does that seem reasonable?
>>
>>
>>
>>>
>>> C& C::operator=(C rhs);
>>> C& C::operator=(C&& rhs);
>>>
>>> However, if the compilers could choose the rvalue reference version over the pass-by-value version for rvalue arguments (i.e. c2 = c1 + c1), it could lead to an efficient copy-swap idiom implementation.
>>>
>>> Below is a sample code that demonstrates the problem. The issue is explained by the long comment block inside the main function:
>>>
>>>
>>> #include <algorithm>
>>>
>>> class C
>>> {
>>>     int* data;
>>>
>>>      public:
>>>
>>>      C() : data(nullptr) { }
>>>
>>>      C(int data) : data(new int)
>>>      {
>>>          *(this->data) = data;
>>>      }
>>>
>>>      C(const C& rhs) : data(new int)
>>>      {
>>>          *data = *(rhs.data);
>>>      }
>>>
>>>      C(C&& rhs) : C()
>>>      {
>>>          // Move constructor is first creating a default
>>>          // object and swapping it with the rvalue reference.
>>>          swap(*this, rhs);
>>>      }
>>>
>>>      C& operator=(C rhs)
>>>      {
>>>          // We let the compiler copy into rhs and we swap the
>>>          // current object with this copy. Together with the
>>>          // move constructor above, this implements the copy-swap
>>>          // idiom. Thanks to the move-constructor above, the
>>>          // copy to rhs is not a deep copy if the input is an rvalue
>>>          // reference.
>>>          swap(*this, rhs);
>>>          return *this;
>>>      }
>>>
>>>      // The function below is commented out because it fails compilation
>>>      // due to ambiguity with the above function. However, if it worked
>>>      // it could have saved us an extra call to the move constructor when
>>>      // we make calls such as c2 = c1 + c1 (see operator+ below). If it
>>> had
>>>      // worked, the temporary created from c1 + c1 would have been
>>> directly
>>>      // taken by rvalue reference instead of its copy  (albeit shallow)
>>> being
>>>      // created.
>>>
>>>      /*
>>>      C& operator=(C&& rhs)
>>>      {
>>>          swap(*this, rhs);
>>>          return *this;
>>>      }
>>>      */
>>>
>>>      C operator+(const C& rhs)
>>>      {
>>>          C result(*data + *(rhs.data));
>>>          return result;
>>>      }
>>>
>>>      friend void swap(C& lhs, C& rhs);
>>>
>>>      ~C()
>>>      {
>>>          delete data;
>>>      }
>>> };
>>>
>>> void swap(C& lhs, C& rhs)
>>> {
>>>     std::swap(lhs.data, rhs.data);
>>> }
>>>
>>> int main()
>>> {
>>>     C c1(7);
>>>     C c2;
>>>
>>>     // The following will first create the "result" inside operator+.
>>>     // The return value will then get move-constructed from the result
>>>     // (I'm assuming that -fno-elide-constructors option is used). Then
>>>     // the "rhs" parameter of operator= will get move-constructed from
>>>     // this return temporary.
>>>     //
>>>     // But if we could overload operator=(C&&), this second
>>> move-construction
>>>     // could have been avoided as the return temporary could have been
>>> directly
>>>     // captured by rvalue reference.
>>>     //
>>>     // Granted that we can implement operator=(const C&) and
>>> operator=(C&&)
>>>     // to make assignment as efficient as possible for both lvalue and
>>> rvalue
>>>     // inputs. However, to my knowledge, having operator=(const C&) would
>>>     // essentially prevent us from having the copy-swap idiom.
>>>
>>>     c2 = c1 + c1;
>>>
>>>     return 0;
>>> }
>>>
>>>
>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "ISO C++ Standard - Future Proposals" group.
>>> To unsubscribe from this group and stop receiving emails from it, send
>>> an email to std-proposal...@isocpp.org.
>>> To post to this group, send email to std-pr...@isocpp.org.
>>> To view this discussion on the web visit
>>> https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/62809333-fd1a-4bde-8805-ccc0578a4284%40isocpp.org
>>> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/62809333-fd1a-4bde-8805-ccc0578a4284%40isocpp.org?utm_medium=email&utm_source=footer>
>>> .
>>>
>>
>>

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/ebb1c149-3142-450b-bfdb-ff7bb3f4581a%40isocpp.org.

------=_Part_12471_405560012.1523699273499
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Oops, never mind. You&#39;ve actually answered this questi=
on. In the case of copy-elision, value parameter can be faster than r-value=
 reference (or l-value reference for that matter)!<div><br></div><div>Cheer=
s,</div><div>Oguz<br><br>On Saturday, April 14, 2018 at 12:43:27 PM UTC+3, =
oguz...@gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: =
0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div d=
ir=3D"ltr">I think this is very reasonable. My original question was regard=
ing the case when copy-elision was turned off. However, you are right that =
in a real world setting copy elision will take place and the maximum effici=
ency can be gained by implementing all three versions. Whether this minimal=
 gain in efficiency is worth the effort of adding an extra function is some=
thing that everybody should consider for their own application.<div><br></d=
iv><div>In my original question I also wanted to find out if rules could no=
t be set up to choose an rvalue reference over value parameter in overloadi=
ng resolution. rvalue reference is chosen over lvalue reference, so why not=
 rvalue reference is not chosen over value parameter? Is there a case when =
a programmer would prefer the pass-by-value for a temporary object?<br><div=
><br></div><div>Thanks,</div><div>Oguz<br><br>On Friday, April 13, 2018 at =
2:04:47 PM UTC+3, Richard Hodges wrote:<blockquote class=3D"gmail_quote" st=
yle=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1=
ex"><div dir=3D"ltr"><br><div><br><div class=3D"gmail_quote">On 13 April 20=
18 at 07:11,  <span dir=3D"ltr">&lt;<a rel=3D"nofollow">oguz...@gmail.com</=
a>&gt;</span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0=
 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">Let=
 me know if this is a stupid idea or something that is already considered. =
But to my knowledge, if we have the following operator overloads for a clas=
s, compilers will generate an ambiguity error (probably enforced by the sta=
ndard):<br></div></blockquote><div><br></div><div>Imagine an external funct=
ion, foo:<br></div><div><br></div><div><font face=3D"monospace, monospace">=
extern void foo(Bar b);</font></div><div><br></div><div><b>where foo is def=
ined in an another compilation unit</b>.=C2=A0</div><div><br></div><div>Tha=
t function is not expecting a reference, it is expecting a fully formed Bar=
 to exist in its arguments (i.e. for all intents and purposes &#39;on the s=
tack&#39;)</div><div><br></div><div>assume at the call site:=C2=A0</div><di=
v><br></div><div><font face=3D"monospace, monospace">foo(Bar(arguments, of,=
 bar));</font></div><div><br></div><div>A well behaved compiler will:</div>=
<div>1. allocate space on the stack, in foo&#39;s argument stack frame</div=
><div>2. construct b right there on the stack.</div><div>3. assume that foo=
 will destroy b.</div><div><br></div><div>In other words, copy elision will=
 take place. The b belongs to foo. The caller constructed it on foo&#39;s b=
ehalf.</div><div><br></div><div>Now consider:</div><div><br></div><div><fon=
t face=3D"monospace, monospace">extern void foo(Bar&amp;&amp; b);</font></d=
iv><div><br></div><div>The same compiler will:</div><div><div style=3D"colo=
r:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:nor=
mal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;=
text-transform:none;white-space:normal;word-spacing:0px;background-color:rg=
b(255,255,255)">1. allocate space on the stack, in the <u>caller&#39;s</u> =
stack frame</div><div style=3D"color:rgb(34,34,34);font-family:arial,sans-s=
erif;font-size:small;font-style:normal;font-weight:400;letter-spacing:norma=
l;text-align:start;text-indent:0px;text-transform:none;white-space:normal;w=
ord-spacing:0px;background-color:rgb(255,255,255)">2. construct b right the=
re on the stack.</div><div style=3D"color:rgb(34,34,34);font-family:arial,s=
ans-serif;font-size:small;font-style:normal;font-weight:400;letter-spacing:=
normal;text-align:start;text-indent:0px;text-transform:none;white-space:nor=
mal;word-spacing:0px;background-color:rgb(255,255,255)">3. pass the address=
 of b to foo</div><div style=3D"color:rgb(34,34,34);font-family:arial,sans-=
serif;font-size:small;font-style:normal;font-weight:400;letter-spacing:norm=
al;text-align:start;text-indent:0px;text-transform:none;white-space:normal;=
word-spacing:0px;background-color:rgb(255,255,255)">4. call b&#39;s destruc=
tor upon foo&#39;s return</div><div style=3D"color:rgb(34,34,34);font-famil=
y:arial,sans-serif;font-size:small;font-style:normal;font-weight:400;letter=
-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-=
space:normal;word-spacing:0px;background-color:rgb(255,255,255)"><br></div>=
<div style=3D"color:rgb(34,34,34);font-size:small;font-style:normal;font-we=
ight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transf=
orm:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,2=
55)"><div style=3D"font-family:arial,sans-serif">Now consider</div><div sty=
le=3D"font-family:arial,sans-serif"><br></div><div><font face=3D"monospace,=
 monospace">extern void foo(Bar const&amp; b);</font></div><div style=3D"fo=
nt-family:arial,sans-serif"><br></div><div style=3D"font-family:arial,sans-=
serif">The same compiler will:</div><div style=3D"font-family:arial,sans-se=
rif"><div style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-si=
ze:small;font-style:normal;font-weight:400;letter-spacing:normal;text-align=
:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:=
0px;background-color:rgb(255,255,255)">1. allocate space on the stack, in t=
he caller&#39;s stack frame</div><div style=3D"color:rgb(34,34,34);font-fam=
ily:arial,sans-serif;font-size:small;font-style:normal;font-weight:400;lett=
er-spacing:normal;text-align:start;text-indent:0px;text-transform:none;whit=
e-space:normal;word-spacing:0px;background-color:rgb(255,255,255)">2. const=
ruct b right there on the stack.</div><div style=3D"color:rgb(34,34,34);fon=
t-family:arial,sans-serif;font-size:small;font-style:normal;font-weight:400=
;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none=
;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255)">3. =
pass the address of b to foo</div><div style=3D"color:rgb(34,34,34);font-fa=
mily:arial,sans-serif;font-size:small;font-style:normal;font-weight:400;let=
ter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;whi=
te-space:normal;word-spacing:0px;background-color:rgb(255,255,255)">4. call=
 b&#39;s destructor upon foo&#39;s return</div><br></div>In the pass-by-ref=
erence cases the code incurs a cost of one extra operation on the stack - p=
ushing the address of b. The only difference in the implementations is when=
 the work of destruction is done. The same amount of work is actually done.=
</div><div style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-s=
ize:small;font-style:normal;font-weight:400;letter-spacing:normal;text-alig=
n:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing=
:0px;background-color:rgb(255,255,255)"><br></div><div style=3D"color:rgb(3=
4,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;fon=
t-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-tr=
ansform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,2=
55,255)">The question is, do we mind about this minuscule extra cost?</div>=
<div style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:sm=
all;font-style:normal;font-weight:400;letter-spacing:normal;text-align:star=
t;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;b=
ackground-color:rgb(255,255,255)"><br></div><div style=3D"color:rgb(34,34,3=
4);font-family:arial,sans-serif;font-size:small;font-style:normal;font-weig=
ht:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transfor=
m:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255=
)">If we absolutely do, then it&#39;s worth thinking about allowing the 3 o=
verloads to coexist (this may be a can of worms?).</div><div style=3D"color=
:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:norm=
al;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;t=
ext-transform:none;white-space:normal;word-spacing:0px;background-color:rgb=
(255,255,255)"><br></div><div style=3D"color:rgb(34,34,34);font-family:aria=
l,sans-serif;font-size:small;font-style:normal;font-weight:400;letter-spaci=
ng:normal;text-align:start;text-indent:0px;text-transform:none;white-space:=
normal;word-spacing:0px;background-color:rgb(255,255,255)">If we don&#39;t =
mind about the push, probably best to leave it alone.</div><div style=3D"co=
lor:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:n=
ormal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0p=
x;text-transform:none;white-space:normal;word-spacing:0px;background-color:=
rgb(255,255,255)"><br></div><div style=3D"color:rgb(34,34,34);font-family:a=
rial,sans-serif;font-size:small;font-style:normal;font-weight:400;letter-sp=
acing:normal;text-align:start;text-indent:0px;text-transform:none;white-spa=
ce:normal;word-spacing:0px;background-color:rgb(255,255,255)">That&#39;s my=
 2c.</div><br></div><div>Does that seem reasonable?</div><div><br></div><di=
v>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;=
border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><br><pre><cod=
e><span>C</span><span>&amp;</span><span> C::</span><span>operator</span><sp=
an>=3D(</span><span>C rhs</span><span>);<br></span></code><code><span>C</sp=
an><span>&amp;</span><span> C::</span><span>operator</span><span>=3D(</span=
><span>C&amp;&amp; rhs</span><span>);</span></code><br><br>However, if the =
compilers could choose the rvalue reference version over the pass-by-value =
version for rvalue arguments (i.e. c2 =3D c1 + c1), it could lead to an eff=
icient copy-swap idiom implementation.<br><br>Below is a sample code that d=
emonstrates the problem. The issue is explained by the long comment block i=
nside the main function:<br><code><span></span></code></pre><br><div style=
=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);border-=
style:solid;border-width:1px"><code><div><span style=3D"color:#000">#includ=
e &lt;algorithm&gt;<br><br></span><span style=3D"color:#008">class</span><s=
pan style=3D"color:#000"> C<br></span><span style=3D"color:#660">{</span><s=
pan style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#008=
">int</span><span style=3D"color:#660">*</span><span style=3D"color:#000"> =
data</span><span style=3D"color:#660">;</span><span style=3D"color:#000"><b=
r><br>=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#008">public</span><s=
pan style=3D"color:#660">:</span><span style=3D"color:#000"><br><br>=C2=A0 =
=C2=A0 =C2=A0C</span><span style=3D"color:#660">()</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#660">:</span><span style=3D"color:#0=
00"> data</span><span style=3D"color:#660">(</span><span style=3D"color:#00=
8">nullptr</span><span style=3D"color:#660">)</span><span style=3D"color:#0=
00"> </span><span style=3D"color:#660">{</span><span style=3D"color:#000"> =
</span><span style=3D"color:#660">}</span><span style=3D"color:#000"><br><b=
r>=C2=A0 =C2=A0 =C2=A0C</span><span style=3D"color:#660">(</span><span styl=
e=3D"color:#008">int</span><span style=3D"color:#000"> data</span><span sty=
le=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D=
"color:#660">:</span><span style=3D"color:#000"> data</span><span style=3D"=
color:#660">(</span><span style=3D"color:#008">new</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#008">int</span><span style=3D"color:=
#660">)</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0</span><sp=
an style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660">*(</span><span st=
yle=3D"color:#008">this</span><span style=3D"color:#660">-&gt;</span><span =
style=3D"color:#000">data</span><span style=3D"color:#660">)</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#660">=3D</span><span style=
=3D"color:#000"> data</span><span style=3D"color:#660">;</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660">}=
</span><span style=3D"color:#000"><br><br>=C2=A0 =C2=A0 =C2=A0C</span><span=
 style=3D"color:#660">(</span><span style=3D"color:#008">const</span><span =
style=3D"color:#000"> C</span><span style=3D"color:#660">&amp;</span><span =
style=3D"color:#000"> rhs</span><span style=3D"color:#660">)</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#660">:</span><span style=
=3D"color:#000"> data</span><span style=3D"color:#660">(</span><span style=
=3D"color:#008">new</span><span style=3D"color:#000"> </span><span style=3D=
"color:#008">int</span><span style=3D"color:#660">)</span><span style=3D"co=
lor:#000"><br>=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660">{</span=
><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><s=
pan style=3D"color:#660">*</span><span style=3D"color:#000">data </span><sp=
an style=3D"color:#660">=3D</span><span style=3D"color:#000"> </span><span =
style=3D"color:#660">*(</span><span style=3D"color:#000">rhs</span><span st=
yle=3D"color:#660">.</span><span style=3D"color:#000">data</span><span styl=
e=3D"color:#660">);</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=
=A0</span><span style=3D"color:#660">}</span><span style=3D"color:#000"><br=
><br>=C2=A0 =C2=A0 =C2=A0C</span><span style=3D"color:#660">(</span><span s=
tyle=3D"color:#000">C</span><span style=3D"color:#660">&amp;&amp;</span><sp=
an style=3D"color:#000"> rhs</span><span style=3D"color:#660">)</span><span=
 style=3D"color:#000"> </span><span style=3D"color:#660">:</span><span styl=
e=3D"color:#000"> C</span><span style=3D"color:#660">()</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660">{=
</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</s=
pan><span style=3D"color:#800">// Move constructor is first creating a defa=
ult</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=
</span><span style=3D"color:#800">// object and swapping it with the rvalue=
 reference.</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0swap</span><span style=3D"color:#660">(*</span><span style=3D"col=
or:#008">this</span><span style=3D"color:#660">,</span><span style=3D"color=
:#000"> rhs</span><span style=3D"color:#660">);</span><span style=3D"color:=
#000"><br>=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660">}</span><sp=
an style=3D"color:#000"><br><br>=C2=A0 =C2=A0 =C2=A0C</span><span style=3D"=
color:#660">&amp;</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#008">operator</span><span style=3D"color:#660">=3D(</span><span style=
=3D"color:#000">C rhs</span><span style=3D"color:#660">)</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660">{=
</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</s=
pan><span style=3D"color:#800">// We let the compiler copy into rhs and we =
swap the</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0</span><span style=3D"color:#800">// current object with this copy. T=
ogether with the</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0</span><span style=3D"color:#800">// move constructor above, t=
his implements the copy-swap</span><span style=3D"color:#000"><br>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#800">// idiom. Than=
ks to the move-constructor above, the</span><span style=3D"color:#000"><br>=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#800">// copy=
 to rhs is not a deep copy if the input is an rvalue<br>=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 // reference.</span><span style=3D"color:#00=
0"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0swap</span><span style=3D"color:#6=
60">(*</span><span style=3D"color:#008">this</span><span style=3D"color:#66=
0">,</span><span style=3D"color:#000"> rhs</span><span style=3D"color:#660"=
>);</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=
</span><span style=3D"color:#008">return</span><span style=3D"color:#000"> =
</span><span style=3D"color:#660">*</span><span style=3D"color:#008">this</=
span><span style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=
=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660">}</span><span style=3D"c=
olor:#000"><br><br></span>=C2=A0=C2=A0=C2=A0=C2=A0 // The function below is=
 commented out because it fails compilation<br>=C2=A0=C2=A0=C2=A0=C2=A0 // =
due to ambiguity with the above function. However, if it worked<br>=C2=A0=
=C2=A0=C2=A0=C2=A0 // it could have saved us an extra call to the move cons=
tructor when<br>=C2=A0=C2=A0=C2=A0=C2=A0 // we make calls such as c2 =3D c1=
 + c1 (see operator+ below). If it had<br>=C2=A0=C2=A0=C2=A0=C2=A0 // worke=
d, the temporary created from c1 + c1 would have been directly <br>=C2=A0=
=C2=A0=C2=A0=C2=A0 // taken by rvalue reference instead of its copy=C2=A0 (=
albeit shallow) being<br>=C2=A0=C2=A0=C2=A0=C2=A0 // created. <br>=C2=A0=C2=
=A0=C2=A0=C2=A0 <br>=C2=A0=C2=A0=C2=A0=C2=A0 /*<br><span style=3D"color:#00=
0"><code><span style=3D"color:#000">=C2=A0=C2=A0=C2=A0=C2=A0 C</span><span =
style=3D"color:#660">&amp;</span><span style=3D"color:#000"> </span><span s=
tyle=3D"color:#008">operator</span><span style=3D"color:#660">=3D(</span><s=
pan style=3D"color:#000">C&amp;&amp; rhs</span><span style=3D"color:#660">)=
</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0=C2=A0 </span><span styl=
e=3D"color:#660">{</span><span style=3D"color:#000"></span><span style=3D"c=
olor:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0swap</span><span style=3D"=
color:#660">(*</span><span style=3D"color:#008">this</span><span style=3D"c=
olor:#660">,</span><span style=3D"color:#000"> rhs</span><span style=3D"col=
or:#660">);</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0</span><span style=3D"color:#008">return</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#660">*</span><span style=3D"color:#0=
08">this</span><span style=3D"color:#660">;</span><span style=3D"color:#000=
"><br>=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660">}</span><span s=
tyle=3D"color:#000"><br>=C2=A0=C2=A0=C2=A0=C2=A0 */<br></span></code><br>=
=C2=A0 =C2=A0 =C2=A0C </span><span style=3D"color:#008">operator</span><spa=
n style=3D"color:#660">+(</span><span style=3D"color:#008">const</span><spa=
n style=3D"color:#000"> C</span><span style=3D"color:#660">&amp;</span><spa=
n style=3D"color:#000"> rhs</span><span style=3D"color:#660">)</span><span =
style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#6=
60">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0C result</span><span style=3D"color:#660">(*</span><span style=3D"color:=
#000">data </span><span style=3D"color:#660">+</span><span style=3D"color:#=
000"> </span><span style=3D"color:#660">*(</span><span style=3D"color:#000"=
>rhs</span><span style=3D"color:#660">.</span><span style=3D"color:#000">da=
ta</span><span style=3D"color:#660">));</span><span style=3D"color:#000"><b=
r>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#008">retur=
n</span><span style=3D"color:#000"> result</span><span style=3D"color:#660"=
>;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0</span><span st=
yle=3D"color:#660">}</span><span style=3D"color:#000"><br><br>=C2=A0</span>=
<span style=3D"color:#008">=C2=A0=C2=A0=C2=A0 friend</span><span style=3D"c=
olor:#000"> </span><span style=3D"color:#008">void</span><span style=3D"col=
or:#000"> swap</span><span style=3D"color:#660">(</span><span style=3D"colo=
r:#000">C</span><span style=3D"color:#660">&amp;</span><span style=3D"color=
:#000"> lhs</span><span style=3D"color:#660">,</span><span style=3D"color:#=
000"> C</span><span style=3D"color:#660">&amp;</span><span style=3D"color:#=
000"> rhs</span><span style=3D"color:#660">);</span><span style=3D"color:#0=
00"><br><br>=C2=A0=C2=A0=C2=A0=C2=A0 </span><span style=3D"color:#660">~</s=
pan><span style=3D"color:#000">C</span><span style=3D"color:#660">()</span>=
<span style=3D"color:#000"><br>=C2=A0</span><span style=3D"color:#660">=C2=
=A0=C2=A0=C2=A0 {</span><span style=3D"color:#000"><br>=C2=A0</span><span s=
tyle=3D"color:#008">=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 delete</span=
><span style=3D"color:#000"> data</span><span style=3D"color:#660">;</span>=
<span style=3D"color:#000"><br>=C2=A0=C2=A0=C2=A0=C2=A0 </span><span style=
=3D"color:#660">}</span><span style=3D"color:#000"><br></span><span style=
=3D"color:#660">};</span><span style=3D"color:#000"><br><br></span><span st=
yle=3D"color:#008">void</span><span style=3D"color:#000"> swap</span><span =
style=3D"color:#660">(</span><span style=3D"color:#000">C</span><span style=
=3D"color:#660">&amp;</span><span style=3D"color:#000"> lhs</span><span sty=
le=3D"color:#660">,</span><span style=3D"color:#000"> C</span><span style=
=3D"color:#660">&amp;</span><span style=3D"color:#000"> rhs</span><span sty=
le=3D"color:#660">)</span><span style=3D"color:#000"><br></span><span style=
=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0=C2=A0=C2=A0 s=
td</span><span style=3D"color:#660">::</span><span style=3D"color:#000">swa=
p</span><span style=3D"color:#660">(</span><span style=3D"color:#000">lhs</=
span><span style=3D"color:#660">.</span><span style=3D"color:#000">data</sp=
an><span style=3D"color:#660">,</span><span style=3D"color:#000"> rhs</span=
><span style=3D"color:#660">.</span><span style=3D"color:#000">data</span><=
span style=3D"color:#660">);</span><span style=3D"color:#000"><br></span><s=
pan style=3D"color:#660">}</span><span style=3D"color:#000"><br><br></span>=
<span style=3D"color:#008">int</span><span style=3D"color:#000"> main</span=
><span style=3D"color:#660">()</span><span style=3D"color:#000"><br></span>=
<span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0=C2=
=A0=C2=A0 C c1</span><span style=3D"color:#660">(</span><span style=3D"colo=
r:#066">7</span><span style=3D"color:#660">);</span><span style=3D"color:#0=
00"><br>=C2=A0=C2=A0=C2=A0 C c2</span><span style=3D"color:#660">;</span><s=
pan style=3D"color:#000"></span><span style=3D"color:#000"><br><br>=C2=A0=
=C2=A0=C2=A0 // The following will first create the &quot;result&quot; insi=
de operator+.<br>=C2=A0 =C2=A0 // The return value will then get move-const=
ructed from the result<br>=C2=A0=C2=A0=C2=A0 // (I&#39;m assuming that -fno=
-elide-constructors option is used). Then<br>=C2=A0=C2=A0=C2=A0 // the &quo=
t;rhs&quot; parameter of operator=3D will get move-constructed from<br>=C2=
=A0=C2=A0=C2=A0 // this return temporary.<br>=C2=A0=C2=A0=C2=A0 //<br>=C2=
=A0=C2=A0=C2=A0 // But if we could overload operator=3D(C&amp;&amp;), this =
second move-construction<br>=C2=A0=C2=A0=C2=A0 // could have been avoided a=
s the return temporary could have been directly<br>=C2=A0=C2=A0=C2=A0 // ca=
ptured by rvalue reference.<br>=C2=A0=C2=A0=C2=A0 //<br>=C2=A0=C2=A0=C2=A0 =
// Granted that we can implement operator=3D(const C&amp;) and operator=3D(=
C&amp;&amp;)<br>=C2=A0=C2=A0=C2=A0 // to make assignment as efficient as po=
ssible for both lvalue and rvalue<br>=C2=A0=C2=A0=C2=A0 // inputs. However,=
 to my knowledge, having operator=3D(const C&amp;) would<br>=C2=A0=C2=A0=C2=
=A0 // essentially prevent us from having the copy-swap idiom.<br><br>=C2=
=A0=C2=A0=C2=A0 c2 </span><span style=3D"color:#660">=3D</span><span style=
=3D"color:#000"> c1 </span><span style=3D"color:#660">+</span><span style=
=3D"color:#000"> c1</span><span style=3D"color:#660">;</span><span style=3D=
"color:#000"><br><br>=C2=A0</span><span style=3D"color:#008">=C2=A0=C2=A0 r=
eturn</span><span style=3D"color:#000"> </span><span style=3D"color:#066">0=
</span><span style=3D"color:#660">;</span><span style=3D"color:#000"><br></=
span><span style=3D"color:#660">}</span><span><font color=3D"#888888"><span=
 style=3D"color:#000"><br></span></font></span></div></code></div><span><fo=
nt color=3D"#888888"><br><br></font></span></div><span><font color=3D"#8888=
88">

<p></p>

-- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a rel=3D"nofollow">std-proposal...@isocpp.org</a>.<br>
To post to this group, send email to <a rel=3D"nofollow">std-pr...@isocpp.o=
rg</a>.<br>
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/62809333-fd1a-4bde-8805-ccc0578a4284%=
40isocpp.org?utm_medium=3Demail&amp;utm_source=3Dfooter" rel=3D"nofollow" t=
arget=3D"_blank" onmousedown=3D"this.href=3D&#39;https://groups.google.com/=
a/isocpp.org/d/msgid/std-proposals/62809333-fd1a-4bde-8805-ccc0578a4284%40i=
socpp.org?utm_medium\x3demail\x26utm_source\x3dfooter&#39;;return true;" on=
click=3D"this.href=3D&#39;https://groups.google.com/a/isocpp.org/d/msgid/st=
d-proposals/62809333-fd1a-4bde-8805-ccc0578a4284%40isocpp.org?utm_medium\x3=
demail\x26utm_source\x3dfooter&#39;;return true;">https://groups.google.com=
/a/<wbr>isocpp.org/d/msgid/std-<wbr>proposals/62809333-fd1a-4bde-<wbr>8805-=
ccc0578a4284%40isocpp.org</a><wbr>.<br>
</font></span></blockquote></div><br></div></div>
</blockquote></div></div></div></blockquote></div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/ebb1c149-3142-450b-bfdb-ff7bb3f4581a%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/ebb1c149-3142-450b-bfdb-ff7bb3f4581a=
%40isocpp.org</a>.<br />

------=_Part_12471_405560012.1523699273499--

------=_Part_12470_1064850336.1523699273498--

.


Author: oguzakyuz@gmail.com
Date: Wed, 18 Apr 2018 19:56:44 -0700 (PDT)
Raw View
------=_Part_827_1668056776.1524106604411
Content-Type: multipart/alternative;
 boundary="----=_Part_828_1402306567.1524106604413"

------=_Part_828_1402306567.1524106604413
Content-Type: text/plain; charset="UTF-8"

Thinking and experimenting a bit more about it, the three overloads cannot
co-exist right?

My observation has been that as soon as you have "void foo(Bar b)" together
with the either reference version, you start to get ambiguous overload
error from the compiler. This doesn't work:

class C
{
};


void f(C a)
{
}


void f(const C& a)
{
}


void f(C&& a)
{
}


int main()
{
    f(C());
    return 0;
}


Cheers,
Oguz

On Friday, April 13, 2018 at 2:04:47 PM UTC+3, Richard Hodges wrote:
>
>
>
> On 13 April 2018 at 07:11, <oguz...@gmail.com <javascript:>> wrote:
>
>> Let me know if this is a stupid idea or something that is already
>> considered. But to my knowledge, if we have the following operator
>> overloads for a class, compilers will generate an ambiguity error (probably
>> enforced by the standard):
>>
>
> Imagine an external function, foo:
>
> extern void foo(Bar b);
>
> *where foo is defined in an another compilation unit*.
>
> That function is not expecting a reference, it is expecting a fully formed
> Bar to exist in its arguments (i.e. for all intents and purposes 'on the
> stack')
>
> assume at the call site:
>
> foo(Bar(arguments, of, bar));
>
> A well behaved compiler will:
> 1. allocate space on the stack, in foo's argument stack frame
> 2. construct b right there on the stack.
> 3. assume that foo will destroy b.
>
> In other words, copy elision will take place. The b belongs to foo. The
> caller constructed it on foo's behalf.
>
> Now consider:
>
> extern void foo(Bar&& b);
>
> The same compiler will:
> 1. allocate space on the stack, in the *caller's* stack frame
> 2. construct b right there on the stack.
> 3. pass the address of b to foo
> 4. call b's destructor upon foo's return
>
> Now consider
>
> extern void foo(Bar const& b);
>
> The same compiler will:
> 1. allocate space on the stack, in the caller's stack frame
> 2. construct b right there on the stack.
> 3. pass the address of b to foo
> 4. call b's destructor upon foo's return
>
> In the pass-by-reference cases the code incurs a cost of one extra
> operation on the stack - pushing the address of b. The only difference in
> the implementations is when the work of destruction is done. The same
> amount of work is actually done.
>
> The question is, do we mind about this minuscule extra cost?
>
> If we absolutely do, then it's worth thinking about allowing the 3
> overloads to coexist (this may be a can of worms?).
>
> If we don't mind about the push, probably best to leave it alone.
>
> That's my 2c.
>
> Does that seem reasonable?
>
>
>
>>
>> C& C::operator=(C rhs);
>> C& C::operator=(C&& rhs);
>>
>> However, if the compilers could choose the rvalue reference version over the pass-by-value version for rvalue arguments (i.e. c2 = c1 + c1), it could lead to an efficient copy-swap idiom implementation.
>>
>> Below is a sample code that demonstrates the problem. The issue is explained by the long comment block inside the main function:
>>
>>
>> #include <algorithm>
>>
>> class C
>> {
>>     int* data;
>>
>>      public:
>>
>>      C() : data(nullptr) { }
>>
>>      C(int data) : data(new int)
>>      {
>>          *(this->data) = data;
>>      }
>>
>>      C(const C& rhs) : data(new int)
>>      {
>>          *data = *(rhs.data);
>>      }
>>
>>      C(C&& rhs) : C()
>>      {
>>          // Move constructor is first creating a default
>>          // object and swapping it with the rvalue reference.
>>          swap(*this, rhs);
>>      }
>>
>>      C& operator=(C rhs)
>>      {
>>          // We let the compiler copy into rhs and we swap the
>>          // current object with this copy. Together with the
>>          // move constructor above, this implements the copy-swap
>>          // idiom. Thanks to the move-constructor above, the
>>          // copy to rhs is not a deep copy if the input is an rvalue
>>          // reference.
>>          swap(*this, rhs);
>>          return *this;
>>      }
>>
>>      // The function below is commented out because it fails compilation
>>      // due to ambiguity with the above function. However, if it worked
>>      // it could have saved us an extra call to the move constructor when
>>      // we make calls such as c2 = c1 + c1 (see operator+ below). If it
>> had
>>      // worked, the temporary created from c1 + c1 would have been
>> directly
>>      // taken by rvalue reference instead of its copy  (albeit shallow)
>> being
>>      // created.
>>
>>      /*
>>      C& operator=(C&& rhs)
>>      {
>>          swap(*this, rhs);
>>          return *this;
>>      }
>>      */
>>
>>      C operator+(const C& rhs)
>>      {
>>          C result(*data + *(rhs.data));
>>          return result;
>>      }
>>
>>      friend void swap(C& lhs, C& rhs);
>>
>>      ~C()
>>      {
>>          delete data;
>>      }
>> };
>>
>> void swap(C& lhs, C& rhs)
>> {
>>     std::swap(lhs.data, rhs.data);
>> }
>>
>> int main()
>> {
>>     C c1(7);
>>     C c2;
>>
>>     // The following will first create the "result" inside operator+.
>>     // The return value will then get move-constructed from the result
>>     // (I'm assuming that -fno-elide-constructors option is used). Then
>>     // the "rhs" parameter of operator= will get move-constructed from
>>     // this return temporary.
>>     //
>>     // But if we could overload operator=(C&&), this second
>> move-construction
>>     // could have been avoided as the return temporary could have been
>> directly
>>     // captured by rvalue reference.
>>     //
>>     // Granted that we can implement operator=(const C&) and
>> operator=(C&&)
>>     // to make assignment as efficient as possible for both lvalue and
>> rvalue
>>     // inputs. However, to my knowledge, having operator=(const C&) would
>>     // essentially prevent us from having the copy-swap idiom.
>>
>>     c2 = c1 + c1;
>>
>>     return 0;
>> }
>>
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "ISO C++ Standard - Future Proposals" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to std-proposal...@isocpp.org <javascript:>.
>> To post to this group, send email to std-pr...@isocpp.org <javascript:>.
>> To view this discussion on the web visit
>> https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/62809333-fd1a-4bde-8805-ccc0578a4284%40isocpp.org
>> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/62809333-fd1a-4bde-8805-ccc0578a4284%40isocpp.org?utm_medium=email&utm_source=footer>
>> .
>>
>
>

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/bfbf87e6-1949-4560-9bad-ac939b2db71f%40isocpp.org.

------=_Part_828_1402306567.1524106604413
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Thinking and experimenting a bit more about it, the three =
overloads cannot co-exist right?<div><br></div><div>My observation has been=
 that as soon as you have &quot;<span style=3D"font-family: monospace, mono=
space;">void foo(Bar b)&quot; together with the either reference version, y=
ou start to get ambiguous overload error from the compiler. This doesn&#39;=
t work:</span></div><div><span style=3D"font-family: monospace, monospace;"=
><br></span></div><div><div class=3D"prettyprint" style=3D"background-color=
: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: solid=
; border-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><d=
iv class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-by=
-prettify">class</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> C<br></span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">};</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"><br><br><br></span><s=
pan style=3D"color: #008;" class=3D"styled-by-prettify">void</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> f</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify">C a</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br><br><=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">void</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> f</span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">const</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> C</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">&amp;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> a</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">)</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br><br><br></span><spa=
n style=3D"color: #008;" class=3D"styled-by-prettify">void</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> f</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify">C</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">&amp;&amp;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> a</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">)</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br><br><br></span><spa=
n style=3D"color: #008;" class=3D"styled-by-prettify">int</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> main</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">()</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br>=C2=A0 =C2=A0 f</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify">C</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">());</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">return</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> </span><span style=3D"color: #066;" class=3D"styled-by-prettify">0=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">}</span></div></code></di=
v><div style=3D""><br></div></div><div><font face=3D"monospace, monospace">=
<br></font></div><div><font face=3D"monospace, monospace">Cheers,</font></d=
iv><div><font face=3D"monospace, monospace">Oguz</font></div><div><font fac=
e=3D"monospace, monospace"><br></font>On Friday, April 13, 2018 at 2:04:47 =
PM UTC+3, Richard Hodges wrote:<blockquote class=3D"gmail_quote" style=3D"m=
argin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"=
><div dir=3D"ltr"><br><div><br><div class=3D"gmail_quote">On 13 April 2018 =
at 07:11,  <span dir=3D"ltr">&lt;<a href=3D"javascript:" target=3D"_blank" =
gdf-obfuscated-mailto=3D"rL4IJPuUCAAJ" rel=3D"nofollow" onmousedown=3D"this=
..href=3D&#39;javascript:&#39;;return true;" onclick=3D"this.href=3D&#39;jav=
ascript:&#39;;return true;">oguz...@gmail.com</a>&gt;</span> wrote:<br><blo=
ckquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #c=
cc solid;padding-left:1ex"><div dir=3D"ltr">Let me know if this is a stupid=
 idea or something that is already considered. But to my knowledge, if we h=
ave the following operator overloads for a class, compilers will generate a=
n ambiguity error (probably enforced by the standard):<br></div></blockquot=
e><div><br></div><div>Imagine an external function, foo:<br></div><div><br>=
</div><div><font face=3D"monospace, monospace">extern void foo(Bar b);</fon=
t></div><div><br></div><div><b>where foo is defined in an another compilati=
on unit</b>.=C2=A0</div><div><br></div><div>That function is not expecting =
a reference, it is expecting a fully formed Bar to exist in its arguments (=
i.e. for all intents and purposes &#39;on the stack&#39;)</div><div><br></d=
iv><div>assume at the call site:=C2=A0</div><div><br></div><div><font face=
=3D"monospace, monospace">foo(Bar(arguments, of, bar));</font></div><div><b=
r></div><div>A well behaved compiler will:</div><div>1. allocate space on t=
he stack, in foo&#39;s argument stack frame</div><div>2. construct b right =
there on the stack.</div><div>3. assume that foo will destroy b.</div><div>=
<br></div><div>In other words, copy elision will take place. The b belongs =
to foo. The caller constructed it on foo&#39;s behalf.</div><div><br></div>=
<div>Now consider:</div><div><br></div><div><font face=3D"monospace, monosp=
ace">extern void foo(Bar&amp;&amp; b);</font></div><div><br></div><div>The =
same compiler will:</div><div><div style=3D"color:rgb(34,34,34);font-family=
:arial,sans-serif;font-size:small;font-style:normal;font-weight:400;letter-=
spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-s=
pace:normal;word-spacing:0px;background-color:rgb(255,255,255)">1. allocate=
 space on the stack, in the <u>caller&#39;s</u> stack frame</div><div style=
=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-s=
tyle:normal;font-weight:400;letter-spacing:normal;text-align:start;text-ind=
ent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-=
color:rgb(255,255,255)">2. construct b right there on the stack.</div><div =
style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;f=
ont-style:normal;font-weight:400;letter-spacing:normal;text-align:start;tex=
t-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;backgr=
ound-color:rgb(255,255,255)">3. pass the address of b to foo</div><div styl=
e=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-=
style:normal;font-weight:400;letter-spacing:normal;text-align:start;text-in=
dent:0px;text-transform:none;white-space:normal;word-spacing:0px;background=
-color:rgb(255,255,255)">4. call b&#39;s destructor upon foo&#39;s return</=
div><div style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-siz=
e:small;font-style:normal;font-weight:400;letter-spacing:normal;text-align:=
start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0=
px;background-color:rgb(255,255,255)"><br></div><div style=3D"color:rgb(34,=
34,34);font-size:small;font-style:normal;font-weight:400;letter-spacing:nor=
mal;text-align:start;text-indent:0px;text-transform:none;white-space:normal=
;word-spacing:0px;background-color:rgb(255,255,255)"><div style=3D"font-fam=
ily:arial,sans-serif">Now consider</div><div style=3D"font-family:arial,san=
s-serif"><br></div><div><font face=3D"monospace, monospace">extern void foo=
(Bar const&amp; b);</font></div><div style=3D"font-family:arial,sans-serif"=
><br></div><div style=3D"font-family:arial,sans-serif">The same compiler wi=
ll:</div><div style=3D"font-family:arial,sans-serif"><div style=3D"color:rg=
b(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;=
font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text=
-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(25=
5,255,255)">1. allocate space on the stack, in the caller&#39;s stack frame=
</div><div style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-s=
ize:small;font-style:normal;font-weight:400;letter-spacing:normal;text-alig=
n:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing=
:0px;background-color:rgb(255,255,255)">2. construct b right there on the s=
tack.</div><div style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;f=
ont-size:small;font-style:normal;font-weight:400;letter-spacing:normal;text=
-align:start;text-indent:0px;text-transform:none;white-space:normal;word-sp=
acing:0px;background-color:rgb(255,255,255)">3. pass the address of b to fo=
o</div><div style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-=
size:small;font-style:normal;font-weight:400;letter-spacing:normal;text-ali=
gn:start;text-indent:0px;text-transform:none;white-space:normal;word-spacin=
g:0px;background-color:rgb(255,255,255)">4. call b&#39;s destructor upon fo=
o&#39;s return</div><br></div>In the pass-by-reference cases the code incur=
s a cost of one extra operation on the stack - pushing the address of b. Th=
e only difference in the implementations is when the work of destruction is=
 done. The same amount of work is actually done.</div><div style=3D"color:r=
gb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal=
;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;tex=
t-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(2=
55,255,255)"><br></div><div style=3D"color:rgb(34,34,34);font-family:arial,=
sans-serif;font-size:small;font-style:normal;font-weight:400;letter-spacing=
:normal;text-align:start;text-indent:0px;text-transform:none;white-space:no=
rmal;word-spacing:0px;background-color:rgb(255,255,255)">The question is, d=
o we mind about this minuscule extra cost?</div><div style=3D"color:rgb(34,=
34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-=
weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-tran=
sform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255=
,255)"><br></div><div style=3D"color:rgb(34,34,34);font-family:arial,sans-s=
erif;font-size:small;font-style:normal;font-weight:400;letter-spacing:norma=
l;text-align:start;text-indent:0px;text-transform:none;white-space:normal;w=
ord-spacing:0px;background-color:rgb(255,255,255)">If we absolutely do, the=
n it&#39;s worth thinking about allowing the 3 overloads to coexist (this m=
ay be a can of worms?).</div><div style=3D"color:rgb(34,34,34);font-family:=
arial,sans-serif;font-size:small;font-style:normal;font-weight:400;letter-s=
pacing:normal;text-align:start;text-indent:0px;text-transform:none;white-sp=
ace:normal;word-spacing:0px;background-color:rgb(255,255,255)"><br></div><d=
iv style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:smal=
l;font-style:normal;font-weight:400;letter-spacing:normal;text-align:start;=
text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;bac=
kground-color:rgb(255,255,255)">If we don&#39;t mind about the push, probab=
ly best to leave it alone.</div><div style=3D"color:rgb(34,34,34);font-fami=
ly:arial,sans-serif;font-size:small;font-style:normal;font-weight:400;lette=
r-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white=
-space:normal;word-spacing:0px;background-color:rgb(255,255,255)"><br></div=
><div style=3D"color:rgb(34,34,34);font-family:arial,sans-serif;font-size:s=
mall;font-style:normal;font-weight:400;letter-spacing:normal;text-align:sta=
rt;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;=
background-color:rgb(255,255,255)">That&#39;s my 2c.</div><br></div><div>Do=
es that seem reasonable?</div><div><br></div><div>=C2=A0</div><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;=
padding-left:1ex"><div dir=3D"ltr"><br><pre><code><span>C</span><span>&amp;=
</span><span> C::</span><span>operator</span><span>=3D(</span><span>C rhs</=
span><span>);<br></span></code><code><span>C</span><span>&amp;</span><span>=
 C::</span><span>operator</span><span>=3D(</span><span>C&amp;&amp; rhs</spa=
n><span>);</span></code><br><br>However, if the compilers could choose the =
rvalue reference version over the pass-by-value version for rvalue argument=
s (i.e. c2 =3D c1 + c1), it could lead to an efficient copy-swap idiom impl=
ementation.<br><br>Below is a sample code that demonstrates the problem. Th=
e issue is explained by the long comment block inside the main function:<br=
><code><span></span></code></pre><br><div style=3D"background-color:rgb(250=
,250,250);border-color:rgb(187,187,187);border-style:solid;border-width:1px=
"><code><div><span style=3D"color:#000">#include &lt;algorithm&gt;<br><br><=
/span><span style=3D"color:#008">class</span><span style=3D"color:#000"> C<=
br></span><span style=3D"color:#660">{</span><span style=3D"color:#000"><br=
>=C2=A0 =C2=A0 </span><span style=3D"color:#008">int</span><span style=3D"c=
olor:#660">*</span><span style=3D"color:#000"> data</span><span style=3D"co=
lor:#660">;</span><span style=3D"color:#000"><br><br>=C2=A0 =C2=A0 =C2=A0</=
span><span style=3D"color:#008">public</span><span style=3D"color:#660">:</=
span><span style=3D"color:#000"><br><br>=C2=A0 =C2=A0 =C2=A0C</span><span s=
tyle=3D"color:#660">()</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">:</span><span style=3D"color:#000"> data</span><span style=
=3D"color:#660">(</span><span style=3D"color:#008">nullptr</span><span styl=
e=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=3D"=
color:#660">{</span><span style=3D"color:#000"> </span><span style=3D"color=
:#660">}</span><span style=3D"color:#000"><br><br>=C2=A0 =C2=A0 =C2=A0C</sp=
an><span style=3D"color:#660">(</span><span style=3D"color:#008">int</span>=
<span style=3D"color:#000"> data</span><span style=3D"color:#660">)</span><=
span style=3D"color:#000"> </span><span style=3D"color:#660">:</span><span =
style=3D"color:#000"> data</span><span style=3D"color:#660">(</span><span s=
tyle=3D"color:#008">new</span><span style=3D"color:#000"> </span><span styl=
e=3D"color:#008">int</span><span style=3D"color:#660">)</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660">{=
</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</s=
pan><span style=3D"color:#660">*(</span><span style=3D"color:#008">this</sp=
an><span style=3D"color:#660">-&gt;</span><span style=3D"color:#000">data</=
span><span style=3D"color:#660">)</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#660">=3D</span><span style=3D"color:#000"> data</span=
><span style=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =
=C2=A0 =C2=A0</span><span style=3D"color:#660">}</span><span style=3D"color=
:#000"><br><br>=C2=A0 =C2=A0 =C2=A0C</span><span style=3D"color:#660">(</sp=
an><span style=3D"color:#008">const</span><span style=3D"color:#000"> C</sp=
an><span style=3D"color:#660">&amp;</span><span style=3D"color:#000"> rhs</=
span><span style=3D"color:#660">)</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#660">:</span><span style=3D"color:#000"> data</span><=
span style=3D"color:#660">(</span><span style=3D"color:#008">new</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#008">int</span><span s=
tyle=3D"color:#660">)</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =
=C2=A0</span><span style=3D"color:#660">{</span><span style=3D"color:#000">=
<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660">*</=
span><span style=3D"color:#000">data </span><span style=3D"color:#660">=3D<=
/span><span style=3D"color:#000"> </span><span style=3D"color:#660">*(</spa=
n><span style=3D"color:#000">rhs</span><span style=3D"color:#660">.</span><=
span style=3D"color:#000">data</span><span style=3D"color:#660">);</span><s=
pan style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0</span><span style=3D"colo=
r:#660">}</span><span style=3D"color:#000"><br><br>=C2=A0 =C2=A0 =C2=A0C</s=
pan><span style=3D"color:#660">(</span><span style=3D"color:#000">C</span><=
span style=3D"color:#660">&amp;&amp;</span><span style=3D"color:#000"> rhs<=
/span><span style=3D"color:#660">)</span><span style=3D"color:#000"> </span=
><span style=3D"color:#660">:</span><span style=3D"color:#000"> C</span><sp=
an style=3D"color:#660">()</span><span style=3D"color:#000"><br>=C2=A0 =C2=
=A0 =C2=A0</span><span style=3D"color:#660">{</span><span style=3D"color:#0=
00"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#800"=
>// Move constructor is first creating a default</span><span style=3D"color=
:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#8=
00">// object and swapping it with the rvalue reference.</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0swap</span><span styl=
e=3D"color:#660">(*</span><span style=3D"color:#008">this</span><span style=
=3D"color:#660">,</span><span style=3D"color:#000"> rhs</span><span style=
=3D"color:#660">);</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=
=A0</span><span style=3D"color:#660">}</span><span style=3D"color:#000"><br=
><br>=C2=A0 =C2=A0 =C2=A0C</span><span style=3D"color:#660">&amp;</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#008">operator</span><=
span style=3D"color:#660">=3D(</span><span style=3D"color:#000">C rhs</span=
><span style=3D"color:#660">)</span><span style=3D"color:#000"><br>=C2=A0 =
=C2=A0 =C2=A0</span><span style=3D"color:#660">{</span><span style=3D"color=
:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#8=
00">// We let the compiler copy into rhs and we swap the</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D=
"color:#800">// current object with this copy. Together with the</span><spa=
n style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span s=
tyle=3D"color:#800">// move constructor above, this implements the copy-swa=
p</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</=
span><span style=3D"color:#800">// idiom. Thanks to the move-constructor ab=
ove, the</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0</span><span style=3D"color:#800">// copy to rhs is not a deep copy i=
f the input is an rvalue<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0 // reference.</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0=
 =C2=A0 =C2=A0swap</span><span style=3D"color:#660">(*</span><span style=3D=
"color:#008">this</span><span style=3D"color:#660">,</span><span style=3D"c=
olor:#000"> rhs</span><span style=3D"color:#660">);</span><span style=3D"co=
lor:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color=
:#008">return</span><span style=3D"color:#000"> </span><span style=3D"color=
:#660">*</span><span style=3D"color:#008">this</span><span style=3D"color:#=
660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0</span><spa=
n style=3D"color:#660">}</span><span style=3D"color:#000"><br><br></span>=
=C2=A0=C2=A0=C2=A0=C2=A0 // The function below is commented out because it =
fails compilation<br>=C2=A0=C2=A0=C2=A0=C2=A0 // due to ambiguity with the =
above function. However, if it worked<br>=C2=A0=C2=A0=C2=A0=C2=A0 // it cou=
ld have saved us an extra call to the move constructor when<br>=C2=A0=C2=A0=
=C2=A0=C2=A0 // we make calls such as c2 =3D c1 + c1 (see operator+ below).=
 If it had<br>=C2=A0=C2=A0=C2=A0=C2=A0 // worked, the temporary created fro=
m c1 + c1 would have been directly <br>=C2=A0=C2=A0=C2=A0=C2=A0 // taken by=
 rvalue reference instead of its copy=C2=A0 (albeit shallow) being<br>=C2=
=A0=C2=A0=C2=A0=C2=A0 // created. <br>=C2=A0=C2=A0=C2=A0=C2=A0 <br>=C2=A0=
=C2=A0=C2=A0=C2=A0 /*<br><span style=3D"color:#000"><code><span style=3D"co=
lor:#000">=C2=A0=C2=A0=C2=A0=C2=A0 C</span><span style=3D"color:#660">&amp;=
</span><span style=3D"color:#000"> </span><span style=3D"color:#008">operat=
or</span><span style=3D"color:#660">=3D(</span><span style=3D"color:#000">C=
&amp;&amp; rhs</span><span style=3D"color:#660">)</span><span style=3D"colo=
r:#000"><br>=C2=A0 =C2=A0=C2=A0 </span><span style=3D"color:#660">{</span><=
span style=3D"color:#000"></span><span style=3D"color:#000"><br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0swap</span><span style=3D"color:#660">(*</span><spa=
n style=3D"color:#008">this</span><span style=3D"color:#660">,</span><span =
style=3D"color:#000"> rhs</span><span style=3D"color:#660">);</span><span s=
tyle=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span styl=
e=3D"color:#008">return</span><span style=3D"color:#000"> </span><span styl=
e=3D"color:#660">*</span><span style=3D"color:#008">this</span><span style=
=3D"color:#660">;</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0=
</span><span style=3D"color:#660">}</span><span style=3D"color:#000"><br>=
=C2=A0=C2=A0=C2=A0=C2=A0 */<br></span></code><br>=C2=A0 =C2=A0 =C2=A0C </sp=
an><span style=3D"color:#008">operator</span><span style=3D"color:#660">+(<=
/span><span style=3D"color:#008">const</span><span style=3D"color:#000"> C<=
/span><span style=3D"color:#660">&amp;</span><span style=3D"color:#000"> rh=
s</span><span style=3D"color:#660">)</span><span style=3D"color:#000"><br>=
=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660">{</span><span style=
=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0C result</span><span =
style=3D"color:#660">(*</span><span style=3D"color:#000">data </span><span =
style=3D"color:#660">+</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">*(</span><span style=3D"color:#000">rhs</span><span style=
=3D"color:#660">.</span><span style=3D"color:#000">data</span><span style=
=3D"color:#660">));</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0</span><span style=3D"color:#008">return</span><span style=
=3D"color:#000"> result</span><span style=3D"color:#660">;</span><span styl=
e=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color:#660">=
}</span><span style=3D"color:#000"><br><br>=C2=A0</span><span style=3D"colo=
r:#008">=C2=A0=C2=A0=C2=A0 friend</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#008">void</span><span style=3D"color:#000"> swap</spa=
n><span style=3D"color:#660">(</span><span style=3D"color:#000">C</span><sp=
an style=3D"color:#660">&amp;</span><span style=3D"color:#000"> lhs</span><=
span style=3D"color:#660">,</span><span style=3D"color:#000"> C</span><span=
 style=3D"color:#660">&amp;</span><span style=3D"color:#000"> rhs</span><sp=
an style=3D"color:#660">);</span><span style=3D"color:#000"><br><br>=C2=A0=
=C2=A0=C2=A0=C2=A0 </span><span style=3D"color:#660">~</span><span style=3D=
"color:#000">C</span><span style=3D"color:#660">()</span><span style=3D"col=
or:#000"><br>=C2=A0</span><span style=3D"color:#660">=C2=A0=C2=A0=C2=A0 {</=
span><span style=3D"color:#000"><br>=C2=A0</span><span style=3D"color:#008"=
>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 delete</span><span style=3D"col=
or:#000"> data</span><span style=3D"color:#660">;</span><span style=3D"colo=
r:#000"><br>=C2=A0=C2=A0=C2=A0=C2=A0 </span><span style=3D"color:#660">}</s=
pan><span style=3D"color:#000"><br></span><span style=3D"color:#660">};</sp=
an><span style=3D"color:#000"><br><br></span><span style=3D"color:#008">voi=
d</span><span style=3D"color:#000"> swap</span><span style=3D"color:#660">(=
</span><span style=3D"color:#000">C</span><span style=3D"color:#660">&amp;<=
/span><span style=3D"color:#000"> lhs</span><span style=3D"color:#660">,</s=
pan><span style=3D"color:#000"> C</span><span style=3D"color:#660">&amp;</s=
pan><span style=3D"color:#000"> rhs</span><span style=3D"color:#660">)</spa=
n><span style=3D"color:#000"><br></span><span style=3D"color:#660">{</span>=
<span style=3D"color:#000"><br>=C2=A0=C2=A0=C2=A0 std</span><span style=3D"=
color:#660">::</span><span style=3D"color:#000">swap</span><span style=3D"c=
olor:#660">(</span><span style=3D"color:#000">lhs</span><span style=3D"colo=
r:#660">.</span><span style=3D"color:#000">data</span><span style=3D"color:=
#660">,</span><span style=3D"color:#000"> rhs</span><span style=3D"color:#6=
60">.</span><span style=3D"color:#000">data</span><span style=3D"color:#660=
">);</span><span style=3D"color:#000"><br></span><span style=3D"color:#660"=
>}</span><span style=3D"color:#000"><br><br></span><span style=3D"color:#00=
8">int</span><span style=3D"color:#000"> main</span><span style=3D"color:#6=
60">()</span><span style=3D"color:#000"><br></span><span style=3D"color:#66=
0">{</span><span style=3D"color:#000"><br>=C2=A0=C2=A0=C2=A0 C c1</span><sp=
an style=3D"color:#660">(</span><span style=3D"color:#066">7</span><span st=
yle=3D"color:#660">);</span><span style=3D"color:#000"><br>=C2=A0=C2=A0=C2=
=A0 C c2</span><span style=3D"color:#660">;</span><span style=3D"color:#000=
"></span><span style=3D"color:#000"><br><br>=C2=A0=C2=A0=C2=A0 // The follo=
wing will first create the &quot;result&quot; inside operator+.<br>=C2=A0 =
=C2=A0 // The return value will then get move-constructed from the result<b=
r>=C2=A0=C2=A0=C2=A0 // (I&#39;m assuming that -fno-elide-constructors opti=
on is used). Then<br>=C2=A0=C2=A0=C2=A0 // the &quot;rhs&quot; parameter of=
 operator=3D will get move-constructed from<br>=C2=A0=C2=A0=C2=A0 // this r=
eturn temporary.<br>=C2=A0=C2=A0=C2=A0 //<br>=C2=A0=C2=A0=C2=A0 // But if w=
e could overload operator=3D(C&amp;&amp;), this second move-construction<br=
>=C2=A0=C2=A0=C2=A0 // could have been avoided as the return temporary coul=
d have been directly<br>=C2=A0=C2=A0=C2=A0 // captured by rvalue reference.=
<br>=C2=A0=C2=A0=C2=A0 //<br>=C2=A0=C2=A0=C2=A0 // Granted that we can impl=
ement operator=3D(const C&amp;) and operator=3D(C&amp;&amp;)<br>=C2=A0=C2=
=A0=C2=A0 // to make assignment as efficient as possible for both lvalue an=
d rvalue<br>=C2=A0=C2=A0=C2=A0 // inputs. However, to my knowledge, having =
operator=3D(const C&amp;) would<br>=C2=A0=C2=A0=C2=A0 // essentially preven=
t us from having the copy-swap idiom.<br><br>=C2=A0=C2=A0=C2=A0 c2 </span><=
span style=3D"color:#660">=3D</span><span style=3D"color:#000"> c1 </span><=
span style=3D"color:#660">+</span><span style=3D"color:#000"> c1</span><spa=
n style=3D"color:#660">;</span><span style=3D"color:#000"><br><br>=C2=A0</s=
pan><span style=3D"color:#008">=C2=A0=C2=A0 return</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#066">0</span><span style=3D"color:#6=
60">;</span><span style=3D"color:#000"><br></span><span style=3D"color:#660=
">}</span><span><font color=3D"#888888"><span style=3D"color:#000"><br></sp=
an></font></span></div></code></div><span><font color=3D"#888888"><br><br><=
/font></span></div><span><font color=3D"#888888">

<p></p>

-- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"=
rL4IJPuUCAAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D&#39;javascript:&=
#39;;return true;" onclick=3D"this.href=3D&#39;javascript:&#39;;return true=
;">std-proposal...@<wbr>isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"javascript:" target=3D"_bla=
nk" gdf-obfuscated-mailto=3D"rL4IJPuUCAAJ" rel=3D"nofollow" onmousedown=3D"=
this.href=3D&#39;javascript:&#39;;return true;" onclick=3D"this.href=3D&#39=
;javascript:&#39;;return true;">std-pr...@isocpp.org</a>.<br>
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/62809333-fd1a-4bde-8805-ccc0578a4284%=
40isocpp.org?utm_medium=3Demail&amp;utm_source=3Dfooter" target=3D"_blank" =
rel=3D"nofollow" onmousedown=3D"this.href=3D&#39;https://groups.google.com/=
a/isocpp.org/d/msgid/std-proposals/62809333-fd1a-4bde-8805-ccc0578a4284%40i=
socpp.org?utm_medium\x3demail\x26utm_source\x3dfooter&#39;;return true;" on=
click=3D"this.href=3D&#39;https://groups.google.com/a/isocpp.org/d/msgid/st=
d-proposals/62809333-fd1a-4bde-8805-ccc0578a4284%40isocpp.org?utm_medium\x3=
demail\x26utm_source\x3dfooter&#39;;return true;">https://groups.google.com=
/a/<wbr>isocpp.org/d/msgid/std-<wbr>proposals/62809333-fd1a-4bde-<wbr>8805-=
ccc0578a4284%40isocpp.org</a><wbr>.<br>
</font></span></blockquote></div><br></div></div>
</blockquote></div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/bfbf87e6-1949-4560-9bad-ac939b2db71f%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/bfbf87e6-1949-4560-9bad-ac939b2db71f=
%40isocpp.org</a>.<br />

------=_Part_828_1402306567.1524106604413--

------=_Part_827_1668056776.1524106604411--

.