问题
I'm quite new to c++ and I'm trying to achieve something a bit tricky, for which I can't seem to find a satisfiable solution.
Let's say I have these two functions:
template <class T1, class T2> void foo(T1 param1, T2 param2){...};
template <class T1, class T2> void bar(T1 param1, T2 param2){...};
And at runtime, I want to select on of these two functions, and instantiate it with some template types obtained from a user input, say a char c. So I could do something like:
double d;
float f;
switch(c) {
case 'a':
foo(d, f); break;
case 'b':
foo(f, d); break;
case 'c':
bar(d, f); break;
case 'd':
bar(f, d); break;
But this solution is ugly, not scalable (I want to be able to add more function, and more template parameters), etc. And also, I can't see a way to assign one of the functions foo or bar to a function pointer, as the template parameters are unknown before runtime.
So if someone can provide me with a nice, clean solution to this problem, I'd be very happy! Cheers.
Edit Let me clarify a few things.
I'm accessing binary files, in which the data can be stored as floats or doubles. Obviously, the program has no way of knowing this type, so the user has to specify it in some way.
Then some mathematical computation has to be done on the data loaded from the file. And there are several of these computation possible, represented above by the functions foo and bar.
So I would like the user to be able to specify the type of the data in the file at runtime, and then select a function to apply to the loaded data at runtime too. The switch(c) was just an illustration of how I thought the user could select such things.
回答1:
You can't take pointers to function templates, because they are not functions, but need to be instantiated before. You can get a pointer like this:
typedef void (*Tfkt_int_int)( int, int );
Tfkt_int_int Ptr = &foo<int,int>;
As you can see, you need to specify possible combinations of types.
If there is many, and you want cleaner code, you can put all functions that share the same signature into one map. (That is, you need one map per signature.) Then distinguish which map to use in a switch statement.
std::map<char, Tfkt_int_int> Map_int_int;
Map_int_int['a'] = &foo<int,int>;
Map_int_int['b'] = &bar<int,int>;
// more ...
typdef void (*Tfkt_int_double)( int, double );
std::map<char, Tfkt_int_double> Map_int_double;
Map_int_double['a'] = &foo<int,double>;
Map_int_double['b'] = &bar<int,double>;
// more ...
If you want only one map, and are willing to sacrifice some of type savety, you can cast around the parameter types. It might be not as much of a loss in you situation, since you read that data from a byte stream already.
template <class T1, class T2> void foo(char* param1, char* param2)
{
T1 P1 = *(reinterpret_cast<T1*>( param1 ));
T2 P2 = *(reinterpret_cast<T2*>( param2 ));
// ...
};
typedef void (*Tfkt)( char*, char* );
std::map<char, Tfkt> Map;
Map['a'] = &foo<int,int>;
Map['b'] = &foo<int,double>;
// more ...
Then call as:
double d;
int i;
char c = 'b';
(*(Map[c]))( reinterpret_cast<char*>(&i), reinterpret_cast<char*>(&d) );
来源:https://stackoverflow.com/questions/26627618/template-instantiation-and-function-selection-at-runtime