I'm doing a linear genetic programming project, where programs are bred and evolved by means of natural evolution mechanisms. Their "DNA" is basically a container (I've used arrays and vectors successfully) which contain function pointers to a set of functions available. Now, for simple problems, such as mathematical problems, I could use one type-defined function pointer which could point to functions that all return a double and all take as parameters two doubles.
Unfortunately this is not very practical. I need to be able to have a container which can have different sorts of function pointers, say a function pointer to a function which takes no arguments, or a function which takes one argument, or a function which returns something, etc (you get the idea)...
Is there any way to do this using any kind of container ? Could I do that using a container which contains polymorphic classes, which in their turn have various kinds of function pointers? I hope someone can direct me towards a solution because redesigning everything I've done so far is going to be painful.
A typical idea for virtual machines is to have a separate stack that is used for argument and return value passing.
Your functions can still all be of type void fn(void), but you do argument passing and returning manually.
You can do something like this:
class ArgumentStack {
public:
void push(double ret_val) { m_stack.push_back(ret_val); }
double pop() {
double arg = m_stack.back();
m_stack.pop_back();
return arg;
}
private:
std::vector<double> m_stack;
};
ArgumentStack stack;
...so a function could look like this:
// Multiplies two doubles on top of the stack.
void multiply() {
// Read arguments.
double a1 = stack.pop();
double a2 = stack.pop();
// Multiply!
double result = a1 * a2;
// Return the result by putting it on the stack.
stack.push(result);
}
This can be used in this way:
// Calculate 4 * 2.
stack.push(4);
stack.push(2);
multiply();
printf("2 * 4 = %f\n", stack.pop());
Do you follow?
You cannot put a polymorphic function in a class, since functions that take (or return) different things cannot be used in the same way (with the same interface), which is something required by polymorphism.
The idea of having a class providing a virtual function for any possible function type you need would work, but (without knowing anything about your problem!) its usage feels weird to me: what functions would a derived class override? Aren't your functions uncorrelated?
If your functions are uncorrelated (if there's no reason why you should group them as members of the same class, or if they would be static function since they don't need member variables) you should opt for something else... If you pick your functions at random you could just have several different containers, one for function type, and just pick a container at random, and then a function within it.
Could you make some examples of what your functions do?
What you mentioned itself can be implemented probably by a container of
std::function
or discriminated union like Boost::variant
.
For example:
#include <functional>
#include <cstdio>
#include <iostream>
struct F {
virtual ~F() {}
};
template< class Return, class Param = void >
struct Func : F {
std::function< Return( Param ) > f;
Func( std::function< Return( Param ) > const& f ) : f( f ) {}
Return operator()( Param const& x ) const { return f( x ); }
};
template< class Return >
struct Func< Return, void > : F {
std::function< Return() > f;
Func( std::function< Return() > const& f ) : f( f ) {}
Return operator()() const { return f(); }
};
static void f_void_void( void ) { puts("void"); }
static int f_int_int( int x ) { return x; }
int main()
{
F *f[] = {
new Func< void >( f_void_void ),
new Func< int, int >( f_int_int ),
};
for ( F **a = f, **e = f + 2; a != e; ++ a ) {
if ( auto p = dynamic_cast< Func< void >* >( *a ) ) {
(*p)();
}
else if ( auto p = dynamic_cast< Func< int, int >* >( *a ) ) {
std::cout<< (*p)( 1 ) <<'\n';
}
}
}
But I'm not sure this is really what you want...
What do you think about Alf P. Steinbach's comment?
来源:https://stackoverflow.com/questions/4699018/how-to-create-a-container-that-holds-different-types-of-function-pointers-in-c