C ++ Primer Chapter XIV operation overloading and type conversion 14.8 function call operator exercises and summary

14.8 function call operator

Overloaded function call operator class that can make an object like a function of behavior, so we call such objects as a function of the object.

Relative to normal function, function objects can save some of the states, which are in fact members of his data.

This fact, in turn and as the lambda expressions, lambda expression is actually a class of objects.

Exercise

14.33

Zero, one, more can, and parameters can have default values

14.34
struct IfThenElse
{

	int operator()(int a,int b,int c) {
		return a ? b : c;
	};
};

14.35

Function object here is to have a state, it is saved

struct ReadString {
	ReadString(istream& _is):is(_is){};

	string operator()() {
		string temp = "";
		getline(is, temp);
		return temp;
	};
	istream& is;
};
14.36
	ReadString read_string(cin);
	string line;
	vector<string> vec;
	while ((line=read_string())!="") {
		vec.push_back(line);
	}
	ostream_iterator<string> out_iter(cout,",");
	std::copy(vec.begin(), vec.end(), out_iter);
14.37

The target can also be written as data members

struct TwoValueEqual
{
	bool operator()(const string&str1,const string& target) {
		return str1 == target;
	};
};

	ReadString read_string(cin);
	string line;
	vector<string> vec;
	while ((line = read_string()) != "") {
		vec.push_back(line);
	}


	ostream_iterator<string> out_iter(cout,"\n");
	std::copy(vec.begin(), vec.end(), out_iter);
	TwoValueEqual func;
	auto new_func = std::bind(func, std::placeholders::_1, "123");
	 //new_func("23");
	std::replace_copy_if(vec.begin(), vec.end(), out_iter,new_func,"666");

14.8.1 lambda is a function object

lambda is actually a function object, the position of an anonymous class to create lambda creates a function object, the function object is const class.

lambda expression is equivalent to a declaration of an overloaded function call operator class. And overloaded function is const type.

The following two statements are basically equivalent.

struct TwoValueEqual
{
	bool operator()(const string&str1,const string& target) {
		return str1 == target;
	};
};

[](const string&str1,const string& target){
	return str1 == target;
};

In lambda expressions, using the parameter value captured, corresponding to the data members of the class, because it is operator () function is const type, so its value can not be modified, if necessary to modify the lambda expression is modified mutable. Captured using a reference value of a reference type, it can be modified directly.
It is also feasible in the class, is the amount of a reference type member can modify its data value function const.

Exercise

14.38
struct StringEqualSize
{
	StringEqualSize(size_t l, size_t u) :_lower(l), _upper(u) {};
	bool operator()(const string&str) const {
		return (str.size() >= _lower) && (str.size() <= _upper);
	};
	size_t _lower;
	size_t _upper;
};

--测试代码-
ifstream fin("data.txt");
	string word;
	map<size_t, size_t>word_count;
	vector<StringEqualSize> vec = {
		StringEqualSize(1, 1),
		StringEqualSize(2, 2),
		StringEqualSize(3, 3),
		StringEqualSize(4, 4),
	};
	while (fin>>word) {
		for (const auto& item:vec)
		{
			if (item(word))
			{
				++word_count[word.size()];
				break;
			}
		}

	}
	for (const auto& item: word_count)
	{
		cout << item.first<<" appear "<<item.second<<"times"<< endl;
	}
14.39
struct StringEqualSize
{
	StringEqualSize(size_t l, size_t u,const string& n) :_lower(l), _upper(u),name(n){};
	StringEqualSize(size_t l, bool flag,const string& n) :_lower(l), only_lower(flag),name(n) {};
	bool operator()(const string&str) const {
		bool flag;
		if (only_lower)
		{
			flag = (str.size() >= _lower);
		}
		else {
			flag= (str.size() >= _lower) && (str.size() <= _upper);
		}
		return flag;
	};
	size_t _lower;
	bool only_lower;
	size_t _upper;
	string name;
};

---

