Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I create anonymous classes in C++ and capture the outside variables like in Java?

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 cannot write a constructor because the class doesn't have a name
  • initializer list doesn't allow inheritance.
  • any change to make it compile makes the code unreadable.

I think I have to move away from anonymous classes.

like image 640
woodings Avatar asked Jan 16 '13 21:01

woodings


People also ask

Can anonymous class have variables?

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.

Can we create anonymous class in Java?

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.

Can anonymous class have multiple methods?

You can't. The only way to be able to call multiple methods is to assign the anonymous class instance to some variable.


2 Answers

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...     ); 
like image 76
Andy Prowl Avatar answered Sep 19 '22 22:09

Andy Prowl


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.

like image 30
Jake Woods Avatar answered Sep 22 '22 22:09

Jake Woods