How to create an std::function from a move-capturing lambda expression?

c lambda capture this
c++ lambda move capture
c++ pass lambda to function
c++ lambda as parameter
std::function member function
std::function lambda
std::function<void
expected variable name or this' in lambda capture list

I'm trying to create an std::function from a move-capturing lambda expression. Note that I can create a move-capturing lambda expression without problems; it's only when I try to wrap it in an std::function that I get an error.

For example:

auto pi = std::make_unique<int>(0);

// no problems here!
auto foo = [q = std::move(pi)] {
    *q = 5;
    std::cout << *q << std::endl;
};

// All of the attempts below yield:
// "Call to implicitly-deleted copy constructor of '<lambda...."

std::function<void()> bar = foo;
std::function<void()> bar{foo};
std::function<void()> bar{std::move(foo)};
std::function<void()> bar = std::move(foo);
std::function<void()> bar{std::forward<std::function<void()>>(foo)};
std::function<void()> bar = std::forward<std::function<void()>>(foo);

I'll explain why I want to write something like this. I've written a UI library which, similar to jQuery or JavaFX, allows the user to handle mouse/keyboard events by passing std::functions to methods with names like on_mouse_down(), on_mouse_drag(), push_undo_action(), etc.

Obviously, the std::function I want to pass in should ideally use a move-capturing lambda expression, otherwise I need to resort to the ugly "release/acquire-in-lambda" idiom I was using when C++11 was the standard:

std::function<void()> baz = [q = pi.release()] {
    std::unique_ptr<int> p{q};
    *p = 5;
    std::cout << *q << std::endl;
};

Note that calling baz twice would be an error in the above code. However, in my code, this closure is guaranteed to be called exactly once.

BTW, in my real code, I'm not passing an std::unique_ptr<int>, but something more interesting.

Finally, I'm using Xcode6-Beta4 which uses the following version of clang:

Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.3.0
Thread model: posix

template<class F> function(F f);

template <class F, class A> function(allocator_arg_t, const A& a, F f);

Requires: F shall be CopyConstructible. f shall be Callable for argument types ArgTypes and return type R. The copy constructor and destructor of A shall not throw exceptions.

§20.9.11.2.1 [func.wrap.func.con]

Note that operator = is defined in terms of this constructor and swap, so the same restrictions apply:

template<class F> function& operator=(F&& f);

Effects: function(std::forward<F>(f)).swap(*this);

§20.9.11.2.1 [func.wrap.func.con]

So to answer your question: Yes, it is possible to construct a std::function from a move-capturing lambda (since this only specifies how the lambda captures), but it is not possible to construct a std::function from a move-only type (e.g. a move-capturing lambda which move-captures something that is not copy constructible).

Lambda expressions (since C++11), Anonymous functions, or lambdas, were introduced in C++11 as a to the [id = expression] syntax in the capture specifier list, allowing us to initialize the such as std::vector might take arbitrarily long to copy, making a move  Questions: I'm trying to create an std::function from a move-capturing lambda expression. Note tha

As std::function<?> has to type-erase the copy constructor of the stored invocable object, you cannot construct it from a move-only type. Your lambda, because it captures a move-only type by value, is a move-only type. So... you cannot solve your problem. std::function cannot store your lambda.

At least not directly.

This is C++, we simply route around the problem.

template<class F>
struct shared_function {
  std::shared_ptr<F> f;
  shared_function() = delete; // = default works, but I don't use it
  shared_function(F&& f_):f(std::make_shared<F>(std::move(f_))){}
  shared_function(shared_function const&)=default;
  shared_function(shared_function&&)=default;
  shared_function& operator=(shared_function const&)=default;
  shared_function& operator=(shared_function&&)=default;
  template<class...As>
  auto operator()(As&&...as) const {
    return (*f)(std::forward<As>(as)...);
  }
};
template<class F>
shared_function< std::decay_t<F> > make_shared_function( F&& f ) {
  return { std::forward<F>(f) };
}

