14.33 一个重载的函数调用运算符应该接受几个运算对象?
一个类可以定义多个不同版本的调用运算符,相互之间应该在参数数量或类型上有所不同即可。
14.34 定义一个函数对象类,令其执行if-then-else的操作:该类的调用运算符接受三个形参,它首先检查第一个形参,如果成功返回第二个形参的值;如果不成功返回第三个形参的值。
#include <iostream>
using namespace std;
class X {
public:
X() = default;
X(const int x, const int y, const int z) :a(x), b(y), c(z) {}
int operator()(const int q, const int w, const int e)
{
if (q > 10) {
return w;
}
else {
return e;
}
}
private:
int a;
int b;
int c;
};
int main()
{
X x, x2;
cout << x(1, 2, 3) << " " << x2(11, 12, 13);
}
练习14.35 编一个类似于PrintString类,令其从istream中读取一行输入,然后返回一个表示我们所读取的内容的string。如果读取失败,返回空string。
#include <iostream>
#include <string>
using namespace std;
class X {
public:
X(std::ostream &o = cout, char c = ' ') :os(o), sep(c) {}
void operator()(const std::string &s) { os << s << sep; }
private:
std::ostream& os;
char sep;
};
int main()
{
string str;
X x;
if (getline(cin, str)) {
x(str);
cout <<"!" <<endl;
}
else {
x(string());
}
}
14.36 使用前一个练习定义的类读取标准输入,将每一行保存为vector的一个元素。
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class X {
public:
X(istream &i = cin, char c = ' ') :is(i), sep(c) {}
string operator()(string &s)
{
getline(cin, s);
if (s.size()) {
return s;
}
else {
return "";
}
}
private:
istream &is;
char sep;
};
int main()
{
vector<string> svec;
string str;
X line;
while (line(str)!="") {
svec.push_back(str);
}
for (auto &i : svec) {
cout << i << "!" << endl;
}
}
练习14.37 编写一个类令其检查两个值是否相等。使用该对象及标准库算法编写程序,令其替换某个序列中具有给定值得所有实例。
练习14.38 编写一个类令其检查某个给定的string对象的长度是否与一个阈值相等。使用该对象编写程序,统计并报告在输入的文件中长度为1的单词有多少个、长度为2的单词有多少个....、长度为10的单词有多少个。
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
class string_n {
public:
string_n(const std::size_t n) :num(n) {}
bool operator()(const std::string &s)
{
return s.size() == num;
}
private:
std::size_t num;
};
int main()
{
vector<std::string> svec{ "paul","pierce","kangkang","c++primer","kobe" };
for (std::size_t i = 1; i <= 10; ++i) {
cout << i << " " << count_if(svec.cbegin(), svec.cend(), string_n(i)) << endl;
}
}
练习14.39 修改上一题的程序令其报长度在1到9间的单词有多少个、长度在10以上的单词又有多少个。
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
class string_n {
public:
string_n(const std::size_t m, const std::size_t n) :max(m), min(n) {}
bool operator()(const std::string &s)
{
return s.size() >= min&&s.size() <= max;
}
private:
std::size_t max;
std::size_t min;
};
int main()
{
std::vector<std::string> svec{ "kobe","joy","congratulation","mcgrady" };
cout << "1-9 " << count_if(svec.cbegin(), svec.cend(), string_n(9, 1)) << endl;
cout << "10- " << count_if(svec.cbegin(), svec.cend(), string_n(999, 10)) << endl;
}
练习14.40 重新编写10.3.2节的biggies函数,使其使用函数对象类替换其中的lambda表达式。
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
class biggies {
public:
biggies(const std::size_t n) :len(n) {}
bool operator()(const std::string &a,const std::string &b)
{
return a.size() < b.size();
}
private:
std::size_t len;
};
int main()
{
vector<string> svec{ "kobe","paul","kangkang","zzz","kobe" };
sort(svec.begin(), svec.end());
auto iter = unique(svec.begin(), svec.end());
svec.erase(iter, svec.end());
stable_sort(svec.begin(), svec.end(), biggies(3));
for (auto &i : svec) {
cout << i << " ";
}
}
练习14.41 你认为C++11新标准为什么要增加lambda?对于你自己来说,什么情况下会使用lambda,什么情况下使用类。
lambda用于小型程序中,出现次数极少,实现简单功能。
类用于大型程序中,频繁出现。
练习14.42 使用标准库函数对象及适配器定义一条表达式,令其
(a) 统计大于1024的值有多少个。
(b) 找到第一个不等于pooh的字符串。
(c) 将所有的值乘以2。
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;
int main()
{
vector<int> ivec{ 7,77,7777,8888,9,1025 };
cout << count_if(ivec.begin(), ivec.end(), bind2nd(greater<int>(), 1024)) << endl;
vector<string> svec{ "hoop","hoop","mcgrady","dddd" };
cout << *find_if(svec.begin(), svec.end(), bind2nd(not_equal_to<string>(), "hoop")) << endl;
vector<int> ivec2 = ivec;
transform(ivec.begin(), ivec.end(),ivec2.begin(), bind2nd(multiplies<int>(), 2));
for (auto &i : ivec2) {
cout << i << " ";
}
}
练习14.43 使用标准库函数对象判断一个给定的int是否能被int容器中所有元素整除。
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;
int main()
{
vector<int>ivec{ 2,4,6,8,10 };
auto num = count_if(ivec.begin(), ivec.end(), bind2nd(modulus<int>(), 2));
if (num == 0) {
cout << "yes" << endl;
}
else {
cout << "no" << endl;
}
}
练习14.44 编写一个简单的桌面计算器使其能处理二元运算。
#include <iostream>
#include <string>
#include <map>
#include <functional>
using namespace std;
int add(int a, int b) { return a + b; }
struct divide {
int operator()(int d, int d2) { return d / d2; }
};
int main()
{
auto mod = [](int i, int j) {return i%j; };
map<string, function<int(int, int)>> binops = {
{"+",add},
{"-",std::minus<int>()},
{"/",divide()},
{"*",[](int i, int j) {return i*j; }},
{"%",mod}
};
cout <<binops["/"](9, 2.9)<<endl;
}