Topic: Automatic Copy to Move Conversion in More Places


Author: malteskarupke@gmail.com
Date: Sun, 16 Mar 2014 15:35:43 -0700 (PDT)
Raw View
------=_Part_5201_446331.1395009343867
Content-Type: text/plain; charset=UTF-8

Hi,

with "automatic copy to move conversion" I mean this:

string f()
{
    string local = "hello";
    //...
    return local; // will be moved, not copied
}

This is a great feature, which means that we have to write std::move() less
often than we would have to without this feature. I believe though that we
can use this in far more places.
Let's start with a variation of the above which I run into somewhat
regularly:

struct Widget
{
    Widget(string);
};

Widget build_widget_a()
{
    string local = "world";
    return local; // will be copied
}
Widget build_widget_b()
{
    string local = "!";
    return std::move(local); // will be moved
}

This is a small variation of the above code, yet I need to write std::move.
While I understand why this is needed, I think that this is not obvious and
comes out of the fact that the rules are too rigid.

Currently the rule for automatic copy to move conversion is that it will be
applied either when copy-elision can be applied, or when you are returning
a stack local variable. The reason why the function returning a Widget can
not perform this conversion automatically is that the string is passed to a
constructor and not returned directly. But the reason for allowing the copy
to move conversion in the first place is that the object is about to go out
of scope, making it safe to move it instead of copying it, and that doesn't
change whether we pass it to a function or return it directly.

So I would like to change the rule for automatic copy to move conversion so
that it can be applied if the next operation that is performed on the
variable is that it is destroyed. Since the only remaining operation on the
string in the above example is that it's destructor is called, it will
therefore be moved into the constructor of Widget.

Once we start down that road, we can get another obvious optimization for
free though:

void moves(string a)
{
    string b = a; // will copy
    a = b; // will move
    return a; // will move
}

Looking at that, there is no good reason for that first copy. After all
whatever is stored inside a will be overwritten in the next line, and there
would be no observable difference between copying and moving. For that
reason I would like to extend the rule that I just proposed to say that
automatic copy to move conversion is applied when the next operation on the
variable is that it is destroyed, or that it is assigned to.

After that there is one final place that I can think of which does not
apply automatic copy-to-move conversion even though it could:

string return_string_a(string str)
{
    return str; // will be moved
}
string return_widget_b(string && str)
{
    return str; // will be copied
}

The reason for this is also not obvious. As far as we know the object is
about to disappear just as if it was a stack local variable, so why do we
have to explicitly move it? For this reason I would like to expand the
above rule to not only include stack local variables, but also rvalue
references.

So in summary I would like automatic copy-to-move conversion for
stack-local-variables and rvalue references if they are about to be
destroyed, or if the next operation on them is that they are assigned to.

What would the consequences of this be?
Well for starters here is a perfect forwarding function with these rules:

template<typename T, typename... Args>
T * make_ptr(Args &&... args)
{
    return new T(args...);
}

Isn't that much nicer than having to type std::forward<Args>(args)...? It
just does the right thing by default.

Other benefits are that working with unique_ptrs and other move only types
becomes much easier:

void sink(unique_ptr<Widget> widget);

void foo()
{
    unique_ptr<Widget> a = make_unique<Widget>();
    sink(a); // ok, no need to write std::move(a)
}

void foo_error()
{
    unique_ptr<Widget> a = make_unique<Widget>();
    sink(a); // compile error: trying to call deleted constructor. can not
convert to move because a is used again in this function
    sink(a);
}

That is a pretty good compile error to have. I think just having the
compiler generate an error if you use a unique_ptr twice is a great reason
for this proposal. Note that because of the rule for assignment, this is
allowed:

void foo_assign()
{
    unique_ptr<Widget> a = make_unique<Widget>();
    sink(a); // ok: the next operation on a is assignment to a
    a = make_unique<Widget>();
    sink(a); // ok the next operation on a is calling of its destructor
}

Now here is the downside of this. This can break existing code, which is
why we have to make the rules a bit more complicated. Consider this:

void keep_reference()
{
    string a = "ahoy";
    reference_wrapper<string> r = a;
    cout << r.get() << endl;
    string b = a; // will move because it looks like a is not used again
    cout << r.get() << endl;
}

Luckily the solution for this is not too restrictive: Automatic
copy-to-move conversion can only be applied if the variable was never
passed as a (possibly cv-qualified) lvalue reference. Since we only use
this for stack local variables and rvalue references passed to this
function, we can know whether any lvalue references exist to this variable.
We may also have to disallow automatic copy-to-move conversion if any
references to the variable exist in the current function, but since we can
reason about those, we may not have to do that. I'll defer to compiler
implementers on that.

Since we still allow passing of the object as an rvalue reference we don't
break any of the previous examples. (because they always pass the objects
as rvalue references)

We do break this example though which I would really like to work, because
it's neat:

string concat(string, string);

string bar()
{
    string local = "neat";
    return concat(local, local); // one move constructs, one copy constructs
}

Since the compiler knows in which order it initializes the function
arguments, it should be able to move construct the argument that gets
constructed last. Unfortunately my previous rule amendment about lvalue
references would break this, because the construction of the first argument
would mean that an lvalue reference was created to the local variable.
To work around that I think it is safe to define this amendment to the
amendment: The existence of a lvalue reference shall not inhibit
copy-to-move construction if that lvalue is used for a copy constructor.

So in summary the rules for this are actually quite complex, but I believe
that the out come would be rules that make much more sense and that would
allow the compiler to do the right thing in most cases.

Here are all the rules:
The compiler shall perform automatic copy-to-move conversion on stack local
variables to the current function and on rvalue references,
- if the rules for copy elision apply
- if the next operation that is performed with that variable is either
destruction of the variable or assignment to the variable, but not if a
(possibly cv-qualified) lvalue reference has been created to that variable,
except if that lvalue reference is only used as the argument to a copy
constructor

With the possible amendment that we may also want to disallow any
copy-to-move conversion if any references to the variable exist in the
local function. (this would include rvalue references, but this may not be
needed because we can reason about local references) By that I mean this:

void ref()
{
    string a = "str";
    string & r = a;
    string b = a; // will copy because a reference to a exists
}

This last restriction may or may not be needed, because we can reason about
local references. But lvalue references that are passed to other functions
will prevent copy-to-move conversion.

What does this not handle?
This proposal only handles the case where we are absolutely certain about
what will happen with the variable next. Consider this:

void conditional(bool b)
{
    unique_ptr<Widget> a = make_unique<Widget>();
    unique_ptr<Widget> other = a; // error because a may be used again
    if (b)
       a.get();
}

In the above example we would still have to manually call std::move() to
assign the unique_ptr. I think that this is not a great loss. In fact I
don't think that we need to be smart about this. This can be an error:

void conditional_b(bool b)
{
    unique_ptr<Widget> widget = make_unique<Widget>();
    if (b)
    {
        unique_ptr<Widget> other = widget; // error: widget may be used
again
    }
    // ...
    if (!b)
    {
        widget.get();
    }
}

Even though we could statically reason that the widget is never used again,
I think it is no big loss to demand that people still have to write
std::move() here. If compiler implementers think that this case is easy to
handle, then we may allow this, but I would be fine with disallowing this.
This however should be allowed:

void conditional_c(bool b)
{
    unique_ptr<Widget> widget = make_unique<Widget>();
    if (b)
    {
        unique_ptr<Widget> other = widget; // ok
    }
    else
    {
       widget.get();
    }
}

In this case reasoning that widget is not used again is easier because you
don't have to keep track of what state the variables are in.

Any comments or suggestions? Which cases did I forget to handle?

--

---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_5201_446331.1395009343867
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Hi,<br><br>with "automatic copy to move conversion" I mean=
 this:<br><br><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"><div class=
=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">string</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
f</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">{</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"><br>&nbsp; &nbsp; </span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">string</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">local</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> </span><span style=3D"color: #080;" class=3D"styled-by-pr=
ettify">"hello"</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
&nbsp; &nbsp; </span><span style=3D"color: #800;" class=3D"styled-by-pretti=
fy">//...</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><=
br>&nbsp; &nbsp; </span><span style=3D"color: #008;" class=3D"styled-by-pre=
ttify">return</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">local<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #800;" class=3D"styled-by-prettify">// will be moved, not copied=
</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 st=
yle=3D"color: #000;" class=3D"styled-by-prettify"><br></span></div></code><=
/div><br>This is a great feature, which means that we have to write std::mo=
ve() less often than we would have to without this feature. I believe thoug=
h that we can use this in far more places.<br>Let's start with a variation =
of the above which I run into somewhat regularly:<br><br><div class=3D"pret=
typrint" style=3D"background-color: rgb(250, 250, 250); border-color: rgb(1=
87, 187, 187); border-style: solid; border-width: 1px; word-wrap: break-wor=
d;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=
=3D"color: #008;" class=3D"styled-by-prettify">struct</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #6=
06;" class=3D"styled-by-prettify">Widget</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"color: #000;" class=3D"style=
d-by-prettify"><br>&nbsp; &nbsp; </span><span style=3D"color: #606;" class=
=3D"styled-by-prettify">Widget</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">(</span><span style=3D"color: #008;" class=3D"styled-by=
-prettify">string</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">);</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><=
br></span><span style=3D"color: #660;" class=3D"styled-by-prettify">};</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br></span>=
<span style=3D"color: #606;" class=3D"styled-by-prettify">Widget</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> build_widget_a</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">()</span><span s=
tyle=3D"color: #000;" class=3D"styled-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>&nbsp; &nbsp; </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">string</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #0=
08;" class=3D"styled-by-prettify">local</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #080;" class=3D"styled-by-pretti=
fy">"world"</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbs=
p; &nbsp; </span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
return</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </s=
pan><span style=3D"color: #008;" class=3D"styled-by-prettify">local</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: #800;" class=3D"styled-by-prettify">// will be copied</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #606;" cla=
ss=3D"styled-by-prettify">Widget</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> build_widget_b</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"style=
d-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br>&nbsp; &nbsp; </span><span style=3D"color: #008;" class=3D"styled=
-by-prettify">string</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify"=
>local</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #080;" 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"><br>&nbsp; &nbsp; </span><span style=3D"colo=
r: #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-prettify">move</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">(</span><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">local</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: #800;" class=3D"styled-by-prettify">// will be moved=
</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 st=
yle=3D"color: #000;" class=3D"styled-by-prettify"><br></span></div></code><=
/div><br>This is a small variation of the above code, yet I need to write s=
td::move. While I understand why this is needed, I think that this is not o=
bvious and comes out of the fact that the rules are too rigid.<br><br>Curre=
ntly the rule for automatic copy to move conversion is that it will be appl=
ied either when copy-elision can be applied, or when you are returning a st=
ack local variable. The reason why the function returning a Widget can not =
perform this conversion automatically is that the string is passed to a con=
structor and not returned directly. But the reason for allowing the copy to=
 move conversion in the first place is that the object is about to go out o=
f scope, making it safe to move it instead of copying it, and that doesn't =
change whether we pass it to a function or return it directly.<br><br>So I =
would like to change the rule for automatic copy to move conversion so that=
 it can be applied if the next operation that is performed on the variable =
is that it is destroyed. Since the only remaining operation on the string i=
n the above example is that it's destructor is called, it will therefore be=
 moved into the constructor of Widget.<br><br>Once we start down that road,=
 we can get another obvious optimization for free though:<br><br><div class=
=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); border-colo=
r: rgb(187, 187, 187); border-style: solid; border-width: 1px; word-wrap: b=
reak-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span=
 style=3D"color: #008;" class=3D"styled-by-prettify">void</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> moves</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #0=
08;" class=3D"styled-by-prettify">string</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"style=
d-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br>&nbsp; &nbsp; </span><span style=3D"color: #008;" class=3D"styled-by-pr=
ettify">string</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> b </span><span style=3D"color: #660;" class=3D"styled-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-prettify">;</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #800;" class=3D"styled-by-prettify">// will copy</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br>&nbsp; &nbsp; a </span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">=3D</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;" cl=
ass=3D"styled-by-prettify"> </span><span style=3D"color: #800;" class=3D"st=
yled-by-prettify">// will move</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"><br>&nbsp; &nbsp; </span><span style=3D"color: #008;" c=
lass=3D"styled-by-prettify">return</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: #800;" class=3D"styled-by-prettify">//=
 will move</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br></span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span></di=
v></code></div><br>Looking at that, there is no good reason for that first =
copy. After all whatever is stored inside a will be overwritten in the next=
 line, and there would be no observable difference between copying and movi=
ng. For that reason I would like to extend the rule that I just proposed to=
 say that automatic copy to move conversion is applied when the next operat=
ion on the variable is that it is destroyed, or that it is assigned to.<br>=
<br>After that there is one final place that I can think of which does not =
apply automatic copy-to-move conversion even though it could:<br><br><div c=
lass=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); border-=
color: rgb(187, 187, 187); border-style: solid; border-width: 1px; word-wra=
p: break-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><=
span style=3D"color: #008;" class=3D"styled-by-prettify">string</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify"> return_string_a</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span st=
yle=3D"color: #008;" class=3D"styled-by-prettify">string</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> str</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br></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>&nbsp; &nbsp; </span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">return</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> str</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> </span><span style=3D"color: #800;" class=3D"styled-by-prettify">// =
will be moved</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"><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: #008;" class=3D"styled-by-prettify">string</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify"> return_widget_b</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span st=
yle=3D"color: #008;" class=3D"styled-by-prettify">string</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">&amp;&amp;</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> str</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"st=
yled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br>&nbsp; &nbsp; </span><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">return</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> str</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: #800;" class=3D"styled-by-prettify">// will be =
copied</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
</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></div></=
code></div><br>The reason for this is also not obvious. As far as we know t=
he object is about to disappear just as if it was a stack local variable, s=
o why do we have to explicitly move it? For this reason I would like to exp=
and the above rule to not only include stack local variables, but also rval=
ue references.<br><br>So in summary I would like automatic copy-to-move con=
version for stack-local-variables and rvalue references if they are about t=
o be destroyed, or if the next operation on them is that they are assigned =
to.<br><br>What would the consequences of this be?<br>Well for starters her=
e is a perfect forwarding function with these rules:<br><br><div class=3D"p=
rettyprint" style=3D"background-color: rgb(250, 250, 250); border-color: rg=
b(187, 187, 187); border-style: solid; border-width: 1px; word-wrap: break-=
word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span styl=
e=3D"color: #008;" class=3D"styled-by-prettify">template</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">typename</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> T</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">typename</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">...</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">Arg=
s</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&gt;</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>T </span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">*</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> make_ptr</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color=
: #606;" class=3D"styled-by-prettify">Args</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">&amp;&amp;...</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> args</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br>&nbsp; &nbsp; </span><span style=3D"color: #008;" class=3D"styled-by-pr=
ettify">return</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">new</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> T</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">args</span><span style=3D"co=
lor: #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">}</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"><br></span></div></code></div><br>Isn't that much nice=
r than having to type std::forward&lt;Args&gt;(args)...? It just does the r=
ight thing by default.<br><br>Other benefits are that working with unique_p=
trs and other move only types becomes much easier:<br><br><div class=3D"pre=
ttyprint" style=3D"background-color: rgb(250, 250, 250); border-color: rgb(=
187, 187, 187); border-style: solid; border-width: 1px; word-wrap: break-wo=
rd;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=
=3D"color: #008;" class=3D"styled-by-prettify">void</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> sink</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify">unique_ptr</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">&lt;</span><span style=3D"color: #606;" class=3D=
"styled-by-prettify">Widget</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">&gt;</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> widget</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">);</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify">vo=
id</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> foo</sp=
an><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">{</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br>&nbsp; &nbsp; unique_ptr</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span st=
yle=3D"color: #606;" class=3D"styled-by-prettify">Widget</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&gt;</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> a </span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> make_unique</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #606;" class=
=3D"styled-by-prettify">Widget</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">&gt;();</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"><br>&nbsp; &nbsp; sink</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-prettif=
y"> </span><span style=3D"color: #800;" class=3D"styled-by-prettify">// ok,=
 no need to write std::move(a)</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"color: #000;" class=3D"styled-by-prett=
ify"><br><br></span><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">void</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> fo=
o_error</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">{</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbsp; &nbsp; unique_p=
tr</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</sp=
an><span style=3D"color: #606;" class=3D"styled-by-prettify">Widget</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">&gt;</span><span s=
tyle=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"styled-by-prettify"> make_unique</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #60=
6;" class=3D"styled-by-prettify">Widget</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">&gt;();</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"><br>&nbsp; &nbsp; sink</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-b=
y-prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-prettif=
y">// compile error: trying to call deleted constructor. can not convert to=
 move because a is used again in this function</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"><br>&nbsp; &nbsp; sink</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">(</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"><br></span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br></span></div></code></div><br>That is a pretty good compile er=
ror to have. I think just having the compiler generate an error if you use =
a unique_ptr twice is a great reason for this proposal. Note that because o=
f the rule for assignment, this is allowed:<br><br><div class=3D"prettyprin=
t" style=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 18=
7, 187); border-style: solid; border-width: 1px; word-wrap: break-word;"><c=
ode class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"colo=
r: #008;" class=3D"styled-by-prettify">void</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> foo_assign</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">()</span><span style=3D"color: #000;" cla=
ss=3D"styled-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>&nbsp; &nbsp; unique_ptr</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #606;" class=
=3D"styled-by-prettify">Widget</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">&gt;</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"> a </span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
 make_unique</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">&lt;</span><span style=3D"color: #606;" class=3D"styled-by-prettify">Widg=
et</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&gt;();<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbsp; =
&nbsp; sink</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 st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #800;" class=3D"styled-by-prettify">// ok: the next operation on a is =
assignment to a</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"><br>&nbsp; &nbsp; a </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> make_unique</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">&lt;</span><span style=3D"color: #606;" class=3D"styled-by-pretti=
fy">Widget</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
&gt;();</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br=
>&nbsp; &nbsp; sink</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">);</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #800;" class=3D"styled-by-prettify">// ok the next operation o=
n a is calling of its destructor</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br></span></div></code></div><br>Now here is the downside of this=
.. This can break existing code, which is why we have to make the rules a bi=
t more complicated. Consider this:<br><br><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 clas=
s=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #008;=
" class=3D"styled-by-prettify">void</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> keep_reference</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"st=
yled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br>&nbsp; &nbsp; </span><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">string</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> a </span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span><span style=3D"color: #080;" class=3D"styled-by-prettify">"ahoy"</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbsp; &nbsp; refer=
ence_wrapper</span><span style=3D"color: #080;" class=3D"styled-by-prettify=
">&lt;string&gt;</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> 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</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbsp; &nbsp; cout <=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;&lt;</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> r</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">.</span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">get</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: #660;" class=
=3D"styled-by-prettify">&lt;&lt;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> endl</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"><br>&nbsp; &nbsp; </span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">string</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"> b </span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">=3D</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: #800;" class=3D"styled-by-prettify">// will move because it lo=
oks like a is not used again</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"><br>&nbsp; &nbsp; cout </span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">&lt;&lt;</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> r</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">.</span><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">get</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">()</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;&lt;</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> endl</span><s=
pan 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"co=
lor: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br></span></div></code></div><br>Luckily t=
he solution for this is not too restrictive: Automatic copy-to-move convers=
ion can only be applied if the variable was never passed as a (possibly cv-=
qualified) lvalue reference. Since we only use this for stack local variabl=
es and rvalue references passed to this function, we can know whether any l=
value references exist to this variable. We may also have to disallow autom=
atic copy-to-move conversion if any references to the variable exist in the=
 current function, but since we can reason about those, we may not have to =
