C++ Primer 习题14.37
使用标准库函数对象和函数适配器,定义一个对象用于能:
1. 检查大于1024的所有值;
2. 查找不等于pooh 的所有字符串
3. 将所有值乘以2
#include <iostream>
#include <iterator>
#include <algorithm>
#include <fstream>
#include <list>
#include <string>
#include <vector>
#include <set>
#include<utility>
bool GT6(const std::string &s)
{
return s.size() >6;
}
class GT_cls
{
public:
GT_cls(std::size_t val = 0):bound(val) {}
bool operator() (const std::string & s) { return s.size() >= bound;}
private:
std::string::size_type bound;
};
class equal_cls
{
public:
equal_cls(int i = 0):val(i) {}
bool operator() (const int & i ) { return i==val; }
private:
int val;
};
//test code
int main()
{
std::vector<std::string> words;
std::string word;
while(std::cin>>word)
{
words.push_back(word);
}
std::vector<std::string>::size_type wc = std::count_if(words.begin(),words.end(),GT6);
std::cout<<wc<<std::endl;
std::vector<std::string>::size_type wc1 = std::count_if(words.begin(),words.end(),GT_cls(6));
std::cout<<wc1<<std::endl;
std::vector<std::string>::size_type wc2 = std::count_if(words.begin(),words.end(),GT_cls(2));
std::cout<<wc2<<std::endl;
std::vector<std::string>::iterator i = std::find_if(words.begin(), words.end(),GT_cls(2));
std::cout<<*i<<std::endl;
//test equal_cls
std::vector<int> ivec(10);
std::vector<int>::size_type cn = std::count_if(ivec.begin(), ivec.end(),equal_cls());
std::cout<<cn<<std::endl;
std::vector<int>::size_type cn1 = std::count_if(ivec.begin(),ivec.end(),equal_cls(10));
std::cout<<cn1<<std::endl;
//use std::functional and function adapter
std::vector<int> ivec;
ivec.reserve(1030);
for(int i = 0 ; i <1030 ;++i)
{
ivec.push_back(i);
}
//find all value that is greater than 1024
std::vector<int>::iterator result = std::find_if(ivec.begin() , ivec.end() , std::bind2nd(std::greater<int>() ,1024) );
while(result != ivec.end())
{
std::cout<<*result<<std::endl;
result = std::find_if( ++result , ivec.end() , std::bind2nd(std::greater<int>() ,1024) );
}
std::vector<std::string> svec;
svec.push_back("hello world");
svec.push_back("test");
svec.push_back("huqijun");
svec.push_back("pooh");
//find all value that is not equal to "pooh"
std::vector<std::string>::iterator ret = std::find_if(svec.begin(),svec.end(),std::bind2nd(std::not_equal_to<std::string>(),"pooh") );
while(ret != svec.end())
{
std::cout<<*ret<<std::endl;
ret = std::find_if(++ret,svec.end(),std::bind2nd(std::not_equal_to<std::string>(),"pooh") );
}
//double every value
std::vector<int> ivec2;
ivec2.reserve(12);
for(int i = 0; i<12 ; ++i)
{
ivec2.push_back(i);
}
<span style="background-color: rgb(255, 0, 0);"> std::for_each(ivec2.begin(),ivec2.end(),std::bind2nd(std::multiplies<int>(),2) );
for(std::vector<int>::iterator i = ivec2.begin() ; i!= ivec2.end() ; ++i)
{
std::cout<<*i<<std::endl;
}</span>
return 0;
}
上面的代码,最后一段实现将所有值乘以2 是失败的,没有实现目的
原因是for_each 算法是不改变序列的算法, for_each 会忽略第三个参数函数的返回值:
UnaryFunction for_each( InputIt
first, InputIt last, UnaryFunction f );
| ||
Applies the given function object f
to the result of dereferencing every iterator in the range [first,
last)
, in order.
If InputIt
is a mutable iterator, f
may
modify the elements of the range through the dereferenced iterator. If f
returns a result, the result is
ignored.
而std::mutiplies<int>() 就是会返回值,因为被忽略了:
constexpr T operator()(const T &lhs, const T &rhs) const { return lhs * rhs; }
所以用for_each 和std::mutiplies 是实现不了将所有值乘2的目的
std::transform(b.begin(),b.end(), b.begin(),std::bind2nd(std::multiplies<int>(),2) );
使用std::tranform 可以实现我们目的:
std::transform
applies
the given function to a range and stores the result in another range, beginning at d_first
.
std::transform会见f 运算的结果保存下来,所以可以实现都乘以2的目的