In Java, when I need a callback function, I have to implement an anonymous class. Inside the anonymous class, I can access the outside variables if they're final
.
Now I'm doing the same thing in C++. I understand that C++ lambda works better but sometimes I need to pass in many functions where with anonymous classes, I only need to pass in one instance.
I tried the following example. It works with GCC 4.3.4.
class IA { public: virtual int f(int x) = 0; }; int main() { class : public IA { int f(int x) { return x + 1; } } a; doFancyWork(&a); return 0; }
Is it possible to capture the outside variables like this?
int main() { int y = 100; // mark y as final if possible class : public IA { int f(int x) { return x + y; } } a; return 0; }
UPDATE:
The second example won't compile. The errors are here,
prog.cpp: In member function ‘virtual int main()::<anonymous class>::f(int)’: prog.cpp:9: error: use of ‘auto’ variable from containing function prog.cpp:7: error: ‘int y’ declared here prog.cpp: In function ‘int main()’: prog.cpp:7: warning: unused variable ‘y’
UPDATE:
I just realized a few more problems in doing this:
I think I have to move away from anonymous classes.
An anonymous class cannot access local variables in its enclosing scope that are not declared as final or effectively final. Like a nested class, a declaration of a type (such as a variable) in an anonymous class shadows any other declarations in the enclosing scope that have the same name.
In Java, a class can contain another class known as nested class. It's possible to create a nested class without giving any name. A nested class that doesn't have any name is known as an anonymous class. Anonymous classes usually extend subclasses or implement interfaces.
You can't. The only way to be able to call multiple methods is to assign the anonymous class instance to some variable.
There is no way to automatically capture those variables, but you can use an alternative approach. This is if you want to capture by reference:
int main() { int y = 100; // mark y as final if possible class IB : public IA { public: IB(int& y) : _y(y) {} int f(int x) { return x + _y; } private: int& _y; } a (y); return 0; }
If you want to capture by value, just change int&
into int
.
Anyway, you may consider using a tuple of lambdas as a "multi-callback" object if that is what bothers you about individual lambdas. You would still have everything packed in one object and capturing would be done for free.
Just as an example:
auto callbacks = make_tuple( [] (int x) { cout << x << endl; }, [&] () { cout << y << endl; }, // y is captured by reference [=] (int x) { cout << x + y << endl; }, // y is captured by value // other lambdas here, if you want... );
You can capture the variable manually (which is similar to what a lambda capture does behind the scenes):
int main() { int y = 100; struct { int& y; int operator()(int x) { return x + y; } } anon = { y }; }
You can then use it like this:
#include <iostream> ... std::cout << anon(10) << std::endl;
Prints 110 as expected. Unfortunately you can't have the anonymous type inherit from another with this method as initializer-list constructable types can't inherit from another type. If inheritance is crucial then you should use the constructor method outlined by Andy Prowl.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With