STL源码剖析 第七章 仿函数(函数对象)

53 篇文章 1 订阅
31 篇文章 2 订阅
  • 函数对象:具有函数性质的对象
  • 使得用户像使用函数一样使用它
  • 一般函数提供两个版本,第一个版本使用operator < ;第二版本需要用户 指定某种操作
  • 第二版本就是设计一个函数,将函数指针作为算法的一个参数;或者将函数操作设计成为一个仿函数,就语言层面是一个class,再以该仿函数产生一个对象,并以此对象作为算法的一个参数
  • 函数指针就可以完成任务,为啥需要引入 函数对象呢?因为函数指针无法满足STL对抽象性的要求,也无法适配STL的其余组件(适配器)搭配,产生灵活的变化
  • 仿函数就是行为类似函数的对象,为了实现这个功能点,其类别定义中必须自定义(改写或者重载)function call运算子(operator() ),这样就可以在函数的对象后面加上一对小括号,以此来调用函数所定义的 operator() 

 分类

  • 操作个数:一元、二元
  • 功能划分:算法运算、关系运算、逻辑运算

unary_function

  • 用于呈现一元函数的参数型别 和 返回值的型别
//STL规定 每一个Adaptable Unary Function都应该继承这个型别
template <class Arg,class Result>
struct unary_function{
    typedef Arg argument_type;
    typedef Result result_type;
};
  • 某一个仿函数继承了 unary_function ,其用户便可以获取这个仿函数的参数型别
//以下函数继承了unary_function
template <class T>
struct negate : public unary_function<T,T>{
    T operator()(const T& x)const {return -x;}
};

//以下配接器(adapter) 用来表示某个仿函数的逻辑
template <class Predicate>
class ungry_negate{
public:
    bool operator()(const typename Predicate::argument_type& x)const{
        
    }
};

 binary_function

  • 用于呈现二元函数的第一参数型别、第二参数型别和返回数值型别

//STL规定 每一个Adaptable Binary Function都应该继承这个型别
template <class Arg1,class Arg2,class Result>
struct binary_function{
    typedef Arg1 first_argument_type;
    typedef Arg2 second_argument_type;
    typedef Result result_type;
};

//以下函数继承了unary_function
template <class T>
struct plus : public binary_function<T,T,T>{
    T operator()(const T& x,const T&y)const {return x+y;}
};

//以下配接器(adapter) 用来将某个二元函数转化为一元函数
template <class Operation>
class binder1st{
protected:
    Operation op;
    typedef typename Operation::first_argument_type value;
public:
    typename Operation::result_type operator()
    (const typename Operation::second_argument_type& x)const{

    }
};

算数类仿函数

  • 加法、减法、乘法、除法、模(余数)、否
  • 除了否是一元函数,其余的都是二元函数
  • 加法  plus<T>
template <class T> struct plus {
  T operator() (const T& x, const T& y) const {return x+y;}
  typedef T first_argument_type;
  typedef T second_argument_type;
  typedef T result_type;
};
// plus example
#include <iostream>     // std::cout
#include <functional>   // std::plus
#include <algorithm>    // std::transform

int main () {
  int first[]={1,2,3,4,5};
  int second[]={10,20,30,40,50};
  int results[5];
  std::transform (first, first+5, second, results, std::plus<int>());
  for (int i=0; i<5; i++)
	std::cout << results[i] << ' ';
  std::cout << '\n';
  return 0;
}
  • 减法  minus<T>
template <class T> struct minus {
  T operator() (const T& x, const T& y) const {return x-y;}
  typedef T first_argument_type;
  typedef T second_argument_type;
  typedef T result_type;
};
// minus example
#include <iostream>     // std::cout
#include <functional>   // std::minus
#include <algorithm>    // std::transform

int main () {
  int numbers[]={10,20,30};
  int result;
  result = std::accumulate (numbers, numbers+3, 100, std::minus<int>());
  std::cout << "The result of 100-10-20-30 is " << result << ".\n";
  return 0;
}
  • 乘法  multiplies<T>
