Last active
January 26, 2018 20:29
-
-
Save meshula/43a9ec7e0180ce70f3ee78961fbdce56 to your computer and use it in GitHub Desktop.
template trait to discover if a return value is void
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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