template<typename F, typename R, typename C, typename ...AS, std::size_t... IS>
procedurecall _make_procedurecall(const F &f
, R(C::*)(AS...)const // template引数R, C, ASを受け付けるためのダミー
, std::index_sequence<IS...> // template引数ISを受け付けるためのダミー
)
{
// request -> response ではなくparams -> result
return [f](const bytes& src)->bytes
{
// unpack args
auto parser = msgpackpp::parser(src);
std::tuple<AS...> args;
parser >> args;
// call
auto r = f(std::get<IS>(args)...); // 可変長テンプレート引数を展開できる。ISと...が離れていることに注意
// pack result
msgpackpp::packer packer;
packer << r;
return packer.get_payload();
};
}
template<typename F, typename R, typename C, typename ...AS>
procedurecall _make_procedurecall(F f
, R(C::*)(AS...)const // template引数R, C, ASを受け付けるためのダミー
)
{
return _make_procedurecall(f
, &decltype(f)::operator() // lambdaの返り値と引数の型を次のテンプレートに渡す
, std::index_sequence_for<AS...>{} // std::get呼び出しのためにindex_sequenceを作る。
);
}
//
// あらゆる型のlambdaを受け付けるようにした
//
template<typename F>
procedurecall make_procedurecall(F f)
{
return _make_procedurecall(f
, &decltype(f)::operator() // lambdaの返り値と引数の型を次のテンプレートに渡す
);
}
msgpack_call
template<typename F, typename R, typename C, typename ...AS>
decltype(auto) _msgpack_call(F f
, R(C::*)(AS...)const // template引数R, C, ASを受けるためのダミー
, AS... args)
{
auto proc = msgpackpp::rpc::make_procedurecall(f);
// call
msgpackpp::packer packer;
packer << std::make_tuple(args...); // 可変長テンプレート引数を展開できる
auto result = proc(packer.get_payload());
// unpack result
R value;
msgpackpp::parser(result) >> value;
return value;
}
template<typename F, typename ...AS>
decltype(auto) msgpack_call(F f, AS... args) // 返り値の型はreturnから型推論
{
return _msgpack_call(f
, &decltype(f)::operator() // lambdaの返り値と引数の型をテンプレート引数に渡す
, args...
);
}