do that. I'll defer to compiler implementers on that.<br><br>Since we still=
 allow passing of the object as an rvalue reference we don't break any of t=
he previous examples. (because they always pass the objects as rvalue refer=
ences)<br><br>We do break this example though which I would really like to =
work, because it's neat:<br><br><div class=3D"prettyprint" style=3D"backgro=
und-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-sty=
le: solid; border-width: 1px; word-wrap: break-word;"><code class=3D"pretty=
print"><div class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"=
styled-by-prettify">string</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> concat</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">(</span><span style=3D"color: #008;" class=3D"styled-by-pretti=
fy">string</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">string</span><span=
 style=3D"color: #660;" class=3D"styled-by-prettify">);</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br><br></span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">string</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> bar</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">{</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br>&nbsp; &nbsp; </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">string</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by=
-prettify">local</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><s=
pan style=3D"color: #080;" class=3D"styled-by-prettify">"neat"</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"><br>&nbsp; &nbsp; </span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">return</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> concat</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #=
008;" class=3D"styled-by-prettify">local</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-b=
y-prettify">local</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">);</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span><span style=3D"color: #800;" class=3D"styled-by-prettify">// one mov=
e constructs, one copy constructs</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br></span></div></code></div><br>Since the compiler knows in whic=
h order it initializes the function arguments, it should be able to move co=
nstruct the argument that gets constructed last. Unfortunately my previous =
rule amendment about lvalue references would break this, because the constr=
uction of the first argument would mean that an lvalue reference was create=
d to the local variable.<br>To work around that I think it is safe to defin=
e this amendment to the amendment: The existence of a lvalue reference shal=
l not inhibit copy-to-move construction if that lvalue is used for a copy c=
onstructor.<br><br>So in summary the rules for this are actually quite comp=
lex, but I believe that the out come would be rules that make much more sen=
se and that would allow the compiler to do the right thing in most cases.<b=
r><br>Here are all the rules:<br>The compiler shall perform automatic copy-=
to-move conversion on stack local variables to the current function and on =
rvalue references,<br>- if the rules for copy elision apply<br>- if the nex=
t operation that is performed with that variable is either destruction of t=
he variable or assignment to the variable, but not if a (possibly cv-qualif=
ied) lvalue reference has been created to that variable, except if that lva=
lue reference is only used as the argument to a copy constructor<br><br>Wit=
h the possible amendment that we may also want to disallow any copy-to-move=
 conversion if any references to the variable exist in the local function. =
(this would include rvalue references, but this may not be needed because w=
e can reason about local references) By that I mean this:<br><br><div class=
=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); border-colo=
r: rgb(187, 187, 187); border-style: solid; border-width: 1px; word-wrap: b=
reak-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span=
 style=3D"color: #008;" class=3D"styled-by-prettify">void</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">ref</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"st=
