Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing function into function with std::function and template argument

I am trying to pass a pointer to the predicate function into the Foo and Bar functions. The Bar function works correctly, but the Foo function raises a compile-time error:

error: no matching function for call to Foo<int>(bool (&)(int))

Why does the compiler raise an error? Is there any difference between Foo's and Bar's template arguments types after Args' unpacking?

#include <functional>

bool predicate(int a) {
    return (a > 5);
}

// sizeof...(Args) == 1 and I suppose it is int
template<typename... Args>
void Foo(std::function<bool(Args...)> predicate) {
    // clang: note: candidate template ignored:
    //        could not match 'function<bool (int, type-parameter-0-0...)>' 
    //        against 'bool (*)(int)'
}

template<typename Args>
void Bar(std::function<bool(Args)> predicate) {

}

int main(int argc, char const *argv[]) {
    // gcc: error: no matching function for call to
    //      'Foo<int>(bool (&)(int))'
    Foo<int>(predicate);
    Bar<int>(predicate);
    
    return 0;
}

See Compiler Explorer for a live example.

I also tried to change the Foo function a little and it works somehow:

template<typename... Args>
void Foo(bool(*predicate)(Args...)) {
  std::function<bool(Args...)> func(predicate);
}

I want to have std::function type argument in the Foo function, but I don't know how to do it

like image 272
Hakkerwell Hakkerwell Avatar asked Aug 28 '20 10:08

Hakkerwell Hakkerwell


People also ask

How do you pass a function as a parameter in CPP?

Function Call When calling a function with a function parameter, the value passed must be a pointer to a function. Use the function's name (without parentheses) for this: func(print); would call func , passing the print function to it.

Can function be passed as argument?

We cannot pass the function as an argument to another function. But we can pass the reference of a function as a parameter by using a function pointer. This process is known as call by reference as the function parameter is passed as a pointer that holds the address of arguments.

How to pass arguments when calling a function template?

So when calling a function template, there is no need to explictly pass the arguments, on the contrary, it can do harm! Consider the example I gave right at the start: We have reference parameters, so case two described above. This means that the type of the template argument will be the same as the type of the argument without references.

Can a function be passed as a parameter in a template?

Function pointers can be passed as template parameters, and this is part of standard C++ . However in the template they are declared and used as functions rather than pointer-to-function. At template instantiation one passes the address of the function rather than just the name.

What is a function passed as an argument?

Because functions are objects we can pass them as arguments to other functions. Functions that can accept other functions as arguments are also called higher-order functions. In the example below, a function greet is created which takes a function as an argument. greeting = func ("Hi, I am created by a function passed as an argument.")

How to pass a function to another function in C++?

A function can also be passed to another function by passing its address to that function. Below is the C++ program to illustrate the same: In C++ 11, there is a std::function<> template class that allows to pass functions as objects. An object of std::function<> can be created as follows.


Video Answer


1 Answers

The error is because the exact type of std::function is not same as predicate. To get around this, you can explicitly call the constructor of std::function:

int main() {
    Foo<int>( std::function<bool(int){predicate} );
    //OR
    Foo<int>( {predicate} );
    return 0;
}
like image 79
Waqar Avatar answered Sep 30 '22 09:09

Waqar