rodion rodion - 1 month ago 7
C++ Question

Passing a lambda into a function template

I'm learning C++, and I'm trying to implement a binary search function that finds the first element for which a predicate holds. The function's first argument is a vector and the second argument is a function that evaluates the predicate for a given element. The binary search function looks like this:

template <typename T> int binsearch(const std::vector<T> &ts, bool (*predicate)(T)) {
...
}


This works as expected if used like this:

bool gte(int x) {
return x >= 5;
}

int main(int argc, char** argv) {
std::vector<int> a = {1, 2, 3};
binsearch(a, gte);
return 0;
}


But if I use a lambda function as a predicate, I get a compiler error:

search-for-a-range.cpp:20:5: error: no matching function for call to 'binsearch'
binsearch(a, [](int e) -> bool { return e >= 5; });
^~~~~~~~~
search-for-a-range.cpp:6:27: note: candidate template ignored: could not match 'bool (*)(T)' against '(lambda at
search-for-a-range.cpp:20:18)'
template <typename T> int binsearch(const std::vector<T> &ts,
^
1 error generated.


The above error is generated by

binsearch(a, [](int e) -> bool { return e >= 5; });


What's wrong? Why is the compiler not convinced that my lambda has the right type?

Answer

Your function binsearch takes a function pointer as argument. A lambda and a function pointer are different types: a lambda may be considered as an instance of a struct implementing operator().

You should make your function binsearch more generic, something like:

template <typename T, typename F>
T binsearch(const std::vector<T> &ts, F f) {

    // usage

    for(auto& t : ts)
    {
        if(f(t)) return t;
    }

    // default value if f always returned false

    return T{};
}

Take inspiration from standard algorithms library.

Comments