yled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br>&nbsp; &nbsp; </span><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">string</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> a </span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span><span style=3D"color: #080;" class=3D"styled-by-prettify">"str"</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbsp; &nbsp; </span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">string</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&amp;</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> r </span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" c=
lass=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"><br>&nbsp; &nbsp; </span><span style=3D"color: #008;" class=3D"s=
tyled-by-prettify">string</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> b </span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">=3D</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 st=
yle=3D"color: #800;" class=3D"styled-by-prettify">// will copy because a re=
ference to a exists</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">}</span></div></code></div><br>This last restriction may or may not be n=
eeded, because we can reason about local references. But lvalue references =
that are passed to other functions will prevent copy-to-move conversion.<br=
><br>What does this not handle?<br>This proposal only handles the case wher=
e we are absolutely certain about what will happen with the variable next. =
Consider this:<br><br><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"><di=
v class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-by-=
prettify">void</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> conditional</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">(</span><span style=3D"color: #008;" class=3D"styled-by-prettify">boo=
l</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"><br></span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br>&nbsp; &nbsp; unique_ptr</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=
=3D"color: #606;" class=3D"styled-by-prettify">Widget</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">&gt;</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"styled-by-prettify"> make_unique</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">&lt;</span><span style=3D"color: #606;" class=3D"=
styled-by-prettify">Widget</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">&gt;();</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"><br>&nbsp; &nbsp; unique_ptr</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">&lt;</span><span style=3D"color: #606;" clas=
s=3D"styled-by-prettify">Widget</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">&gt;</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> other </span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> a</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: #800;" class=3D"styled-by-prettify">// error because a ma=
y be used again</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"><br>&nbsp; &nbsp; </span><span style=3D"color: #008;" class=3D"styled-=
by-prettify">if</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</s=
pan><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"><br>&nbsp; &nbsp; &nbsp; &nbsp;=
a</span><span style=3D"color: #660;" class=3D"styled-by-prettify">.</span><=
span style=3D"color: #008;" class=3D"styled-by-prettify">get</span><span st=
yle=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">}</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"><br></span></div></code></div><br>In the above =
example we would still have to manually call std::move() to assign the uniq=
ue_ptr. I think that this is not a great loss. In fact I don't think that w=
e need to be smart about this. This can be an error:<br><br><div class=3D"p=
rettyprint" style=3D"background-color: rgb(250, 250, 250); border-color: rg=
b(187, 187, 187); border-style: solid; border-width: 1px; word-wrap: break-=
word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span styl=
e=3D"color: #008;" class=3D"styled-by-prettify">void</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> conditional_b</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">bool</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"><br></span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br>&nbsp; &nbsp; unique_ptr</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">&lt;</span><span style=3D"color: #606;" class=3D"styled-b=
y-prettify">Widget</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">&gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> widget </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> make_u=
nique</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;<=
/span><span style=3D"color: #606;" class=3D"styled-by-prettify">Widget</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">&gt;();</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbsp; &nbsp; =
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">if</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">b</span><span style=3D"color: #660;"=
 class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"><br>&nbsp; &nbsp; </span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"><br>&nbsp; &nbsp; &nbsp; &nbsp; unique_ptr</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=
=3D"color: #606;" class=3D"styled-by-prettify">Widget</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">&gt;</span><span style=3D"color:=
 #000;" class=3D"styled-by-prettify"> other </span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> widget</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: #800;" class=3D"styled-by-pret=
tify">// error: widget may be used again</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"><br>&nbsp; &nbsp; </span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br>&nbsp; &nbsp; </span><span style=3D"color:=
 #800;" class=3D"styled-by-prettify">// ...</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"><br>&nbsp; &nbsp; </span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">if</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(!</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify">b</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><b=
r>&nbsp; &nbsp; </span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br=
>&nbsp; &nbsp; &nbsp; &nbsp; widget</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">.</span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">get</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">();</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"><br>&nbsp; &nbsp; </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">}</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span></d=
iv></code></div><br>Even though we could statically reason that the widget =
is never used again, I think it is no big loss to demand that people still =
have to write std::move() here. If compiler implementers think that this ca=
se is easy to handle, then we may allow this, but I would be fine with disa=
llowing this. This however should be allowed:<br><br><div class=3D"prettypr=
int" 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"><div class=3D"subprettyprint"><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">void</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> conditional_c</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #008;"=
 class=3D"styled-by-prettify">bool</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> b</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>&nbs=
p; &nbsp; unique_ptr</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">&lt;</span><span style=3D"color: #606;" class=3D"styled-by-pretti=
fy">Widget</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
&gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> widge=
t </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> make_unique</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><s=
pan style=3D"color: #606;" class=3D"styled-by-prettify">Widget</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">&gt;();</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbsp; &nbsp; </span><=
span style=3D"color: #008;" class=3D"styled-by-prettify">if</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">b</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br>&nbsp; &nbsp; </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br>&nbsp; &nbsp; &nbsp; &nbsp; unique_ptr</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=3D"co=
lor: #606;" class=3D"styled-by-prettify">Widget</span><span style=3D"color:=
 #660;" class=3D"styled-by-prettify">&gt;</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> other </span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> widget</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> </span><span style=3D"color: #800;" class=3D"styled-by-prettify">=
// ok</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&=
nbsp; &nbsp; </span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&n=
bsp; &nbsp; </span><span style=3D"color: #008;" class=3D"styled-by-prettify=
">else</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
&nbsp; &nbsp; </span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&=
nbsp; &nbsp; &nbsp; &nbsp;widget</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">.</span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">get</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">();</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
><br>&nbsp; &nbsp; </span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">}</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br></span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span></di=
v></code></div><br>In this case reasoning that widget is not used again is =
easier because you don't have to keep track of what state the variables are=
 in.<br><br>Any comments or suggestions? Which cases did I forget to handle=
?<br></div>

<p></p>

-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_5201_446331.1395009343867--

.


Author: Jens Maurer <Jens.Maurer@gmx.net>
Date: Sun, 16 Mar 2014 23:53:33 +0100
Raw View
On 03/16/2014 11:35 PM, malteskarupke@gmail.com wrote:
> struct Widget
> {
>     Widget(string);
> };
>
> Widget build_widget_a()
> {
>     string local="world";
>     return local;       // will be copied
> }

I agree it sounds reasonable to automatically move here.

> So I would like to change the rule for automatic copy to move
> conversion so that it can be applied if the next operation that is
> performed on the variable is that it is destroyed. Since the only
> remaining operation on the string in the above example is that it's
> destructor is called, it will therefore be moved into the constructor
> of Widget.

"Next operation that is performed on the variable" is too fuzzy
for me, and I'd really like to restrict the automatic move
optimization to cases that are syntactically within the "return"
statement (as above).

Jens

--

---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Mon, 17 Mar 2014 00:54:13 +0200
Raw View
On 17 March 2014 00:35,  <malteskarupke@gmail.com> wrote:
> Here are all the rules:
> The compiler shall perform automatic copy-to-move conversion on stack local
> variables to the current function and on rvalue references,
> - if the rules for copy elision apply
> - if the next operation that is performed with that variable is either
> destruction of the variable or assignment to the variable, but not if a
> (possibly cv-qualified) lvalue reference has been created to that variable,
> except if that lvalue reference is only used as the argument to a copy
> constructor


Currently, if I have

void f(Movable m)
{
// whatever code
    return m;
}

the return will prefer a move, regardless of the code that precedes it.
With the rules you propose,

void f()
{
    Movable m;
    // whatever code
    Movable m2 = move(m);   // #1
}

The overload resolution of m in "whatever code" now changes completely whether
#1 is present or not, including branch decisions made. I may have an overload
set of
void g(const Movable&);
void g(Movable&&);
used in that code, and the latter may reset the Movable it refers to, and the
"whatever code" may do selection statements based on that. This is a serious
"come-from" facility where the meaning of code can change silently depending
on the code that follows it. It may silently start moving from things
that are not
normally movable-from. It may silently stop moving from things I expected it
to move from.

In short, I'm not convinced this is a good idea.

--

---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Mon, 17 Mar 2014 01:08:38 +0200
Raw View
On 17 March 2014 00:53, Jens Maurer <Jens.Maurer@gmx.net> wrote:
> On 03/16/2014 11:35 PM, malteskarupke@gmail.com wrote:
>> struct Widget
>> {
>>     Widget(string);
>> };
>>
>> Widget build_widget_a()
>> {
>>     string local="world";
>>     return local;       // will be copied
>> }
>
> I agree it sounds reasonable to automatically move here.

This thread might be of interest:
https://groups.google.com/a/isocpp.org/d/msg/std-proposals/Tc1p52jg-1Y/ntMVTa0F38cJ

--

---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

.


Author: malteskarupke@gmail.com
Date: Sun, 16 Mar 2014 17:54:31 -0700 (PDT)
Raw View
------=_Part_5241_26399477.1395017671525
Content-Type: text/plain; charset=UTF-8

@Ville Voutilainen:
The only behavior in your example that would change would be copy
assignment operators or copy constructors that use m. This would not change
which functions are called except if that function is a copy constructor or
copy assignment.

Ideally I do not want to change observable semantics with this.

I intend to only change paragraph 12.8.32 of the standard which deals with
copy constructors that are replaced by move constructors. But I will also
make it apply to copy assignment operators. No other functions will change
behavior though, which is also why all functions in my examples take their
argument by copy, not by reference.

The one place where this would result in observable change in behavior is
if your copy constructor has different side effects to your move
constructor. But the standard already ignores those side effects when it
allows copy-elision and automatic copy-to-move conversion on return
statements.

On Sunday, March 16, 2014 6:54:13 PM UTC-4, Ville Voutilainen wrote:
>
> On 17 March 2014 00:35,  <maltes...@gmail.com <javascript:>> wrote:
> > Here are all the rules:
> > The compiler shall perform automatic copy-to-move conversion on stack
> local
> > variables to the current function and on rvalue references,
> > - if the rules for copy elision apply
> > - if the next operation that is performed with that variable is either
> > destruction of the variable or assignment to the variable, but not if a
> > (possibly cv-qualified) lvalue reference has been created to that
> variable,
> > except if that lvalue reference is only used as the argument to a copy
> > constructor
>
>
> Currently, if I have
>
> void f(Movable m)
> {
> // whatever code
>     return m;
> }
>
> the return will prefer a move, regardless of the code that precedes it.
> With the rules you propose,
>
> void f()
> {
>     Movable m;
>     // whatever code
>     Movable m2 = move(m);   // #1
> }
>
> The overload resolution of m in "whatever code" now changes completely
> whether
> #1 is present or not, including branch decisions made. I may have an
> overload
> set of
> void g(const Movable&);
> void g(Movable&&);
> used in that code, and the latter may reset the Movable it refers to, and
> the
> "whatever code" may do selection statements based on that. This is a
> serious
> "come-from" facility where the meaning of code can change silently
> depending
> on the code that follows it. It may silently start moving from things
> that are not
> normally movable-from. It may silently stop moving from things I expected
> it
> to move from.
>
> In short, I'm not convinced this is a good idea.
>

--

---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_5241_26399477.1395017671525
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">@Ville Voutilainen:<br>The only behavior in your example t=
hat would change would be copy assignment operators or copy constructors th=
at use m. This would not change which functions are called except if that f=
unction is a copy constructor or copy assignment.<br><br>Ideally I do not w=
ant to change observable semantics with this.<br><br>I intend to only chang=
e paragraph 12.8.32 of the standard which deals with copy constructors that=
 are replaced by move constructors. But I will also make it apply to copy a=
ssignment operators. No other functions will change behavior though, which =
is also why all functions in my examples take their argument by copy, not b=
y reference.<br><br>The one place where this would result in observable cha=
nge in behavior is if your copy constructor has different side effects to y=
our move constructor. But the standard already ignores those side effects w=
hen it allows copy-elision and automatic copy-to-move conversion on return =
statements.<br><br>On Sunday, March 16, 2014 6:54:13 PM UTC-4, Ville Voutil=
ainen wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On 17 March 2014 0=
0:35, &nbsp;&lt;<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-ma=
ilto=3D"nC0Ghe2EPgAJ" onmousedown=3D"this.href=3D'javascript:';return true;=
" onclick=3D"this.href=3D'javascript:';return true;">maltes...@gmail.com</a=
>&gt; wrote:
<br>&gt; Here are all the rules:
<br>&gt; The compiler shall perform automatic copy-to-move conversion on st=
ack local
<br>&gt; variables to the current function and on rvalue references,
<br>&gt; - if the rules for copy elision apply
<br>&gt; - if the next operation that is performed with that variable is ei=
ther
<br>&gt; destruction of the variable or assignment to the variable, but not=
 if a
<br>&gt; (possibly cv-qualified) lvalue reference has been created to that =
variable,
<br>&gt; except if that lvalue reference is only used as the argument to a =
copy
<br>&gt; constructor
<br>
<br>
<br>Currently, if I have
<br>
<br>void f(Movable m)
<br>{
<br>// whatever code
<br>&nbsp; &nbsp; return m;
<br>}
<br>
<br>the return will prefer a move, regardless of the code that precedes it.
<br>With the rules you propose,
<br>
<br>void f()
<br>{
<br>&nbsp; &nbsp; Movable m;
<br>&nbsp; &nbsp; // whatever code
<br>&nbsp; &nbsp; Movable m2 =3D move(m); &nbsp; // #1
<br>}
<br>
<br>The overload resolution of m in "whatever code" now changes completely =
whether
<br>#1 is present or not, including branch decisions made. I may have an ov=
erload
<br>set of
<br>void g(const Movable&amp;);
<br>void g(Movable&amp;&amp;);
<br>used in that code, and the latter may reset the Movable it refers to, a=
nd the
<br>"whatever code" may do selection statements based on that. This is a se=
rious
<br>"come-from" facility where the meaning of code can change silently depe=
nding
<br>on the code that follows it. It may silently start moving from things
<br>that are not
<br>normally movable-from. It may silently stop moving from things I expect=
ed it
<br>to move from.
<br>
<br>In short, I'm not convinced this is a good idea.
<br></blockquote></div>

<p></p>

-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_5241_26399477.1395017671525--

.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Mon, 17 Mar 2014 08:22:12 +0200
Raw View
On 17 March 2014 02:54,  <malteskarupke@gmail.com> wrote:
> @Ville Voutilainen:
> The only behavior in your example that would change would be copy assignment
> operators or copy constructors that use m. This would not change which
> functions are called except if that function is a copy constructor or copy
> assignment.

Well, that would include functions that take their argument by value, I suppose.
The copy/move happens when passing the argument.

> Ideally I do not want to change observable semantics with this.

I fail to see how that is attainable if code in the function selects copy/move
differently depending on what comes after that copy/move. As Jens said,
the return case is something we can handle, as is throwing, but other
operations not much so.

--

---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

.


Author: Geoffrey Romer <gromer@google.com>
Date: Mon, 17 Mar 2014 01:32:59 -0700
Raw View
--001a11c12d325dda5304f4c94410
Content-Type: text/plain; charset=UTF-8

This became national body comment US 13, which was marked ACCEPTED in
Chicago. However, I can't seem to find the corresponding wording in the
latest draft. Anyone know what the story is there?
On Mar 17, 2014 12:08 PM, "Ville Voutilainen" <ville.voutilainen@gmail.com>
wrote:

> On 17 March 2014 00:53, Jens Maurer <Jens.Maurer@gmx.net> wrote:
> > On 03/16/2014 11:35 PM, malteskarupke@gmail.com wrote:
> >> struct Widget
> >> {
> >>     Widget(string);
> >> };
> >>
> >> Widget build_widget_a()
> >> {
> >>     string local="world";
> >>     return local;       // will be copied
> >> }
> >
> > I agree it sounds reasonable to automatically move here.
>
> This thread might be of interest:
>
> https://groups.google.com/a/isocpp.org/d/msg/std-proposals/Tc1p52jg-1Y/ntMVTa0F38cJ
>
> --
>
> ---
> 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.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>

--

---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

--001a11c12d325dda5304f4c94410
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<p dir=3D"ltr">This became national body comment US 13, which was marked AC=
CEPTED in Chicago. However, I can&#39;t seem to find the corresponding word=
ing in the latest draft. Anyone know what the story is there?</p>
<div class=3D"gmail_quote">On Mar 17, 2014 12:08 PM, &quot;Ville Voutilaine=
n&quot; &lt;<a href=3D"mailto:ville.voutilainen@gmail.com">ville.voutilaine=
n@gmail.com</a>&gt; wrote:<br type=3D"attribution"><blockquote class=3D"gma=
il_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-lef=
t:1ex">
On 17 March 2014 00:53, Jens Maurer &lt;<a href=3D"mailto:Jens.Maurer@gmx.n=
et">Jens.Maurer@gmx.net</a>&gt; wrote:<br>
&gt; On 03/16/2014 11:35 PM, <a href=3D"mailto:malteskarupke@gmail.com">mal=
teskarupke@gmail.com</a> wrote:<br>
&gt;&gt; struct Widget<br>
&gt;&gt; {<br>
&gt;&gt; =C2=A0 =C2=A0 Widget(string);<br>
&gt;&gt; };<br>
&gt;&gt;<br>
&gt;&gt; Widget build_widget_a()<br>
&gt;&gt; {<br>
&gt;&gt; =C2=A0 =C2=A0 string local=3D&quot;world&quot;;<br>
&gt;&gt; =C2=A0 =C2=A0 return local; =C2=A0 =C2=A0 =C2=A0 // will be copied=
<br>
&gt;&gt; }<br>
&gt;<br>
&gt; I agree it sounds reasonable to automatically move here.<br>
<br>
This thread might be of interest:<br>
<a href=3D"https://groups.google.com/a/isocpp.org/d/msg/std-proposals/Tc1p5=
2jg-1Y/ntMVTa0F38cJ" target=3D"_blank">https://groups.google.com/a/isocpp.o=
rg/d/msg/std-proposals/Tc1p52jg-1Y/ntMVTa0F38cJ</a><br>
<br>
--<br>
<br>
---<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%2Bunsubscribe@isocpp.org">std-propo=
sals+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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</blockquote></div>

<p></p>

-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

--001a11c12d325dda5304f4c94410--

.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Mon, 17 Mar 2014 11:22:31 +0200
Raw View
On 17 March 2014 10:32, Geoffrey Romer <gromer@google.com> wrote:
> This became national body comment US 13, which was marked ACCEPTED in
> Chicago. However, I can't seem to find the corresponding wording in the
> latest draft. Anyone know what the story is there?

On the Chicago wiki, the drafting (by Jens) is

When the criteria for elision of a copy operation are met<del> or
would be met save for the fact that the source object is a function
parameter</del>, and the object to be copied is designated by an
lvalue<ins>, or when the expression in a return statement is a
(possibly parenthesized) id-expression that names an object with
automatic storage duration declared in the body or
parameter-declaration-clause of the innermost enclosing function or
lambda-expression</ins>, overload resolution to select the constructor
for the copy is first performed as if the object were designated by an
rvalue. If overload resolution fails, or if the type of the first
parameter of the selected constructor is not an rvalue reference to
the object's type (possibly cv-qualified), overload resolution is
performed again, considering the object as an lvalue.

This also seems to be in the current working draft.

--

---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

.


Author: Geoffrey Romer <gromer@google.com>
Date: Mon, 17 Mar 2014 07:37:49 -0700
Raw View
--001a1132f03c1abc4204f4ce5d12
Content-Type: text/plain; charset=UTF-8

You're right, sorry. I was looking at a stale draft.
On Mar 17, 2014 10:22 PM, "Ville Voutilainen" <ville.voutilainen@gmail.com>
wrote:

> On 17 March 2014 10:32, Geoffrey Romer <gromer@google.com> wrote:
> > This became national body comment US 13, which was marked ACCEPTED in
> > Chicago. However, I can't seem to find the corresponding wording in the
> > latest draft. Anyone know what the story is there?
>
> On the Chicago wiki, the drafting (by Jens) is
>
> When the criteria for elision of a copy operation are met<del> or
> would be met save for the fact that the source object is a function
> parameter</del>, and the object to be copied is designated by an
> lvalue<ins>, or when the expression in a return statement is a
> (possibly parenthesized) id-expression that names an object with
> automatic storage duration declared in the body or
> parameter-declaration-clause of the innermost enclosing function or
> lambda-expression</ins>, overload resolution to select the constructor
> for the copy is first performed as if the object were designated by an
> rvalue. If overload resolution fails, or if the type of the first
> parameter of the selected constructor is not an rvalue reference to
> the object's type (possibly cv-qualified), overload resolution is
> performed again, considering the object as an lvalue.
>
> This also seems to be in the current working draft.
>
> --
>
> ---
> 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.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>

--

---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

--001a1132f03c1abc4204f4ce5d12
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<p dir=3D"ltr">You&#39;re right, sorry. I was looking at a stale draft.</p>
<div class=3D"gmail_quote">On Mar 17, 2014 10:22 PM, &quot;Ville Voutilaine=
n&quot; &lt;<a href=3D"mailto:ville.voutilainen@gmail.com">ville.voutilaine=
n@gmail.com</a>&gt; wrote:<br type=3D"attribution"><blockquote class=3D"gma=
il_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-lef=
t:1ex">
On 17 March 2014 10:32, Geoffrey Romer &lt;<a href=3D"mailto:gromer@google.=
com">gromer@google.com</a>&gt; wrote:<br>
&gt; This became national body comment US 13, which was marked ACCEPTED in<=
br>
&gt; Chicago. However, I can&#39;t seem to find the corresponding wording i=
n the<br>
&gt; latest draft. Anyone know what the story is there?<br>
<br>
On the Chicago wiki, the drafting (by Jens) is<br>
<br>
When the criteria for elision of a copy operation are met&lt;del&gt; or<br>
would be met save for the fact that the source object is a function<br>
parameter&lt;/del&gt;, and the object to be copied is designated by an<br>
lvalue&lt;ins&gt;, or when the expression in a return statement is a<br>
(possibly parenthesized) id-expression that names an object with<br>
automatic storage duration declared in the body or<br>
parameter-declaration-clause of the innermost enclosing function or<br>
lambda-expression&lt;/ins&gt;, overload resolution to select the constructo=
r<br>
for the copy is first performed as if the object were designated by an<br>
rvalue. If overload resolution fails, or if the type of the first<br>
parameter of the selected constructor is not an rvalue reference to<br>
the object&#39;s type (possibly cv-qualified), overload resolution is<br>
performed again, considering the object as an lvalue.<br>
<br>
This also seems to be in the current working draft.<br>
<br>
--<br>
<br>
---<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%2Bunsubscribe@isocpp.org">std-propo=
sals+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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</blockquote></div>

<p></p>

-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

--001a1132f03c1abc4204f4ce5d12--

.


Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Mon, 17 Mar 2014 16:42:33 +0200
Raw View
On 17 March 2014 16:37, Geoffrey Romer <gromer@google.com> wrote:
> You're right, sorry. I was looking at a stale draft.


That's ok. Does it cover the string->Widget conversion mentioned in this thread?
I'd think it does.

--

---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

.


Author: Geoffrey Romer <gromer@google.com>
Date: Tue, 18 Mar 2014 04:32:17 -0700
Raw View
--001a11c13da28be39d04f4dfe3c5
Content-Type: text/plain; charset=UTF-8

Yes, it should cover that example. The basic principle of the NB comment is
that "return foo;" and "return std::move(foo);" should have identical
behavior when foo is a local variable. I haven't looked at the wording in
detail (I'm on vacation), but I trust the drafters to have expressed that
principle correctly.
On Mar 17, 2014 10:42 PM, "Ville Voutilainen" <ville.voutilainen@gmail.com>
wrote:

> On 17 March 2014 16:37, Geoffrey Romer <gromer@google.com> wrote:
> > You're right, sorry. I was looking at a stale draft.
>
>
> That's ok. Does it cover the string->Widget conversion mentioned in this
> thread?
> I'd think it does.
>
> --
>
> ---
> 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.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>

--

---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

--001a11c13da28be39d04f4dfe3c5
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<p dir=3D"ltr">Yes, it should cover that example. The basic principle of th=
e NB comment is that &quot;return foo;&quot; and &quot;return std::move(foo=
);&quot; should have identical behavior when foo is a local variable. I hav=
en&#39;t looked at the wording in detail (I&#39;m on vacation), but I trust=
 the drafters to have expressed that principle correctly.</p>

<div class=3D"gmail_quote">On Mar 17, 2014 10:42 PM, &quot;Ville Voutilaine=
n&quot; &lt;<a href=3D"mailto:ville.voutilainen@gmail.com">ville.voutilaine=
n@gmail.com</a>&gt; wrote:<br type=3D"attribution"><blockquote class=3D"gma=
il_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-lef=
t:1ex">
On 17 March 2014 16:37, Geoffrey Romer &lt;<a href=3D"mailto:gromer@google.=
com">gromer@google.com</a>&gt; wrote:<br>
&gt; You&#39;re right, sorry. I was looking at a stale draft.<br>
<br>
<br>
That&#39;s ok. Does it cover the string-&gt;Widget conversion mentioned in =
this thread?<br>
I&#39;d think it does.<br>
<br>
--<br>
<br>
---<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%2Bunsubscribe@isocpp.org">std-propo=
sals+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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</blockquote></div>

<p></p>

-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

--001a11c13da28be39d04f4dfe3c5--

.


Author: Christ-Jan Wijtmans <cj.wijtmans@gmail.com>
Date: Wed, 19 Mar 2014 08:57:56 -0700 (PDT)
Raw View
------=_Part_295_26240890.1395244676985
Content-Type: text/plain; charset=UTF-8

A proper compiler already does this, i dont know if it will do any good to
make this part of the standard.

Op zondag 16 maart 2014 23:35:43 UTC+1 schreef maltes...@gmail.com:
>
> Hi,
>
> with "automatic copy to move conversion" I mean this:
>
> string f()
> {
>     string local = "hello";
>     //...
>     return local; // will be moved, not copied
> }
>
> This is a great feature, which means that we have to write std::move()
> less often than we would have to without this feature. I believe though
> that we can use this in far more places.
> Let's start with a variation of the above which I run into somewhat
> regularly:
>
> struct Widget
> {
>     Widget(string);
> };
>
> Widget build_widget_a()
> {
>     string local = "world";
>     return local; // will be copied
> }
> Widget build_widget_b()
> {
>     string local = "!";
>     return std::move(local); // will be moved
> }
>
> This is a small variation of the above code, yet I need to write
> std::move. While I understand why this is needed, I think that this is not
> obvious and comes out of the fact that the rules are too rigid.
>
> Currently the rule for automatic copy to move conversion is that it will
> be applied either when copy-elision can be applied, or when you are
> returning a stack local variable. The reason why the function returning a
> Widget can not perform this conversion automatically is that the string is
> passed to a constructor and not returned directly. But the reason for
> allowing the copy to move conversion in the first place is that the object
> is about to go out of scope, making it safe to move it instead of copying
> it, and that doesn't change whether we pass it to a function or return it
> directly.
>
> So I would like to change the rule for automatic copy to move conversion
> so that it can be applied if the next operation that is performed on the
> variable is that it is destroyed. Since the only remaining operation on the
> string in the above example is that it's destructor is called, it will
> therefore be moved into the constructor of Widget.
>
> Once we start down that road, we can get another obvious optimization for
> free though:
>
> void moves(string a)
> {
>     string b = a; // will copy
>     a = b; // will move
>     return a; // will move
> }
>
> Looking at that, there is no good reason for that first copy. After all
> whatever is stored inside a will be overwritten in the next line, and there
> would be no observable difference between copying and moving. For that
> reason I would like to extend the rule that I just proposed to say that
> automatic copy to move conversion is applied when the next operation on the
> variable is that it is destroyed, or that it is assigned to.
>
> After that there is one final place that I can think of which does not
> apply automatic copy-to-move conversion even though it could:
>
> string return_string_a(string str)
> {
>     return str; // will be moved
> }
> string return_widget_b(string && str)
> {
>     return str; // will be copied
> }
>
> The reason for this is also not obvious. As far as we know the object is
> about to disappear just as if it was a stack local variable, so why do we
> have to explicitly move it? For this reason I would like to expand the
> above rule to not only include stack local variables, but also rvalue
> references.
>
> So in summary I would like automatic copy-to-move conversion for
> stack-local-variables and rvalue references if they are about to be
> destroyed, or if the next operation on them is that they are assigned to.
>
> What would the consequences of this be?
> Well for starters here is a perfect forwarding function with these rules:
>
> template<typename T, typename... Args>
> T * make_ptr(Args &&... args)
> {
>     return new T(args...);
> }
>
> Isn't that much nicer than having to type std::forward<Args>(args)...? It
> just does the right thing by default.
>
> Other benefits are that working with unique_ptrs and other move only types
> becomes much easier:
>
> void sink(unique_ptr<Widget> widget);
>
> void foo()
> {
>     unique_ptr<Widget> a = make_unique<Widget>();
>     sink(a); // ok, no need to write std::move(a)
> }
>
> void foo_error()
> {
>     unique_ptr<Widget> a = make_unique<Widget>();
>     sink(a); // compile error: trying to call deleted constructor. can
> not convert to move because a is used again in this function
>     sink(a);
> }
>
> That is a pretty good compile error to have. I think just having the
> compiler generate an error if you use a unique_ptr twice is a great reason
> for this proposal. Note that because of the rule for assignment, this is
> allowed:
>
> void foo_assign()
> {
>     unique_ptr<Widget> a = make_unique<Widget>();
>     sink(a); // ok: the next operation on a is assignment to a
>     a = make_unique<Widget>();
>     sink(a); // ok the next operation on a is calling of its destructor
> }
>
> Now here is the downside of this. This can break existing code, which is
> why we have to make the rules a bit more complicated. Consider this:
>
> void keep_reference()
> {
>     string a = "ahoy";
>     reference_wrapper<string> r = a;
>     cout << r.get() << endl;
>     string b = a; // will move because it looks like a is not used again
>     cout << r.get() << endl;
> }
>
> Luckily the solution for this is not too restrictive: Automatic
> copy-to-move conversion can only be applied if the variable was never
> passed as a (possibly cv-qualified) lvalue reference. Since we only use
> this for stack local variables and rvalue references passed to this
> function, we can know whether any lvalue references exist to this variable.
> We may also have to disallow automatic copy-to-move conversion if any
> references to the variable exist in the current function, but since we can
> reason about those, we may not have to do that. I'll defer to compiler
> implementers on that.
>
> Since we still allow passing of the object as an rvalue reference we don't
> break any of the previous examples. (because they always pass the objects
> as rvalue references)
>
> We do break this example though which I would really like to work, because
> it's neat:
>
> string concat(string, string);
>
> string bar()
> {
>     string local = "neat";
>     return concat(local, local); // one move constructs, one copy
> constructs
> }
>
> Since the compiler knows in which order it initializes the function
> arguments, it should be able to move construct the argument that gets
> constructed last. Unfortunately my previous rule amendment about lvalue
> references would break this, because the construction of the first argument
> would mean that an lvalue reference was created to the local variable.
> To work around that I think it is safe to define this amendment to the
> amendment: The existence of a lvalue reference shall not inhibit
> copy-to-move construction if that lvalue is used for a copy constructor.
>
> So in summary the rules for this are actually quite complex, but I believe
> that the out come would be rules that make much more sense and that would
> allow the compiler to do the right thing in most cases.
>
> Here are all the rules:
> The compiler shall perform automatic copy-to-move conversion on stack
> local variables to the current function and on rvalue references,
> - if the rules for copy elision apply
> - if the next operation that is performed with that variable is either
> destruction of the variable or assignment to the variable, but not if a
> (possibly cv-qualified) lvalue reference has been created to that variable,
> except if that lvalue reference is only used as the argument to a copy
> constructor
>
> With the possible amendment that we may also want to disallow any
> copy-to-move conversion if any references to the variable exist in the
> local function. (this would include rvalue references, but this may not be
> needed because we can reason about local references) By that I mean this:
>
> void ref()
> {
>     string a = "str";
>     string & r = a;
>     string b = a; // will copy because a reference to a exists
> }
>
> This last restriction may or may not be needed, because we can reason
> about local references. But lvalue references that are passed to other
> functions will prevent copy-to-move conversion.
>
> What does this not handle?
> This proposal only handles the case where we are absolutely certain about
> what will happen with the variable next. Consider this:
>
> void conditional(bool b)
> {
>     unique_ptr<Widget> a = make_unique<Widget>();
>     unique_ptr<Widget> other = a; // error because a may be used again
>     if (b)
>        a.get();
> }
>
> In the above example we would still have to manually call std::move() to
> assign the unique_ptr. I think that this is not a great loss. In fact I
> don't think that we need to be smart about this. This can be an error:
>
> void conditional_b(bool b)
> {
>     unique_ptr<Widget> widget = make_unique<Widget>();
>     if (b)
>     {
>         unique_ptr<Widget> other = widget; // error: widget may be used
> again
>     }
>     // ...
>     if (!b)
>     {
>         widget.get();
>     }
> }
>
> Even though we could statically reason that the widget is never used
> again, I think it is no big loss to demand that people still have to write
> std::move() here. If compiler implementers think that this case is easy to
> handle, then we may allow this, but I would be fine with disallowing this.
> This however should be allowed:
>
> void conditional_c(bool b)
> {
>     unique_ptr<Widget> widget = make_unique<Widget>();
>     if (b)
>     {
>         unique_ptr<Widget> other = widget; // ok
>     }
>     else
>     {
>        widget.get();
>     }
> }
>
> In this case reasoning that widget is not used again is easier because you
> don't have to keep track of what state the variables are in.
>
> Any comments or suggestions? Which cases did I forget to handle?
>

--

---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

------=_Part_295_26240890.1395244676985
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">A proper compiler already does this, i dont know if it wil=
l do any good to make this part of the standard.<br><br>Op zondag 16 maart =
2014 23:35:43 UTC+1 schreef maltes...@gmail.com:<blockquote class=3D"gmail_=
quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pa=
dding-left: 1ex;"><div dir=3D"ltr">Hi,<br><br>with "automatic copy to move =
conversion" I mean this:<br><br><div 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><div><span style=3D"color:#008">string</span><span =
style=3D"color:#000"> f</span><span style=3D"color:#660">()</span><span sty=
le=3D"color:#000"><br></span><span style=3D"color:#660">{</span><span style=
=3D"color:#000"><br>&nbsp; &nbsp; </span><span style=3D"color:#008">string<=
/span><span style=3D"color:#000"> </span><span style=3D"color:#008">local</=
span><span style=3D"color:#000"> </span><span style=3D"color:#660">=3D</spa=
n><span style=3D"color:#000"> </span><span style=3D"color:#080">"hello"</sp=
an><span style=3D"color:#660">;</span><span style=3D"color:#000"><br>&nbsp;=
 &nbsp; </span><span style=3D"color:#800">//...</span><span style=3D"color:=
#000"><br>&nbsp; &nbsp; </span><span style=3D"color:#008">return</span><spa=
n style=3D"color:#000"> </span><span style=3D"color:#008">local</span><span=
 style=3D"color:#660">;</span><span style=3D"color:#000"> </span><span styl=
e=3D"color:#800">// will be moved, not copied</span><span style=3D"color:#0=
00"><br></span><span style=3D"color:#660">}</span><span style=3D"color:#000=
"><br></span></div></code></div><br>This is a great feature, which means th=
at we have to write std::move() less often than we would have to without th=
is feature. I believe though that we can use this in far more places.<br>Le=
t's start with a variation of the above which I run into somewhat regularly=
:<br><br><div style=3D"background-color:rgb(250,250,250);border-color:rgb(1=
87,187,187);border-style:solid;border-width:1px;word-wrap:break-word"><code=
><div><span style=3D"color:#008">struct</span><span style=3D"color:#000"> <=
/span><span style=3D"color:#606">Widget</span><span style=3D"color:#000"><b=
r></span><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=
&nbsp; &nbsp; </span><span style=3D"color:#606">Widget</span><span style=3D=
"color:#660">(</span><span style=3D"color:#008">string</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:#606">Widget</span><span style=3D"color:#000"> build_widget_a</sp=
an><span style=3D"color:#660">()</span><span style=3D"color:#000"><br></spa=
n><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>&nbsp; =
&nbsp; </span><span style=3D"color:#008">string</span><span style=3D"color:=
#000"> </span><span style=3D"color:#008">local</span><span style=3D"color:#=
000"> </span><span style=3D"color:#660">=3D</span><span style=3D"color:#000=
"> </span><span style=3D"color:#080">"world"</span><span style=3D"color:#66=
0">;</span><span style=3D"color:#000"><br>&nbsp; &nbsp; </span><span style=
=3D"color:#008">return</span><span style=3D"color:#000"> </span><span style=
=3D"color:#008">local</span><span style=3D"color:#660">;</span><span style=
=3D"color:#000"> </span><span style=3D"color:#800">// will be copied</span>=
<span style=3D"color:#000"><br></span><span style=3D"color:#660">}</span><s=
pan style=3D"color:#000"><br></span><span style=3D"color:#606">Widget</span=
><span style=3D"color:#000"> build_widget_b</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>&nbsp; &nbsp; </span><span style=3D=
"color:#008">string</span><span style=3D"color:#000"> </span><span style=3D=
"color:#008">local</span><span style=3D"color:#000"> </span><span style=3D"=
color:#660">=3D</span><span style=3D"color:#000"> </span><span style=3D"col=
or:#080">"!"</span><span style=3D"color:#660">;</span><span style=3D"color:=
#000"><br>&nbsp; &nbsp; </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:#008">local</span><span style=3D"color:#660">);</span><span s=
tyle=3D"color:#000"> </span><span style=3D"color:#800">// will be moved</sp=
an><span style=3D"color:#000"><br></span><span style=3D"color:#660">}</span=
><span style=3D"color:#000"><br></span></div></code></div><br>This is a sma=
ll variation of the above code, yet I need to write std::move. While I unde=
rstand why this is needed, I think that this is not obvious and comes out o=
f the fact that the rules are too rigid.<br><br>Currently the rule for auto=
matic copy to move conversion is that it will be applied either when copy-e=
lision can be applied, or when you are returning a stack local variable. Th=
e reason why the function returning a Widget can not perform this conversio=
n automatically is that the string is passed to a constructor and not retur=
ned directly. But the reason for allowing the copy to move conversion in th=
e first place is that the object is about to go out of scope, making it saf=
e to move it instead of copying it, and that doesn't change whether we pass=
 it to a function or return it directly.<br><br>So I would like to change t=
he rule for automatic copy to move conversion so that it can be applied if =
the next operation that is performed on the variable is that it is destroye=
d. Since the only remaining operation on the string in the above example is=
 that it's destructor is called, it will therefore be moved into the constr=
uctor of Widget.<br><br>Once we start down that road, we can get another ob=
vious optimization for free though:<br><br><div style=3D"background-color:r=
gb(250,250,250);border-color:rgb(187,187,187);border-style:solid;border-wid=
th:1px;word-wrap:break-word"><code><div><span style=3D"color:#008">void</sp=
an><span style=3D"color:#000"> moves</span><span style=3D"color:#660">(</sp=
an><span style=3D"color:#008">string</span><span style=3D"color:#000"> a</s=
pan><span style=3D"color:#660">)</span><span style=3D"color:#000"><br></spa=
n><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>&nbsp; =
&nbsp; </span><span style=3D"color:#008">string</span><span style=3D"color:=
#000"> b </span><span style=3D"color:#660">=3D</span><span style=3D"color:#=
000"> a</span><span style=3D"color:#660">;</span><span style=3D"color:#000"=
> </span><span style=3D"color:#800">// will copy</span><span style=3D"color=
:#000"><br>&nbsp; &nbsp; a </span><span style=3D"color:#660">=3D</span><spa=
n style=3D"color:#000"> b</span><span style=3D"color:#660">;</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#800">// will move</span><s=
pan style=3D"color:#000"><br>&nbsp; &nbsp; </span><span style=3D"color:#008=
">return</span><span style=3D"color:#000"> a</span><span style=3D"color:#66=
0">;</span><span style=3D"color:#000"> </span><span style=3D"color:#800">//=
 will move</span><span style=3D"color:#000"><br></span><span style=3D"color=
:#660">}</span><span style=3D"color:#000"><br></span></div></code></div><br=
>Looking at that, there is no good reason for that first copy. After all wh=
atever is stored inside a will be overwritten in the next line, and there w=
ould be no observable difference between copying and moving. For that reaso=
n I would like to extend the rule that I just proposed to say that automati=
c copy to move conversion is applied when the next operation on the variabl=
e is that it is destroyed, or that it is assigned to.<br><br>After that the=
re is one final place that I can think of which does not apply automatic co=
py-to-move conversion even though it could:<br><br><div style=3D"background=
-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;bo=
rder-width:1px;word-wrap:break-word"><code><div><span style=3D"color:#008">=
string</span><span style=3D"color:#000"> return_string_a</span><span style=
=3D"color:#660">(</span><span style=3D"color:#008">string</span><span style=
=3D"color:#000"> str</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>&nbsp; &nbsp; </span><span style=3D"color:#008">return<=
/span><span style=3D"color:#000"> str</span><span style=3D"color:#660">;</s=
pan><span style=3D"color:#000"> </span><span style=3D"color:#800">// will b=
e moved</span><span style=3D"color:#000"><br></span><span style=3D"color:#6=
60">}</span><span style=3D"color:#000"><br></span><span style=3D"color:#008=
">string</span><span style=3D"color:#000"> return_widget_b</span><span styl=
e=3D"color:#660">(</span><span style=3D"color:#008">string</span><span styl=
e=3D"color:#000"> </span><span style=3D"color:#660">&amp;&amp;</span><span =
style=3D"color:#000"> str</span><span style=3D"color:#660">)</span><span st=
yle=3D"color:#000"><br></span><span style=3D"color:#660">{</span><span styl=
e=3D"color:#000"><br>&nbsp; &nbsp; </span><span style=3D"color:#008">return=
</span><span style=3D"color:#000"> str</span><span style=3D"color:#660">;</=
span><span style=3D"color:#000"> </span><span style=3D"color:#800">// will =
be copied</span><span style=3D"color:#000"><br></span><span style=3D"color:=
#660">}</span><span style=3D"color:#000"><br></span></div></code></div><br>=
The reason for this is also not obvious. As far as we know the object is ab=
out to disappear just as if it was a stack local variable, so why do we hav=
e to explicitly move it? For this reason I would like to expand the above r=
ule to not only include stack local variables, but also rvalue references.<=
br><br>So in summary I would like automatic copy-to-move conversion for sta=
ck-local-variables and rvalue references if they are about to be destroyed,=
 or if the next operation on them is that they are assigned to.<br><br>What=
 would the consequences of this be?<br>Well for starters here is a perfect =
forwarding function with these rules:<br><br><div style=3D"background-color=
:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;border-w=
idth:1px;word-wrap:break-word"><code><div><span style=3D"color:#008">templa=
te</span><span style=3D"color:#660">&lt;</span><span style=3D"color:#008">t=
ypename</span><span style=3D"color:#000"> T</span><span style=3D"color:#660=
">,</span><span style=3D"color:#000"> </span><span style=3D"color:#008">typ=
ename</span><span style=3D"color:#660">...</span><span style=3D"color:#000"=
> </span><span style=3D"color:#606">Args</span><span style=3D"color:#660">&=
gt;</span><span style=3D"color:#000"><br>T </span><span style=3D"color:#660=
">*</span><span style=3D"color:#000"> make_ptr</span><span style=3D"color:#=
660">(</span><span style=3D"color:#606">Args</span><span style=3D"color:#00=
0"> </span><span style=3D"color:#660">&amp;&amp;...</span><span style=3D"co=
lor:#000"> args</span><span style=3D"color:#660">)</span><span style=3D"col=
or:#000"><br></span><span style=3D"color:#660">{</span><span style=3D"color=
:#000"><br>&nbsp; &nbsp; </span><span style=3D"color:#008">return</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#008">new</span><span =
style=3D"color:#000"> T</span><span style=3D"color:#660">(</span><span styl=
e=3D"color:#000">args</span><span style=3D"color:#660">...);</span><span st=
yle=3D"color:#000"><br></span><span style=3D"color:#660">}</span><span styl=
e=3D"color:#000"><br></span></div></code></div><br>Isn't that much nicer th=
an having to type std::forward&lt;Args&gt;(args)...? It just does the right=
 thing by default.<br><br>Other benefits are that working with unique_ptrs =
and other move only types becomes much easier:<br><br><div style=3D"backgro=
und-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid=
;border-width:1px;word-wrap:break-word"><code><div><span style=3D"color:#00=
8">void</span><span style=3D"color:#000"> sink</span><span style=3D"color:#=
660">(</span><span style=3D"color:#000">unique_ptr</span><span style=3D"col=
or:#660">&lt;</span><span style=3D"color:#606">Widget</span><span style=3D"=
color:#660">&gt;</span><span style=3D"color:#000"> widget</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"> foo</span><span s=
tyle=3D"color:#660">()</span><span style=3D"color:#000"><br></span><span st=
yle=3D"color:#660">{</span><span style=3D"color:#000"><br>&nbsp; &nbsp; uni=
que_ptr</span><span style=3D"color:#660">&lt;</span><span style=3D"color:#6=
06">Widget</span><span style=3D"color:#660">&gt;</span><span style=3D"color=
:#000"> a </span><span style=3D"color:#660">=3D</span><span style=3D"color:=
#000"> make_unique</span><span style=3D"color:#660">&lt;</span><span style=
=3D"color:#606">Widget</span><span style=3D"color:#660">&gt;();</span><span=
 style=3D"color:#000"><br>&nbsp; &nbsp; sink</span><span style=3D"color:#66=
0">(</span><span style=3D"color:#000">a</span><span style=3D"color:#660">);=
</span><span style=3D"color:#000"> </span><span style=3D"color:#800">// ok,=
 no need to write std::move(a)</span><span style=3D"color:#000"><br></span>=
<span style=3D"color:#660">}</span><span style=3D"color:#000"><br><br></spa=
n><span style=3D"color:#008">void</span><span style=3D"color:#000"> foo_err=
or</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>&=
nbsp; &nbsp; unique_ptr</span><span style=3D"color:#660">&lt;</span><span s=
tyle=3D"color:#606">Widget</span><span style=3D"color:#660">&gt;</span><spa=
n style=3D"color:#000"> a </span><span style=3D"color:#660">=3D</span><span=
 style=3D"color:#000"> make_unique</span><span style=3D"color:#660">&lt;</s=
pan><span style=3D"color:#606">Widget</span><span style=3D"color:#660">&gt;=
();</span><span style=3D"color:#000"><br>&nbsp; &nbsp; sink</span><span sty=
le=3D"color:#660">(</span><span style=3D"color:#000">a</span><span style=3D=
"color:#660">);</span><span style=3D"color:#000"> </span><span style=3D"col=
or:#800">// compile error: trying to call deleted constructor. can not conv=
ert to move because a is used again in this function</span><span style=3D"c=
olor:#000"><br>&nbsp; &nbsp; sink</span><span style=3D"color:#660">(</span>=
<span style=3D"color:#000">a</span><span style=3D"color:#660">);</span><spa=
n style=3D"color:#000"><br></span><span style=3D"color:#660">}</span><span =
style=3D"color:#000"><br></span></div></code></div><br>That is a pretty goo=
d compile error to have. I think just having the compiler generate an error=
 if you use a unique_ptr twice is a great reason for this proposal. Note th=
