Skip to content

Instantly share code, notes, and snippets.

@meshula
Last active January 26, 2018 20:29
Show Gist options
  • Save meshula/43a9ec7e0180ce70f3ee78961fbdce56 to your computer and use it in GitHub Desktop.
Save meshula/43a9ec7e0180ce70f3ee78961fbdce56 to your computer and use it in GitHub Desktop.
template trait to discover if a return value is void
#include <iostream>
#include <functional>
void f() {}
void g(int) {}
void h(int*,char&) {}
void i(float,bool) {}
void j(const char *const) {}
void k(void()) {}
int l() { return {}; }
float m(int) { return {}; }
// msgpack-rpc is commonly supported standard
// https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md
// and can be used to communicate between languages. For example, a javascript,
// C++, and Python implementation can all receive and send via the same msgpack data.
//
enum class RequestKind : uint8_t { Call = 0, Notification = 2 };
int NextRpcCallIndex()
{
static std::atomic<int> idx = 0;
return idx++;
}
// A notification has the form [RequestKind::Notification, function_name, param]
//
template <typename... Args>
inline auto MsgPackRpcNotify(std::string_view const &func, Args... args_in)
{
std::string func_name(func.begin(), func.end());
auto args = std::make_tuple(args_in...);
auto rpc = std::make_tuple(RequestKind::Notification, func_name, args);
nlohmann::json j(rpc);
return nlohmann::json::to_msgpack(j);
}
template <typename... Args>
inline auto MsgPackRpcCall(std::string_view const &func, Args... args_in)
{
std::string func_name(func.begin(), func.end());
auto args = std::make_tuple(args_in...);
auto rpc = std::make_tuple(RequestKind::Call, NextRpcCallIndex, func_name, args);
nlohmann::json j(rpc);
return nlohmann::json::to_msgpack(j);
}
typedef std::variant<bool, int64_t, uint64_t, double, std::string> BaseArgType;
typedef std::variant<BaseArgType, std::vector<BaseArgType>> ArgType;
struct RpcCall
{
std::string name;
std::vector<ArgType> args;
};
inline RpcCall RpcNotify(const std::vector<uint8_t>& msgpack)
{
using nlohmann::json;
auto j = json::from_msgpack(msgpack);
RequestKind kind = j[0]; /// @TODO Sanity check against RequestKind::Notification
auto args = j[2];
size_t arg_count = args.size();
RpcCall ret;
ret.name = j[1];
for (size_t i = 0; i < arg_count; ++i)
{
switch (args[i].type())
{
case json::value_t::object:
case json::value_t::array:
break; // @TODO
case json::value_t::string: { std::string v = args[i]; ret.args.push_back(v); } break;
case json::value_t::boolean: { bool v = args[i]; ret.args.push_back(v); } break;
case json::value_t::number_integer: { int64_t v = args[i]; ret.args.push_back(v); } break;
case json::value_t::number_unsigned: { uint64_t v = args[i]; ret.args.push_back(v); } break;
case json::value_t::number_float: { double v = args[i]; ret.args.push_back(v); } break;
}
}
}
void bind(std::string_view const& name, std::function<void()> func) { std::cout << "void()\n"; }
template <typename R> void bind(std::string_view const& name, std::function<R()> func) { std::cout << "R()\n"; }
template <typename ... Args> void bind(std::string_view const& name, std::function<void(Args...)> func) { std::cout << "void(args)\n"; }
template <typename R, typename ... Args> void bind(std::string_view const& name, std::function<R(Args...)> func) { std::cout << "R(args)\n"; }
template<typename T> struct memfun_type { using type = void; };
template<typename Ret, typename Class, typename... Args>
struct memfun_type<Ret(Class::*)(Args...) const> { using type = std::function<Ret(Args...)>; };
template<typename F>
void bind(std::string_view const& name, F const& func)
{
typename memfun_type<decltype(&F::operator())>::type bound_func = func;
bind(name, bound_func);
}
int main ()
{
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment