21 minutes ago, Shaarigan said:
I already have the code down that deals with signature extraction in very much the same way. I ended up having a little bit of trouble getting it to work with constant member functions, though. Anyway, here's the solution I came up with yesterday. I haven't tested it thoroughly, but it does seem to work.
A short rundown of what the code does:
- first, remove const from member functions. I don't know why but, return type deduction does not work when const is present and reports the decltype to be an incomplete type. Perhaps someone can fill me in here?
- next, use really simple manual return type deduction.
- as far as I can tell, there is no way to deduce the current class at compile time without previously noting it down somewhere. This is fine in my case as I'm writing a kind of a plugin system, which requires the user to implement a default interface with something like IMPLEMENT_EXTENSION(...classnamehere...) in the main body of the class anyway. Nevertheless, here the solution is to simply typedef the class somewhere near the top of the class declaration.
Here's a short test snippet that works in VS2013. It automatically forwards any call to the base class, but it's trivial to make it do anything.
// return type deduction from a member function
template<class T>
struct return_type;
template<class C, class R, class... Args>
struct return_type<R(C::*)(Args...)> { using type = R; };
// const removal from a member function
template <typename T>
struct function_remove_const;
template <typename R, typename C, typename... Args>
struct function_remove_const<R(C::*)(Args...)> { using type = R(C::*)(Args...); };
template <typename R, typename C, typename... Args>
struct function_remove_const<R(C::*)(Args...)const> { using type = R(C::*)(Args...); };
// just to hide the local clutter
#define FORWARD_EVENT(_fn, ...) \
using _fn##_FUNTYPE = function_remove_const<decltype(&CLASS_TYPE::_fn)>::type; \
using _fn##_RETTYPE = return_type<_fn##_FUNTYPE>::type; \
return _fn##_RETTYPE(this->TESTBASE::_fn(__VA_ARGS__));
class TESTBASE {
public:
virtual
void voidfn() const {
}
virtual
bool boolfn(int32 arg) const {
return arg == 1;
}
};
class TESTCLASS
: public TESTBASE {
public:
// need this in FORWARD_EVENT()
using CLASS_TYPE = TESTCLASS;
void voidfn() const override {
// returning void is not an issue
FORWARD_EVENT(voidfn);
}
bool boolfn(int32 arg) const override {
FORWARD_EVENT(boolfn, arg);
}
};
I found nothing of this sort on the web, so hopefully someone finds this useful.