「テンプレート関数ポインタ」を達成するために他にどのように?
-
05-09-2019 - |
質問
これは手動で行うの手間をかけずに、テンプレート関数ポインタのセットを確立することは可能ですか?ここで何が一体私が話しているものを説明するための例です。
のは、私は動的に切り替えるできるようにしたいと思い、私は2つの実装(WRITE0とWRITE1)を持っているの頻繁に呼び出される関数「書き込み」を持っているとしましょう。これらの書き込み関数は、引数の型にテンプレート化されています。これを行う1つの方法は、単に内部的にif文を使用して、テンプレートのフロントエンド機能の書き込みを()することです。
これは私のニーズに十分に高速であることが判明したが、今私はそれを用いた関数ポインタ(楽しみのためだけに)行うことができるかどうか疑問に残っていました。このアプローチの問題点は、関数ポインタを設定することは面倒であるということです。基本的に、書き込みの理想を達成するための他の方法があります()は、条件(ダイレクト静的派遣)なし?
(他の「ルール」:私は、ライト()メソッドを持っているメッセージクラスを変更することはできません、と私はMSGS用のアダプタでのMSGを置き換えるために使用するサイトコードを変更することはできません)
他のヒント
また、ドンClugstonの FastDelegates のヘッダを使用することができます。一切実行時のオーバーヘッドを生成しないと、本当にデリゲートをオブジェクト指向。それらを使用するための構文は完璧ではないですが、それは生の関数ポインタをいじるよりも少し簡単です。
なぜあなたは、関数ポインタの配列を使用していない?
#include <iostream>
using namespace std;
template<typename T> void write0(T msg) { cout << "write0: " << msg.name() << endl; }
template<typename T> void write1(T msg) { cout << "write1: " << msg.name() << endl; }
template<typename T> struct WriteSelector
{
static void(* const s_functions[])(T msg);
};
template<typename T> void(* const WriteSelector<T>::s_functions[])(T msg)=
{
&write0<T>,
&write1<T>
};
unsigned write_index=0;
template<typename T> void write(T msg)
{
WriteSelector<T>::s_functions[write_index](msg);
}
struct MsgA { const char *name() { return "MsgA"; } };
struct MsgB { const char *name() { return "MsgB"; } };
struct MsgC { const char *name() { return "MsgC"; } };
struct MsgD { const char *name() { return "MsgD"; } };
void Test()
{
write(MsgA());
write(MsgB());
write(MsgC());
write(MsgD());
}
int main()
{
Test();
write_index=1;
Test();
return 0;
}
書き込みの変動の2つの車軸があります。
概念的意味しますwrite
機能のN×Mの実装を必要とします。書き込み実装が追加された、またはメッセージタイプが追加された場合はもちろん、これはRESPにつながります。 MまたはN余分な機能を追加します。
は、両方の車軸のためには、静的または動的な多型を使用してそれらを実装するかどうかを選択できます。静的な多型は、テンプレートを使用したり、関数のオーバーライドを使用して行うことができます。
これは、各クラスのMライト機能を持つN個の要素クラス階層を作成することによって行うことができます。しかし、それはすぐにメンテナンスの悪夢になるだろう。メッセージの内容は、実行時多型でない限り。しかし、問題は、メッセージのための静的な多型についてです。
ランタイム多型があるため、あまりにも精巧で除外される(そして、あなたがオーバーライドの冗長性を減少させることになる、仮想テンプレート機能を持つことができない)ので、我々は、コンパイルにランタイム情報を変換し、少し型派遣ルーチンを実装する必要があります-time情報ます。
具体的には:作家に使用して(Tmain
と呼ばれる例では)主なアクションをテンプレート化し、「本当の」main
から右のテンプレート引数でそれを呼び出す
これは、「グローバル」の選択変数の使用を省略し、まだオブジェクト指向かつ簡潔です。
// twodimensionalpolymorph.cpp
//
#include <iostream>
using namespace std;
class Write0 {
public:
template< typename tMsg >
void operator()( /*const*/ tMsg& msg ) { cout << "write0: " << msg.name() << endl; };
};
class Write1 {
public:
template< typename tMsg >
void operator()( /*const*/ tMsg& msg ) { cout << "write1: "<< msg.name() << endl; };
};
struct MsgA { const char *name() { return "MsgA"; } };
struct MsgB { const char *name() { return "MsgB"; } };
struct MsgC { const char *name() { return "MsgC"; } };
struct MsgD { const char *name() { return "MsgD"; } };
// the Tmain does the real action
//
template< typename Writer >
int Tmain( Writer& write, int argc, char** args ) {
write( MsgA() );
write( MsgB() );
write( MsgB() );
write( MsgD() );
return 0;
}
// the main merely chooses the writer to use
//
int main( int argc, char** args ) {
if( argc==1 )
return Tmain( Write0(), argc, args);
else
return Tmain( Write1(), argc, args);
}