So, I took a bunch of your work that you do in a macro and pulled it out.
can_apply_taccepts template<class...>classboth a package of types and is true if the types can be applied to the template legally.
template<class...>struct voider { using type=void; };
template<class...Ts>using void_t=typename voider<Ts...>::type;
template<class...>struct types{ using type=types; };
namespace details {
template<template<class...>class Z, class types, class=void>
struct can_apply : std::false_type {};
template<template<class...>class Z, class...Ts>
struct can_apply<Z, types<Ts...>, void_t< Z<Ts...> > >:
std::true_type
{};
}
template<template<class...>class Z, class...Ts>
using can_apply_t = details::can_apply<Z, types<Ts...>>;
Then we get replacements for your macros. I separate method names from object names and do this in a few steps. These steps can be performed outside the class for each method:
#define CALL_METHOD_RESULT(Name, Method) \
template<class Sig, class=void> \
struct Name {}; \
template<class C, class...Ts> \
struct Name< C(Ts...), void_t< \
decltype( std::declval<C>().Method(std::declval<Ts>()...) ) \
>> { \
using type = decltype( std::declval<C>().Method(std::declval<Ts>()...) ); \
}; \
template<class Sig> \
using Name ## _t = typename Name< Sig >::type
The above example defines Name_twhich is a feature class that accepts Object(Args...)and tells you the return type Object.Method(Args...)in a friendly SFINAE context.
can_call_Method, , can_apply_t:
#define CAN_CALL_METHOD( Method ) \
CALL_METHOD_RESULT( call_ ## Method, Method ); \
template<class Sig> \
using can_call_ ## Method = can_apply_t< call_ ## Method ## _t, Sig >
, FORWARD, Name, target.Method(Args...) Target target, , =delete , , .
/// Forward to function Name, if is exists.
template <class... Args> \
auto Name(Args&&... args) \
-> call_
{ \
return target.Method(std::forward<Args>(args)...); \
} \
template <class...Args> \
std::enable_if_t<!can_call_
Name ( Args&&...) = delete
DEFINE. :
#define DEFINE(Name) \
CAN_CALL_METHOD(Name); \
FORWARD(Name, Name, Base, base)
=delete - , , , .
, =delete, - ( !)
, ,
Base* operator->(){ return &base; }
Base const* operator->()const{ return &base; }
Base wrapper->foo(whatever). Base.