Wiki
Function Objects and Predicates
1.STL - Function Objects
1.1.Function object
1.1.1.Function object concept
Concept:
- overloadingfunction call operatorclass, whose objects are often calledfunction object
- function objectwhen using overloaded (), the behavior is similar to a function call, also calledfunctor
Essence:
A function object (functor) is aclass, not a function
1.1.2.Function object usage
Features:
- When a function object is used, it can be called like an ordinary function, can take parameters, and can have a return value.
- Function objects go beyond the concept of ordinary functions; a function object can have its own state.
- A function object can be passed as a parameter.
Example:
#include <iostream>
#include <string>
using namespace std;
//1、函数对象在使用时,可以像普通函数那样调用, 可以有参数,可以有返回值
class MyAdd
{
public :
int operator()(int v1,int v2)
{
return v1 + v2;
}
};
void test01()
{
MyAdd myAdd;
cout << myAdd(10, 10) << endl;
}
//2、函数对象可以有自己的状态
class MyPrint
{
public:
MyPrint()
{
count = 0;
}
void operator()(string test)
{
cout << test << endl;
count++; //统计使用次数
}
int count; //内部自己的状态
};
void test02()
{
MyPrint myPrint;
myPrint("hello world");
myPrint("hello world");
myPrint("hello world");
cout << "myPrint调用次数为: " << myPrint.count << endl;
}
//3、函数对象可以作为参数传递
void doPrint(MyPrint &mp , string test)
{
mp(test);
}
void test03()
{
MyPrint myPrint;
doPrint(myPrint, "Hello C++");
}
int main() {
//test01();
//test02();
test03();
return 0;
}
Operation result:
Hello C++
Summary:
- Functors are very flexible in their syntax and can be passed as parameters.
1.2.predicate
1.2.1.Predicate concept
Concept:
- A functor that returns a bool type is called apredicate
- If operator() accepts one parameter, then it is called a unary predicate
- If operator() accepts two parameters, then it is called a binary predicate
1.2.2.Unary predicate
Example:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
//1.一元谓词
struct GreaterFive{
bool operator()(int val) {
return val > 5;
}
};
void test01() {
vector<int> v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
vector<int>::iterator it = find_if(v.begin(), v.end(), GreaterFive());
if (it == v.end()) {
cout << "没找到!" << endl;
}
else {
cout << "找到:" << *it << endl;
}
}
int main() {
test01();
return 0;
}
Operation result:
找到:6
Summary: A predicate with only one parameter is called a unary predicate.
1.2.3.binary predicate
Example:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
//二元谓词
class MyCompare
{
public:
bool operator()(int num1, int num2)
{
return num1 > num2;
}
};
void test01()
{
vector<int> v;
v.push_back(10);
v.push_back(40);
v.push_back(20);
v.push_back(30);
v.push_back(50);
//默认从小到大
sort(v.begin(), v.end());
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
cout << "----------------------------" << endl;
//使用函数对象改变算法策略,排序从大到小
sort(v.begin(), v.end(), MyCompare());
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
int main() {
test01();
return 0;
}
Operation result:
10 20 30 40 50
----------------------------
50 40 30 20 10
Summary: A predicate with only two parameters is called a binary predicate.
1.3.Built-in function objects
1.3.1.Significance of built-in function objects
Concept:
- STL has some built-in function objects
Category:
-
arithmetic functors
-
relational functors
-
logical functors
Usage:
- The objects produced by these function objects are used in exactly the same way as ordinary functions.
- To use built-in function objects, you need to include the header file
#include<functional>
1.3.2.arithmetic functor
Function description:
- Implement the four arithmetic operations
- Among them, negate is a unary operation, while the others are binary operations
Functor prototype:
template<class T> T plus<T>// Addition functortemplate<class T> T minus<T>// Subtraction functortemplate<class T> T multiplies<T>// Multiplication functortemplate<class T> T divides<T>// Division functortemplate<class T> T modulus<T>// Modulus functortemplate<class T> T negate<T>// Negation functor
Example:
#include <iostream>
#include <functional>
using namespace std;
//negate
void test01()
{
negate<int> n;
cout << n(50) << endl;
}
//plus
void test02()
{
plus<int> p;
cout << p(10, 20) << endl;
}
int main() {
test01();
test02();
return 0;
}
Operation result:
-50
30
Summary: When using built-in function objects, the header file must be included #include <functional>
1.3.3.Relation functor
Function description:
- Implementation relationship comparison
Functor prototype:
template<class T> bool equal_to<T>//Equal totemplate<class T> bool not_equal_to<T>//Not equal totemplate<class T> bool greater<T>//Greater thantemplate<class T> bool greater_equal<T>//Greater than or equal totemplate<class T> bool less<T>//Less thantemplate<class T> bool less_equal<T>//Less than or equal to
Example:
#include <iostream>
#include <functional>
#include <vector>
#include <algorithm>
using namespace std;
class MyCompare
{
public:
bool operator()(int v1,int v2)
{
return v1 > v2;
}
};
void test01()
{
vector<int> v;
v.push_back(10);
v.push_back(30);
v.push_back(50);
v.push_back(40);
v.push_back(20);
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
cout << *it << " ";
}
cout << endl;
//自己实现仿函数
//sort(v.begin(), v.end(), MyCompare());
//STL内建仿函数 大于仿函数
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();
return 0;
}
Operation result:
10 30 50 40 20
50 40 30 20 10
Summary: The most commonly used relational functor is greater<>, for greater-than.
1.3.4.logical functor
Function description:
- Implement logical operations
Function prototype:
template<class T> bool logical_and<T>//logical ANDtemplate<class T> bool logical_or<T>//logical ORtemplate<class T> bool logical_not<T>//logical NOT
Example:
#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>
using namespace std;
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;
//逻辑非 将v容器搬运到v2中,并执行逻辑非运算
vector<bool> v2;
v2.resize(v.size());
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();
return 0;
}
Operation result:
1 0 1 0
0 1 0 1
Summary: Logical functors are rarely used in practice; just understand them.