I want to pass a mutable lambda which captures a unique_ptr
to another function as shown in the code snippet below.
#include <functional>
#include <memory>
#include <iostream>
struct Adder {
Adder(int val1, std::unique_ptr<int> val2) : val1_(val1), val2_(std::move(val2)) {
}
int Add() {
return val1_ *val2_;
}
int val1_;
std::unique_ptr<int> val2_;
};
void CallAdder(std::function<int ()> func) {
std::cout << func() << "\n";
}
int main() {
auto ptr = std::make_unique<int>(40);
int byRef = 2;
auto lam = [&, p = std::move(ptr)]() mutable
{
return Adder(byRef, std::move(p)).Add();
};
CallAdder(std::move(lam));
}
Above code gives me a deleted copy constructor error for the lambda as follows.
$ clang -14 -o lam lambda.cc
In file included from lambda.cc:2:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c /10/functional:59:
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c /10/bits/std_function.h:161:10: error: call to implicitly-deleted copy constructor of '(lambda at lambda.cc:25:16)'
new _Functor(*__source._M_access<const _Functor*>());
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c /10/bits/std_function.h:196:8: note: in instantiation of member function 'std::_Function_base::_Base_manager<(lambda at lambda.cc:25:16)>::_M_clone' requested here
_M_clone(__dest, __source, _Local_storage());
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c /10/bits/std_function.h:283:13: note: in instantiation of member function 'std::_Function_base::_Base_manager<(lambda at lambda.cc:25:16)>::_M_manager' requested here
_Base::_M_manager(__dest, __source, __op);
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c /10/bits/std_function.h:611:33: note: in instantiation of member function 'std::_Function_handler<int (), (lambda at lambda.cc:25:16)>::_M_manager' requested here
_M_manager = &_My_handler::_M_manager;
^
lambda.cc:30:15: note: in instantiation of function template specialization 'std::function<int ()>::function<(lambda at lambda.cc:25:16), void, void>' requested here
CallAdder(std::move(lam));
^
lambda.cc:25:20: note: copy constructor of '' is implicitly deleted because field '' has a deleted copy constructor
auto lam = [&, p = std::move(ptr)]() mutable
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../include/c /10/bits/unique_ptr.h:468:7: note: 'unique_ptr' has been explicitly marked deleted here
unique_ptr(const unique_ptr&) = delete;
^
I also tried passing lambda as a reference as per cannot pass deleted lambda function with move? but I was getting a type error which complains about it not being able to typecheck the lambda against the std::function
in the CallAdder
signature. How would I fix this error?
CodePudding user response:
You can template CallAdder
on a function parameter.
#include <functional>
#include <iostream>
#include <memory>
struct Adder {
Adder(int val1, std::unique_ptr<int> val2)
: val1_(val1), val2_(std::move(val2)) {}
int Add() { return val1_ *val2_; }
int val1_;
std::unique_ptr<int> val2_;
};
template <typename F>
void CallAdder(F&& func) { std::cout << std::forward<F>(func)() << "\n"; }
int main() {
auto ptr = std::make_unique<int>(40);
int byRef = 2;
auto lam = [&byRef, p = std::move(ptr)]() mutable {
return Adder(byRef, std::move(p)).Add();
};
CallAdder(std::move(lam));
}
// Outputs: 42
Or just:
#include <functional>
#include <iostream>
#include <memory>
struct Adder {
Adder(int val1, std::unique_ptr<int> val2)
: val1_(val1), val2_(std::move(val2)) {}
int Add() { return val1_ *val2_; }
int val1_;
std::unique_ptr<int> val2_;
};
void CallAdder(std::function<int()> func) { std::cout << func() << "\n"; }
int main() {
auto ptr = std::make_unique<int>(40);
int byRef = 2;
auto lam = [&]() {
return Adder(byRef, std::move(ptr)).Add();
};
CallAdder(lam);
}