The so-called function objects and predicates in C++11

1. Function object

Answer: In "C++ Primer Plus", a function object is any object that can be used in combination with () in a functional manner. This includes function names, pointers to functions, and class objects that have overloaded the "operator()" operator. (After C++11, the overloaded "operator()" method is used to use function objects), for example:

#include <iostream>
#include <string>
#include <vector>

using namespace std;

class FuncObject{
public: 
    FuncObject(int n = 0) : num(n), count(1){}

    bool operator()(int) {
        return count++ == num;
    }

    int GetCount(){
        return count;
    }
private:
    int count;
    int num;
};

int main(){
    int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    vector<int> vec(a, a + 10);
    FuncObject test(3);  
    vector<int>::iterator itr = find_if(vec.begin(),vec.end(), test);  
    cout << "3rd:" << *itr << endl;  
    cout << "State:" << test.GetCount() << endl; 

}
 

2. Predicate

Answer: In "C++ Primer", a predicate is a callable expression, and its return result is a value that can be used as a judgment condition. (There is also a popular name that returns a bool type functor called a predicate)

The algorithm used by the standard library includes two predicates: unary predicate (accepts only one parameter) and binary predicate (accepts only two parameters).

For example, the following is a binary predicate: 

bool   isShort(const string &s1, const string &s2)

 {

           return s1<s2;

 }

Let's take a look at the prototype of sort:

template <class RandomAccessIterator>  

void sort ( RandomAccessIterator first, RandomAccessIterator last );  

 

template <class RandomAccessIterator, class Compare>  

void sort ( RandomAccessIterator first, RandomAccessIterator last, Compare comp );

It can be seen that the second version can specify the third parameter, here we use a binary predicate:

vector<string>  vecStr={"12432", "sadf", "hjjhh"};

sort(vecStr.begin(), vecStr.end(), isShort);

Of course, our predicate can also be written like this:

class isShorter

{

public:

          bool operator()(const string &s1, const string &s2)

         {

  1.           return s1<s2;

         }

};

The call is like this:

sort(vecStr.begin(), vecStr.end(), isShorter());

Note: When using a function object (a class object that overloads operator(), there is no difference between calling it a predicate or a function object), you must use a "()" to call the operator, and the function pointer does not need "() ", which means that there should be a conversion from a function pointer to a function object.

 

Summary: The third parameter of find_if we use is a function object, and the third parameter of sort is a version of the binary predicate. Some common points can be found:

(1) Predicate is a kind of function object, it is a branch of function object, and they have conversion relationship.

(2) Regardless of whether it is a function pointer or a class object, the parameters obtained by "()" are obtained directly from the algorithm traversal, so the parameter type needs to be consistent with the traversed element type. If there are other stricter comparison rules, you can use the class object that overloads operator(). For example, if you need to determine whether the traversed element is greater than a certain value passed in, you can use the constructor of the class object to save it to the member, and then Use this value in the overloaded operator() function later.

Many standard library algorithms in C++ use predicates. Of course, predicates have some limitations (such as only accepting unary and binary parameters). Many times we will use overloaded operator() class objects to operate.

Guess you like

Origin blog.csdn.net/qq_38915078/article/details/106648953