at because of the rule for assignment, this is allowed:<br><br><div 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><div><span style=
=3D"color:#008">void</span><span style=3D"color:#000"> foo_assign</span><sp=
an style=3D"color:#660">()</span><span style=3D"color:#000"><br></span><spa=
n style=3D"color:#660">{</span><span style=3D"color:#000"><br>&nbsp; &nbsp;=
 unique_ptr</span><span style=3D"color:#660">&lt;</span><span style=3D"colo=
r:#606">Widget</span><span style=3D"color:#660">&gt;</span><span style=3D"c=
olor:#000"> a </span><span style=3D"color:#660">=3D</span><span style=3D"co=
lor:#000"> make_unique</span><span style=3D"color:#660">&lt;</span><span st=
yle=3D"color:#606">Widget</span><span style=3D"color:#660">&gt;();</span><s=
pan style=3D"color:#000"><br>&nbsp; &nbsp; sink</span><span style=3D"color:=
#660">(</span><span style=3D"color:#000">a</span><span style=3D"color:#660"=
>);</span><span style=3D"color:#000"> </span><span style=3D"color:#800">// =
ok: the next operation on a is assignment to a</span><span style=3D"color:#=
000"><br>&nbsp; &nbsp; a </span><span style=3D"color:#660">=3D</span><span =
style=3D"color:#000"> make_unique</span><span style=3D"color:#660">&lt;</sp=
an><span style=3D"color:#606">Widget</span><span style=3D"color:#660">&gt;(=
);</span><span style=3D"color:#000"><br>&nbsp; &nbsp; sink</span><span styl=
e=3D"color:#660">(</span><span style=3D"color:#000">a</span><span style=3D"=
color:#660">);</span><span style=3D"color:#000"> </span><span style=3D"colo=
r:#800">// ok the next operation on a is calling of its destructor</span><s=
pan style=3D"color:#000"><br></span><span style=3D"color:#660">}</span><spa=
n style=3D"color:#000"><br></span></div></code></div><br>Now here is the do=
wnside of this. This can break existing code, which is why we have to make =
the rules a bit more complicated. Consider this:<br><br><div style=3D"backg=
round-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:sol=
id;border-width:1px;word-wrap:break-word"><code><div><span style=3D"color:#=
008">void</span><span style=3D"color:#000"> keep_reference</span><span styl=
e=3D"color:#660">()</span><span style=3D"color:#000"><br></span><span style=
=3D"color:#660">{</span><span style=3D"color:#000"><br>&nbsp; &nbsp; </span=
><span style=3D"color:#008">string</span><span style=3D"color:#000"> a </sp=
an><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#080">"ahoy"</span><span style=3D"color:#660">;</span>=
<span style=3D"color:#000"><br>&nbsp; &nbsp; reference_wrapper</span><span =
style=3D"color:#080">&lt;string&gt;</span><span style=3D"color:#000"> r </s=
pan><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> a</spa=
n><span style=3D"color:#660">;</span><span style=3D"color:#000"><br>&nbsp; =
&nbsp; cout </span><span style=3D"color:#660">&lt;&lt;</span><span style=3D=
"color:#000"> r</span><span style=3D"color:#660">.</span><span style=3D"col=
or:#008">get</span><span style=3D"color:#660">()</span><span style=3D"color=
:#000"> </span><span style=3D"color:#660">&lt;&lt;</span><span style=3D"col=
or:#000"> endl</span><span style=3D"color:#660">;</span><span style=3D"colo=
r:#000"><br>&nbsp; &nbsp; </span><span style=3D"color:#008">string</span><s=
pan style=3D"color:#000"> b </span><span style=3D"color:#660">=3D</span><sp=
an style=3D"color:#000"> a</span><span style=3D"color:#660">;</span><span s=
tyle=3D"color:#000"> </span><span style=3D"color:#800">// will move because=
 it looks like a is not used again</span><span style=3D"color:#000"><br>&nb=
sp; &nbsp; cout </span><span style=3D"color:#660">&lt;&lt;</span><span styl=
e=3D"color:#000"> r</span><span style=3D"color:#660">.</span><span style=3D=
"color:#008">get</span><span style=3D"color:#660">()</span><span style=3D"c=
olor:#000"> </span><span style=3D"color:#660">&lt;&lt;</span><span style=3D=
"color:#000"> endl</span><span style=3D"color:#660">;</span><span style=3D"=
color:#000"><br></span><span style=3D"color:#660">}</span><span style=3D"co=
lor:#000"><br></span></div></code></div><br>Luckily the solution for this i=
s not too restrictive: Automatic copy-to-move conversion can only be applie=
d if the variable was never passed as a (possibly cv-qualified) lvalue refe=
rence. Since we only use this for stack local variables and rvalue referenc=
es passed to this function, we can know whether any lvalue references exist=
 to this variable. We may also have to disallow automatic copy-to-move conv=
ersion if any references to the variable exist in the current function, but=
 since we can reason about those, we may not have to do that. I'll defer to=
 compiler implementers on that.<br><br>Since we still allow passing of the =
object as an rvalue reference we don't break any of the previous examples. =
(because they always pass the objects as rvalue references)<br><br>We do br=
eak this example though which I would really like to work, because it's nea=
t:<br><br><div style=3D"background-color:rgb(250,250,250);border-color:rgb(=
187,187,187);border-style:solid;border-width:1px;word-wrap:break-word"><cod=
e><div><span style=3D"color:#008">string</span><span style=3D"color:#000"> =
concat</span><span style=3D"color:#660">(</span><span style=3D"color:#008">=
string</span><span style=3D"color:#660">,</span><span style=3D"color:#000">=
 </span><span style=3D"color:#008">string</span><span style=3D"color:#660">=
);</span><span style=3D"color:#000"><br><br></span><span style=3D"color:#00=
8">string</span><span style=3D"color:#000"> bar</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>&nbsp; &nbsp; </span><span styl=
e=3D"color:#008">string</span><span style=3D"color:#000"> </span><span styl=
e=3D"color:#008">local</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">=3D</span><span style=3D"color:#000"> </span><span style=3D=
"color:#080">"neat"</span><span style=3D"color:#660">;</span><span style=3D=
"color:#000"><br>&nbsp; &nbsp; </span><span style=3D"color:#008">return</sp=
an><span style=3D"color:#000"> concat</span><span style=3D"color:#660">(</s=
pan><span style=3D"color:#008">local</span><span style=3D"color:#660">,</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#008">local</spa=
n><span style=3D"color:#660">);</span><span style=3D"color:#000"> </span><s=
pan style=3D"color:#800">// one move constructs, one copy constructs</span>=
<span style=3D"color:#000"><br></span><span style=3D"color:#660">}</span><s=
pan style=3D"color:#000"><br></span></div></code></div><br>Since the compil=
er knows in which order it initializes the function arguments, it should be=
 able to move construct the argument that gets constructed last. Unfortunat=
