Cのコールバック関数をC++のメンバ関数にバインディングする方法

たとえば libevent のような C 言語でかかれたイベント駆動型のライブラリを C++ から使っていると、C++メンバ関数をコールバックとしてセットできたらうれしいことが多いですよね。以下のようにすればできます。

たとえば、コールバック関数をセットする関数の型が、

void set_foo_callback(void (*)(void* cb_arg), void* cb_arg);

なら、以下のようにクラスとメンバ関数を引数にとるテンプレート関数を定義し、

template <typename T, void (T::*FUNC)()>
void to_foo_callback(void* cb_arg)
{
  T* obj = reinterpret_cast<T*>(cb_arg);
  (obj->*FUNC)();
}

以下のように受け渡せばいい。

class K {
public:
  K() {
    set_foo_callback(to_foo_callback<K, &K::on_foo>, this);
  }
protected:
  void on_foo() {
    ...
  }
};

メンバ関数を呼び出すラッパー関数をいちいち書かなくていいのでうれしい。

前世紀の GCC だと関数ポインタをテンプレート引数に渡せなかったと思うんですが、最近はできるんですね。