RVO applies to situations where we have a clear "exit" channel
and after which the affected object is "history".
unexpected gotchas in the code parts following the closure construction.
Daniel,
RVO applies to situations where we have a clear "exit" channelWe have a clear exit channel- into the lambda.
it would fail to compile if slightly modified:
Except for cases where the local variable is passed elsewhere in addition to the lambda.
it would fail to compile if slightly modified:We already have an identical situation with function return values.std::unique_ptr<int> f(std::unique_ptr<int> in) { return in; }std::unique_ptr<int> func() {auto p = std::make_unique<int>();return p; // Fineauto var = p;
std::cout << "loggity loggity log\n";return var; // Not fine.}
But finally, again, there is no difference here between "Move p into return value" and "Move p into lambda and move lambda into return value".
Except for cases where the local variable is passed elsewhere in addition to the lambda.It's gonna be UB for them to access that variable after the lambda is constructed and the function returns, and they can't access it whilst the lambda is being constructed because, y'know, the lambda is of a strict form which does not permit that. In the examplestd::function<int()> func()
{
auto p = std::make_unique<int>();f(p); // assume reference, say
return [p]{ return *p; };}
Why should lambdas be special? If it works for lambdas it would work here too
This line would fail, not the return.
Sure. But do you think it should be different to have
Sure. But do you think it should be different to haveReplace [p] { return *p; } with p, and you have exactly the same issues. This doesn't bring anything new to the table.
Er, if you return a lambda. I obviously don't mean for some arbitrary lambda creation.
That's why I asked whether you really want [p] to mean move capture in some situations, and copy-capture in others, depending on the surrounding context.
We already have an identical situation with function return values.
I think the bottom line is that
Why should lambdas be special?
Can we please stop trying to squeeze every possible language feature into lambdas?
Not everything can or should be done with lambdas, especially if it makes the rest of the language into second-class citizens.
The latter two samples fail to compile because auto x = [p]{ return *p; }; is obviously not of the form return lambda so no implicit move can be applied and unique_ptr has no copy constructor. So as I previously stated, they behave exactly the same as if [p] { return *p; } was replaced with p (also the return type adjusted and std::function requires copyability.. but I get your meaning). The
Except that if you do that replacement, they will compile fine. :P
you can move into a lambda with the c++14 init-captures
Except that if you do that replacement, they will compile fine. :PEr, if you doauto f() {auto p = std::make_unique<int>();auto x = p;I'm pretty sure you will get a compiler error.
you can move into a lambda with the c++14 init-capturesYou could also explicitly move a return value. That didn't stop us implementing it before.
On 5 June 2013 18:53, DeadMG <wolfei...@gmail.com> wrote:
Except that if you do that replacement, they will compile fine. :PEr, if you doauto f() {auto p = std::make_unique<int>();auto x = p;I'm pretty sure you will get a compiler error.Ah, I stand corrected. With auto&&, the situation is different.
std::vector<int> make_foo_vect();
void use_vect(std::vector<int> asd);
void f() {
std::vector<int> foo = make_foo_vect();
use_vect(foo); //copy
use_vect(foo); //copy
use_vect(foo); //move
}
@Robert: Try what happens when use_vect uses a hidden global reference to it's arguments, directly or indirectly.The simple fact is that generalized moving is not possible. It is only possible in some very limited contexts. Lambdas are one of those contexts.
@Richard: That issue will have already been addressed by return id-expression, but more seriously, you are returning a reference to a local variable.
I am thinking something like, for each capture, if that capture is a simple-capture which captures a non-reference local variable, then capture by move.
I think the bottom line is that(1) lambdas are designed to capture the context; in this case when returned from a function they should MOVE the captured local values effortlessly;(2) some compilers already optimize that automatically (which means that writing v1= std::move(v1) is just stating the obvious);
>But I hope not -- just keep the relationship between value categories
>and expression types as simple as possible, programmer will thank
>you.