STL function object
-
- 4.1 Function objects
- 4.2 Predicates
-
- 4.2.1 Unary predicates
- 4.2.2 Binary predicates
- 4.3 Built-in function objects
-
- 4.3.1 Arithmetic functors
- 4.3.2 Relational functors
- 4.3.3 Logical functors
4.1 Function objects
Objects of classes that overload the function call operator are called function objects. When a function object uses the overloaded ()
, it acts like a function call, so it is called a functor. Essentially, a function object (functor) is a class, not a function.
Use of function objects:
- Function objects can be called like ordinary functions, but they can also have parameters and return values.
- Function objects go beyond the concept of ordinary functions, and function objects can have their own state.
- Function objects can be passed as arguments
Example:
#include<iostream> using namespace std; #include<string> // 1. Function objects can be called like ordinary functions, but they can also have parameters and return values. class MyAdd {<!-- --> public: int operator()(int v1, int v2) {<!-- --> return v2 + v2; } }; void test01() {<!-- --> MyAdd myAdd; // myAdd is the function object cout << myAdd(10,10) << endl; } // 2. Function objects are beyond the concept of ordinary functions, and function objects can have their own state. // For an ordinary function, if you want to count the number of function executions, you need to define a global variable // The functor can directly define properties in the class to record the number of function executions class MyPrint {<!-- --> public: MyPrint() {<!-- --> this->count = 0; } void operator()(string text) {<!-- --> cout << text << endl; this->count + + ; } int count; // internal own state }; void test02() {<!-- --> MyPrint myPrint; myPrint("Hello World!"); myPrint("Hello World!"); myPrint("Hello World!"); cout << "MyPrint calls: " << myPrint.count << endl; } // 3. Function objects can be passed as parameters void doPrint(MyPrint & mp, string text) {<!-- --> mp(text); } void test03() {<!-- --> MyPrint myPrint; doPrint(myPrint,"Hello!"); } int main() {<!-- --> test01(); test02(); test03(); system("pause"); return 0; }
4.2 Predicate
A functor that returns a bool
type is called a predicate.
If operator()
receives one parameter, it is called a unary predicate; if operator()
receives two parameters, it is called a binary predicate.
4.2.1 Unary predicates
#include<iostream> using namespace std; #include <vector> #include <algorithm> class GreaterFive {<!-- --> public: bool operator()(int val) {<!-- --> return val>5; } }; void test01() {<!-- --> vector<int> v; for(int i = 0;i<10;i ++ ) {<!-- --> v.push_back(i); } // Find if there is a number greater than 5 in the container vector<int>::iterator it = find_if(v.begin(),v.end(),GreaterFive()); //GreaterFive() is an anonymous object if(it==v.end()) {<!-- --> cout << "Not found!" << endl; } else {<!-- --> cout << "The number greater than 5 found is: " << *it << endl; } } int main() {<!-- --> test01(); system("pause"); return 0; }
A new algorithm find_if
is used here, and three parameters need to be passed: the start position and end position (interval) represented by an iterator, and a predicate. Its return value is an iterator, which returns an iterator of the first element that satisfies the condition (the predicate returns true).
4.2.2 Binary predicates
#include<iostream> using namespace std; #include <algorithm> #include <vector> class myCmp {<!-- --> public: bool operator()(int v1, int v2) {<!-- --> return v1>v2; } }; void test01() {<!-- --> vector<int> v; v.push_back(5); v.push_back(2); v.push_back(4); v.push_back(3); v.push_back(1); //sort sort(v.begin(),v.end()); for(vector<int>::iterator it = v.begin();it!=v.end();it++ ) {<!-- --> cout << *it << " "; } cout << endl; // Using the function object, change the sorting rule to descending sort(v.begin(),v.end(),myCmp()); for(vector<int>::iterator it = v.begin();it!=v.end();it++ ) {<!-- --> cout << *it << " "; } cout << endl; } int main() {<!-- --> test01(); system("pause"); return 0; }
operation result:
4.3 Built-in function objects
STL has some built-in function objects (like functions), which can be used directly after including the header file
. Built-in function objects can be divided into three categories:
Arithmetic functors, relational functors, logical functors.
4.3.1 Arithmetic functors
Function: Realize four operations
The prototype of the functor is as follows, where negate
is a unary operation, and the rest are binary operations.
template<class T> T plus<T> // addition functor template<class T> T minus<T> // subtraction functor template<class T> T multiplies<T> // multiplication functor template<class T> T divides<T> // division functor template<class T> T modules<T> // take imitation function template<class T> T negate<T> // negate functor
Example:
#include<iostream> using namespace std; #include <functional> // negate void test01() {<!-- --> negate<int> n;//create function object cout << n(50) << endl; } //plus void test02() {<!-- --> plus<int> p; // Although two data need to be passed in, only one type declaration is required, because the operation is performed between the same type cout << p(10,20) << endl; } int main() {<!-- --> test01(); test02(); system("pause"); return 0; }
Results of the:
4.3.2 Relational functors
Functor prototype:
template<class T> bool equal_to<T> // equal to template<class T> bool not_equal_to<T> // not equal to template<class T> bool greater<T> // greater than template<class T> bool greater_equal<T> // greater than or equal to template<class T> bool less<T> // less than template<class T> bool less_equal<T> // less than or equal to
Example:
#include<iostream> using namespace std; #include <vector> #include<functional> //Include header files #include <algorithm> void test01() {<!-- --> vector<int> v; v.push_back(10); v. push_back(50); v. push_back(30); v.push_back(20); v. push_back(40); for(vector<int>::iterator it = v.begin();it!=v.end();it++ ) {<!-- --> cout << *it << " "; } cout << endl; // Sort in descending order using the built-in functor sort(v.begin(),v.end(),greater<int>()); for(vector<int>::iterator it = v.begin();it!=v.end();it++ ) {<!-- --> cout << *it << " "; } cout << endl; } int main() {<!-- --> test01(); system("pause"); return 0; }
4.3.3 Logical functors
(not used much)
Function prototype:
template<class T> bool logic_and<T> // logic and template<class T> bool logic_or<T> // logical or template<class T> bool logic_not<T> // logical not
Example:
#include<iostream> using namespace std; #include <vector> #include <algorithm> void test01() {<!-- --> vector<bool> v; v.push_back(true); v.push_back(false); v.push_back(true); v.push_back(false); for(vector<bool>::iterator it = v.begin();it!=v.end();it++ ) {<!-- --> cout << *it << " "; } cout << endl; vector<bool> v2; v2.resize(v.size()); // There must be space first, and then the transform algorithm can be used transform(v.begin(),v.end(),v2.begin(),logical_not<bool>()); for(vector<bool>::iterator it = v2.begin();it!=v2.end();it++ ) {<!-- --> cout << *it << " "; } cout << endl; } int main() {<!-- --> test01(); system("pause"); return 0; }
operation result: