Home > database >  Why can't C deduce a template type argument from a function pointer prototype individually bu
Why can't C deduce a template type argument from a function pointer prototype individually bu

Time:06-09

This code compiles with both gcc and clang:

#define PACK //...

template <typename Result, typename PACK Args, typename Last>
auto g(Result (*f)(Args PACK, Last)) -> Result (*)(Args PACK)
{
    return reinterpret_cast<Result (*)(Args PACK)>(f);
}

double af(char c, int i);

auto ag{g(&af)};

However, if I change the first line to:

#define PACK ...

Neither compiler will accept it. The error says that template type argument detection failed. Why can an individual type be detected, but not as a (degenerate) pack?

(Some background: I'm working with an application that takes advantage of the fact that, using reinterpret cast, typical ABIs guarantee it's safe to assign a function address to a function pointer if the function's argument types are prefix of the argument types of the pointed to function type, and the return types match. I was trying to write a template that would statically check for this condition.)

CodePudding user response:

The correct syntax for the second case to work would be as shown below. Note how the order of Last and Args... is changed.

Method 1

//----------------------------------------------------vvvv--->OK: Last is deducible
template <typename Result, typename... Args, typename Last>
auto g(Result (*f)(Last, Args...)) -> Result (*)(Args...)
//-----------------------^^^^------------------------------>order changed here
{
    return reinterpret_cast<Result (*)(Args...)>(f);
}

int func(int, float, double, char, bool);

auto ptr = g(&func);

Demo


Method 2

//---------------------------------vvvv--------------------->Last comes before Args though this is not necessary here as it is deducible as shown in method 1 above
template <typename Result,typename Last, typename... Args>
auto g(Result (*f)(Last, Args...)) -> Result (*)(Args...)
//-----------------------^^^^------------------------------>order changed here
{
    return reinterpret_cast<Result (*)(Args...)>(f);
}

int func(int, float, double, char, bool);

auto ptr = g(&func);

Demo

CodePudding user response:

As 康桓瑋 noted in a comment on the question, parameter packs are only permitted at the end of a function's formal parameter list.

  • Related