Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using std::find with user supplied predicate - homemade find() overload

Tags:

c++

I have a class which is essentially a std::vector<T> with some additional functionality. The class has find(const T& value ) method which will return index of first occurence of value or -1:

int my::find(const T& value) {
    auto iter = std::find(this->data.begin(), this->data.end(), value);
    if (iter == this->data.end())
        return -1;

    return std::distance(this->data.begin(), iter);
}

all good. I then wanted to create a find() overload which took in a arbitrary predicate instead of a value - I have tried:

int my::find(const std::function<bool(const T&)>& pred) {
    auto iter = std::find(this->data.begin(), this->data.end(), pred);
    ...
}

and also:

template <typename P>
int my::find(P&& pred) {
    auto iter = ...
}

But both cases fail to compile because "the compiler" tries to find pred in a vector of pred type values, instead of applying pred to the values, i.e. when when I have instantiated my<int> I get compiler errors like:

/usr/include/c++/5/bits/predefined_ops.h:194:17: error: no match for ‘operator==’ (operand types are ‘int’ and ‘const std::function<bool(const int&)>’)
  { return *__it == _M_value; }
like image 505
user422005 Avatar asked Apr 02 '19 05:04

user422005


2 Answers

The algorithm std::find will always treat its third argument as a value that is compared to elements in the given sequence by operator==. The predicate you pass in can't be compared to the T instances of the class, hence the compiler error.

You are looking for std::find_if (overloads #3-4), which takes a predicate as the third argument.

like image 102
lubgr Avatar answered Nov 05 '22 21:11

lubgr


When you use a predicate, use std::find_if.

int my::find(const std::function<bool(const T&)>& pred) {
    auto iter = std::find_if(this->data.begin(), this->data.end(), pred);
    ...
}

In keeping with function names in the standard library, I think you should change your function name also to find_if when you use a predicate.

int my::find_if(const std::function<bool(const T&)>& pred) {
    auto iter = std::find_if(this->data.begin(), this->data.end(), pred);
    ...
}
like image 25
R Sahu Avatar answered Nov 05 '22 19:11

R Sahu