运行时的模板实例化和功能选择

Template instantiation and function selection at runtime

本文关键字:功能 选择 实例化 运行时      更新时间:2023-10-16

我对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)只是我认为用户可以选择这些东西的一个例子。

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

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

如果您只想要一个映射,并且愿意牺牲一些类型savety,则可以对参数类型进行强制转换。在您的情况下,这可能不会有太大的损失,因为您已经从字节流中读取了数据。

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) );