- 论坛徽章:
- 2
|
本帖最后由 OwnWaterloo 于 2012-03-03 12:40 编辑
回复 1# asker160
你与donet8、jeanlove_cu之间有神马基情…… 怎么都在用这段代码……
istream_iterator、vector、greater是类模板,copy、back_inserter、sort是函数模板。
函数模板可以根据函数实际参数推导出模板实际参数,但不一定总是能成功。
比如:
- template<typename T>
- T max(T a, T b) { return a<b? b: a; }
- max(12,26); // 两个实际参数类型都是int, 可以推导出这是max<int>(12,26);
- max<int>(12,26); // 或者也可以显式指定
- max(12,2.6); // 一个实际参数是int,另一个是double,于是无法推导出T
- max<int>(12,2.6); // 必须显式指定, 相当于 max(12,static_cast<int>(2.6));
- max<double(12,2.6); // 或者 max(static_cast<double>(12), 2.6);
- max<double>(12,26); // 即使能推导出,也可以显示指定
复制代码 12,26,2.6是函数的实际参数,int,double是模板的实际参数。
而类模板没有前者,所以没法通过前者推导出后者,只能显式写出模板实际参数。
于是有种技巧…… 最简单的例子是std:: pair。
- map<int,int> m;
- m.insert(pair<int,int>(12,26) ); // pair是类模板,必须显式写出实际模板参数
- m.insert(make_pair(12,26) ); // make_pair是函数模板, 可以通过函数实际参数推导
复制代码 make_pair的实现类似于:
- template<typename T,typename U>
- pair<T,U> make_pair(T a, U b) { // 通过函数参数a,b推导出类型参数T,U
- return pair<T,U>(a,b);
- }
复制代码 除了make_pair,back_inserter那一坨也是这种技巧中的函数模板, 类似的还有bind那一坨, ptr_fun神马的……
istream_iterator也可以这么搞…… 不过与pair/make_pair有区别……
pair<int,int>(12,26); // 两个函数实际参数分别对应两个模板实际参数, 后者的信息可以由前者提供。
于是可以 make_pair(12,26);
istream_iterator<int>(); // eof 没有实际参数
istream_iterator<int>(cin); // cin 只能提供source信息 —— 从哪获取数据, 无法提供格式信息 —— 将一系列字符解释为int。
可以类似地实现(但STL里没有):
make_istream_iterator(0);
make_istream_iterator(cin,0);
0仅仅协助make_istream_iterator推导模板参数,make_istream_iterator函数并不使用这个参数。
而sort,STL那个3参数的重载类似这样:
- template<typename RanIt,typename F>
- void sort(RanIt beg, RanIt end, F cmp) {
- ...
- cmp(a,b);
- ...
- }
- bool great(int a, int b) { return a>b; }
- sort(v.begin(), v.end(), great); // 可以推导出F=bool (*)(int,int)
复制代码 但greater不行,它是一个类模板。类模板不能作为实际参数。
就算是greater<int> 都不行, 不能将类型作为函数实际参数进行函数调用。类似于可以max(12,26),但不能max(int,26);
所以要greater<int>(), 这才是一个值, 可以作为函数实际参数, 推导出F=greater<int>。
也许可以另外实现一个:
sort_by<greater>(v.begin(), v.end() );
先不说究竟能不能实现, 我有点忘了…… 总之这与两参数的sort(v.begin(), v.end() ); 冲突, 得换个名字 sort_by, 而且STL也没有提供这个。
|
|