ifstream fin("data.txt");
	string word;
	map<string, size_t>word_count;
	vector<StringEqualSize> vec = {
		StringEqualSize(1u, 9u,"1~9"),
		StringEqualSize(10u, true,">=10")
	};
	while (fin>>word) {
		for (const auto& item:vec)
		{
			if (item(word))
			{
				++word_count[item.name];
				break;
			}
		}

	}
	for (const auto& item: word_count)
	{
		cout << item.first<<" appear "<<item.second<<"times"<< endl;
	}
14.40

slightly

14.41

Because the use of lambda expressions more quickly, without much definition, if you want to use in the past with a state function objects need to define the class, this will be very tedious.

For some simple logic and will only appear once or several small function may lambda, in addition to the need to preserve parameter additional parameters outside, you can also use lambda.

14.8.2 The library defines function objects

The standard library provides a function object to arithmetic operators, relational operators, bit operators, these functions are template objects. .

Flexible objects using standard library functions, algorithms, and function adapters can simplify part of our work.

Here Insert Picture Description

14.42

a.

vector<int>vec = { 1231,2312,4123,31,32,4321,543,123,132412 };
auto func = std::bind(std::greater<int>(), std::placeholders::_1, 1024);
auto count = std::count_if(vec.begin(), vec.end(), func);
cout << count << endl;

b.

	vector<string> vec = { "pooch","pooch","adsf","pooch","12312" };
	auto func = std::bind(std::not_equal_to<string>(), std::placeholders::_1, "pooch");
	auto iter =	std::find_if(vec.begin(), vec.end(), func);
	if (iter!=vec.end())
	{
		cout << *iter << endl;
	}

c.

I wanted to use the copy, but the copy source and target iterator iterator iterator can not be the same container

vector<int>vec = { 1231,2312,4123,31,32,4321,543,123,132412 };
	auto func = std::bind(std::multiplies<int>(), std::placeholders::_1, 2);
	std::transform(vec.begin(), vec.end(),vec.begin(),func);
	//vector<int> vec;
	for (const auto& item:vec) {
		cout<<item<<endl;
	}
14.43

Using modulo, if divisible i.e. 0 refers to false, if the value is not divisible 1, true, so that if the find_if () is returned iterator End (), then the sequence is divisible by all the elements in it.

	vector<int>vec = { 2,3,8 };
	auto func = std::bind(std::modulus<int>(), 16, std::placeholders::_1);
	auto iter = std::find_if(vec.begin(), vec.end(), func);
	if (iter==vec.end()) {
		cout<<"所有元素都能整除它"<<endl;
	}
	else {
		cout << "有元素不能整除它" << endl;
	}

14.8.3 callable objects and function

For the function, function pointers, lambda expressions, overloaded () class and std :: bind () they are all callable object.

These callable object has its own type, but different types of callable objects can be shared call form .

In the form of call and the type of the return value of the argument types.

All callables 14.44 in practice, they all belong

double(double,double)

Call form.

We can form a unified management of these calls the same function, such as using a map, but because they are not the same type.

So how to determine the value of the type of map, this time you can use the function type , it can be of different types but the same call in the form of callable objects are converted to the same type.

I think essentially added a layer of packaging.

Here are some specific types of operations function. We need to pass specific call in the form of angle brackets.
Here Insert Picture Description

Exercise

14.44
double my_minus(double a,double b) {
	return a - b;
}
struct my_multi
{
	double operator()(double a, double b) {
		return a * b;
	};
};
struct my_divides
{
	double operator()(double a, double b,double c) {
		return a / b;
	};
};


map<string, std::function<double(double, double)>> caculate;
	caculate["+"] = [](double a, double  b)->double{return a + b; };
	caculate["-"] = my_minus;
	caculate["*"] = my_multi();
	//caculate["/"] = std::divides<int>();
	caculate["/"] = std::bind(my_divides(), std::placeholders::_1, std::placeholders::_2, 0.0);
	double a,b;
	string oper = "";
	while (cin>>a>>oper>>b)
	{
		cout << a<<oper<<b<<"="<<caculate[oper](a, b) << endl;;
	}
Published 54 original articles · won praise 6 · views 3278

Guess you like

Origin blog.csdn.net/zengqi12138/article/details/104553000