ely my previous rule amendment about lvalue references would break this, be=
cause the construction of the first argument would mean that an lvalue refe=
rence was created to the local variable.<br>To work around that I think it =
is safe to define this amendment to the amendment: The existence of a lvalu=
e reference shall not inhibit copy-to-move construction if that lvalue is u=
sed for a copy constructor.<br><br>So in summary the rules for this are act=
ually quite complex, but I believe that the out come would be rules that ma=
ke much more sense and that would allow the compiler to do the right thing =
in most cases.<br><br>Here are all the rules:<br>The compiler shall perform=
 automatic copy-to-move conversion on stack local variables to the current =
function and on rvalue references,<br>- if the rules for copy elision apply=
<br>- if the next operation that is performed with that variable is either =
destruction of the variable or assignment to the variable, but not if a (po=
ssibly cv-qualified) lvalue reference has been created to that variable, ex=
cept if that lvalue reference is only used as the argument to a copy constr=
uctor<br><br>With the possible amendment that we may also want to disallow =
any copy-to-move conversion if any references to the variable exist in the =
local function. (this would include rvalue references, but this may not be =
needed because we can reason about local references) By that I mean this:<b=
r><br><div 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><d=
iv><span style=3D"color:#008">void</span><span style=3D"color:#000"> </span=
><span style=3D"color:#008">ref</span><span style=3D"color:#660">()</span><=
span style=3D"color:#000"><br></span><span style=3D"color:#660">{</span><sp=
an style=3D"color:#000"><br>&nbsp; &nbsp; </span><span style=3D"color:#008"=
>string</span><span style=3D"color:#000"> a </span><span style=3D"color:#66=
0">=3D</span><span style=3D"color:#000"> </span><span style=3D"color:#080">=
"str"</span><span style=3D"color:#660">;</span><span style=3D"color:#000"><=
br>&nbsp; &nbsp; </span><span style=3D"color:#008">string</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">&amp;</span><span style=
=3D"color:#000"> r </span><span style=3D"color:#660">=3D</span><span style=
=3D"color:#000"> a</span><span style=3D"color:#660">;</span><span style=3D"=
color:#000"><br>&nbsp; &nbsp; </span><span style=3D"color:#008">string</spa=
n><span style=3D"color:#000"> b </span><span style=3D"color:#660">=3D</span=
><span style=3D"color:#000"> a</span><span style=3D"color:#660">;</span><sp=
an style=3D"color:#000"> </span><span style=3D"color:#800">// will copy bec=
ause a reference to a exists</span><span style=3D"color:#000"><br></span><s=
pan style=3D"color:#660">}</span></div></code></div><br>This last restricti=
on may or may not be needed, because we can reason about local references. =
But lvalue references that are passed to other functions will prevent copy-=
to-move conversion.<br><br>What does this not handle?<br>This proposal only=
 handles the case where we are absolutely certain about what will happen wi=
th the variable next. Consider this:<br><br><div style=3D"background-color:=
rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;border-wi=
dth:1px;word-wrap:break-word"><code><div><span style=3D"color:#008">void</s=
pan><span style=3D"color:#000"> conditional</span><span style=3D"color:#660=
">(</span><span style=3D"color:#008">bool</span><span style=3D"color:#000">=
 b</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>&n=
bsp; &nbsp; unique_ptr</span><span style=3D"color:#660">&lt;</span><span st=
yle=3D"color:#606">Widget</span><span style=3D"color:#660">&gt;</span><span=
 style=3D"color:#000"> a </span><span style=3D"color:#660">=3D</span><span =
style=3D"color:#000"> make_unique</span><span style=3D"color:#660">&lt;</sp=
an><span style=3D"color:#606">Widget</span><span style=3D"color:#660">&gt;(=
);</span><span style=3D"color:#000"><br>&nbsp; &nbsp; unique_ptr</span><spa=
n style=3D"color:#660">&lt;</span><span style=3D"color:#606">Widget</span><=
span style=3D"color:#660">&gt;</span><span style=3D"color:#000"> other </sp=
an><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> a</span=
><span style=3D"color:#660">;</span><span style=3D"color:#000"> </span><spa=
n style=3D"color:#800">// error because a may be used again</span><span sty=
le=3D"color:#000"><br>&nbsp; &nbsp; </span><span style=3D"color:#008">if</s=
pan><span style=3D"color:#000"> </span><span style=3D"color:#660">(</span><=
span style=3D"color:#000">b</span><span style=3D"color:#660">)</span><span =
style=3D"color:#000"><br>&nbsp; &nbsp; &nbsp; &nbsp;a</span><span style=3D"=
color:#660">.</span><span style=3D"color:#008">get</span><span style=3D"col=
or:#660">();</span><span style=3D"color:#000"><br></span><span style=3D"col=
or:#660">}</span><span style=3D"color:#000"><br></span></div></code></div><=
br>In the above example we would still have to manually call std::move() to=
 assign the unique_ptr. I think that this is not a great loss. In fact I do=
n't think that we need to be smart about this. This can be an error:<br><br=
><div style=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,1=
87);border-style:solid;border-width:1px;word-wrap:break-word"><code><div><s=
pan style=3D"color:#008">void</span><span style=3D"color:#000"> conditional=
_b</span><span style=3D"color:#660">(</span><span style=3D"color:#008">bool=
</span><span style=3D"color:#000"> b</span><span style=3D"color:#660">)</sp=
an><span style=3D"color:#000"><br></span><span style=3D"color:#660">{</span=
><span style=3D"color:#000"><br>&nbsp; &nbsp; unique_ptr</span><span style=
=3D"color:#660">&lt;</span><span style=3D"color:#606">Widget</span><span st=
yle=3D"color:#660">&gt;</span><span style=3D"color:#000"> widget </span><sp=
an style=3D"color:#660">=3D</span><span style=3D"color:#000"> make_unique</=
span><span style=3D"color:#660">&lt;</span><span style=3D"color:#606">Widge=
t</span><span style=3D"color:#660">&gt;();</span><span style=3D"color:#000"=
><br>&nbsp; &nbsp; </span><span style=3D"color:#008">if</span><span style=
=3D"color:#000"> </span><span style=3D"color:#660">(</span><span style=3D"c=
olor:#000">b</span><span style=3D"color:#660">)</span><span style=3D"color:=
#000"><br>&nbsp; &nbsp; </span><span style=3D"color:#660">{</span><span sty=
le=3D"color:#000"><br>&nbsp; &nbsp; &nbsp; &nbsp; unique_ptr</span><span st=
yle=3D"color:#660">&lt;</span><span style=3D"color:#606">Widget</span><span=
 style=3D"color:#660">&gt;</span><span style=3D"color:#000"> other </span><=
span style=3D"color:#660">=3D</span><span style=3D"color:#000"> widget</spa=
n><span style=3D"color:#660">;</span><span style=3D"color:#000"> </span><sp=
an style=3D"color:#800">// error: widget may be used again</span><span styl=
e=3D"color:#000"><br>&nbsp; &nbsp; </span><span style=3D"color:#660">}</spa=
n><span style=3D"color:#000"><br>&nbsp; &nbsp; </span><span style=3D"color:=
#800">// ...</span><span style=3D"color:#000"><br>&nbsp; &nbsp; </span><spa=
n style=3D"color:#008">if</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"><br>&nbsp; &nbsp; </span=
><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>&nbsp; &=
nbsp; &nbsp; &nbsp; widget</span><span style=3D"color:#660">.</span><span s=
tyle=3D"color:#008">get</span><span style=3D"color:#660">();</span><span st=
yle=3D"color:#000"><br>&nbsp; &nbsp; </span><span style=3D"color:#660">}</s=
pan><span style=3D"color:#000"><br></span><span style=3D"color:#660">}</spa=
n><span style=3D"color:#000"><br></span></div></code></div><br>Even though =
we could statically reason that the widget is never used again, I think it =
is no big loss to demand that people still have to write std::move() here. =
If compiler implementers think that this case is easy to handle, then we ma=
y allow this, but I would be fine with disallowing this. This however shoul=
d be allowed:<br><br><div 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><div><span style=3D"color:#008">void</span><span style=3D"colo=
r:#000"> conditional_c</span><span style=3D"color:#660">(</span><span style=
=3D"color:#008">bool</span><span style=3D"color:#000"> b</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>&nbsp; &nbsp; unique=
_ptr</span><span style=3D"color:#660">&lt;</span><span style=3D"color:#606"=
>Widget</span><span style=3D"color:#660">&gt;</span><span style=3D"color:#0=
00"> widget </span><span style=3D"color:#660">=3D</span><span style=3D"colo=
r:#000"> make_unique</span><span style=3D"color:#660">&lt;</span><span styl=
e=3D"color:#606">Widget</span><span style=3D"color:#660">&gt;();</span><spa=
n style=3D"color:#000"><br>&nbsp; &nbsp; </span><span style=3D"color:#008">=
if</span><span style=3D"color:#000"> </span><span style=3D"color:#660">(</s=
pan><span style=3D"color:#000">b</span><span style=3D"color:#660">)</span><=
span style=3D"color:#000"><br>&nbsp; &nbsp; </span><span style=3D"color:#66=
0">{</span><span style=3D"color:#000"><br>&nbsp; &nbsp; &nbsp; &nbsp; uniqu=
e_ptr</span><span style=3D"color:#660">&lt;</span><span style=3D"color:#606=
">Widget</span><span style=3D"color:#660">&gt;</span><span style=3D"color:#=
000"> other </span><span style=3D"color:#660">=3D</span><span style=3D"colo=
r:#000"> widget</span><span style=3D"color:#660">;</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#800">// ok</span><span style=3D"colo=
r:#000"><br>&nbsp; &nbsp; </span><span style=3D"color:#660">}</span><span s=
tyle=3D"color:#000"><br>&nbsp; &nbsp; </span><span style=3D"color:#008">els=
e</span><span style=3D"color:#000"><br>&nbsp; &nbsp; </span><span style=3D"=
color:#660">{</span><span style=3D"color:#000"><br>&nbsp; &nbsp; &nbsp; &nb=
sp;widget</span><span style=3D"color:#660">.</span><span style=3D"color:#00=
8">get</span><span style=3D"color:#660">();</span><span style=3D"color:#000=
"><br>&nbsp; &nbsp; </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></span></div></code></div><br>In this case reasoning th=
at widget is not used again is easier because you don't have to keep track =
of what state the variables are in.<br><br>Any comments or suggestions? Whi=
ch cases did I forget to handle?<br></div></blockquote></div>

<p></p>

-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_295_26240890.1395244676985--

.


Author: Philipp Maximilian Stephani <p.stephani2@gmail.com>
Date: Wed, 19 Mar 2014 19:57:42 +0000
Raw View
--047d7b6d9f82cddd2904f4fb104b
Content-Type: text/plain; charset=UTF-8

Compilers are not allowed to perform such translations in the general case
because they cannot know whether the copy/move operations have observable
effects. The only cases where compilers are free to ignore potential
observable effects (e.g. copy elisions) have to be enumerated in the
standard because they aren't covered by the as-if rule.

On Wed Mar 19 2014 at 16:57:59, Christ-Jan Wijtmans <cj.wijtmans@gmail.com>
wrote:

> A proper compiler already does this, i dont know if it will do any good to
> make this part of the standard.
>
> Op zondag 16 maart 2014 23:35:43 UTC+1 schreef maltes...@gmail.com:
>
>> Hi,
>>
>> with "automatic copy to move conversion" I mean this:
>>
>> string f()
>> {
>>     string local = "hello";
>>     //...
>>     return local; // will be moved, not copied
>> }
>>
>> This is a great feature, which means that we have to write std::move()
>> less often than we would have to without this feature. I believe though
>> that we can use this in far more places.
>> Let's start with a variation of the above which I run into somewhat
>> regularly:
>>
>> struct Widget
>> {
>>     Widget(string);
>> };
>>
>> Widget build_widget_a()
>> {
>>     string local = "world";
>>     return local; // will be copied
>> }
>> Widget build_widget_b()
>> {
>>     string local = "!";
>>     return std::move(local); // will be moved
>> }
>>
>> This is a small variation of the above code, yet I need to write
>> std::move. While I understand why this is needed, I think that this is not
>> obvious and comes out of the fact that the rules are too rigid.
>>
>> Currently the rule for automatic copy to move conversion is that it will
>> be applied either when copy-elision can be applied, or when you are
>> returning a stack local variable. The reason why the function returning a
>> Widget can not perform this conversion automatically is that the string is
>> passed to a constructor and not returned directly. But the reason for
>> allowing the copy to move conversion in the first place is that the object
>> is about to go out of scope, making it safe to move it instead of copying
>> it, and that doesn't change whether we pass it to a function or return it
>> directly.
>>
>> So I would like to change the rule for automatic copy to move conversion
>> so that it can be applied if the next operation that is performed on the
>> variable is that it is destroyed. Since the only remaining operation on the
>> string in the above example is that it's destructor is called, it will
>> therefore be moved into the constructor of Widget.
>>
>> Once we start down that road, we can get another obvious optimization for
>> free though:
>>
>> void moves(string a)
>> {
>>     string b = a; // will copy
>>     a = b; // will move
>>     return a; // will move
>> }
>>
>> Looking at that, there is no good reason for that first copy. After all
>> whatever is stored inside a will be overwritten in the next line, and there
>> would be no observable difference between copying and moving. For that
>> reason I would like to extend the rule that I just proposed to say that
>> automatic copy to move conversion is applied when the next operation on the
>> variable is that it is destroyed, or that it is assigned to.
>>
>> After that there is one final place that I can think of which does not
>> apply automatic copy-to-move conversion even though it could:
>>
>> string return_string_a(string str)
>> {
>>     return str; // will be moved
>> }
>> string return_widget_b(string && str)
>> {
>>     return str; // will be copied
>> }
>>
>> The reason for this is also not obvious. As far as we know the object is
>> about to disappear just as if it was a stack local variable, so why do we
>> have to explicitly move it? For this reason I would like to expand the
>> above rule to not only include stack local variables, but also rvalue
>> references.
>>
>> So in summary I would like automatic copy-to-move conversion for
>> stack-local-variables and rvalue references if they are about to be
>> destroyed, or if the next operation on them is that they are assigned to.
>>
>> What would the consequences of this be?
>> Well for starters here is a perfect forwarding function with these rules:
>>
>> template<typename T, typename... Args>
>> T * make_ptr(Args &&... args)
>> {
>>     return new T(args...);
>> }
>>
>> Isn't that much nicer than having to type std::forward<Args>(args)...? It
>> just does the right thing by default.
>>
>> Other benefits are that working with unique_ptrs and other move only
>> types becomes much easier:
>>
>> void sink(unique_ptr<Widget> widget);
>>
>> void foo()
>> {
>>     unique_ptr<Widget> a = make_unique<Widget>();
>>     sink(a); // ok, no need to write std::move(a)
>> }
>>
>> void foo_error()
>> {
>>     unique_ptr<Widget> a = make_unique<Widget>();
>>     sink(a); // compile error: trying to call deleted constructor. can
>> not convert to move because a is used again in this function
>>     sink(a);
>> }
>>
>> That is a pretty good compile error to have. I think just having the
>> compiler generate an error if you use a unique_ptr twice is a great reason
>> for this proposal. Note that because of the rule for assignment, this is
>> allowed:
>>
>> void foo_assign()
>> {
>>     unique_ptr<Widget> a = make_unique<Widget>();
>>     sink(a); // ok: the next operation on a is assignment to a
>>     a = make_unique<Widget>();
>>     sink(a); // ok the next operation on a is calling of its destructor
>> }
>>
>> Now here is the downside of this. This can break existing code, which is
>> why we have to make the rules a bit more complicated. Consider this:
>>
>> void keep_reference()
>> {
>>     string a = "ahoy";
>>     reference_wrapper<string> r = a;
>>     cout << r.get() << endl;
>>     string b = a; // will move because it looks like a is not used again
>>     cout << r.get() << endl;
>> }
>>
>> Luckily the solution for this is not too restrictive: Automatic
>> copy-to-move conversion can only be applied if the variable was never
>> passed as a (possibly cv-qualified) lvalue reference. Since we only use
>> this for stack local variables and rvalue references passed to this
>> function, we can know whether any lvalue references exist to this variable.
>> We may also have to disallow automatic copy-to-move conversion if any
>> references to the variable exist in the current function, but since we can
>> reason about those, we may not have to do that. I'll defer to compiler
>> implementers on that.
>>
>> Since we still allow passing of the object as an rvalue reference we
>> don't break any of the previous examples. (because they always pass the
>> objects as rvalue references)
>>
>> We do break this example though which I would really like to work,
>> because it's neat:
>>
>> string concat(string, string);
>>
>> string bar()
>> {
>>     string local = "neat";
>>     return concat(local, local); // one move constructs, one copy
>> constructs
>> }
>>
>> Since the compiler knows in which order it initializes the function
>> arguments, it should be able to move construct the argument that gets
>> constructed last. Unfortunately my previous rule amendment about lvalue
>> references would break this, because the construction of the first argument
>> would mean that an lvalue reference was created to the local variable.
>> To work around that I think it is safe to define this amendment to the
>> amendment: The existence of a lvalue reference shall not inhibit
>> copy-to-move construction if that lvalue is used for a copy constructor.
>>
>> So in summary the rules for this are actually quite complex, but I
>> believe that the out come would be rules that make much more sense and that
>> would allow the compiler to do the right thing in most cases.
>>
>> Here are all the rules:
>> The compiler shall perform automatic copy-to-move conversion on stack
>> local variables to the current function and on rvalue references,
>> - if the rules for copy elision apply
>> - if the next operation that is performed with that variable is either
>> destruction of the variable or assignment to the variable, but not if a
>> (possibly cv-qualified) lvalue reference has been created to that variable,
>> except if that lvalue reference is only used as the argument to a copy
>> constructor
>>
>> With the possible amendment that we may also want to disallow any
>> copy-to-move conversion if any references to the variable exist in the
>> local function. (this would include rvalue references, but this may not be
>> needed because we can reason about local references) By that I mean this:
>>
>> void ref()
>> {
>>     string a = "str";
>>     string & r = a;
>>     string b = a; // will copy because a reference to a exists
>> }
>>
>> This last restriction may or may not be needed, because we can reason
>> about local references. But lvalue references that are passed to other
>> functions will prevent copy-to-move conversion.
>>
>> What does this not handle?
>> This proposal only handles the case where we are absolutely certain about
>> what will happen with the variable next. Consider this:
>>
>> void conditional(bool b)
>> {
>>     unique_ptr<Widget> a = make_unique<Widget>();
>>     unique_ptr<Widget> other = a; // error because a may be used again
>>     if (b)
>>        a.get();
>> }
>>
>> In the above example we would still have to manually call std::move() to
>> assign the unique_ptr. I think that this is not a great loss. In fact I
>> don't think that we need to be smart about this. This can be an error:
>>
>> void conditional_b(bool b)
>> {
>>     unique_ptr<Widget> widget = make_unique<Widget>();
>>     if (b)
>>     {
>>         unique_ptr<Widget> other = widget; // error: widget may be used
>> again
>>     }
>>     // ...
>>     if (!b)
>>     {
>>         widget.get();
>>     }
>> }
>>
>> Even though we could statically reason that the widget is never used
>> again, I think it is no big loss to demand that people still have to write
>> std::move() here. If compiler implementers think that this case is easy to
>> handle, then we may allow this, but I would be fine with disallowing this.
>> This however should be allowed:
>>
>> void conditional_c(bool b)
>> {
>>     unique_ptr<Widget> widget = make_unique<Widget>();
>>     if (b)
>>     {
>>         unique_ptr<Widget> other = widget; // ok
>>     }
>>     else
>>     {
>>        widget.get();
>>     }
>> }
>>
>> In this case reasoning that widget is not used again is easier because
>> you don't have to keep track of what state the variables are in.
>>
>> Any comments or suggestions? Which cases did I forget to handle?
>>
>  --
>
> ---
> 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.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>

