やや醜いテンプレートコーディングを書き直そうとしています。
参考までに、オリジナルはこちら: https://codereview.stackexchange.com/questions/69545/recode-cc-trampoline-function-macros-using-templates
class Final : Base
{
void Foo(){...}
void Bar(){...}
static void init(){
// register_method populates a table of "extern C" function pointers.
register_method( "foo", & FooHandler );
register_method( "bar", & BarHandler );
}
:
// trampolines
static void FooHandler( void* pInstance ) {
Final* f = reinterpret_cast<Final*>(pInstance);
f->Foo();
}
static void BarHandler( void* pInstance ) {
Final* f = reinterpret_cast<Final*>(pInstance);
f->Bar();
}
}
私のコードは CPython (C ライブラリ) とインターフェイスします。Python ランタイムは "myInst.foo" を認識し、テーブルで "foo" を検索して呼び出します。
Final::FooHandler( pointer_to_myInst );
(静的メソッドを C 関数ポインターに型キャストできることに注意してください)
FooHandler は、Final の正しいインスタンスの Foo メソッドにトランポリンします。
実際には、ハンドルはそれほどきれいではなく、それぞれが同一のハンドラーを必要とするメソッドが多数あります (ただし、関数アドレスは異なります)。
ハンドラーメカニズムを次のような基本クラスに抽象化しようとしています:
class Final : Base<Final>
{
void Foo(){...}
void Bar(){...}
static void init(){
// register_method populates a table of "extern C" function pointers.
register_method( "foo", & Foo, Handler< &Foo> );
register_method( "bar", & Bar, Handler< &Bar> );
}
:
}
class Base<Final>
{
typedef void (Final::*FuncSig)(void);
typedef void (Final::*HandlerSig)(void*); // takes 1 pvoid param
void register_method( std::string name, FuncSig meth, HandlerSig handler ) {
...
}
// generic trampoline
template< Sig sig>
static void Handler( void* pInstance ) {
Final* f = reinterpret_cast<Final*>(pInstance);
f ->* sig();
}
}
現在、コンパイラ エラー ( http://ideone.com/vOtbcD ) でスタックしているため、この手法が有効かどうかさえわかりません。
これを行う方法はありますか、それとも本当にマクロが必要な場合の 1 つにすぎませんか?
参考までに、オリジナルはこちら: https://codereview.stackexchange.com/questions/69545/recode-cc-trampoline-function-macros-using-templates
ご覧のとおり、オリジナルはかなり醜いマクロを使用しています。