Refugnic Eternium
Refugnic Eternium

Reputation: 4291

Conflicting types for variadic parameter

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.

Upvotes: 1

Views: 76

Answers (1)

max66
max66

Reputation: 66230

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.

Upvotes: 2

Related Questions