算法中的函数对象和谓词

函数对象    谓词

//算法中的函数对象和谓词
//for_each		find_if		transform		sort

#include <iostream>
#include <algorithm>
//#include <functional>
#include <vector>
#include <string>
#include <set>

using namespace std;

template <typename T>	//定义类模板
class ShowElemt
{
public:
	ShowElemt()
	{
		n = 0;
	}
	void operator()(T &t)	//定义函数对象
	{
		n++;	//保持调用状态信息
		cout << t << " ";
		printN();
	}
	void printN()
	{
		cout << "n: " << n << endl;
	}
private:
	int n;
};

template <typename T>	//定义函数模板
void showElemt(T &t)
{
	cout << t << endl;
}

void showElemt2(int &t)	//定义普通函数
{
	cout << t << " ";	
}

//函数对象的定义 函数对象和普通函数的异同
void test01()
{
	int a = 10;
	ShowElemt<int> s1;
	s1(a);		//函数对象的调用和普通函数很相似
	showElemt<int>(a);
	showElemt2(a);
}

//函数对象属于类对象,能保持调用状态信息
//函数对象的好处
//for_each算法中,函数对象做函数参数
//for_each算法中,函数对象做返回值
void test02()
{
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(3);
	v1.push_back(5);
	//遍历的作用
	for_each(v1.begin(), v1.end(), ShowElemt<int>());	//匿名函数对象 匿名仿函数

	for_each(v1.begin(), v1.end(), showElemt2);	//通过回调函数 谁使用for_each 谁去填写回回调函数入口地址

	ShowElemt<int> s1;
	//函数对象做函数参数
	for_each(v1.begin(), v1.end(), s1);
	s1.printN();	//此时 n=0 ==>函数对象的传递 是 实参值赋给形参 是元素值传递 不是引用

	cout << "通过for_each算法的返回值看调用次数:" << endl;
	s1= for_each(v1.begin(), v1.end(), s1);	//返回函数对象
	s1.printN();
}
//结论 要点:分清楚STL算法返回的值是 迭代器 还是 谓词(函数对象) 是STL算法入门的重要点

//一元谓词案例
template <typename T>
class IsDiv
{
public:
	IsDiv(const T &divisor)
	{
		this->divisor = divisor;
	}
	bool operator()(T &t)
	{
		return (t%divisor == 0);
	}
private:
	T divisor;
};

void test03()
{
	vector<int> v2;
	for (int i = 20; i < 33; i++)
	{
		v2.push_back(i);
	}
	vector<int>::iterator it;
	it = find_if(v2.begin(), v2.end(), IsDiv<int>(4));	//一元谓词做函数参数
	if (it == v2.end())
	{
		cout << "v2 中没有被4整除的值" << endl;
	}
	else
	{
		cout << "第一个被4整除的值是:" << *it << endl;
	}
}

//二元函数对象案例
template <typename T>
class SunAdd
{
public:
	T operator()(T t1, T t2)	//二元函数对象
	{
		return t1 + t2;
	}
};

void test04()
{
	//v1 v2 ==> v3
	vector<int> v1, v2;
	vector<int> v3;
	v1.push_back(1);
	v1.push_back(3);
	v1.push_back(5);
	v2.push_back(2);
	v2.push_back(4);
	v2.push_back(6);

	v3.resize(10);
	//二元函数对象做函数参数
	transform(v1.begin(), v1.end(), v2.begin(), v3.begin(), SunAdd<int>());

	for (vector<int>::iterator it = v3.begin(); it != v3.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

//二元谓词案例
template <typename T>
bool myCompare(const T &a, const T &b)
{
	return a > b;	//降序排列
}

void test05()
{
	vector<int> v1;
	for (int i = 0; i < 10; i++)
	{
		int tmp = rand() % 100;
		v1.push_back(tmp);
	}
	for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
	//也可以用for_each来遍历
	for_each(v1.begin(), v1.end(), showElemt2);
	cout << endl;

	sort(v1.begin(), v1.end(), myCompare<int>);	//二元谓词做函数参数
	for_each(v1.begin(), v1.end(), showElemt2);
	cout << endl;
}

//二元谓词在set集合中的应用
struct CompareNoCase
{
	bool operator()(string &str1, string &str2)
	{
		//将两个字符串都变为大写或小写进行比较,则不需要区分大小写
		string str1_;
		str1_.resize(str1.size());	//为str1_分配空间
		transform(str1.begin(), str1.end(), str1_.begin(), tolower);//都转换为小写 预定义函数对象

		string str2_;
		str2_.resize(str2.size());	//为str1_分配空间
		transform(str2.begin(), str2.end(), str2_.begin(), tolower);//都转换为小写

		return str1_ < str2_;
	}
};

void test06()
{
	set<string> s1;
	s1.insert("aaa");
	s1.insert("bbb");
	s1.insert("ccc");
	set<string>::iterator it = s1.find("aAa");	//find函数默认区分大小写
	if (it == s1.end())
	{
		cout << "没有找到 aaa" << endl;
	}
	else
	{
		cout << "找到 aaa" << endl;
	}
	
	//使用二元谓词使find不区分大小写
	set<string, CompareNoCase> s2;
	s2.insert("aaa");
	s2.insert("bbb");
	s2.insert("ccc");
	set<string, CompareNoCase>::iterator it2 = s2.find("aAa");
	if (it2 == s2.end())
	{
		cout << "没有找到 aaa" << endl;
	}
	else
	{
		cout << "不区分大小写 找到 aaa" << endl;
	}
}


int main()
{
	//test01();
	//test02();
	//test03();
	//test04();
	//test05();
	test06();
	system("pause");
	return 0;
}

测试 test06 后

出现问题:

严重性    代码    说明    项目    文件    行    禁止显示状态
错误    C2664    “bool CompareNoCase::operator ()(std::string &,std::string &)”: 无法将参数 1 从“const std::basic_string<char,std::char_traits<char>,std::allocator<char>>”转换为“std::string &”    Test014    d:\vs2017\visual studio ide\vc\tools\msvc\14.16.27023\include\xtree    1426    

然后先前可以正常运行的 test01-test05 都出现这个错误了......

why???

 

问题解决:

set<string, CompareNoCase> 具有const属性,但是调用该set<string, CompareNoCase>的表达式(也就是bool operator()(const string &str1, const string &str2)不具有const属性,丢失const,所以无法通过编译。

调用operator()的时候要求operator()也具有const属性,否则就会导致丢失const限定符的错误。

因此解决办法就是给operator()加上const属性

如下:

struct CompareNoCase
{
	//要给函数加上const解决只读属性的问题
	//bool operator()(const string &str1, const string &str2)
	bool operator()(const string &str1, const string &str2) const
	{
		//将两个字符串都变为大写或小写进行比较,则不需要区分大小写
		string str1_;
		str1_.resize(str1.size());	//为str1_分配空间
		transform(str1.begin(), str1.end(), str1_.begin(), tolower);//都转换为小写 预定义函数对象

		string str2_;
		str2_.resize(str2.size());	//为str1_分配空间
		transform(str2.begin(), str2.end(), str2_.begin(), tolower);//都转换为小写

		return (str1_ < str2_);
	}
};

 

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值