19

Current C++11 standard does not support move capture of variable in lambda expression like

unique_ptr<int[]> msg(new int[1000000]);
async_op([&&msg] { // compile error : move capture is not supported
   /* do something */
});

Since message passing and unique ownership has some critical role in some asynchronous system design, I think move semantic should be treated as first class language semantic. But lambda doesn't support move capture.

Of course I know that there is some workaround using move capture proxy - but I wonder the reason of decision that this functionality not to be included in the C++11 standard, despite of its importance.

summerlight
  • 882
  • 7
  • 16
  • 8
    The reason is most likely that they simply didn't think of it when lambdas were introduced. FWIW, the committee is reworking the capturing part and thinking about generalizing it by allowing initializers to captures (aka `[m = std::move(msg)]{ ... }`). – Xeo Nov 23 '12 at 02:10
  • Thank you for answer. Allowing initializer expression in capture list looks promising. – summerlight Nov 23 '12 at 02:37
  • 1
    this can also be interesting for you http://stackoverflow.com/questions/8640393/move-capture-in-lambda – user1802174 Nov 23 '12 at 12:21
  • @Summerlight - One argument against it is the problem of defining what `async([&&]{ });` would do. Move from everything in sight? – Bo Persson Nov 24 '12 at 10:12
  • @Xeo: how would that work in practice? Is the move performed when the lambda is "created", or is it moved each time the lambda is called? How would copying such a lambda work? Would the copy move the move-captured variable again? – rubenvb Nov 25 '12 at 11:04
  • 1
    @rubenvb: Is a capture copied every time a lambda is called? :P And for copying, I'd assume the capture to be copied too. If it's move-only, well, the lambda won't be copyable. – Xeo Nov 25 '12 at 11:58
  • @Xeo: I can imagine a bunch of hidden problems popping up that are hard to track down if you try to copy a move-only capture. But hey, let's leave that to the language committee people :) – rubenvb Nov 25 '12 at 12:49
  • @rubenvb: Remember, a lambda is just syntactic sugar for a local type. Mind elaborating on those "hidden problems"? – Xeo Nov 25 '12 at 12:56
  • @Xeo I figured the "hidden" move's could confuse people not quite up to speed about their implications on the lambda captures. I might be rambling though. – rubenvb Nov 25 '12 at 14:02
  • 1
    @rubenvb: I don't see where there are hidden moves. If you move the lambda, you move the captures. If you copy the lambda, you (try to) copy the captures. I can't see how that might be confusing, but maybe that's just me. – Xeo Nov 25 '12 at 18:28

1 Answers1

5

The C++ spec tries to be pretty conservative. It's really bad for the next language spec to break programs that were compliant under the previous spec.

Move semantics took a while to mature. There were changes as late as 2009, if I recall. Meanwhile lambdas weren't implemented in many compilers until a similar timeframe. There was no time to fill in the gaps and still release a standard in 2011, which was already very late. (Prototype the spec with the compilers, test the compilers, go back and debate the spec, draft, prototype, test, repeat. Takes a while.)

Lambdas will be extended greatly in the next standard, gaining type deduction (auto polymorphism). Xeo mentions one potential solution to move initialization.

Note that lambdas are only syntactic sugar. They are specified in terms of an automatically-defined class, but contain nothing you can't do yourself. As for the present language standard, you are expected to manually flesh out that implementation when the sugar runs out.

By the way, you can possibly work around the missing feature by capturing an old fashioned auto_ptr, which is C++03's now-deprecated attempt at a smart pointer. It is invalidated by its own copy constructor, essentially implementing move-on-copy. But it is deprecated by C++11 and may cause warnings. You could try implementing something similar, though.

Potatoswatter
  • 134,909
  • 25
  • 265
  • 421