zack
zack

Reputation: 23

Variadic template function arguments not accepted

The following code won't build, any feedback on the cause would be appreciated.

void bar(std::string str, int& a, int& b)
{
}

template<typename T, typename ... Args>
void foo(std::function<void(T, Args...)> fcn, Args ... args)
{
    // Some code that calls fcn
}

void run()
{
    int a = 3;
    int b = 5;
    foo<std::string, int&, int&>(bar, a, b);
}

It is a modified implementation of the first solution proposed in this SO answer.

The IDE gives the following error on the line calling foo:

C++ template<class T, class... Args> void foo(std::function<void (T, Args...)> fcn, Args ...args)

no instance of function template "foo" matches the argument list
argument types are:
(void (std::string str, int &a, int &b), int, int)

Tested separately, it seems like passing a fcn argument with template arguments are fine. The issue seems to be with passing a function argument where the function can accept variadic template arguments.

Upvotes: 1

Views: 109

Answers (3)

zack
zack

Reputation: 23

Thanks all. Going off of the answer by serkan the following seems to work.

#include <iostream>
#include <functional> 

void bar(std::string str, int& a, int& b)
{
}

template<typename T, typename ... Args>
void foo(std::function<void(T, Args...)> fcn, Args ... args)
{
    // Some code that calls fcn
}

int main() {
    std::function<void(std::string, std::reference_wrapper<int>, std::reference_wrapper<int>)> func_1 = bar;
    int a = 3;
    int b = 5;
    foo(func_1, std::ref(a), std::ref(b));
    foo((std::function<void(std::string, std::reference_wrapper<int>, std::reference_wrapper<int>)>)bar, std::ref(a), std::ref(b));
    return 0;
}

I'll run more tests, there might still be some changes needed.

Upvotes: 1

serkan
serkan

Reputation: 146

  • & when I removed it, there was no error
#include <iostream>
#include <functional> 

void bar(std::string str, int a, int b)
{
}

template<typename T, typename ... Args>
void foo(std::function<void(T, Args...)> fcn, Args ... args)
{
    // Some code that calls fcn
}


int main() {
    std::function<void(std::string, int, int)> func_1 = bar;
    int a = 3;
    int b = 5;
    foo(func_1, a, b);
    return 0;
}
  • If it is necessary to use Call by Reference, I tried it by giving a direct address and it worked in this case too.
#include <iostream>
#include <functional> 

void bar(std::string str, int* a, int* b)
{
}

template<typename T, typename ... Args>
void foo(std::function<void(T, Args...)> fcn, Args ... args)
{
    // Some code that calls fcn
}


int main() {
    std::function<void(std::string, int*, int*)> func_1 = bar;
    int a = 3;
    int b = 5;
    foo(func_1, &a, &b);
    return 0;
}

Upvotes: 1

Jarod42
Jarod42

Reputation: 218323

Function (pointer) is not a std::function, so doesn't work for deduction.

You might make Ts... non deducible in that context

template<typename T, typename ... Args>
void foo(std::function<void(T, std::type_identity_t<Args>...)> fcn, Args ... args)
{
    // Some code that calls fcn
}

Demo

or drop std::function completely

template<typename T, typename F, typename ... Args>
requires (std::is_invocable<F, T, Args...>::value)
void foo(F fcn, Args&& ... args)
{
    // Some code that calls fcn
}

Demo

Upvotes: 3

Related Questions