手動で行う手間をかけずに、テンプレート化された関数ポインターのセットを確立することは可能ですか? これは、私が話していることを説明するための例です。
頻繁に呼び出される関数「write」があり、その 2 つの実装 (write0 と write1) を動的に切り替えられるようにしたいとします。これらの書き込み関数は、引数の型でテンプレート化されています。これを行う 1 つの方法は、内部で if ステートメントを使用するテンプレート化されたフロントエンド関数 write() を使用することです。
これは私のニーズに対して十分に高速であることが判明しましたが、関数ポインターを使用して同じことができるかどうか疑問に思っていました (楽しみのためだけに)。このアプローチの問題点は、関数ポインタの設定が面倒なことです。write() の理想を本質的に達成するが、条件付き (直接静的ディスパッチ) を使用しない他の方法はありますか?
(その他の「ルール」: Msg クラスを write() メソッドを持つように変更することはできず、use サイト コードを変更して Msgs を Msgs のアダプターに置き換えることはできません。)
FWIW、私はこの記事が基本的に私がここで言っているのと同じことを言っているのを見つけました。
#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; }
// This isn't so bad, since it's just a conditional (which the processor will
// likely predict correctly most of the time).
bool use_write0;
template<typename T> void write(T msg) { if (use_write0) write0(msg); else write1(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"; } };
// This doesn't work: templates may not be virtual.
#if 0
struct Writer { template<typename T> virtual void write(T msg) = 0; };
struct Writer0 { template<typename T> virtual void write(T msg) { cout << "write0: " << msg.name() << endl; } };
struct Writer1 { template<typename T> virtual void write(T msg) { cout << "write0: " << msg.name() << endl; } };
#endif
int main(int argc, char **argv) {
use_write0 = argc == 1;
// I can do this:
write(MsgA());
// Can I achieve the following without the verbosity (manual setup, named
// template instantiations, etc.)?
void (*pwriteA)(MsgA) = use_write0 ? (void(*)(MsgA)) write0<MsgA> : (void(*)(MsgA)) write1<MsgA>;
void (*pwriteB)(MsgB) = use_write0 ? (void(*)(MsgB)) write0<MsgB> : (void(*)(MsgB)) write1<MsgB>;
void (*pwriteC)(MsgC) = use_write0 ? (void(*)(MsgC)) write0<MsgC> : (void(*)(MsgC)) write1<MsgC>;
void (*pwriteD)(MsgD) = use_write0 ? (void(*)(MsgD)) write0<MsgD> : (void(*)(MsgD)) write1<MsgD>;
pwriteA(MsgA());
pwriteB(MsgB());
pwriteC(MsgC());
pwriteD(MsgD());
return 0;
}