Se si passa per valore, si copierà l'oggetto di chiusura (presumendo che non si definisca il lambda in linea, nel qual caso verrà spostato). Ciò potrebbe essere indesiderato se lo stato è costoso da copiare e non riuscirà a compilare se lo stato non è copiabile.
template <class Function>
void higherOrderFunction(Function f);
std::unique_ptr<int> 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
Se si passa da const
riferimento, allora non può passare un lambda mutable
che modifica suoi membri di dati come argomento higherOrderFunction()
perché un lambda mutable
ha un non const
operator()
, e non si può invocare che su un const
oggetto.
template <class Function>
void higherOrderFunction(Function const& f);
int i = 0;
higherOrderFunction([=]() mutable { i = 0; }); // will not compile
L'opzione migliore è utilizzare un riferimento di inoltro. Quindi, higherOrderFunction
può accettare sia lvalue che rvalue passati al chiamante.
template <class Function>
void higherOrderFunction(Function&& f) {
std::forward<Function>(f)();
}
Ciò consente la compilazione dei casi semplici e di quelli menzionati sopra. Per una discussione sul motivo per cui è necessario utilizzare std::forward
, vedere this answer.
Live demo
Credo che questo non copia, ma spostare. Dovrebbe essere abbastanza veloce con una implementazione decente. Lambdas è progettato per essere passato per valore come questo - tutti gli algoritmi standard prendono i loro funtori di valore. –