在C ++中构建一个模板函数的调用表

时间:2009-08-10 10:20:16

标签: c++ templates

我有一个模板函数,其中template参数是一个整数。在我的程序中,我需要使用在运行时确定的小整数来调用该函数。我可以手工制作一张桌子,例如:

void (*f_table[3])(void) = {f<0>,f<1>,f<2>};

并使用

调用我的函数
f_table[i]();

现在,问题是是否有一些自动方式将此表构建为任意顺序。我能想到的最好的就是使用宏

#define TEMPLATE_TAB(n) {n<0>,n<1>,n<2>}

至少可以避免重复使用函数名称(我的实际函数的名称比“f”长)。但是,允许的最大订单仍然是硬编码的。理想情况下,表大小应仅由代码中的单个参数确定。是否可以使用模板解决此问题?

4 个答案:

答案 0 :(得分:6)

可以通过'递归'调度来完成:模板函数可以检查它的运行时参数是否与它的模板参数匹配,并使用模板参数返回目标函数。

#include <iostream>
template< int i > int tdispatch() { return i; }

// metaprogramming to generate runtime dispatcher of 
// required size:
template< int i > int r_dispatch( int ai ) {
    if( ai == i ) {
      return tdispatch< i > ();
    } else {
      return r_dispatch< i-1 >( ai );
    }
}
template<> int r_dispatch<-1>( int ){ return -1; }

// non-metaprogramming wrapper
int dispatch( int i ) { return r_dispatch<100>(i); }

int main() {
   std::cout << dispatch( 10 );
   return 0;
}

答案 1 :(得分:4)

您可以创建一个使用递归初始化查找表的模板;然后你可以通过查找表中的函数来调用第i个函数:

#include <iostream>

// recursive template function to fill up dispatch table
template< int i > bool dispatch_init( fpointer* pTable ) {
  pTable[ i ] = &function<i>;
  return dispatch_init< i - 1 >( pTable );
}

// edge case of recursion
template<> bool dispatch_init<-1>() { return true; }

// call the recursive function
const bool initialized = dispatch_init< _countof(ftable) >( ftable );


// the template function to be dispatched
template< int i > void function() { std::cout << i; }


// dispatch functionality: a table and a function
typedef void (*fpointer)();    
fpointer ftable[100];

void dispatch( int i ){ return (ftable[i])(); }


int main() {
  dispatch( 10 );
}

答案 2 :(得分:3)

[证明错误:我认为这不能完全用模板完成。]

看一下boost预处理器库。

答案 3 :(得分:0)

关于xtofl我决定使用下面显示的以下宏/模板解决方案。我需要宏,因为我想为许多函数构建这些调度表,而我无法看到如何使用单个模板函数来实现这一点。

#include <iostream>

using namespace std;

#define MAX_ORDER 8

#define DISPATCH_TABLE(table,fpointer,function,N)               \
template< int i > fpointer *function##dispatch_init(fpointer function_table[]) \
{ \
  function_table[i] = function<i>; \
  return function##dispatch_init< i - 1 >(function_table); \
} \
template<> fpointer *function##dispatch_init<-1>(fpointer function_table[]) \
{  \
  return function_table; \
} \
const fpointer *table = function##dispatch_init<N>(new fpointer[N])

typedef void (*fpointer)(void);

template<int N>
void printN(void)
{
  cout << N << endl;
}

DISPATCH_TABLE(printN_table, fpointer, printN, MAX_ORDER);

int main(void)
{
  for (int i = 0; i < MAX_ORDER; i++)
    printN_table[i]();
  return 0;
}