[C++] Predicates in C++

You must have heard in English grammar class before that the most basic sentence structure is: subject-verb-object, and the predicate is a word that can have the meaning of "verb".
In fact, such predicates also exist in C++, and functions are typical predicate semantics. Predicates in STL look like this: bool func(T&a); or bool func(T&a,T&b);

Common predicates: functions, function pointers, function objects, lambda expressions, library-defined function objects. For example, find_if(), count_if() and other functions need to pass in bool-type judgment condition parameters, so predicates are often used. The following uses the count_if() function as an example to briefly introduce the implementation methods of the above predicates.

1. Using functions as predicates

#include<iostream>
#include<vector>
#include<functional>      //bind2nd函数需使用
#include<algorithm>
using namespace std;

//定义函数,作为传入参数
bool bigthan3(int val)
{
	return val > 3;
}
//计算容器vec中大于3的元素个数
int main(void)
{
	vector<int> vec={1,2,3,4,5,6};
	int CountNum = count_if(vec.begin(),vec.end(),bigthan3);   //传入的是bigthan3谓词,返回的是bool类型,其中自动将vec容器中的元素值传给bigthan3函数
	cout<<"CountNum = "<<CountNum <<endl;
	return 0;
}
//输出结果:CountNum = 3;

2. Using a function pointer as a predicate is basically the same as the above function as a predicate, except that the function pointer is used to transfer once.

#include<iostream>
#include<vector>
#include<functional>      //bind2nd函数需使用
#include<algorithm>
using namespace std;

//定义函数,作为传入参数
bool bigthan3(int val)
{
	return val > 3;
}
//计算容器vec中大于3的元素个数
int main(void)
{
	bool (*p_bigthan3)(int);	//定义函数指针
	p_bigthan3 = bigthan3;
	vector<int> vec={1,2,3,4,5,6};
	int CountNum = count_if(vec.begin(),vec.end(),p_bigthan3);   //传入的是p_bigthan3函数指针做谓词,返回的是bool类型,其中自动将vec容器中的元素值传给bigthan3函数
	cout<<"CountNum = "<<CountNum <<endl;
	return 0;
}
//输出结果:CountNum = 3;

3. Use function objects as predicates (unary functor, fixed comparison parameters)

The essence of using function objects is to perform operator overloading on (), and the return type is bool.

#include<iostream>
#include<vector>
#include<functional>      //bind2nd函数需使用
#include<algorithm>
using namespace std;

//定义仿函数类
class bigthan3
{
public:
	bool operator()(int val)const  //对()实现重载,注意一定要加const修饰
	{
		return val > 3;
	}
};
//计算容器vec中大于3的元素个数
int main(void)
{
	vector<int> vec={1,2,3,4,5,6};
	int CountNum = count_if(vec.begin(),vec.end(),bigthan3());   //传入的是bigthan3仿函数,返回的是bool类型,其中自动将vec容器中的元素值传给bigthan3函数
	cout<<"CountNum = "<<CountNum <<endl;
	return 0;
}
//输出结果:CountNum = 3;

In addition, for the use of function objects, the comparison parameter can also be passed to the () operator overloaded function as the constructor of the function object. The specific usage is as follows:

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

using namespace std;
class myfind
{
public:
	//默认构造函数
	myfind() {}
	//有参构造函数
	myfind(int my_n):n(my_n)
	{
	}
	bool operator()(int val)
	{
		return val > n;
	}
private:
	int n;
};
int main(void)
{
	vector<int>vec1 = { 1,2,4,9,5,54,45,56 };
	auto iter = find_if(vec1.begin(), vec1.end(), myfind(1));	  //使用函数对象做谓词,并且入口参数作为谓词判断的条件
	for_each(iter, vec1.end(), [](int val) {cout << val << " "; });
	cout << endl;
}

Among them, myfind(1) is the function object that is called, 1 is the constructor passed to the myfind object, not the () operator overloaded function, and the elements of the vec1 container traversed using the find_if generic algorithm are passed to the () operator overloaded function . Be sure to distinguish clearly! So myfind(1) actually completes two things here: one is to call the constructor of myfind, and the other is to pass the () operator overloaded function as a predicate to the find_if generic algorithm.

4. Use lambda expressions as judgment condition parameters

#include<iostream>
#include<vector>
#include<functional>      //bind2nd函数需使用
#include<algorithm>
using namespace std;

//计算容器vec中大于3的元素个数
int main(void)
{
	vector<int> vec={1,2,3,4,5,6};
	int CountNum = count_if(vec.begin(),vec.end(),[](int val){return val>3;});   //传入的是lambda表达式,返回的是bool类型,其中val为遍历vec容器传入的元素值
	cout<<"CountNum = "<<CountNum <<endl;
	return 0;
}
//输出结果:CountNum = 3;

5. Use the functor plus bind2nd to realize the input of binary parameters, and the comparison parameters are not fixed.

Observing the above four methods, we can see that the comparison conditions are all greater than 3, and the parameter 3 can only be fixed, because the above method can only pass in one parameter, which is the element of vec itself. If you want to customize the comparison parameters, you need to pass in two parameters to the bool comparison function, so you can use the functor combined with the bind2nd function.

#include<iostream>
#include<vector>
#include<functional>      //bind2nd函数需使用
#include<algorithm>
using namespace std;

//定义仿函数类
class bigthan3:public binary_function<int, int, bool>  //必须继承binary_function类,<参数1,参数2,返回值>
{
public:
	bool operator()(int val1,int val2)const  //对()实现重载,注意一定要加const修饰
	{
		return val1 > val2;
	}
};
//计算容器vec中大于4的元素个数
int main(void)
{
	vector<int> vec={1,2,3,4,5,6};
	int a = 4;   //比较值可以自定义
	int CountNum = count_if(vec.begin(),vec.end(),bing2nd(bigthan3(),a));   //传入的是bigthan3仿函数,并且通过bind2nd函数给bigthan3添加了一个参数a,这样比较的入口参数就包含vec本身元素及a共两个,返回的是bool类型
	cout<<"CountNum = "<<CountNum <<endl;
	return 0;
}
//输出结果:CountNum = 2;

/*
bind2nd绑定的使用步骤:
1.包含bind2nd头文件:#include<functional>
2.在find_if中进行绑定:bind2nd(mycompare,p1)
3.在mycompare类中进行绑定登记:
首先继承public binary_function<person,person,bool>,其中<>中的参数代表第一个参数,第二个参数,返回值
然后定义operator()函数为const类型
*/

Summarize

The above examples show several common implementation methods of predicates, which can be used for other similar functions such as find_if. In addition, the elements in the vector can be generalized into classes, not limited to a specific data type, only need to specify the comparison method in the overloaded function.

Guess you like

Origin blog.csdn.net/weixin_43717839/article/details/132622489
C++