Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why can't C++ deduce a template type argument from a function pointer prototype individually but not as a pack?

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?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

(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.)

>Solution :

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

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading