Mike van Dyke
Mike van Dyke

Reputation: 2858

C++11 lambda capture by copy unless wrapped in std::ref

When passing the arguments to std::bind they are always copied or moved, unless wrapped by std::ref and I want to do the same with a lambda expression. The Problem is, that I want to wrap the generation of the lambda expression in a function and forward the arguments as passed by the user to the lambda. The reason I want to do this, is that I want to call the lambda asynchronously and let the user decide if the arguments shall be passed by reference or by copy.

Consider the following example. I have the function print_address that takes the parameter as reference. Then I have the function combine_and_call_bind that forwards the arguments into std::bind.

void print_address(int& a) {
  std::cout << "Adress of a = " << &a << std::endl;
}

template<typename F, typename Args>
void combine_and_call_bind(F f, Args&& args) {
  auto a = std::bind(f, std::forward<Args>(args));

  a();
}

The user can the specify when calling the combine_and_call_bind-function if the arguments shall be copied into std::bind or if they shall be passed by reference by wrapping the arguments in std::ref:

combine_and_call_bind(print_address, a); // copy a into std::bind
combine_and_call_bind(print_address, std::ref(a)); // pass a as reference into std::bind

How can I do the same with the following function combine_and_call_lambda, while using C++11?

template<typename F, typename Args>
void combine_and_call_lambda(F f, Args&& args) {
  auto a = [/* std::forward<Args>(args) */, f] {
    f(args);
  };

  a();
}

Upvotes: 0

Views: 173

Answers (1)

Edgar Rokjān
Edgar Rokjān

Reputation: 17483

You might try to capture everything by value:

template<typename F, typename... Args>
void combine_and_call_lambda(F f, Args&&... args) {
    auto a = [=]() mutable {
        f(args...);
    };

    a();
}

Then use:

combine_and_call_lambda(print_address, a);
combine_and_call_lambda(print_address, std::ref(a));

DEMO

As we can see at lambda:

captures - a comma-separated list of zero or more captures, optionally beginning with a capture-default.

Capture list can be passed as follows (see below for the detailed description):

...

[=] captures all automatic variables used in the body of the lambda by copy and current object by reference if exists

So, in the code above everything is copied and stored inside the lambda object.

Upvotes: 1

Related Questions