--

---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

--047d7b6d9f82cddd2904f4fb104b
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

Compilers are not allowed to perform such translations in the general case =
because they cannot know whether the copy/move operations have observable e=
ffects. The only cases where compilers are free to ignore potential observa=
ble effects (e.g. copy elisions) have to be enumerated in the standard beca=
use they aren&#39;t covered by the as-if rule.<br>
<br><div>On Wed Mar 19 2014 at 16:57:59, Christ-Jan Wijtmans &lt;<a href=3D=
"mailto:cj.wijtmans@gmail.com">cj.wijtmans@gmail.com</a>&gt; wrote:</div><b=
lockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px =
#ccc solid;padding-left:1ex">
<div dir=3D"ltr">A proper compiler already does this, i dont know if it wil=
l do any good to make this part of the standard.<br><br>Op zondag 16 maart =
2014 23:35:43 UTC+1 schreef <a href=3D"mailto:maltes...@gmail.com" target=
=3D"_blank">maltes...@gmail.com</a>:</div>
<div dir=3D"ltr"><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">H=
i,<br><br>with &quot;automatic copy to move conversion&quot; I mean this:<b=
r><br>
<div style=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,18=
7);border-style:solid;border-width:1px;word-wrap:break-word"><code><div><sp=
an style=3D"color:#008">string</span><span style> f</span><span style=3D"co=
lor:#660">()</span><span style><br>
</span><span style=3D"color:#660">{</span><span style><br>=C2=A0 =C2=A0 </s=
pan><span style=3D"color:#008">string</span><span style> </span><span style=
=3D"color:#008">local</span><span style> </span><span style=3D"color:#660">=
=3D</span><span style> </span><span style=3D"color:#080">&quot;hello&quot;<=
/span><span style=3D"color:#660">;</span><span style><br>
=C2=A0 =C2=A0 </span><span style=3D"color:#800">//...</span><span style><br=
>=C2=A0 =C2=A0 </span><span style=3D"color:#008">return</span><span style> =
</span><span style=3D"color:#008">local</span><span style=3D"color:#660">;<=
/span><span style> </span><span style=3D"color:#800">// will be moved, not =
copied</span><span style><br>
</span><span style=3D"color:#660">}</span><span style><br></span></div></co=
de></div><br>This is a great feature, which means that we have to write std=
::move() less often than we would have to without this feature. I believe t=
hough that we can use this in far more places.<br>
Let&#39;s start with a variation of the above which I run into somewhat reg=
ularly:<br><br><div 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><div><span style=3D"color:#008">struct</span><span style> </span><spa=
n style=3D"color:#606">Widget</span><span style><br></span><span style=3D"c=
olor:#660">{</span><span style><br>=C2=A0 =C2=A0 </span><span style=3D"colo=
r:#606">Widget</span><span style=3D"color:#660">(</span><span style=3D"colo=
r:#008">string</span><span style=3D"color:#660">);</span><span style><br>
</span><span style=3D"color:#660">};</span><span style><br><br></span><span=
 style=3D"color:#606">Widget</span><span style> build_widget_a</span><span =
style=3D"color:#660">()</span><span style><br></span><span style=3D"color:#=
660">{</span><span style><br>
=C2=A0 =C2=A0 </span><span style=3D"color:#008">string</span><span style> <=
/span><span style=3D"color:#008">local</span><span style> </span><span styl=
e=3D"color:#660">=3D</span><span style> </span><span style=3D"color:#080">&=
quot;world&quot;</span><span style=3D"color:#660">;</span><span style><br>
=C2=A0 =C2=A0 </span><span style=3D"color:#008">return</span><span style> <=
/span><span style=3D"color:#008">local</span><span style=3D"color:#660">;</=
span><span style> </span><span style=3D"color:#800">// will be copied</span=
><span style><br>
</span><span style=3D"color:#660">}</span><span style><br></span><span styl=
e=3D"color:#606">Widget</span><span style> build_widget_b</span><span style=
=3D"color:#660">()</span><span style><br></span><span style=3D"color:#660">=
{</span><span style><br>
=C2=A0 =C2=A0 </span><span style=3D"color:#008">string</span><span style> <=
/span><span style=3D"color:#008">local</span><span style> </span><span styl=
e=3D"color:#660">=3D</span><span style> </span><span style=3D"color:#080">&=
quot;!&quot;</span><span style=3D"color:#660">;</span><span style><br>
=C2=A0 =C2=A0 </span><span style=3D"color:#008">return</span><span style> s=
td</span><span style=3D"color:#660">::</span><span style>move</span><span s=
tyle=3D"color:#660">(</span><span style=3D"color:#008">local</span><span st=
yle=3D"color:#660">);</span><span style> </span><span style=3D"color:#800">=
// will be moved</span><span style><br>
</span><span style=3D"color:#660">}</span><span style><br></span></div></co=
de></div><br>This is a small variation of the above code, yet I need to wri=
te std::move. While I understand why this is needed, I think that this is n=
ot obvious and comes out of the fact that the rules are too rigid.<br>
<br>Currently the rule for automatic copy to move conversion is that it wil=
l be applied either when copy-elision can be applied, or when you are retur=
ning a stack local variable. The reason why the function returning a Widget=
 can not perform this conversion automatically is that the string is passed=
 to a constructor and not returned directly. But the reason for allowing th=
e copy to move conversion in the first place is that the object is about to=
 go out of scope, making it safe to move it instead of copying it, and that=
 doesn&#39;t change whether we pass it to a function or return it directly.=
<br>
<br>So I would like to change the rule for automatic copy to move conversio=
n so that it can be applied if the next operation that is performed on the =
variable is that it is destroyed. Since the only remaining operation on the=
 string in the above example is that it&#39;s destructor is called, it will=
 therefore be moved into the constructor of Widget.<br>
<br>Once we start down that road, we can get another obvious optimization f=
or free though:<br><br><div style=3D"background-color:rgb(250,250,250);bord=
er-color:rgb(187,187,187);border-style:solid;border-width:1px;word-wrap:bre=
ak-word">
<code><div><span style=3D"color:#008">void</span><span style> moves</span><=
span style=3D"color:#660">(</span><span style=3D"color:#008">string</span><=
span style> a</span><span style=3D"color:#660">)</span><span style><br></sp=
an><span style=3D"color:#660">{</span><span style><br>
=C2=A0 =C2=A0 </span><span style=3D"color:#008">string</span><span style> b=
 </span><span style=3D"color:#660">=3D</span><span style> a</span><span sty=
le=3D"color:#660">;</span><span style> </span><span style=3D"color:#800">//=
 will copy</span><span style><br>
=C2=A0 =C2=A0 a </span><span style=3D"color:#660">=3D</span><span style> b<=
/span><span style=3D"color:#660">;</span><span style> </span><span style=3D=
"color:#800">// will move</span><span style><br>=C2=A0 =C2=A0 </span><span =
style=3D"color:#008">return</span><span style> a</span><span style=3D"color=
:#660">;</span><span style> </span><span style=3D"color:#800">// will move<=
/span><span style><br>
</span><span style=3D"color:#660">}</span><span style><br></span></div></co=
de></div><br>Looking at that, there is no good reason for that first copy. =
After all whatever is stored inside a will be overwritten in the next line,=
 and there would be no observable difference between copying and moving. Fo=
r that reason I would like to extend the rule that I just proposed to say t=
hat automatic copy to move conversion is applied when the next operation on=
 the variable is that it is destroyed, or that it is assigned to.<br>
<br>After that there is one final place that I can think of which does not =
apply automatic copy-to-move conversion even though it could:<br><br><div s=
tyle=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);bor=
der-style:solid;border-width:1px;word-wrap:break-word">
<code><div><span style=3D"color:#008">string</span><span style> return_stri=
ng_a</span><span style=3D"color:#660">(</span><span style=3D"color:#008">st=
ring</span><span style> str</span><span style=3D"color:#660">)</span><span =
style><br>
</span><span style=3D"color:#660">{</span><span style><br>=C2=A0 =C2=A0 </s=
pan><span style=3D"color:#008">return</span><span style> str</span><span st=
yle=3D"color:#660">;</span><span style> </span><span style=3D"color:#800">/=
/ will be moved</span><span style><br>
</span><span style=3D"color:#660">}</span><span style><br></span><span styl=
e=3D"color:#008">string</span><span style> return_widget_b</span><span styl=
e=3D"color:#660">(</span><span style=3D"color:#008">string</span><span styl=
e> </span><span style=3D"color:#660">&amp;&amp;</span><span style> str</spa=
n><span style=3D"color:#660">)</span><span style><br>
</span><span style=3D"color:#660">{</span><span style><br>=C2=A0 =C2=A0 </s=
pan><span style=3D"color:#008">return</span><span style> str</span><span st=
yle=3D"color:#660">;</span><span style> </span><span style=3D"color:#800">/=
/ will be copied</span><span style><br>
</span><span style=3D"color:#660">}</span><span style><br></span></div></co=
de></div><br>The reason for this is also not obvious. As far as we know the=
 object is about to disappear just as if it was a stack local variable, so =
why do we have to explicitly move it? For this reason I would like to expan=
d the above rule to not only include stack local variables, but also rvalue=
 references.<br>
<br>So in summary I would like automatic copy-to-move conversion for stack-=
local-variables and rvalue references if they are about to be destroyed, or=
 if the next operation on them is that they are assigned to.<br><br>What wo=
uld the consequences of this be?<br>
Well for starters here is a perfect forwarding function with these rules:<b=
r><br><div 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><d=
iv>
<span style=3D"color:#008">template</span><span style=3D"color:#660">&lt;</=
span><span style=3D"color:#008">typename</span><span style> T</span><span s=
tyle=3D"color:#660">,</span><span style> </span><span style=3D"color:#008">=
typename</span><span style=3D"color:#660">...</span><span style> </span><sp=
an style=3D"color:#606">Args</span><span style=3D"color:#660">&gt;</span><s=
pan style><br>
T </span><span style=3D"color:#660">*</span><span style> make_ptr</span><sp=
an style=3D"color:#660">(</span><span style=3D"color:#606">Args</span><span=
 style> </span><span style=3D"color:#660">&amp;&amp;...</span><span style> =
args</span><span style=3D"color:#660">)</span><span style><br>
</span><span style=3D"color:#660">{</span><span style><br>=C2=A0 =C2=A0 </s=
pan><span style=3D"color:#008">return</span><span style> </span><span style=
=3D"color:#008">new</span><span style> T</span><span style=3D"color:#660">(=
</span><span style>args</span><span style=3D"color:#660">...);</span><span =
style><br>
</span><span style=3D"color:#660">}</span><span style><br></span></div></co=
de></div><br>Isn&#39;t that much nicer than having to type std::forward&lt;=
Args&gt;(args)...? It just does the right thing by default.<br><br>Other be=
nefits are that working with unique_ptrs and other move only types becomes =
much easier:<br>
<br><div style=3D"background-color:rgb(250,250,250);border-color:rgb(187,18=
7,187);border-style:solid;border-width:1px;word-wrap:break-word"><code><div=
><span style=3D"color:#008">void</span><span style> sink</span><span style=
=3D"color:#660">(</span><span style>unique_ptr</span><span style=3D"color:#=
660">&lt;</span><span style=3D"color:#606">Widget</span><span style=3D"colo=
r:#660">&gt;</span><span style> widget</span><span style=3D"color:#660">);<=
/span><span style><br>
<br></span><span style=3D"color:#008">void</span><span style> foo</span><sp=
an style=3D"color:#660">()</span><span style><br></span><span style=3D"colo=
r:#660">{</span><span style><br>=C2=A0 =C2=A0 unique_ptr</span><span style=
=3D"color:#660">&lt;</span><span style=3D"color:#606">Widget</span><span st=
yle=3D"color:#660">&gt;</span><span style> a </span><span style=3D"color:#6=
60">=3D</span><span style> make_unique</span><span style=3D"color:#660">&lt=
;</span><span style=3D"color:#606">Widget</span><span style=3D"color:#660">=
&gt;();</span><span style><br>
=C2=A0 =C2=A0 sink</span><span style=3D"color:#660">(</span><span style>a</=
span><span style=3D"color:#660">);</span><span style> </span><span style=3D=
"color:#800">// ok, no need to write std::move(a)</span><span style><br></s=
pan><span style=3D"color:#660">}</span><span style><br>
<br></span><span style=3D"color:#008">void</span><span style> foo_error</sp=
an><span style=3D"color:#660">()</span><span style><br></span><span style=
=3D"color:#660">{</span><span style><br>=C2=A0 =C2=A0 unique_ptr</span><spa=
n style=3D"color:#660">&lt;</span><span style=3D"color:#606">Widget</span><=
span style=3D"color:#660">&gt;</span><span style> a </span><span style=3D"c=
olor:#660">=3D</span><span style> make_unique</span><span style=3D"color:#6=
60">&lt;</span><span style=3D"color:#606">Widget</span><span style=3D"color=
:#660">&gt;();</span><span style><br>
=C2=A0 =C2=A0 sink</span><span style=3D"color:#660">(</span><span style>a</=
span><span style=3D"color:#660">);</span><span style> </span><span style=3D=
"color:#800">// compile error: trying to call deleted constructor. can not =
convert to move because a is used again in this function</span><span style>=
<br>
=C2=A0 =C2=A0 sink</span><span style=3D"color:#660">(</span><span style>a</=
span><span style=3D"color:#660">);</span><span style><br></span><span style=
=3D"color:#660">}</span><span style><br></span></div></code></div><br>That =
is a pretty good compile error to have. I think just having the compiler ge=
nerate an error if you use a unique_ptr twice is a great reason for this pr=
oposal. Note that because of the rule for assignment, this is allowed:<br>
<br><div style=3D"background-color:rgb(250,250,250);border-color:rgb(187,18=
7,187);border-style:solid;border-width:1px;word-wrap:break-word"><code><div=
><span style=3D"color:#008">void</span><span style> foo_assign</span><span =
style=3D"color:#660">()</span><span style><br>
</span><span style=3D"color:#660">{</span><span style><br>=C2=A0 =C2=A0 uni=
que_ptr</span><span style=3D"color:#660">&lt;</span><span style=3D"color:#6=
06">Widget</span><span style=3D"color:#660">&gt;</span><span style> a </spa=
n><span style=3D"color:#660">=3D</span><span style> make_unique</span><span=
 style=3D"color:#660">&lt;</span><span style=3D"color:#606">Widget</span><s=
pan style=3D"color:#660">&gt;();</span><span style><br>
=C2=A0 =C2=A0 sink</span><span style=3D"color:#660">(</span><span style>a</=
span><span style=3D"color:#660">);</span><span style> </span><span style=3D=
"color:#800">// ok: the next operation on a is assignment to a</span><span =
style><br>=C2=A0 =C2=A0 a </span><span style=3D"color:#660">=3D</span><span=
 style> make_unique</span><span style=3D"color:#660">&lt;</span><span style=
=3D"color:#606">Widget</span><span style=3D"color:#660">&gt;();</span><span=
 style><br>
=C2=A0 =C2=A0 sink</span><span style=3D"color:#660">(</span><span style>a</=
span><span style=3D"color:#660">);</span><span style> </span><span style=3D=
"color:#800">// ok the next operation on a is calling of its destructor</sp=
an><span style><br>
</span><span style=3D"color:#660">}</span><span style><br></span></div></co=
de></div><br>Now here is the downside of this. This can break existing code=
, which is why we have to make the rules a bit more complicated. Consider t=
his:<br>
<br><div style=3D"background-color:rgb(250,250,250);border-color:rgb(187,18=
7,187);border-style:solid;border-width:1px;word-wrap:break-word"><code><div=
><span style=3D"color:#008">void</span><span style> keep_reference</span><s=
pan style=3D"color:#660">()</span><span style><br>
</span><span style=3D"color:#660">{</span><span style><br>=C2=A0 =C2=A0 </s=
pan><span style=3D"color:#008">string</span><span style> a </span><span sty=
le=3D"color:#660">=3D</span><span style> </span><span style=3D"color:#080">=
&quot;ahoy&quot;</span><span style=3D"color:#660">;</span><span style><br>
=C2=A0 =C2=A0 reference_wrapper</span><span style=3D"color:#080">&lt;string=
&gt;</span><span style> r </span><span style=3D"color:#660">=3D</span><span=
 style> a</span><span style=3D"color:#660">;</span><span style><br>=C2=A0 =
=C2=A0 cout </span><span style=3D"color:#660">&lt;&lt;</span><span style> r=
</span><span style=3D"color:#660">.</span><span style=3D"color:#008">get</s=
pan><span style=3D"color:#660">()</span><span style> </span><span style=3D"=
color:#660">&lt;&lt;</span><span style> endl</span><span style=3D"color:#66=
0">;</span><span style><br>
=C2=A0 =C2=A0 </span><span style=3D"color:#008">string</span><span style> b=
 </span><span style=3D"color:#660">=3D</span><span style> a</span><span sty=
le=3D"color:#660">;</span><span style> </span><span style=3D"color:#800">//=
 will move because it looks like a is not used again</span><span style><br>
=C2=A0 =C2=A0 cout </span><span style=3D"color:#660">&lt;&lt;</span><span s=
tyle> r</span><span style=3D"color:#660">.</span><span style=3D"color:#008"=
>get</span><span style=3D"color:#660">()</span><span style> </span><span st=
yle=3D"color:#660">&lt;&lt;</span><span style> endl</span><span style=3D"co=
lor:#660">;</span><span style><br>
</span><span style=3D"color:#660">}</span><span style><br></span></div></co=
de></div><br>Luckily the solution for this is not too restrictive: Automati=
c copy-to-move conversion can only be applied if the variable was never pas=
sed as a (possibly cv-qualified) lvalue reference. Since we only use this f=
or stack local variables and rvalue references passed to this function, we =
can know whether any lvalue references exist to this variable. We may also =
have to disallow automatic copy-to-move conversion if any references to the=
 variable exist in the current function, but since we can reason about thos=
e, we may not have to do that. I&#39;ll defer to compiler implementers on t=
hat.<br>
<br>Since we still allow passing of the object as an rvalue reference we do=
n&#39;t break any of the previous examples. (because they always pass the o=
bjects as rvalue references)<br><br>We do break this example though which I=
 would really like to work, because it&#39;s neat:<br>
