c++ 函数适配器,模板的运用:count_if,less,bind2nd,binder2nd

这篇博客探讨了C++中模板在函数适配器如count_if、less、bind2nd和binder2nd中的应用。内容涉及如何使仿函数适应STL体系,比较了C++98和C++11中less函数的不同实现方式,并提及C++11后bind2nd和binder2nd被弃用,取而代之的是更强大的bind函数。

下面这小小的一个函数,包含了模板的基本应用,学习标准库基本内容来提高对模板的认识。

#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);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值