Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is wrong with this program calling a function pointer with a parameter pack?

According to my understanding, the following program should obviously print:

1.0 hello world 42

However, it fails to compile. Why?

#include <iostream>
#include <string>
using namespace std;

template<class... InitialArgTypes>
void CallWithExtraParameter(void (*funcPtr)(InitialArgTypes..., int), InitialArgTypes... initialArgs)
{
    (*funcPtr)(initialArgs..., 42);
}

void Callee(double a, string b, int c)
{
    cout << a << " " << b << " " << c << endl;
}

int main()
{
    CallWithExtraParameter<double, string>(Callee, 1.0, string("hello world"));
}

Compiler output:

prog.cpp: In function 'int main()':
prog.cpp:18:75: error: no matching function for call to 'CallWithExtraParameter(void (&)(double, std::string, int), double, std::string)'
  CallWithExtraParameter<double, string>(Callee, 1.0, string("hello world"));
                                                                           ^
prog.cpp:6:6: note: candidate: template<class ... InitialArgTypes> void CallWithExtraParameter(void (*)(InitialArgTypes ..., int), InitialArgTypes ...)
 void CallWithExtraParameter(void (*funcPtr)(InitialArgTypes..., int), InitialArgTypes... initialArgs)
      ^
prog.cpp:6:6: note:   template argument deduction/substitution failed:
prog.cpp:18:75: note:   mismatched types 'int' and 'double'
  CallWithExtraParameter<double, string>(Callee, 1.0, string("hello world"));
                                                                           ^
like image 912
user253751 Avatar asked Mar 22 '16 23:03

user253751


People also ask

What is the problem of function pointer?

There are two main issues with function pointers: Function pointer casts can cause function pointer calls to fail. This may be related to a function pointer cast problem as implicit declarations may have a different type than how you call them.

How do you pass a pointer to a function as a parameter?

Pass-by-pointer means to pass a pointer argument in the calling function to the corresponding formal parameter of the called function. The called function can modify the value of the variable to which the pointer argument points. When you use pass-by-pointer, a copy of the pointer is passed to the function.

What is parameter pack in C++?

Parameter packs (C++11) A parameter pack can be a type of parameter for templates. Unlike previous parameters, which can only bind to a single argument, a parameter pack can pack multiple parameters into a single parameter by placing an ellipsis to the left of the parameter name.

Can a function pointer be used to call a function?

A function pointer is a pointer variable, but it holds the address of a function, not the address of a data item. The only things you can do with a function pointer are read its value, assign its value, or call the function that it points toward.


1 Answers

First, "hello world" wouldn't deduce to std::string, it would deduce to const char*, which doesn't match Callee, so let's fix your call to be pass "hello world"s instead.

Second, there appears to be some issue with having an argument of type:

void (*funcPtr)(InitialArgTypes..., int)

That is apparently in some limbo between non-deduced context and deducible - in that it's not a non-deduced context (otherwise InitialArgTypes... would've been deduced from the other parameters) and it's not deducible (because it still failed). So let's go one step further and definitively make it a non-deduced context:

template <class T> struct identity { using type = T; };
template <class T> using identity_t = typename identity<T>::type;

template <class... InitialArgTypes>
void CallWithExtraParameter(void (*funcPtr)(identity_t<InitialArgTypes>..., int),
        InitialArgTypes... initialArgs)
{
    (*funcPtr)(initialArgs..., 42);
}

Now, InitialArgTypes... will be deduced from the arguments passed in at the end. Which is what we want, so this works:

CallWithExtraParameter(Callee, 1.0, "hello world"s);
like image 53
Barry Avatar answered Nov 15 '22 14:11

Barry