now that the above is done, we can solve your problem.

auto pi = std::make_unique<int>(0);

auto foo = [q = std::move(pi)] {
  *q = 5;
  std::cout << *q << std::endl;
};

std::function< void() > test = make_shared_function( std::move(foo) );
test(); // prints 5

The semantics of a shared_function is slightly different than other functions, as a copy of it shares the same state (including when turned into a std::function) as the original.

We can also write a move-only fire-once function:

template<class Sig>
struct fire_once;

template<class T>
struct emplace_as {};

template<class R, class...Args>
struct fire_once<R(Args...)> {
  // can be default ctored and moved:
  fire_once() = default;
  fire_once(fire_once&&)=default;
  fire_once& operator=(fire_once&&)=default;

  // implicitly create from a type that can be compatibly invoked
  // and isn't a fire_once itself
  template<class F,
    std::enable_if_t<!std::is_same<std::decay_t<F>, fire_once>{}, int> =0,
    std::enable_if_t<
      std::is_convertible<std::result_of_t<std::decay_t<F>&(Args...)>, R>{}
      || std::is_same<R, void>{},
      int
    > =0
  >
  fire_once( F&& f ):
    fire_once( emplace_as<std::decay_t<F>>{}, std::forward<F>(f) )
  {}
  // emplacement construct using the emplace_as tag type:
  template<class F, class...FArgs>
  fire_once( emplace_as<F>, FArgs&&...fargs ) {
    rebind<F>(std::forward<FArgs>(fargs)...);
  }
  // invoke in the case where R is not void:
  template<class R2=R,
    std::enable_if_t<!std::is_same<R2, void>{}, int> = 0
  >
  R2 operator()(Args...args)&&{
    try {
      R2 ret = invoke( ptr.get(), std::forward<Args>(args)... );
      clear();
      return ret;
    } catch(...) {
      clear();
      throw;
    }
  }
  // invoke in the case where R is void:
  template<class R2=R,
    std::enable_if_t<std::is_same<R2, void>{}, int> = 0
  >
  R2 operator()(Args...args)&&{
    try {
      invoke( ptr.get(), std::forward<Args>(args)... );
      clear();
    } catch(...) {
      clear();
      throw;
    }
  }

  // empty the fire_once:
  void clear() {
    invoke = nullptr;
    ptr.reset();
  }

  // test if it is non-empty:
  explicit operator bool()const{return (bool)ptr;}

  // change what the fire_once contains:
  template<class F, class...FArgs>
  void rebind( FArgs&&... fargs ) {
    clear();
    auto pf = std::make_unique<F>(std::forward<FArgs>(fargs)...);
    invoke = +[](void* pf, Args...args)->R {
      return (*(F*)pf)(std::forward<Args>(args)...);
    };
    ptr = {
      pf.release(),
      [](void* pf){
        delete (F*)(pf);
      }
    };
  }
private:
  // storage.  A unique pointer with deleter
  // and an invoker function pointer:
  std::unique_ptr<void, void(*)(void*)> ptr{nullptr, +[](void*){}};
  void(*invoke)(void*, Args...) = nullptr;
};

which supports even non-movable types via the emplace_as<T> tag.

live example.

Note you have to evaluate () in an rvalue context (ie, after a std::move), as a silent destructive () seemed rude.

This implementation does not use SBO, for if it did it would demand that the type stored be movable, and it would be more work (for me) to boot.

Nested Lambdas and Move Capture in C++14, produces an xvalue expression that identifies its argument t . It is exactly equivalent to a static_cast to an rvalue reference type. Are captured arguments copied during the conversion of lambdas to std::function? I need to convert a lambda that captures a non-copyable type to std::function. So I passed a lambda to std::function

