asio

msgpack-rpc-asioの関数登録と実行
msgpack-rpc-asioの関数登録と実行 msgpack-rpcのリクエストは、によると [type, msgid, method, params] という形式なのでmethod名をstd::stringとしてparamsをstd::tupleとして得られる。 これをサーバ側で如何に呼び出すかについて。 単純な実装だと以下のようにメソッド名をキーにして分岐することになる。 ```c++ int and(int, int); class dispatcher { void dispatch(int msgid, const std::string &method, const msgpack::object &params) { if(method==“add”){ // 引数展開 std::tuple t; params.convert(&t); // 関数実行 int result=add(std::get<0>(t), std::get<1>(t)); // 結果のパッキング // response [type, msgid, error, result] msgpack::sbuffer response; msgpack::packer<msgpack::sbuffer> pk(&response); pk.pack_array(4) pk.pack(1); pk.pack(msgid); pk.pack_nil(); pk.pack(result); // responseを送り返す } else{ throw “unknown func”; } } 引数展開、関数呼び出し、結果のパッキングと一連の操作を定型処理として括りだすと下記のように書ける。c++ // 2引数展開用 class dispatcher { // 実行 void dispatcher::dispatch(int msgid, const std::string &method, const msgpack::object &params) { if(method==“add”){ msgpack::sbuffer response=unpack_exec_pack(msgid, add, params);

可変長テンプレート引数
可変長テンプレート引数 引き続きmsgpack-rpc-asioを実装しているのだが、可変長テンプレート引数(valiadic template)を使うと関数登録のような場合にうまく書けることがわかった。 昨日は関数オブジェクトからstd::functionの型を得るのに下記のようにしていたのだけど、 ```c++ // ret template Ret helper0(Ret (F::*)(Rest…)); template Ret helper0(Ret (F::*)(Rest…) const); // 1 template A1 helper1(Ret (F::*)(A1, Rest…)); template A1 helper1(Ret (F::*)(A1, Rest…) const); // 2 template A2 helper2(Ret (F::*)(A1, A2, Rest…)); template A2 helper2(Ret (F::*)(A1, A2, Rest…) const); template 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); } 次のように書けた。c++ template void add_handler(F handler, R(C::*)(A1, A2)const) { // register function… std::function func(handler); }

lambdaの引数の型を得たい
lambdaの引数の型を得たい msgpack-rpcの関数登録の都合上、 lambda関数から引数の型を得たい。 下記のような書き方をしたい。 ```c++ template void register_func(const std::stiring &func_name, R(*handler)(A1, A2)) { // 関数登録 } int main() { // errorになる register_func(“add”, [](int%20a,%20int%20b)->int{ return a+b; }); return 0; } ``` 上記の書き方では普通の関数ポインタを受けることはできるのだが、 std::functionとlambdaは受けられない。 std::functionを受けるには下記のようにすることでできた。 c++ template<typename R, typename A1, typename A2> void register_func(const std::string &func_name, std::function<R(A1, A2) handler) { // } 残り、lambdaを受けられる記述方法を知りたいのだがどうしたらよいものか。 下記のような手はうまくいかなかった・・・ c++ template<typename F, typename R, typename A1, typename A2> void add_handler(F handler, const std::string &method) { std::function<R(A1, A2)> f(handler); //add_handler }