《Essential C++》读书笔记(四)
来源:互联网 发布:中盈数据恢复机教程 编辑:程序博客网 时间:2024/05/01 14:50
第三章泛型编程风格续
3.6如何设计一个泛型算法
template<typename IteratorType,typename elemType>
IteratorType find(IteratorType first,IteratorType last,const elemType &value){
for(;first!=last;++first)
if(value==*first)
return first;
return last;
}
template<typename InputIterator,typename T>
InputIterator find_if1(InputIterator first,InputIterator last,T p);
因为是模板嘛,所以只是传入的实参类型不同而已。vector<int> filter_ver1(const vector<int> &vec,int filter_value,bool(*pred)(int,int)){
vector<int> nvec;
for(int ix=0;ix<vec.size();++ix)
if(pred(vec[ix],filter_value))
nvec.push_back(vec[ix]);
return nvec;
}
template <class _Tp>
struct plus : public binary_function<_Tp, _Tp, _Tp>
{
_Tp
operator()(const _Tp& __x, const _Tp& __y) const
{ return __x + __y; }
};
虽然叫function object ,只是在传递的时候定义的对象。template<typename InputIterator,typename T>
InputIterator find_if1(InputIterator first,InputIterator last,T p);
若p传递的是less<type>,那么p是个函数对象,应该接受两个参数,而find_if1的内部是逐一遍历元素的,所以只传递给p一个参数,你可能会说,我可以在find_if1内部定义一个变量,将这个变量也传给p,这不就两个了么,但是,这样违背了一个原则,那就是泛型,想一想的确如此嘛,不过,可以在传递p的时候,将p的一个参数绑定到一个变量或是常量上。为了解决这一问题,适配器就来了。
第一种adaptor是binder adapter(绑定配接器),其会将function object的参数绑定至特定值上,使二元function object转化为一元。标准库仅提供了两个binder adapter:bind1st、bind2nd。看字面意思就懂,绑到第一个和绑到第二个。
这样便解决了上面find_if1()的参数问题,相对于find(),find_if1(),仅需修改if中的判断条件仅可,而其它的不用变。
template<typename InputIterator,typename T>
InputIterator find_if1(InputIterator first,InputIterator last,T p){
for(;first!=last;++first)
if(p(*first))
return first;
return 0;
}
假如我们想找到第一个比a大的元素,如下:
find_if1(vec.begin(),vec.end(),bind2nd(greater<int>(),a));
或:
find_if1(vec.begin(),vec.end(),bind1st(less<int>(),a));
这样就很方便了,若是使用带默认参数的函数,是无法达到这样的灵活度的,注意,带默认实参的函数不论在函数声明还是函数调用都是有限制的,并不如这样方便。
写了段代码试了下:
#include<iostream>
#include<functional>
#include<vector>
using namespace std;
template<typename InputIterator,typename T>
InputIterator find_if1(InputIterator first,InputIterator last,T p){
for(;first!=last;++first)
if(p(*first))
return first;
return last;
}
int main(){
vector<int> ivec;
for(int i=0;i!=10;++i)
ivec.push_back(i);
vector<int>::iterator it=find_if1(ivec.begin(),ivec.end(),bind2nd(greater<int>(), 5));
cout<<*it<<endl;
}
输出6,对了。
另一种adaptor是所谓的negator,它会逆转function object的真伪值,not1可逆转unary function object的真伪值,not2可逆转binary function object。
如上例,如果我想找到第一个小于等于5的元素,可这样:
find_if1(ivec.begin(),ivec.end(),not1(bind2nd(greater<int>(),5)));
关于泛型的设计就这样了。
3.7使用map & 3.8使用set
终于到关联容器了,本书对map和set的讲解仅仅3页,都没讲multimap和multiset,真是简略啊!
对于map需要注意的是其下标操作,和pair,不过本书并未提到pair。
对于set注意什么呢?书中说set元素皆依据其所属型别默认的<运算符进行排列,我试了下,的确如此,我又试了下map,发现它是依key值的默认<运算符排序的。
3.9如何使用Iterator Inserters
template<typename _Container>
inline back_insert_iterator<_Container>
back_inserter(_Container& __x)
{ return back_insert_iterator<_Container>(__x); }
template<typename _Container>
class back_insert_iterator
: public iterator<output_iterator_tag, void, void, void, void>
{
protected:
_Container* container;
public:
typedef _Container container_type;
explicit
back_insert_iterator(_Container& __x) : container(&__x) { }
//后面才是重点
back_insert_iterator&
operator=(typename _Container::const_reference __value)
{
container->push_back(__value);
return *this;
}
back_insert_iterator&
operator*()
{ return *this; }
back_insert_iterator&
operator++()
{ return *this; }
back_insert_iterator
operator++(int)
{ return *this; }
};
#include<vector>
#include<iostream>
#include<iterator>
#include<algorithm>
#include<string>
using namespace std;
int main(){
istream_iterator<string> is(cin);
istream_iterator<string> eof;
vector<string> text;
copy(is,eof,back_inserter(text));
sort(text.begin(),text.end());
ostream_iterator<string> os(cout," ");
copy(text.begin(),text.end(),os);
}
#include<vector>
#include<iostream>
#include<iterator>
#include<algorithm>
#include<string>
#include<fstream>
using namespace std;
int main(){
ifstream in_file("input_file.txt");
ofstream out_file("out_file.txt");
if(!in_file||!out_file){
cerr<<"!!unable to open the necessary file.\n";
return -1;
}
istream_iterator<string> is(in_file);
istream_iterator<string> eof;
vector<string> text;
copy(is,eof,back_inserter(text));
sort(text.begin(),text.end());
ostream_iterator<string> os(out_file," ");
copy(text.begin(),text.end(),os);
}
- 《Essential C++》读书笔记(四)
- 《Essential C++》读书笔记(一)
- 《Essential C++》读书笔记(二)
- 《Essential C++》读书笔记(三)
- 《Essential C++》读书笔记(五)
- 《Essential C++》读书笔记(六)
- 《Essential C++》读书笔记(七)
- 《Essential C++》读书笔记(八)
- data model essential 之读书笔记(四)
- 《Essential C++》读书笔记
- essential c++读书笔记(1)
- Essential c++,泛型编程风格读书笔记
- C++Primer读书笔记(四)
- 《Effective C++》读书笔记(四)
- data model essential 之读书笔记(一)
- data model essential 之读书笔记(二)
- data model essential 之读书笔记(三)
- data model essential 之读书笔记(五)
- ssh 公钥方式认证攻略
- 获取SSID以及将账户名转换为字符串类型的SSID
- Maven 和 Ant 的区别
- VC++数据类型及大小
- Windows 8的意义,不仅仅是Metro
- 《Essential C++》读书笔记(四)
- ListView的用法
- sqlserver存储过程与即时查询的计划缓存
- android sharedpreferences 详解 代码 实例
- 生成静态页
- 【设计模式】之模板方法(Template Method)
- 什么是MVC以及PHP如何实现MVC .
- 限制 Domain User 加域设置
- 浅解用PHP实现MVC .