Topic: Moving local objects into lambda closure


Author: daniel.kruegler@googlemail.com
Date: Sat, 25 Apr 2009 16:11:33 CST
Raw View
On 14 Apr., 23:10, litb <Schaub-Johan...@web.de> wrote:
> I've read the lambda wording and revised wording, but i haven't found
> anything that makes the following common (i would think so) usage
> valid:
>
>      function<void(std::string const&)> f() {
>          ostream os(....); // stands for a movable but not copyable
> object
>          return [](std::string const& s) mutable { os << s; };
>      }
>
>      auto g = f; g("hello");
>
> It looks to me as if the following fails if there is no publicly
> accessible copy constructor. I would expect the above to move
> construct a local data-member of the closure object from "os", which
> would in effect make the lambda object non-copyable, but still
> movable.  But the specification says that it captures it by copy and
> does not mention what happens in the above case.
>
> Do i miss some detail about move construction of data-member?
> If no, what were the rationale for disallowing the above?

First the lambda expression is invalid, because it has an empty
capture set but attempts to use a variable of the next current
scope (os). As you have already recognized: It is currently not
possible to use "move-only" types as a captured variable.

While your use-case seems not unreasonable, I also think
that above syntax wouldn't be a good idea, because it does
completely hide the fact that the local os is moved! There
is no single std::move(os) or static_cast<ostream&&>(os)
in sight, which would break all the current syntactical
safety mechanisms provided by the rvalue proposal.

If we try to fix that the nearest syntactic equivalent that
comes to me in the moment would be something like:

function<void(std::string const&)> f() {
   ostream os(....);
   ostream&& ros = std::move(os);
   return [&&ros](std::string const& s) mutable { ros << s; };
}

And some special rules must be added, because
ros is an lvalue and would without extra wording not
implicitly bind to ostream&& again.

Greetings from Bremen,

Daniel Kr   gler


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: litb <Schaub-Johannes@web.de>
Date: Tue, 14 Apr 2009 15:10:22 CST
Raw View
Hello List,

I've read the lambda wording and revised wording, but i haven't found
anything that makes the following common (i would think so) usage
valid:

     function<void(std::string const&)> f() {
         ostream os(....); // stands for a movable but not copyable
object
         return [](std::string const& s) mutable { os << s; };
     }

     auto g = f; g("hello");

It looks to me as if the following fails if there is no publicly
accessible copy constructor. I would expect the above to move
construct a local data-member of the closure object from "os", which
would in effect make the lambda object non-copyable, but still
movable.  But the specification says that it captures it by copy and
does not mention what happens in the above case.

Do i miss some detail about move construction of data-member?
If no, what were the rationale for disallowing the above?

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]