I am trying to find a way to have a container of functors so that I can pass the value to functors and change it, however, I have problems so that functors are not limited in what types they can be and the number of arguments that they can take.
My actual use for this is that I have a number of functors that in any case modify a 3D vector based on input. Having the ability to store these functors in a container, I can manipulate the order in which they are called, and ultimately with another resulting vector, iterating over the container, passing a vector to each functor. I use these vectors to determine position, color, acceleration, etc. Particles. Therefore, in the end, I can create completely different particle effects by taking this modular approach, and in the end I can determine the functor order of the file at runtime. This is my ultimate goal :)
The only way I did this work was through inheritance and a set of void pointers that make the code extremely difficult to track, debug, and use.
Here is my code so far, which hopefully will demonstrate what I'm trying to do better than what I typed above. Keep in mind that I'm very out of my comfort zone, so this code can be horrible and make some of you gurus want to beat me with a stick.
#include <iostream>
Side note: I expect some people to tell me to use the same thing from boost libraries. Despite the fact that I appreciate that I know that there is this option, I still would like to know the best way to implement this without any external libraries, because for me it is something like learning.
Edit
Well, learning about stdarg and boost::any , I think I see a way to make this work beautiful and try it :)
Decision 2
Ok, I reworked the code with boost::any and cstdarg for what I consider to be the best solution. This does not use void pointers and does not limit the number of arguments that functors can have. The newer code also allows you to pass a value using void pointers, everything should have been a reference, which could cause problems: Sub(&result, 1, 1)
#include <iostream> #include <vector> #include <cstdarg> #include <boost\any.hpp> struct Functor { unsigned num_arguments; Functor() : num_arguments(0) {} virtual void operator()(boost::any, ...) = 0; }; template<typename R, typename A1> struct Double : public Functor { Double() { num_arguments = 1; } void operator()(boost::any r, ...) { R* out = boost::any_cast<R*>(r); va_list args; va_start(args, r); A1 first = va_arg(args, A1); va_end(args); *out = first * 2; } }; template<typename R, typename A1, typename A2> struct Sub : public Functor { Sub() { num_arguments = 2; } void operator()(boost::any r, ...) { R* out = boost::any_cast<R*>(r); va_list args; va_start(args, r); A1 first = va_arg(args, A1); A2 second = va_arg(args, A2); va_end(args); *out = first - second; } }; int main() { std::vector<Functor*> functors; functors.push_back(new Double<int, int>); functors.push_back(new Sub<int, int, int>); functors.push_back(new Sub<int, float, float>); int result = 0; for(int i = 0; i < functors.size(); ++i) { (*functors[i])(&result, 2, 2); std::cout << result << std::endl; } std::cin.get(); return 0; }
and now I finally have the right to raise: D