Last active
August 11, 2017 06:11
-
-
Save vector-of-bool/f73782e61723b45167b84a711f5e1d2b to your computer and use it in GitHub Desktop.
Dynamix arbitrary-arity macro
This file contains 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
// Base template | |
// Der: CRTP derived class | |
// ThisType: Type of dynamix object. This carries CV-qualifier information about the message. | |
// Sig: Signature for the message | |
template <typename Der, typename ThisType, typename Sig> struct message_helper; | |
// Impl template. Here we take a signature type as our third argument as a specialization | |
template <typename Derived, typename ThisType, typename Ret, typename... Args> | |
struct message_helper<Derived, ThisType, Ret(Args...)> : public ::dynamix::internal::message_t { | |
using feature_instance_type = ::dynamix::internal::feature_instance<Derived>; | |
using return_type = Ret; | |
using caller_func = Ret (*)(void*, Args...); | |
return_type operator()(ThisType& _d_obj, Args&&... args) { | |
const ::dynamix::feature& _d_self = feature_instance_type::the_feature_fast(); | |
DYNAMIX_ASSERT(static_cast<const ::dynamix::internal::message_t&>(_d_self).mechanism | |
== ::dynamix::internal::message_t::unicast); | |
const ::dynamix::internal::object_type_info::call_table_entry& _d_call_entry | |
= _d_obj._type_info->_call_table[_d_self.id]; | |
const ::dynamix::internal::message_for_mixin* _d_msg_data = _d_call_entry.message_data; | |
DYNAMIX_MSG_THROW_UNLESS(_d_msg_data, ::dynamix::bad_message_call); | |
char* _d_mixin_data = _DYNAMIX_GET_MIXIN_DATA(_d_obj, _d_msg_data->_mixin_id); | |
const char* message_name = Derived::message_name(); | |
auto _d_func = reinterpret_cast<caller_func>(_d_msg_data->caller); | |
return _d_func(_d_mixin_data, std::forward<Args>(args)...); | |
} | |
template <typename Mixin, return_type (Mixin::*Method)(Args...)> | |
static return_type caller_fn(void* _d_ptr, Args... args) { | |
auto _d_m = reinterpret_cast<Mixin*>(_d_ptr); | |
return (_d_m->*Method)(std::forward<Args>(args)...); | |
} | |
template <typename Mixin> dynamix::internal::func_ptr get_caller_for() { | |
using MixinType = typename std::conditional<std::is_const<ThisType>::value, const Mixin, Mixin>::type; | |
static caller_func caller = caller_fn<MixinType, Derived::method_on<Mixin>()>; | |
return reinterpret_cast<dynamix::internal::func_ptr>(caller); | |
} | |
message_helper() | |
: message_t(Derived::message_name(), unicast, false) {} | |
}; | |
// This macro instead of DYNAMIX_MESSAGE_N. The varargs parameter is to capture complex return types that may be | |
// template specializations, since macros choke on those. | |
#define DYNAMIX_SUPERMESSAGE(name, ...) \ | |
namespace { struct _DYNAMIX_MESSAGE_STRUCT_NAME(name) \ | |
: public message_helper<_DYNAMIX_MESSAGE_STRUCT_NAME(name), ::dynamix::object, __VA_ARGS__> { \ | |
static constexpr const char* message_name() { return #name; } \ | |
template <typename Mixin> static constexpr decltype(&Mixin::name) method_on() { return &Mixin::name; } \ | |
} name; } | |
// Usage: First arg is message name, second is a signature expression. | |
DYNAMIX_SUPERMESSAGE(speak, void()); | |
DYNAMIX_SUPERMESSAGE(join, std::string(std::string, std::string)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment