Создание таблицы вызовов для шаблонных функций в C ++ - PullRequest
4 голосов
/ 10 августа 2009

У меня есть функция шаблона, где параметр шаблона является целым числом. В моей программе мне нужно вызывать функцию с маленьким целым числом, которое определяется во время выполнения. От руки я могу сделать таблицу, например:

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 ]

6 голосов
/ 10 августа 2009

Это можно сделать с помощью «рекурсивной» диспетчеризации: функция шаблона может проверить, совпадает ли ее аргумент времени выполнения с аргументом шаблона, и вернуть целевую функцию с аргументом шаблона.

#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;
}
4 голосов
/ 10 августа 2009

Вы можете создать шаблон, который инициализирует таблицу поиска, используя рекурсию; затем вы можете вызвать 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 );
}
3 голосов
/ 10 августа 2009

[Доказано неправильно: я не думаю, что это можно сделать исключительно с помощью шаблонов.]

Взгляните на библиотеку препроцессора boost.

0 голосов
/ 10 августа 2009

После 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...