Code:
#include <iostream>
template <class FunctorType>
void caller(const FunctorType& func) {
func();
}
int main() {
double data[5] = {5., 0., 0., 0., 0.};
auto peek_data = [data]() { std::cout << data[0] << std::endl; };
auto change_data = [data]() mutable { data[0] = 4.2; };
caller(peek_data); // This works
caller(change_data); // This doesn't
return 0;
}
If I compile this with clang -std=c 11 mutable_lambda.cpp
, I got
error: no matching function for call to object of type 'const (lambda at mutable_lambda.cpp:8:22)'
.
Question: Why passing the second lambda expression with mutable copy capture failed to compile? Thanks in advance!
CodePudding user response:
A mutable
lambda has a non-const
operator()
. You are trying to call this non-const
operator()
through a const
reference. That doesn't work for the same reason that calling any non-const
non-static member function doesn't work through a const
reference.
If you want to allow caller
to modify the passed function object (through a non-const
operator()
call) if it is passed as non-const
argument, then take it by forwarding reference instead of const
reference:
template <class FunctorType>
void caller(FunctorType&& func) {
func(); // maybe std::forward<FunctorType>(func)();
}
Also note that change_data
does not change the data
in main
. It changes a copy of it stored inside the lambda. If you want it to change the data
in main
, you need to capture data
by-reference and then the lambda itself also doesn't need to be mutable
anymore:
auto change_data = [&data]() { data[0] = 4.2; };