Here's a simpler solution:

   auto pi = std::make_unique<int>(0);

   auto ppi = std::make_shared<std::unique_ptr<int>>(std::move(pi));

   std::function<void()> bar = [ppi] {
        **ppi = 5;
        std::cout << **ppi << std::endl;
   };

Live example here

std::move, In C++11 and later, a lambda expression—often called a lambda—is a you can capture move-only variables (such as std::unique_ptr) from the This tells the compiler to create the function call operator as a template. Obviously, the std::function I want to pass in should ideally use a move-capturing lambda expression, otherwise I need to resort to the ugly "release/acquire-in-lambda" idiom I was using when C++11 was the standard: std:: function < void ()> baz =

C++11 Lambda : How to capture member variables inside Lambda , Lambdas combine the benefits of function pointers and function objects: like specification and tells the compiler we're creating a lambda expression. In my opinion, inheriting from std::function avoids reinventing the wheel  How to create an std::function from a move-capturing lambda expression? 2 answers This answer explains how to move-capture a variable within a lambda in C++14. But once you've move-captured an un-copyable object (such as a std::unique_ptr ) within a lambda, you cannot copy the lambda itself.

Lambda Expressions in C++, Shouldn't C++14 move capture move ownership of ptr to the lambda object? This is a bit strange since C++ doesn't allow you to create anonymous classes explicitly, but Because in order to construct the std::function instance that's it can be expressed more concretely than auto in C++ by expressing it  How to create an std::function from a move-capturing lambda expression? 3 answers Are captured arguments copied during the conversion of lambdas to std::function ? I need to convert a lambda that captures a non-copyable type to std::function .

Lambdas In C++ With Examples, C++11 permitted automatically deducing the return type of a lambda function where you want the type to exactly “track” some expression you're invoking. auto u = make_unique<some_type>( some, parameters ); // a unique_ptr is move​-only each capture creates a new type-deduced local variable inside the lambda:. How to create an std::function from a move-capturing lambda expression? 2 answers This answer explains how to move-capture a variable within a lambda in C++14. But once you've move-captured an un-copyable object (such as a std::unique_ptr ) within a lambda, you cannot copy the lambda itself.

Comments
  • You can't. std::function requires the function object be CopyConstructible.
  • This is very similar to stackoverflow.com/questions/25330716/… Also, why not just using templates for the functons instead of std::function type erasure? Using std::function as an universal function type is not a good idea.
  • Well the idea was to avoid compilation times getting too long, combined with the fact that the performance penalty for using std::function is acceptable in the context of UI callbacks. (Perhaps premature optimization!)
  • Related question: Move-only version of std::function
  • The range library now included in the standard fixes this problem (only here for backward compatiblity) with a semiregular wrapper: eel.is/c++draft/range.semi.wrap
  • I don't understand the difference between the first and second clauses in your last sentence ("it is possible to construct..." and "but it is not possible..."). Could you perhaps provide an example?
  • @seertaak: Let's say you have a lambda which captures a std::vector by move. The std::vector is moved into the lambda, but std::vector is CopyConstructible, and therefore the lambda is copyable, even though it captured by move. Therefore this lambda, all else being equal, may be used to construct a std::function. I.e. how you capture something isn't really relevant, what's relevant is the properties those objects give the lambda once captured.
  • Wait: ints are copy-constructible, just like std::vector. Why shouldn't it work on ints then?
  • @seertaak you capture std::unique_ptr, not an int. Try to replace it with std::shared_ptr which is copy-constructable.
  • @seertaak See also an explanation of why-on-Earth std::function requires functor to be copy-constructable and a workaround via adapter here.
  • Why would it be a problem to call a fire_once function twice? As long as it holds the callable, it should be fine to call the object, right?
  • @user8 [x=std::optional<T>(x)]()mutable{ auto r = std::move(*x); x=std::nullopt; return r; } is a toy example; a function that when called becomes invalid to call again. Proxy move constructors more generally, and any case where copying costs more than consuming.
  • Similar trick is mentioned in this talk.