<br><div style=3D"background-color:rgb(250,250,250);border-color:rgb(187,18=
7,187);border-style:solid;border-width:1px;word-wrap:break-word"><code><div=
><span style=3D"color:#008">string</span><span style> concat</span><span st=
yle=3D"color:#660">(</span><span style=3D"color:#008">string</span><span st=
yle=3D"color:#660">,</span><span style> </span><span style=3D"color:#008">s=
tring</span><span style=3D"color:#660">);</span><span style><br>
<br></span><span style=3D"color:#008">string</span><span style> bar</span><=
span style=3D"color:#660">()</span><span style><br></span><span style=3D"co=
lor:#660">{</span><span style><br>=C2=A0 =C2=A0 </span><span style=3D"color=
:#008">string</span><span style> </span><span style=3D"color:#008">local</s=
pan><span style> </span><span style=3D"color:#660">=3D</span><span style> <=
/span><span style=3D"color:#080">&quot;neat&quot;</span><span style=3D"colo=
r:#660">;</span><span style><br>
=C2=A0 =C2=A0 </span><span style=3D"color:#008">return</span><span style> c=
oncat</span><span style=3D"color:#660">(</span><span style=3D"color:#008">l=
ocal</span><span style=3D"color:#660">,</span><span style> </span><span sty=
le=3D"color:#008">local</span><span style=3D"color:#660">);</span><span sty=
le> </span><span style=3D"color:#800">// one move constructs, one copy cons=
tructs</span><span style><br>
</span><span style=3D"color:#660">}</span><span style><br></span></div></co=
de></div><br>Since the compiler knows in which order it initializes the fun=
ction arguments, it should be able to move construct the argument that gets=
 constructed last. Unfortunately my previous rule amendment about lvalue re=
ferences would break this, because the construction of the first argument w=
ould mean that an lvalue reference was created to the local variable.<br>
To work around that I think it is safe to define this amendment to the amen=
dment: The existence of a lvalue reference shall not inhibit copy-to-move c=
onstruction if that lvalue is used for a copy constructor.<br><br>So in sum=
mary the rules for this are actually quite complex, but I believe that the =
out come would be rules that make much more sense and that would allow the =
compiler to do the right thing in most cases.<br>
<br>Here are all the rules:<br>The compiler shall perform automatic copy-to=
-move conversion on stack local variables to the current function and on rv=
alue references,<br>- if the rules for copy elision apply<br>- if the next =
operation that is performed with that variable is either destruction of the=
 variable or assignment to the variable, but not if a (possibly cv-qualifie=
d) lvalue reference has been created to that variable, except if that lvalu=
e reference is only used as the argument to a copy constructor<br>
<br>With the possible amendment that we may also want to disallow any copy-=
to-move conversion if any references to the variable exist in the local fun=
ction. (this would include rvalue references, but this may not be needed be=
cause we can reason about local references) By that I mean this:<br>
<br><div style=3D"background-color:rgb(250,250,250);border-color:rgb(187,18=
7,187);border-style:solid;border-width:1px;word-wrap:break-word"><code><div=
><span style=3D"color:#008">void</span><span style> </span><span style=3D"c=
olor:#008">ref</span><span style=3D"color:#660">()</span><span style><br>
</span><span style=3D"color:#660">{</span><span style><br>=C2=A0 =C2=A0 </s=
pan><span style=3D"color:#008">string</span><span style> a </span><span sty=
le=3D"color:#660">=3D</span><span style> </span><span style=3D"color:#080">=
&quot;str&quot;</span><span style=3D"color:#660">;</span><span style><br>
=C2=A0 =C2=A0 </span><span style=3D"color:#008">string</span><span style> <=
/span><span style=3D"color:#660">&amp;</span><span style> r </span><span st=
yle=3D"color:#660">=3D</span><span style> a</span><span style=3D"color:#660=
">;</span><span style><br>
=C2=A0 =C2=A0 </span><span style=3D"color:#008">string</span><span style> b=
 </span><span style=3D"color:#660">=3D</span><span style> a</span><span sty=
le=3D"color:#660">;</span><span style> </span><span style=3D"color:#800">//=
 will copy because a reference to a exists</span><span style><br>
</span><span style=3D"color:#660">}</span></div></code></div><br>This last =
restriction may or may not be needed, because we can reason about local ref=
erences. But lvalue references that are passed to other functions will prev=
ent copy-to-move conversion.<br>
<br>What does this not handle?<br>This proposal only handles the case where=
 we are absolutely certain about what will happen with the variable next. C=
onsider this:<br><br><div 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><div><span style=3D"color:#008">void</span><span style> conditional</=
span><span style=3D"color:#660">(</span><span style=3D"color:#008">bool</sp=
an><span style> b</span><span style=3D"color:#660">)</span><span style><br>=
</span><span style=3D"color:#660">{</span><span style><br>
=C2=A0 =C2=A0 unique_ptr</span><span style=3D"color:#660">&lt;</span><span =
style=3D"color:#606">Widget</span><span style=3D"color:#660">&gt;</span><sp=
an style> a </span><span style=3D"color:#660">=3D</span><span style> make_u=
nique</span><span style=3D"color:#660">&lt;</span><span style=3D"color:#606=
">Widget</span><span style=3D"color:#660">&gt;();</span><span style><br>
=C2=A0 =C2=A0 unique_ptr</span><span style=3D"color:#660">&lt;</span><span =
style=3D"color:#606">Widget</span><span style=3D"color:#660">&gt;</span><sp=
an style> other </span><span style=3D"color:#660">=3D</span><span style> a<=
/span><span style=3D"color:#660">;</span><span style> </span><span style=3D=
"color:#800">// error because a may be used again</span><span style><br>
=C2=A0 =C2=A0 </span><span style=3D"color:#008">if</span><span style> </spa=
n><span style=3D"color:#660">(</span><span style>b</span><span style=3D"col=
or:#660">)</span><span style><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0a</span><span s=
tyle=3D"color:#660">.</span><span style=3D"color:#008">get</span><span styl=
e=3D"color:#660">();</span><span style><br>
</span><span style=3D"color:#660">}</span><span style><br></span></div></co=
de></div><br>In the above example we would still have to manually call std:=
:move() to assign the unique_ptr. I think that this is not a great loss. In=
 fact I don&#39;t think that we need to be smart about this. This can be an=
 error:<br>
<br><div style=3D"background-color:rgb(250,250,250);border-color:rgb(187,18=
7,187);border-style:solid;border-width:1px;word-wrap:break-word"><code><div=
><span style=3D"color:#008">void</span><span style> conditional_b</span><sp=
an style=3D"color:#660">(</span><span style=3D"color:#008">bool</span><span=
 style> b</span><span style=3D"color:#660">)</span><span style><br>
