下面这小小的一个函数,包含了模板的基本应用,学习标准库基本内容来提高对模板的认识。
#include <vector>
#include <iostream>
#include <functional>
#include <algorithm>
int main(int argc char** argv) {
std::vector<int> tmp_vac = {
3, 4, -6, 10, 2, -9
};
// 统计容器中小于0的数,当然可以自己简单的实现一个函数
int num = std::count_if(tmp_vac.begin(), tmp_vac.end(),
std::bind2nd(std::less<int>(),0));
std::cout << "There are " << num << " negative elements" << std::endl;
return 0;
}
// InputIterator 容器的迭代器,UnaryPredicate 需要一个参数的函数(仿函数)
template <class InputIterator, class UnaryPredicate>
// iterator_traits 迭代器萃取,迭代器需要定义5大类型
// difference_type 迭代器距离类型,可以看成 int 类型,但其实不是
typename iterator_traits<InputIterator>::difference_type
count_if (InputIterator first, InputIterator last, UnaryPredicate pred)
{
typename iterator_traits<InputIterator>::difference_type ret = 0;
while (first!=last) {
if (pred(*first)) ++ret;
++first;
}
return ret;
}
如果想要一个仿函数可以很好的融入stl体系里,需要定义参数类型和返回值类型。为什么需要这些内容内,主要是因为stl需要询问这些内容。
// 一个参数,一个返回值类型
template <class Arg, class Result>
struct unary_function {
typedef Arg argument_type;
typedef Result result_type;
};
// 两个参数,一个返回类型
template <class Arg1, class Arg2, class Result>
struct binary_function {
typedef Arg1 first_argument_type;
typedef Arg2 second_argument_type;
typedef Result result_type;
};
less函数,c++98和c++11有点区别,一个通过继承来定义第一个参数类型,第二个参数类型,以及返回值类型,一个自己定义,其实本质是一样;
// c++98
template <class T> struct less :
binary_function <T,T,bool> {
bool operator() (const T& x, const T& y) const {return x<y;}
};
// c++11
template <class T> struct less {
bool operator() (const T& x, const T& y) const {return x<y;}
typedef T first_argument_type;
typedef T second_argument_type;
typedef bool result_type;
};
// 继承一个参数
template <class Operation> class binder2nd
: public unary_function <typename Operation::first_argument_type,
typename Operation::result_type>
{
protected:
Operation op; // 保存操作
// 保存第二个参数数据
typename Operation::second_argument_type value;
public:
// 构造函数
binder2nd ( const Operation& x,
const typename Operation::second_argument_type& y)
: op (x), value(y) {}
// 重载()
typename Operation::result_type
operator() (const typename Operation::first_argument_type& x) const
{ return op(x,value); }
};
// 为什么需要这么一个函数呢? 主要是为了帮助我们推导Operation的类型,减少使用成本
template <class Operation, class T>
binder2nd<Operation> bind2nd (const Operation& op, const T& x)
{
//构建一个binder2nd类,就是一个重载()的仿函数
return binder2nd<Operation>(op,
typename Operation::second_argument_type(x));
}
在c++11之后,bind2nd和binder2nd已经废弃了,但是有一个更加强大的bind,这个比较复杂,还没有研究,如果后续研究再补充。
| simple(1) |
template <class Fn, class... Args> /* unspecified */ bind (Fn&& fn, Args&&... args); |
|---|---|
| with return type (2) |
template <class Ret, class Fn, class... Args> /* unspecified */ bind (Fn&& fn, Args&&... args); |
这篇博客探讨了C++中模板在函数适配器如count_if、less、bind2nd和binder2nd中的应用。内容涉及如何使仿函数适应STL体系,比较了C++98和C++11中less函数的不同实现方式,并提及C++11后bind2nd和binder2nd被弃用,取而代之的是更强大的bind函数。

1512

被折叠的 条评论
为什么被折叠?



