三次元日誌(hugo)

引き続きmsgpack-rpc-asioを実装しているのだが、可変長テンプレート引数(valiadic template)を使うと関数登録のような場合にうまく書けることがわかった。

昨日は関数オブジェクトからstd::functionの型を得るのに下記のようにしていたのだけど、

// ret template Ret helper0(Ret (F::*)(Rest...));
template<typename Ret, typename F, typename... Rest> 
Ret helper0(Ret (F::*)(Rest...) const);

// 1 template A1 helper1(Ret (F::*)(A1, Rest...));
template<typename Ret, typename F, typename A1, typename...Rest>
A1 helper1(Ret (F::*)(A1, Rest...) const);

// 2 template A2 helper2(Ret (F::*)(A1, A2, Rest...));
template<typename Ret, typename F, typename A1, typename A2, typename... Rest>
A2 helper2(Ret (F::*)(A1, A2, Rest...) const);

template <typename F>
void add_handler(F handler, const std::string &method) 
{
    typedef decltype(handler) functor; 
    typedef decltype(helper0(&functor::operator())) R; 
    typedef decltype(helper1(&functor::operator())) A1; 
    typedef decltype(helper2(&functor::operator())) A2;

    // register function...
    std::function<R(A1, A2)> func(handler);
}

次のように書けた。

template<typename F, typename R, typename C, typename A1, typename A2>
void add_handler(F handler, R(C::*)(A1, A2)const) 
{ 
    // register function... 
    std::function<R(A1, A2)> func(handler); 
}

template<typename F> 
void add_handler(F handler, const std::string &method) 
{
    add_handler(handler, &decltype(handler)::operator()); 
}

昨日参照させてもらった http://d.hatena.ne.jp/osyo-manga/20121205/1354674180 のコードがやっとわかるようになってきた。

上記コードはさらに可変長テンプレート引数で

template<typename F, typename R, typename C, typename... A>
void add_handler(F handler, R(C::*)(A...)const) 
{ 
    // register function... 
    std::function<R(A...)> func(handler); 
}

と書けるのですごく便利になる。 msgpack-rpcの関数コールバック登録や、luaのような組み込み言語への関数公開の実装が楽になりそうだ。上記サイトでも取り上げられているが&decltype(functor)::operator()を関数テンプレートの型推論に投げることで関数オブジェクトから型情報を取れるらしい。

気をよくして各所を可変長テンプレート引数を使うように書き換えたのだが、致命的な問題を発見。 vc2010はなんと可変長テンプレート引数を未実装だった。 c++0xの機能がわりと入っているのでできると思っていたのに。 msgpack-rpc-asioは、明瞭にvc2010をターゲットにしているので可変長テンプレート引数の使用を断念した。 2引数関数の操作までしか実装していない時点で気付いて良かった。 ライブラリの不足はboost使えば済むが言語機能が無いのは困るな・・・。 vc2012に乗り換えたくなった。