template <class T> struct multiplies {
  T operator() (const T& x, const T& y) const {return x*y;}
  typedef T first_argument_type;
  typedef T second_argument_type;
  typedef T result_type;
};
// factorials (multiplies example)
#include <iostream>     // std::cout
#include <functional>   // std::multiplies
#include <numeric>      // std::partial_sum

int main () {
  int numbers[9];
  int factorials[9];
  for (int i=0;i<9;i++) numbers[i]=i+1;
  std::partial_sum (numbers, numbers+9, factorials, std::multiplies<int>());
  for (int i=0; i<9; i++)
    std::cout << numbers[i] << "! is " << factorials[i] << '\n';
  return 0;
}
 Edit & Run
  • 除法  divides<T>
template <class T> struct divides {
  T operator() (const T& x, const T& y) const {return x/y;}
  typedef T first_argument_type;
  typedef T second_argument_type;
  typedef T result_type;
};
// divides example
#include <iostream>     // std::cout
#include <functional>   // std::divides
#include <algorithm>    // std::transform

int main () {
  int first[]={10,40,90,40,10};
  int second[]={1,2,3,4,5};
  int results[5];
  std::transform (first, first+5, second, results, std::divides<int>());
  for (int i=0; i<5; i++)
    std::cout << results[i] << ' ';
  std::cout << '\n';
  return 0;
}
  • 模(余数)  modules<T>
template <class T> struct modulus {
  T operator() (const T& x, const T& y) const {return x%y;}
  typedef T first_argument_type;
  typedef T second_argument_type;
  typedef T result_type;
};
// modulus example
#include <iostream>     // std::cout
#include <functional>   // std::modulus, std::bind2nd
#include <algorithm>    // std::transform

int main () {
  int numbers[]={1,2,3,4,5};
  int remainders[5];
  std::transform (numbers, numbers+5, remainders, std::bind2nd(std::modulus<int>(),2));
  for (int i=0; i<5; i++)
    std::cout << numbers[i] << " is " << (remainders[i]==0?"even":"odd") << '\n';
  return 0;
}
  • 否  negate<T>
template <class T> struct negate {
  T operator() (const T& x) const {return -x;}
  typedef T argument_type;
  typedef T result_type;
};
// negate example
#include <iostream>     // std::cout
#include <functional>   // std::negate
#include <algorithm>    // std::transform

int main () {
  int numbers[]={10,-20,30,-40,50};
  std::transform (numbers, numbers+5, numbers, std::negate<int>());
  for (int i=0; i<5; i++)
    std::cout << numbers[i] << ' ';
  std::cout << '\n';
  return 0;
}
  • 可以创建一个指定类型的对象或者产生一个无名的临时对象来履行对应的函数的功能

证同元素

  •  即数值A如果和该元素做op运算,会得到A自己
  • 加法的证同元素为0,因为任何元素加上0仍然是他自己
  • 乘法的证同元素是1 ,因为任何元素乘以1仍然是他自己

关系运算类仿函数

  •  等于 equal_to<T>
template <class T> struct equal_to {
  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;
};


// equal_to example
#include <iostream>     // std::cout
#include <utility>      // std::pair
#include <functional>   // std::equal_to
#include <algorithm>    // std::mismatch

int main () {
  std::pair<int*,int*> ptiter;
  int foo[]={10,20,30,40,50};
  int bar[]={10,20,40,80,160};
  ptiter = std::mismatch (foo, foo+5, bar, std::equal_to<int>());
  std::cout << "First mismatching pair is: " << *ptiter.first;
  std::cout << " and " << *ptiter.second << '\n';
  return 0;
}
  • 不等于 not_equal_to<T>
template <class T> struct not_equal_to {
  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;
};


// not_equal_to example
#include <iostream>     // std::cout
#include <functional>   // std::not_equal_to
#include <algorithm>    // std::adjacent_find

int main () {
  int numbers[]={10,10,10,20,20};
  int* pt = std::adjacent_find (numbers, numbers+5, std::not_equal_to<int>()) +1;
  std::cout << "The first different element is " << *pt << '\n';
  return 0;
}
  • 大于 greater<T>
template <class T> struct greater {
  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;
};

// greater example
#include <iostream>     // std::cout
#include <functional>   // std::greater
#include <algorithm>    // std::sort

