2014-10-29 52 views
3

我对C++很陌生,我试图实现一些有点棘手的事情,对此我似乎找不到可以满足的解决方案。在运行时模板实例化和功能选择

比方说,我有这两个功能:

template <class T1, class T2> void foo(T1 param1, T2 param2){...}; 
template <class T1, class T2> void bar(T1 param1, T2 param2){...}; 

并在运行时,我希望选择在这两个函数,并从用户输入获得了一些模板类型实例化,说一个char c 。所以,我可以这样做:

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; 

但是这种解决方案是丑陋的,不可扩展的(我希望能够增加更多的功能,更多的模板参数)等。还有,我看不到方式将foobar的功能之一分配给函数指针,因为模板参数在运行时前是未知的。

所以如果有人能够为我提供一个很好的,干净的解决方案来解决这个问题,我会非常高兴!干杯。

编辑让我澄清一些事情。

我正在访问二进制文件,其中的数据可以存储为floatsdoubles。显然,程序无法知道这种类型,所以用户必须以某种方式指定它。

然后必须对从文件加载的数据进行一些数学计算。并且有几种可能的计算,上面由foobar功能表示。

所以我希望用户能够在运行时指定数据类型的文件中,然后选择功能在运行时也应用于加载的数据switch(c)只是我认为用户可以选择这些东西的一个例证。

+0

你可以给它是什么你想达到某种背景? – 2014-10-29 10:16:30

+0

调用应遵循的模式究竟是什么(相对于'c')? – Columbo 2014-10-29 10:18:50

+0

模板在运行时不起作用。你可以创建一个'unordered_map '并根据该键调用它。 – 2014-10-29 10:20:31

回答

1

你不能把指针指向函数模板,因为它们不是函数,但需要在之前实例化。你可以得到这样一个指针:

typedef void (*Tfkt_int_int)(int, int); 
Tfkt_int_int Ptr = &foo<int,int>; 

正如你所看到的,你需要指定可能的类型组合。

如果有很多,而且您希望更干净的代码,则可以将共享相同签名的所有功能放入一张地图中。 (也就是说,每个签名需要一个映射。)然后区分在switch语句中使用哪个映射。

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 ... 

如果你只想要一张地图,并且愿意牺牲一些类型的保存,你可以在参数类型周围进行转换。因为您已经从字节流中读取了这些数据,所以在这种情况下可能没有那么大的损失。

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 ... 

然后调用为:

double d; 
int i; 
char c = 'b'; 
(*(Map[c]))(reinterpret_cast<char*>(&i), reinterpret_cast<char*>(&d)); 
+0

您的回答确实帮助我解决了我的问题,尽管我没有完全按照这种方式实施。谢谢! – dranitou 2014-11-03 15:30:29