Typically I use the following pattern when accepting a lambda as an argument to a function (A template class passed-by-value):
template
If you pass by value you will copy the closure object (assuming you don't define the lambda inline, in which case it will be moved). This might be undesirable if the state is expensive to copy, and will fail to compile if the state is not copyable.
template
void higherOrderFunction(Function f);
std::unique_ptr p;
auto l = [p = std::move(p)] {}; // C++14 lambda with init capture
higherOrderFunction(l); // doesn't compile because l is non-copyable
// due to unique_ptr member
higherOrderFunction([p = std::move(p)] {}); // this still works, the closure object is moved
If you pass by const reference, then you cannot pass a mutable lambda that modifies its data members as the argument to higherOrderFunction() because a mutable lambda has a non-const operator(), and you cannot invoke that on a const object.
template
void higherOrderFunction(Function const& f);
int i = 0;
higherOrderFunction([=]() mutable { i = 0; }); // will not compile
The best option is to use a forwarding reference. Then higherOrderFunction can accept either lvalues or rvalues that the caller passes.
template
void higherOrderFunction(Function&& f) {
std::forward(f)();
}
This allows the simple cases as well as the ones mentioned above to compile. For a discussion of why std::forward should be used, see this answer.
Live demo