I would like to support calls like this
class BaseClass {
public:
virtual void print2(float arg1, float arg2) = 0;
};
int main() {
invoke(subclass, &BaseClass::print2, 1, 2);
}
where
subclass
is automatically upcasted to BaseClass
int
to float
I managed to solve the part with the base class. But the argument part gives me a headache. My approach is to extract all the needed type information from the handed function pointer. The other arguments are casted implicitly then (if possible).
What i have so far is this:
template<class Func> struct FunctionPointer2 {};
template<class Class, typename Arg1, typename Arg2> struct FunctionPointer2<void (Class::*)(Arg1, Arg2)> {
typedef Class Class;
typedef Arg1 Argument1;
typedef Arg2 Argument2;
};
template <typename Func>
void invoke2(typename FunctionPointer2<Func>::Class* obj, Func func, typename FunctionPointer2<Func>::Argument1 arg1, typename FunctionPointer2<Func>::Argument2 arg2) {
(obj->*func)(arg1, arg2);
}
It works but for each count of parameters another function, function pointer struct, ... is needed.
So here's the question: Is following even possible? How can i make it possible?
template<class Func> struct FunctionPointer {};
template<class Class, typename ... Args> struct FunctionPointer<void (Class::*)(Args ...)> {
typedef Class Class;
typedef Args Arguments; // pass type parameter pack here
};
template <typename Func>
void invoke(typename FunctionPointer<Func>::Class* obj, Func func, typename FunctionPointer<Func>::Arguments ... params) {
(obj->*func)(params ...);
}
Thanks for you help :)
Both the manual upcast and extracting the parameter types should be unnecessary.
You can just do this:
template <typename T, typename M, typename ...P>
void invoke(T &&object, M member, P &&... params)
{
(std::forward<T>(object).*member)(std::forward<P>(params)...);
}