I am trying to write a general invocation function.
It has the following syntax:
template<int Index, typename ReturnType, typename... Parameter>
ReturnType invokeGlobalFunction(Parameter... parameters)
{
return invocator->invoke<ReturnType>(Index, parameters...);
}
Next, I try to derive two different function points from it, like this:
registerFunction(::someGlobalFunction, &invokeGlobalFunction<0, void>);
registerFunction(::someOtherFunction, &invokeGlobalFunction<1, int>);
Where someGlobalFunction
has the prototype void someGlobalFunction()
and someOtherFunction
has the prototype int someOtherFunction(int, const char *)
.
On the first call, it works like a charm, however the second call throws the error: candidate template ignored: deduced conflicting types for parameter 'Parameter' (<int, const char *> vs. <>)
.
This implies, that the compiler (g++ 7.4.0 on an Ubuntu system btw.) does not overload the invokeGlobalFunction
with the different parameter sets like I expected him to.
A note: When I explicitly set the parameter types on the call
registerFunction(::someOtherFunction, &invokeGlobalFunction<1, int, int, const char *>);
the compiler happily takes it, but I'd like to avoid that, if possible.
As a bonus, it would be great, if I could somehow create a unique function each time the index changes, because that would allow me to have functions with identical parameters but differing return types (which is illegal as far as I know).
Thank you.
but I'd like to avoid that, if possible.
Not with template functions, as far I know.
The problem is that a template parameter isn't a single object but a set of object where a function can accept only an object from the set.
When you write
&invokeGlobalFunction<1, int>
you choose a precise function with Index = 1
, ReturnType = int
and (this is the point) an empty Parameter...
list.
Suggestion: if you can, transform invokeGlobalFunction()
in a template struct
with a template method.
Something as
template <int Index, typename ReturnType>
struct invokeStruct
{
template <typename ... Parameters>
ReturnType operator() (Parameters ... parameters)
{
// ...
}
};
This way you have a set of struct with, in every struct, a set of operator()
in it; passing a invokeStruct<1, int>{}
as argument, you pass a single object but, inside it, you have available a set of method.