Building a call table for template functions in C ++

I have a template function where the template parameter is an integer. In my program, I need to call a function with a small integer that is defined at runtime. By hand I can make a table, for example:

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

and call my function with

f_table[i]();

Now the question is whether there is some automatic way to build this table in random order. The best I can come up with is to use a macro

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

which at least avoids repeating the function name over and over (my real functions have longer names than "f"). However, the maximum allowable order is still hardcoded. Ideally, the size of the table should be determined by only one parameter in the code. Is it possible to solve this problem using templates?

+3
source share
4 answers

You can create a template that initializes the lookup table using recursion; then you can call the i-th function by looking at the function in the table:

#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 );
}
+4
source

: , runtime , .

#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;
}
+6

[Checked incorrectly: I do not think that this can be done only with templates.]

Take a look at the boost preprocessor library.

+3
source

Following xtofl, I decided to go with the following macro / template shown below. I need a macro because I want to build these distribution tables for many functions, and I don’t see how to do it with a single template function.

#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;
}
0
source

Source: https://habr.com/ru/post/1714768/


All Articles