Instantiating a Template and Selecting a Function at Run Time
I'm new to C ++ and I'm trying to achieve something a little tricky for which I can't seem to find a suitable solution.
Let's say I have 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 one of these two functions and instantiate with some types of templates obtained from user input like 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 functionality and more template parameters), etc. And also I don't see a way to assign one of the functions foo
or bar
to the function pointer, since the template parameters are not known before execution.
So, if someone can provide me with a good, clean solution to this problem, I would be very happy! Greetings.
Edit Let me clarify a few things.
I am accessing binaries where data can be stored as floats
or doubles
. Obviously, the program doesn't know this type, so the user must specify it somehow.
Then some math must be done on the data loaded from the file. And some of these calculations are possible, represented by the functions foo
and bar
.
So I would like the user to be able to specify the data type in the file at runtime and then select a function that will be applied to the loaded data at runtime. switch(c)
was just an illustration of how I thought the user could choose such things.
source to share
You cannot accept pointers to functional templates, because they are not functions, but must have been created earlier. 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 are many and you want cleaner code, you can put all the functions that use the same signature on the same card. (That is, you need one card per signature.) Then, distinguish which card to use in the 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 only want one card and are willing to sacrifice some savety types, you can use parameter types. It might not be so much a waste in your situation as you've already read this data from the byte stream.
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 called as:
double d;
int i;
char c = 'b';
(*(Map[c]))( reinterpret_cast<char*>(&i), reinterpret_cast<char*>(&d) );
source to share