Currently I have a template like so:
template<typename func, typename ret, typename... args> class Entry{
public:
PVOID Address;
ret operator()(args...){
return ((func) this->Address)(args...);
}
};
And I'm using it like this:
Entry<int(*)(int), int, int> func;
// ^func ^ret ^args
func.Address = (PVOID) 0xDEADC0DE;
func(123); // calls 0xDEADC0DE with '123' as argument
However, I was wondering if it's possible to only have this:
Entry<int(*)(int)> func;
// ^only specifying the function's prototype once instead of breaking it down
func(123);
If I have it like that, I wouldn't be able to overload operator()
as I cannot split up the function pointer type into arguments and return type (so that I can write return_type operator()(args...)
).
Is there any way to achieve this?
I'm using VS2013 Nov 2013 CTP
You can do it with a specialization like this:
// Entry has one template argument
template<typename func> class Entry;
// and if it's a function type, this specialization is used as best fit.
template<typename ret, typename... args> class Entry<ret(args...)>{
public:
PVOID Address;
ret operator()(args... a){
return ((ret(*)(args...)) this->Address)(a...);
}
};
int main() {
Entry<int(int)> foo;
foo.Address = (PVOID) 0xdeadc0de;
func(123);
}
To use it with a function pointer type like in your example (although I like the function type syntax better), write
// here ------v
template<typename ret, typename... args> class Entry<ret(*)(args...)>{
Addendum: One more thing came to me when I was out getting dinner: There is a (slight) problem with the operator()
that may or may not concern you: You don't run into forwarding problems with parameters that are passed by value or by lvalue reference because they're just passed on as they were passed in (because the argument list is exactly the same for the function pointer and the operator()
), but if you plan to use rvalue-reference parameters, that does not work for them implicitly. For this reason,
Entry<int(int&&)> foo;
foo(123);
does not compile. If you plan to use this with functions that take rvalue references, operator()
can be fixed like so:
ret operator()(args... a){
// explicit forwarding ----v
return ((ret(*)(args...)) this->Address)(std::forward<args>(a)...);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With