int main () {
  int numbers[]={20,40,50,10,30};
  std::sort (numbers, numbers+5, std::greater<int>());
  for (int i=0; i<5; i++)
    std::cout << numbers[i] << ' ';
  std::cout << '\n';
  return 0;
}
  • 大于等于 greater_equal<T>
template <class T> struct greater_equal {
  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;
};


// greater_equal example
#include <iostream>     // std::cout
#include <functional>   // std::greater_equal, std::bind2nd
#include <algorithm>    // std::count_if

int main () {
  int numbers[]={20,-30,10,-40,0};
  int cx = std::count_if (numbers, numbers+5, std::bind2nd(std::greater_equal<int>(),0));
  std::cout << "There are " << cx << " non-negative elements.\n";
  return 0;
}
  • 小于 less<T>
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;
};


// less example
#include <iostream>     // std::cout
#include <functional>   // std::less
#include <algorithm>    // std::sort, std::includes

int main () {
  int foo[]={10,20,5,15,25};
  int bar[]={15,10,20};
  std::sort (foo, foo+5, std::less<int>());  // 5 10 15 20 25
  std::sort (bar, bar+3, std::less<int>());  //   10 15 20
  if (std::includes (foo, foo+5, bar, bar+3, std::less<int>()))
    std::cout << "foo includes bar.\n";
  return 0;
}
  • 小于等于 less_equal<T>
template <class T> struct less_equal {
  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;
};


// less_equal example
#include <iostream>     // std::cout
#include <functional>   // std::less_equal, std::bind2nd
#include <algorithm>    // std::count_if

int main () {
  int numbers[]={25,50,75,100,125};
  int cx = std::count_if (numbers, numbers+5, std::bind2nd(std::less_equal<int>(),100));
  std::cout << "There are " << cx << " elements lower than or equal to 100.\n";
  return 0;
}

逻辑运算类仿函数

  •  and or Not 
  • and 和 or是二元运算符号 Not是一元符号
  • and  logic_and<T>
template <class T> struct logical_and {
  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;
};


// logical_and example
#include <iostream>     // std::cout, std::boolalpha
#include <functional>   // std::logical_and
#include <algorithm>    // std::transform

int main () {
  bool foo[] = {true,false,true,false};
  bool bar[] = {true,true,false,false};
  bool result[4];
  std::transform (foo, foo+4, bar, result, std::logical_and<bool>());
  std::cout << std::boolalpha << "Logical AND:\n";
  for (int i=0; i<4; i++)
    std::cout << foo[i] << " AND " << bar[i] << " = " << result[i] << "\n";
  return 0;
}
  • or    logic_or<T>
template <class T> struct logical_or {
  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;
};


// logical_or example
#include <iostream>     // std::cout, std::boolalpha
#include <functional>   // std::logical_or
#include <algorithm>    // std::transform

int main () {
  bool foo[] = {true,false,true,false};
  bool bar[] = {true,true,false,false};
  bool result[4];
  std::transform (foo, foo+4, bar, result, std::logical_or<bool>());
  std::cout << std::boolalpha << "Logical OR:\n";
  for (int i=0; i<4; i++)
    std::cout << foo[i] << " OR " << bar[i] << " = " << result[i] << "\n";
  return 0;
}
  • not   logical_not<T>
template <class T> struct logical_not {
  bool operator() (const T& x) const {return !x;}
  typedef T argument_type;
  typedef bool result_type;
};


// logical_not example
#include <iostream>     // std::cout, std::boolalpha
#include <functional>   // std::logical_not
#include <algorithm>    // std::transform

int main () {
  bool values[] = {true,false};
  bool result[2];
  std::transform (values, values+2, result, std::logical_not<bool>());
  std::cout << std::boolalpha << "Logical NOT:\n";
  for (int i=0; i<2; i++)
    std::cout << "NOT " << values[i] << " = " << result[i] << "\n";
  return 0;
}

证同、选择、投射

  • 这一章节的仿函数只是将参数原封不动的传回
  • 其中某些仿函数对传回的参数有刻意的选择 、或者刻意的忽略

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值