2009-08-10 9 views
3

私は、テンプレートパラメータが整数であるテンプレート関数を持っています。私のプログラムでは、実行時に決定される小さな整数で関数を呼び出す必要があります。手で、私は例えば、テーブルを作成することができます任意の順番に、このテーブルを構築するためのいくつかの自動的な方法があるかどうC++のテンプレート関数への呼び出しテーブルの構築

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

f_table[i](); 

と私の関数を呼び出す、疑問があります。私が思い付くことができる最高はleastsのことを回避するに何度も関数名を繰り返しマクロ

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

(私の本当の機能は、「F」よりも長い名前を持っている)を使用することです。ただし、許容される最大注文はまだハードコードされています。理想的には、テーブルのサイズはコード内の単一のパラメータによってのみ決定されるべきです。テンプレートを使用してこの問題を解決することは可能でしょうか?

+0

ハード最適化のためにこれを行うとします。小さな整数で作業する場合、解はvoid f(int i)をコード化することができます。テンプレートの代わりに void f();あなたのニーズにお応えできますか? – neuro

答えて

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); 
} 
+0

ありがとう!これは私のニーズに最適です。私はそれを "関数"上にマクロフィングします。なぜなら、私は集計する必要がある関数をたくさん持っているからです。 – uekstrom

+0

+1良い解決策 –

+0

+1あなたのソリューションが好き...新しいファンが生まれましたか? ;-) – neuro

3

[間違った実績:。私は、テンプレートを純粋に行うことができるとは思わない]

ブーストプリプロセッサライブラリを見てみましょう。

+0

ありがとう! BOOST_PP_ENUM_PARAMSはまさに私が必要としているようです。 – uekstrom

+0

できます。 – xtofl

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; 
} 
+0

これはとても素晴らしいです!適切な機能を見つけるための線形コストなしでそれを行う方法は何か知っていますか? – uekstrom

+0

@uekstrom:それを最適化するには、たとえばバイナリ検索はその場で実行されますが、私は今すぐ私の袖からそれを振ることはできません。 – xtofl

+0

@dribeas:私の編集で示されているように、メタプログラミング部分は通常のプログラミング部分と厳密に分離することができます。 – xtofl

0

私は、以下に示す次のマクロ/テンプレート溶液で行くことにしましたxtofl後。私はこれらのディスパッチテーブルを多くの機能のために構築したいのでマクロが必要でしたが、1つのテンプレート機能でどのようにするかわかりません。

#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; 
} 
関連する問題