In C++11, how do you declare a function that takes a lambda expression as an argument? I can find plenty of resources online for declaring lambdas or taking them as template parameters, but what I’d really like to do is be able to make use of lambdas as easy-to-declare callback handlers, similar to what’s made possible by closures in JavaScript and code blocks in Objective-C.
Essentially, the classic C++ construct I want to replace with a lambda is something like:
class MyCallback {
public:
virtual ~MyCallback() {}
virtual void operator(int arg) = 0;
};
void registerCallback(const std::shared_ptr<MyCallback> &);
void foo(void) {
int a, b, c;
class LocalCallback: public MyCallback {
int a, b, c;
public:
LocalCallback(int a, int b, int c): a(a), b(b), c(c) {}
void operator(int arg) { std::cout << (a+b+c)*arg << std::endl; }
};
registerCallback(std::shared_ptr<MyCallback>(new LocalCallback(a,b,c)));
}
which would be simplified into:
void registerCallback(/* WHAT GOES HERE? */);
void foo(void) {
int a, b, c;
registerCallback([=](int arg){std::cout << (a+b+c)*arg << std::endl; })
}
So, what goes where I have written /* WHAT GOES HERE? */?
EDIT: This is for the purpose of storing a callback to be called back later, rather than for it being immediately consumed and called.
Usually
const std::function<void(int)> &orstd::function<void(int)>.I’m not sure what the verdict is on whether
std::functionshould be passed by const reference or by value. Probably by value is fine, especially since you’re going to copy it anyway to store.In case it isn’t clear in the middle of all that syntax,
void(int)is a function type, andstd::function<T>means approximately, “a functor with the same signature as functions of type T”.Lambdas themselves have anonymous types. There is no way to name the type of your lambda expression, and the types of different lambda expressions with the same signature are different:
Hence the need for
std::function, which basically is a type-erasing wrapper to gather together different functors with the same signature into a common type. It’s the bridge between static polymorphism with templates, and the dynamic polymorphism you need if you want to register a callback, store it for later, and then call it without having “remembered” the original type.