</span><span style=3D"color:#660">{</span><span style><br>=C2=A0 =C2=A0 uni=
que_ptr</span><span style=3D"color:#660">&lt;</span><span style=3D"color:#6=
06">Widget</span><span style=3D"color:#660">&gt;</span><span style> widget =
</span><span style=3D"color:#660">=3D</span><span style> make_unique</span>=
<span style=3D"color:#660">&lt;</span><span style=3D"color:#606">Widget</sp=
an><span style=3D"color:#660">&gt;();</span><span style><br>
=C2=A0 =C2=A0 </span><span style=3D"color:#008">if</span><span style> </spa=
n><span style=3D"color:#660">(</span><span style>b</span><span style=3D"col=
or:#660">)</span><span style><br>=C2=A0 =C2=A0 </span><span style=3D"color:=
#660">{</span><span style><br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 unique_ptr</span><span style=3D"color:#660">&lt=
;</span><span style=3D"color:#606">Widget</span><span style=3D"color:#660">=
&gt;</span><span style> other </span><span style=3D"color:#660">=3D</span><=
span style> widget</span><span style=3D"color:#660">;</span><span style> </=
span><span style=3D"color:#800">// error: widget may be used again</span><s=
pan style><br>
=C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span><span style><br>=C2=
=A0 =C2=A0 </span><span style=3D"color:#800">// ...</span><span style><br>=
=C2=A0 =C2=A0 </span><span style=3D"color:#008">if</span><span style> </spa=
n><span style=3D"color:#660">(!</span><span style>b</span><span style=3D"co=
lor:#660">)</span><span style><br>
=C2=A0 =C2=A0 </span><span style=3D"color:#660">{</span><span style><br>=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 widget</span><span style=3D"color:#660">.</span><s=
pan style=3D"color:#008">get</span><span style=3D"color:#660">();</span><sp=
an style><br>=C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span><span =
style><br>
</span><span style=3D"color:#660">}</span><span style><br></span></div></co=
de></div><br>Even though we could statically reason that the widget is neve=
r used again, I think it is no big loss to demand that people still have to=
 write std::move() here. If compiler implementers think that this case is e=
asy to handle, then we may allow this, but I would be fine with disallowing=
 this. This however should be allowed:<br>
<br><div style=3D"background-color:rgb(250,250,250);border-color:rgb(187,18=
7,187);border-style:solid;border-width:1px;word-wrap:break-word"><code><div=
><span style=3D"color:#008">void</span><span style> conditional_c</span><sp=
an style=3D"color:#660">(</span><span style=3D"color:#008">bool</span><span=
 style> b</span><span style=3D"color:#660">)</span><span style><br>
</span><span style=3D"color:#660">{</span><span style><br>=C2=A0 =C2=A0 uni=
que_ptr</span><span style=3D"color:#660">&lt;</span><span style=3D"color:#6=
06">Widget</span><span style=3D"color:#660">&gt;</span><span style> widget =
</span><span style=3D"color:#660">=3D</span><span style> make_unique</span>=
<span style=3D"color:#660">&lt;</span><span style=3D"color:#606">Widget</sp=
an><span style=3D"color:#660">&gt;();</span><span style><br>
=C2=A0 =C2=A0 </span><span style=3D"color:#008">if</span><span style> </spa=
n><span style=3D"color:#660">(</span><span style>b</span><span style=3D"col=
or:#660">)</span><span style><br>=C2=A0 =C2=A0 </span><span style=3D"color:=
#660">{</span><span style><br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 unique_ptr</span><span style=3D"color:#660">&lt=
;</span><span style=3D"color:#606">Widget</span><span style=3D"color:#660">=
&gt;</span><span style> other </span><span style=3D"color:#660">=3D</span><=
span style> widget</span><span style=3D"color:#660">;</span><span style> </=
span><span style=3D"color:#800">// ok</span><span style><br>
=C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span><span style><br>=C2=
=A0 =C2=A0 </span><span style=3D"color:#008">else</span><span style><br>=C2=
=A0 =C2=A0 </span><span style=3D"color:#660">{</span><span style><br>=C2=A0=
 =C2=A0 =C2=A0 =C2=A0widget</span><span style=3D"color:#660">.</span><span =
style=3D"color:#008">get</span><span style=3D"color:#660">();</span><span s=
tyle><br>
=C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span><span style><br></s=
pan><span style=3D"color:#660">}</span><span style><br></span></div></code>=
</div><br>In this case reasoning that widget is not used again is easier be=
cause you don&#39;t have to keep track of what state the variables are in.<=
br>
<br>Any comments or suggestions? Which cases did I forget to handle?<br></d=
iv></blockquote></div>

<p></p>

-- <br>
<br>
--- <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@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</blockquote>

<p></p>

-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

--047d7b6d9f82cddd2904f4fb104b--

.


Author: Zhihao Yuan <zy@miator.net>
Date: Wed, 19 Mar 2014 16:20:35 -0400
Raw View
On Tue, Mar 18, 2014 at 7:32 AM, Geoffrey Romer <gromer@google.com> wrote:
> Yes, it should cover that example.

US 13 and WP covers the conversion one.

> The basic principle of the NB comment is
> that "return foo;" and "return std::move(foo);" should have identical
> behavior when foo is a local variable. I haven't looked at the wording in
> detail (I'm on vacation), but I trust the drafters to have expressed that
> principle correctly.

No, this is US 12 (rejected). `std::move(foo)` does not name a local
variable, and still prevents copy/move elision.

--
Zhihao Yuan, ID lichray
The best way to predict the future is to invent it.
___________________________________________________
4BSD -- http://4bsd.biz/

--

---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

.


Author: Geoffrey Romer <gromer@google.com>
Date: Wed, 19 Mar 2014 17:59:49 -0700
Raw View
--001a1133e4ca455e3804f4ff491b
Content-Type: text/plain; charset=UTF-8

Yeah, I should have said that the two are identical *for purposes of
overload resolution*. You're right that they still differ for purposes of
elision.

On Mar 20, 2014 4:21 AM, "Zhihao Yuan" <zy@miator.net> wrote:
>
> On Tue, Mar 18, 2014 at 7:32 AM, Geoffrey Romer <gromer@google.com> wrote:
> > Yes, it should cover that example.
>
> US 13 and WP covers the conversion one.
>
> > The basic principle of the NB comment is
> > that "return foo;" and "return std::move(foo);" should have identical
> > behavior when foo is a local variable. I haven't looked at the wording
in
> > detail (I'm on vacation), but I trust the drafters to have expressed
that
> > principle correctly.
>
> No, this is US 12 (rejected). `std::move(foo)` does not name a local
> variable, and still prevents copy/move elision.
>
> --
> Zhihao Yuan, ID lichray
> The best way to predict the future is to invent it.
> ___________________________________________________
> 4BSD -- http://4bsd.biz/
>
> --
>
> ---
> 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.
> Visit this group at
http://groups.google.com/a/isocpp.org/group/std-proposals/.

--

---
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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.

--001a1133e4ca455e3804f4ff491b
Content-Type: text/html; charset=UTF-8

<p dir="ltr">Yeah, I should have said that the two are identical *for purposes of overload resolution*. You&#39;re right that they still differ for purposes of elision.</p>
<p dir="ltr">On Mar 20, 2014 4:21 AM, &quot;Zhihao Yuan&quot; &lt;<a href="mailto:zy@miator.net">zy@miator.net</a>&gt; wrote:<br>
&gt;<br>
&gt; On Tue, Mar 18, 2014 at 7:32 AM, Geoffrey Romer &lt;<a href="mailto:gromer@google.com">gromer@google.com</a>&gt; wrote:<br>
&gt; &gt; Yes, it should cover that example.<br>
&gt;<br>
&gt; US 13 and WP covers the conversion one.<br>
&gt;<br>
&gt; &gt; The basic principle of the NB comment is<br>
&gt; &gt; that &quot;return foo;&quot; and &quot;return std::move(foo);&quot; should have identical<br>
&gt; &gt; behavior when foo is a local variable. I haven&#39;t looked at the wording in<br>
&gt; &gt; detail (I&#39;m on vacation), but I trust the drafters to have expressed that<br>
&gt; &gt; principle correctly.<br>
&gt;<br>
&gt; No, this is US 12 (rejected). `std::move(foo)` does not name a local<br>
&gt; variable, and still prevents copy/move elision.<br>
&gt;<br>
&gt; --<br>
&gt; Zhihao Yuan, ID lichray<br>
&gt; The best way to predict the future is to invent it.<br>
&gt; ___________________________________________________<br>
&gt; 4BSD -- <a href="http://4bsd.biz/">http://4bsd.biz/</a><br>
&gt;<br>
&gt; --<br>
&gt;<br>
&gt; ---<br>
&gt; You received this message because you are subscribed to the Google Groups &quot;ISO C++ Standard - Future Proposals&quot; group.<br>
&gt; To unsubscribe from this group and stop receiving emails from it, send an email to <a href="mailto:std-proposals%2Bunsubscribe@isocpp.org">std-proposals+unsubscribe@isocpp.org</a>.<br>
&gt; To post to this group, send email to <a href="mailto:std-proposals@isocpp.org">std-proposals@isocpp.org</a>.<br>
&gt; Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/</a>.<br>
</p>

<p></p>

-- <br />
<br />
--- <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 email to <a href="mailto:std-proposals+unsubscribe@isocpp.org">std-proposals+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href="mailto:std-proposals@isocpp.org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href="http://groups.google.com/a/isocpp.org/group/std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/</a>.<br />

--001a1133e4ca455e3804f4ff491b--

.


Author: Marc <marc.glisse@gmail.com>
Date: Sat, 22 Mar 2014 08:43:07 -0700 (PDT)
Raw View
------=_Part_466_18565458.1395502987284
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

Le dimanche 16 mars 2014 23:35:43 UTC+1, maltes...@gmail.com a =C3=A9crit :
[...]=20

> Here are all the rules:
> The compiler shall perform automatic copy-to-move conversion on stack=20
> local variables to the current function and on rvalue references,
> - if the rules for copy elision apply
> - if [...]
>
=20
Instead of making the rules for copy elision and copy-to-move conversion=20
diverge even more, could we first extend the copy elision rule, please? In=
=20
a number of examples discussed here (maybe not all but at least a=20
significant proportion), copy elision makes as much sense as copy-to-move=
=20
conversion.

--=20

---=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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.

------=_Part_466_18565458.1395502987284
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Le dimanche 16 mars 2014 23:35:43 UTC+1, maltes...@gmail.c=
om a =C3=A9crit&nbsp;:<br><div>[...] <br></div><blockquote class=3D"gmail_q=
uote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pad=
ding-left: 1ex;"><div dir=3D"ltr">Here are all the rules:<br>The compiler s=
hall perform automatic copy-to-move conversion on stack local variables to =
the current function and on rvalue references,<br>- if the rules for copy e=
lision apply<br>- if [...]</div></blockquote><div>&nbsp;<br>Instead of maki=
ng the rules for copy elision and copy-to-move conversion diverge even more=
, could we first extend the copy elision rule, please? In a number of examp=
les discussed here (maybe not all but at least a significant proportion), c=
opy elision makes as much sense as copy-to-move conversion.<br></div></div>

<p></p>

-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

------=_Part_466_18565458.1395502987284--

.


Author: Roman Perepelitsa <roman.perepelitsa@gmail.com>
Date: Sat, 22 Mar 2014 18:43:43 +0100
Raw View
--047d7b66f5fb56108704f5358cf1
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

2014-03-22 16:43 GMT+01:00 Marc <marc.glisse@gmail.com>:

> Le dimanche 16 mars 2014 23:35:43 UTC+1, maltes...@gmail.com a =E9crit :
> [...]
>
>> Here are all the rules:
>> The compiler shall perform automatic copy-to-move conversion on stack
>> local variables to the current function and on rvalue references,
>> - if the rules for copy elision apply
>> - if [...]
>>
>
> Instead of making the rules for copy elision and copy-to-move conversion
> diverge even more, could we first extend the copy elision rule, please? I=
n
> a number of examples discussed here (maybe not all but at least a
> significant proportion), copy elision makes as much sense as copy-to-move
> conversion.
>

Another approach is to allow the compiler to perform a move instead of copy
if it can prove that the source object won't get used after that point.

  {
    Foo a;
    // Requires accessible copy constructor.
    // MAY call the move constructor.
    Foo b =3D a;
  }

Roman Perepelitsa.

--=20

---=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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.

--047d7b66f5fb56108704f5358cf1
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">2014=
-03-22 16:43 GMT+01:00 Marc <span dir=3D"ltr">&lt;<a href=3D"mailto:marc.gl=
isse@gmail.com" target=3D"_blank">marc.glisse@gmail.com</a>&gt;</span>:<br>=
<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">Le dimanche 16 mars 2014 23:35:43 UTC+1, <a href=3D"mailto=
:maltes...@gmail.com" target=3D"_blank">maltes...@gmail.com</a> a =E9crit=
=A0:<br><div>[...] <br></div><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex">

<div dir=3D"ltr"><div class=3D"">Here are all the rules:<br>The compiler sh=
all perform automatic copy-to-move conversion on stack local variables to t=
he current function and on rvalue references,<br>- if the rules for copy el=
ision apply<br>

</div>- if [...]</div></blockquote><div>=A0<br>Instead of making the rules =
for copy elision and copy-to-move conversion diverge even more, could we fi=
rst extend the copy elision rule, please? In a number of examples discussed=
 here (maybe not all but at least a significant proportion), copy elision m=
akes as much sense as copy-to-move conversion.</div>

</div></blockquote><div><br></div><div>Another approach is to allow the com=
piler to perform a move instead of copy if it can prove that the source obj=
ect won&#39;t get used after that point.</div><div><br></div><div><font fac=
e=3D"courier new, monospace">=A0 {</font></div>

<div><font face=3D"courier new, monospace">=A0 =A0 Foo a;</font></div><div>=
<font face=3D"courier new, monospace">=A0 =A0 // Requires accessible copy c=
onstructor.</font></div><div><font face=3D"courier new, monospace">=A0 =A0 =
// MAY call the move constructor.</font></div>

<div><font face=3D"courier new, monospace">=A0 =A0 Foo b =3D a;</font></div=
><div><font face=3D"courier new, monospace">=A0 }</font></div><div><br></di=
v><div>Roman Perepelitsa.<br></div></div></div></div>

<p></p>

-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

--047d7b66f5fb56108704f5358cf1--

.


Author: Felipe Magno de Almeida <felipe.m.almeida@gmail.com>
Date: Sat, 22 Mar 2014 14:47:00 -0300
Raw View
On Sat, Mar 22, 2014 at 2:43 PM, Roman Perepelitsa
<roman.perepelitsa@gmail.com> wrote:
> 2014-03-22 16:43 GMT+01:00 Marc <marc.glisse@gmail.com>:
>
>> Le dimanche 16 mars 2014 23:35:43 UTC+1, maltes...@gmail.com a =E9crit :
>> [...]
>>>
>>> Here are all the rules:
>>> The compiler shall perform automatic copy-to-move conversion on stack
>>> local variables to the current function and on rvalue references,
>>> - if the rules for copy elision apply
>>> - if [...]
>>
>>
>> Instead of making the rules for copy elision and copy-to-move conversion
>> diverge even more, could we first extend the copy elision rule, please? =
In a
>> number of examples discussed here (maybe not all but at least a signific=
ant
>> proportion), copy elision makes as much sense as copy-to-move conversion=
..
>
>
> Another approach is to allow the compiler to perform a move instead of co=
py
> if it can prove that the source object won't get used after that point.
>
>   {
>     Foo a;
>     // Requires accessible copy constructor.
>     // MAY call the move constructor.
>     Foo b =3D a;
>   }

Yeah. I don't know why it isn't possible yet. What code can it break
that isn't already broken?

> Roman Perepelitsa.

Regards,
--=20
Felipe Magno de Almeida

--=20

---=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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.

.


Author: Thiago Macieira <thiago@macieira.org>
Date: Sat, 22 Mar 2014 11:43:35 -0700
Raw View
Em s=E1b 22 mar 2014, =E0s 18:43:43, Roman Perepelitsa escreveu:
> Another approach is to allow the compiler to perform a move instead of co=
py
> if it can prove that the source object won't get used after that point.
>=20
>   {
>     Foo a;
>     // Requires accessible copy constructor.
>     // MAY call the move constructor.
>     Foo b =3D a;
>   }

If you make this a requirement from the standard (compiler "must"), then co=
de=20
later affects code before. This will be hard to implement for simple compil=
ers,=20
syntax checkers, etc.

If you make it optional -- that is, an optimisation -- then it means there =
can=20
be visible effects of the optimisation: a different non-inline function wil=
l get=20
called.

I doubt this can be added to this standard in either form.

--=20
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
   Software Architect - Intel Open Source Technology Center
      PGP/GPG: 0x6EF45358; fingerprint:
      E067 918B B660 DBD1 105C  966C 33F5 F005 6EF4 5358

--=20

---=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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.

.


Author: Roman Perepelitsa <roman.perepelitsa@gmail.com>
Date: Sat, 22 Mar 2014 19:50:24 +0100
Raw View
--047d7b2e5336cec8ee04f5367af6
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

2014-03-22 19:43 GMT+01:00 Thiago Macieira <thiago@macieira.org>:

> Em s=E1b 22 mar 2014, =E0s 18:43:43, Roman Perepelitsa escreveu:
> > Another approach is to allow the compiler to perform a move instead of
> copy
> > if it can prove that the source object won't get used after that point.
> >
> >   {
> >     Foo a;
> >     // Requires accessible copy constructor.
> >     // MAY call the move constructor.
> >     Foo b =3D a;
> >   }
>
> If you make this a requirement from the standard (compiler "must"), then
> code
> later affects code before. This will be hard to implement for simple
> compilers,
> syntax checkers, etc.
>

Not a requirement of course.

If you make it optional -- that is, an optimisation -- then it means there
> can
> be visible effects of the optimisation: a different non-inline function
> will get
> called.
>

This rule would be similar to copy elision where there compiler is granted
a permission to perform optimizations that have observable difference in
behavior.

 I doubt this can be added to this standard in either form.
>

Why not? It's a simple rule and it opens new avenues for optimizations. It
might break existing code although I don't think it's very likely: if a
class has a copy constructor *and* a move constructor, it's a value type.

Roman Perepelitsa.

--=20

---=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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.

--047d7b2e5336cec8ee04f5367af6
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">2014=
-03-22 19:43 GMT+01:00 Thiago Macieira <span dir=3D"ltr">&lt;<a href=3D"mai=
lto:thiago@macieira.org" target=3D"_blank">thiago@macieira.org</a>&gt;</spa=
n>:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-=
left:1px #ccc solid;padding-left:1ex">

Em s=E1b 22 mar 2014, =E0s 18:43:43, Roman Perepelitsa escreveu:<br>
<div class=3D"">&gt; Another approach is to allow the compiler to perform a=
 move instead of copy<br>
&gt; if it can prove that the source object won&#39;t get used after that p=
oint.<br>
&gt;<br>
&gt; =A0 {<br>
&gt; =A0 =A0 Foo a;<br>
&gt; =A0 =A0 // Requires accessible copy constructor.<br>
&gt; =A0 =A0 // MAY call the move constructor.<br>
&gt; =A0 =A0 Foo b =3D a;<br>
&gt; =A0 }<br>
<br>
</div>If you make this a requirement from the standard (compiler &quot;must=
&quot;), then code<br>
later affects code before. This will be hard to implement for simple compil=
ers,<br>
syntax checkers, etc.<br></blockquote><div><br></div><div>Not a requirement=
 of course.</div><div><br></div><blockquote class=3D"gmail_quote" style=3D"=
margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
If you make it optional -- that is, an optimisation -- then it means there =
can<br>
be visible effects of the optimisation: a different non-inline function wil=
l get<br>
called.<br></blockquote><div><br></div><div>This rule would be similar to c=
opy elision where there compiler is granted a permission to perform optimiz=
ations that have observable difference in behavior.</div><div><br></div>

<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
I doubt this can be added to this standard in either form.<br></blockquote>=
<div><br></div><div>Why not? It&#39;s a simple rule and it opens new avenue=
s for optimizations. It might break existing code although I don&#39;t thin=
k it&#39;s very likely: if a class has a copy constructor *and* a move cons=
tructor, it&#39;s a value type.</div>

<div><br></div><div>Roman Perepelitsa.</div></div></div></div>

<p></p>

-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

--047d7b2e5336cec8ee04f5367af6--

.


Author: Brent Friedman <fourthgeek@gmail.com>
Date: Sat, 22 Mar 2014 15:00:01 -0500
Raw View
--047d7bd6bd769729e204f5377276
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

There are already other places where the standard allows optimization to
change the observable behavior of a program, namely RVO. I think this can
be understood just as increasing the scope of RVO to include not only
values returned by a function, but also lvalues within a function.


On Sat, Mar 22, 2014 at 1:50 PM, Roman Perepelitsa <
roman.perepelitsa@gmail.com> wrote:

> 2014-03-22 19:43 GMT+01:00 Thiago Macieira <thiago@macieira.org>:
>
> Em s=E1b 22 mar 2014, =E0s 18:43:43, Roman Perepelitsa escreveu:
>> > Another approach is to allow the compiler to perform a move instead of
>> copy
>> > if it can prove that the source object won't get used after that point=
..
>> >
>> >   {
>> >     Foo a;
>> >     // Requires accessible copy constructor.
>> >     // MAY call the move constructor.
>> >     Foo b =3D a;
>> >   }
>>
>> If you make this a requirement from the standard (compiler "must"), then
>> code
>> later affects code before. This will be hard to implement for simple
>> compilers,
>> syntax checkers, etc.
>>
>
> Not a requirement of course.
>
> If you make it optional -- that is, an optimisation -- then it means ther=
e
>> can
>> be visible effects of the optimisation: a different non-inline function
>> will get
>> called.
>>
>
> This rule would be similar to copy elision where there compiler is grante=
d
> a permission to perform optimizations that have observable difference in
> behavior.
>
>  I doubt this can be added to this standard in either form.
>>
>
> Why not? It's a simple rule and it opens new avenues for optimizations. I=
t
> might break existing code although I don't think it's very likely: if a
> class has a copy constructor *and* a move constructor, it's a value type.
>
> Roman Perepelitsa.
>
> --
>
> ---
> 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.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>

--=20

---=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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.

--047d7bd6bd769729e204f5377276
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><span style=3D"font-family:arial,sans-serif;font-size:13px=
">There are already other places where the standard allows optimization to =
change the observable behavior of a program, namely RVO. I think this can b=
e understood just as increasing the scope of RVO to include not only values=
 returned by a function, but also lvalues within a function.</span></div>
<div class=3D"gmail_extra"><br><br><div class=3D"gmail_quote">On Sat, Mar 2=
2, 2014 at 1:50 PM, Roman Perepelitsa <span dir=3D"ltr">&lt;<a href=3D"mail=
to:roman.perepelitsa@gmail.com" target=3D"_blank">roman.perepelitsa@gmail.c=
om</a>&gt;</span> wrote:<br>
<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"><div class=3D"gmail_extra">=
<div class=3D"gmail_quote">2014-03-22 19:43 GMT+01:00 Thiago Macieira <span=
 dir=3D"ltr">&lt;<a href=3D"mailto:thiago@macieira.org" target=3D"_blank">t=
hiago@macieira.org</a>&gt;</span>:<div class=3D"">
<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-lef=
t:1px #ccc solid;padding-left:1ex">

Em s=E1b 22 mar 2014, =E0s 18:43:43, Roman Perepelitsa escreveu:<br>
<div>&gt; Another approach is to allow the compiler to perform a move inste=
ad of copy<br>
&gt; if it can prove that the source object won&#39;t get used after that p=
oint.<br>
&gt;<br>
&gt; =A0 {<br>
&gt; =A0 =A0 Foo a;<br>
&gt; =A0 =A0 // Requires accessible copy constructor.<br>
&gt; =A0 =A0 // MAY call the move constructor.<br>
&gt; =A0 =A0 Foo b =3D a;<br>
&gt; =A0 }<br>
<br>
</div>If you make this a requirement from the standard (compiler &quot;must=
&quot;), then code<br>
later affects code before. This will be hard to implement for simple compil=
ers,<br>
syntax checkers, etc.<br></blockquote><div><br></div></div><div>Not a requi=
rement of course.</div><div class=3D""><div><br></div><blockquote class=3D"=
gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-=
left:1ex">

If you make it optional -- that is, an optimisation -- then it means there =
can<br>
be visible effects of the optimisation: a different non-inline function wil=
l get<br>
called.<br></blockquote><div><br></div></div><div>This rule would be simila=
r to copy elision where there compiler is granted a permission to perform o=
ptimizations that have observable difference in behavior.</div><div class=
=3D"">
<div><br></div>

<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
I doubt this can be added to this standard in either form.<br></blockquote>=
<div><br></div></div><div>Why not? It&#39;s a simple rule and it opens new =
avenues for optimizations. It might break existing code although I don&#39;=
t think it&#39;s very likely: if a class has a copy constructor *and* a mov=
e constructor, it&#39;s a value type.</div>
<span class=3D"HOEnZb"><font color=3D"#888888">

<div><br></div><div>Roman Perepelitsa.</div></font></span></div></div></div=
><div class=3D"HOEnZb"><div class=3D"h5">

<p></p>

-- <br>
<br>
--- <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@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div>

<p></p>

-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

--047d7bd6bd769729e204f5377276--

.


Author: Geoffrey Romer <gromer@google.com>
Date: Sat, 22 Mar 2014 15:00:59 -0700
Raw View
--001a11330b4030bd9304f53923b8
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

Relatedly, what if elision were permitted any time the compiler decides
it's feasible? This would, among other things, cleanly solve the problem of
std::move sometimes being a pessimization.
On Mar 23, 2014 6:00 AM, "Brent Friedman" <fourthgeek@gmail.com> wrote:

> There are already other places where the standard allows optimization to
> change the observable behavior of a program, namely RVO. I think this can
> be understood just as increasing the scope of RVO to include not only
> values returned by a function, but also lvalues within a function.
>
>
> On Sat, Mar 22, 2014 at 1:50 PM, Roman Perepelitsa <
> roman.perepelitsa@gmail.com> wrote:
>
>> 2014-03-22 19:43 GMT+01:00 Thiago Macieira <thiago@macieira.org>:
>>
>> Em s=C3=A1b 22 mar 2014, =C3=A0s 18:43:43, Roman Perepelitsa escreveu:
>>> > Another approach is to allow the compiler to perform a move instead o=
f
>>> copy
>>> > if it can prove that the source object won't get used after that poin=
t.
>>> >
>>> >   {
>>> >     Foo a;
>>> >     // Requires accessible copy constructor.
>>> >     // MAY call the move constructor.
>>> >     Foo b =3D a;
>>> >   }
>>>
>>> If you make this a requirement from the standard (compiler "must"), the=
n
>>> code
>>> later affects code before. This will be hard to implement for simple
>>> compilers,
>>> syntax checkers, etc.
>>>
>>
>> Not a requirement of course.
>>
>> If you make it optional -- that is, an optimisation -- then it means
>>> there can
>>> be visible effects of the optimisation: a different non-inline function
>>> will get
>>> called.
>>>
>>
>> This rule would be similar to copy elision where there compiler is
>> granted a permission to perform optimizations that have observable
>> difference in behavior.
>>
>>  I doubt this can be added to this standard in either form.
>>>
>>
>> Why not? It's a simple rule and it opens new avenues for optimizations.
>> It might break existing code although I don't think it's very likely: if=
 a
>> class has a copy constructor *and* a move constructor, it's a value type=
..
>>
>> Roman Perepelitsa.
>>
>> --
>>
>> ---
>> You received this message because you are subscribed to the Google Group=
s
>> "ISO C++ Standard - Future Proposals" group.
>> To unsubscribe from this group and stop receiving emails from it, send a=
n
>> email to std-proposals+unsubscribe@isocpp.org.
>> To post to this group, send email to std-proposals@isocpp.org.
>> Visit this group at
>> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>>
>
>  --
>
> ---
> 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.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>

--=20

---=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.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.

--001a11330b4030bd9304f53923b8
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<p dir=3D"ltr">Relatedly, what if elision were permitted any time the compi=
ler decides it&#39;s feasible? This would, among other things, cleanly solv=
e the problem of std::move sometimes being a pessimization.</p>
<div class=3D"gmail_quote">On Mar 23, 2014 6:00 AM, &quot;Brent Friedman&qu=
ot; &lt;<a href=3D"mailto:fourthgeek@gmail.com">fourthgeek@gmail.com</a>&gt=
; wrote:<br type=3D"attribution"><blockquote class=3D"gmail_quote" style=3D=
"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir=3D"ltr"><span style=3D"font-family:arial,sans-serif;font-size:13px=
">There are already other places where the standard allows optimization to =
change the observable behavior of a program, namely RVO. I think this can b=
e understood just as increasing the scope of RVO to include not only values=
 returned by a function, but also lvalues within a function.</span></div>

<div class=3D"gmail_extra"><br><br><div class=3D"gmail_quote">On Sat, Mar 2=
2, 2014 at 1:50 PM, Roman Perepelitsa <span dir=3D"ltr">&lt;<a href=3D"mail=
to:roman.perepelitsa@gmail.com" target=3D"_blank">roman.perepelitsa@gmail.c=
om</a>&gt;</span> wrote:<br>

<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"><div class=3D"gmail_extra">=
<div class=3D"gmail_quote">2014-03-22 19:43 GMT+01:00 Thiago Macieira <span=
 dir=3D"ltr">&lt;<a href=3D"mailto:thiago@macieira.org" target=3D"_blank">t=
hiago@macieira.org</a>&gt;</span>:<div>

<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-lef=
t:1px #ccc solid;padding-left:1ex">

Em s=C3=A1b 22 mar 2014, =C3=A0s 18:43:43, Roman Perepelitsa escreveu:<br>
<div>&gt; Another approach is to allow the compiler to perform a move inste=
ad of copy<br>
&gt; if it can prove that the source object won&#39;t get used after that p=
oint.<br>
&gt;<br>
&gt; =C2=A0 {<br>
&gt; =C2=A0 =C2=A0 Foo a;<br>
&gt; =C2=A0 =C2=A0 // Requires accessible copy constructor.<br>
&gt; =C2=A0 =C2=A0 // MAY call the move constructor.<br>
&gt; =C2=A0 =C2=A0 Foo b =3D a;<br>
&gt; =C2=A0 }<br>
<br>
</div>If you make this a requirement from the standard (compiler &quot;must=
&quot;), then code<br>
later affects code before. This will be hard to implement for simple compil=
ers,<br>
syntax checkers, etc.<br></blockquote><div><br></div></div><div>Not a requi=
rement of course.</div><div><div><br></div><blockquote class=3D"gmail_quote=
" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">


If you make it optional -- that is, an optimisation -- then it means there =
can<br>
be visible effects of the optimisation: a different non-inline function wil=
l get<br>
called.<br></blockquote><div><br></div></div><div>This rule would be simila=
r to copy elision where there compiler is granted a permission to perform o=
ptimizations that have observable difference in behavior.</div><div>
<div><br></div>

<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
I doubt this can be added to this standard in either form.<br></blockquote>=
<div><br></div></div><div>Why not? It&#39;s a simple rule and it opens new =
avenues for optimizations. It might break existing code although I don&#39;=
t think it&#39;s very likely: if a class has a copy constructor *and* a mov=
e constructor, it&#39;s a value type.</div>

<span><font color=3D"#888888">

<div><br></div><div>Roman Perepelitsa.</div></font></span></div></div></div=
><div><div>

<p></p>

-- <br>
<br>
--- <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@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></blockquote></div><br></div>

<p></p>

-- <br>
<br>
--- <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@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>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</blockquote></div>

<p></p>

-- <br />
<br />
--- <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 />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />

--001a11330b4030bd9304f53923b8--

.