仿函数适配器

  • 访函数可适配的条件:继承自unary_function或binary_function,这样这个访函数就有了关于参数和返回值的typedef,当通过仿函数adapter对该仿函数进行改造时,就能正确的回答adapter所需的typedef;同时仿函数适配器也要根据自己接受的参数数量继承unary_function或binary_function,用于支持多层的改造;
    在这里插入图片描述
  • 仿函数adapter:
//bind2nd只是将待改造的仿函数less<int>()和40保存到binder2nd的数据成员中
//当算法真正执行到调用bind2nd(less<int>(), 40)时,由于binder2nd重载了operator(), 此时在operator()中才发生参数绑定,执行op(x, value), 即将保存的40替换为less<int>的第二参数
count_if(vi.begin(), vi.end(), bind2nd(less<int>(), 40)); 

在这里插入图片描述
上图中bind2nd改造less()的详细过程如下:

上图中,传入bind2nd两个参数less<int>()40,因为函数模版有实参推导,因此编译器会推出类型Operation和T,如果Operator继承自unary_function或者binary_function,就代表此Operator是可适配的,bind2nd就能从Operator中知道arg2_type。
然后bind2nd将实际工作交给binder2nd,通过指定推出的Operator模版参数创建一个binder2nd对象,就会调用其构造函数,进而把参数op和arg2_type(x)保存在binder2nd的数据成员op和value中。当算法执行到pred(*first)时,因为binder2nd重载了operator()运算符,此时才会发生参数绑定,即用保存的value替换为op的第二参数,执行op(x,value)

下图中not1改造bin2nd(less(), 40)的详细过程如下:

上面已经介绍了bind2nd改造的过程,改造之后bind2nd(less<int>(), 40)就变成了一个新的仿函数,并被not1改造,下面将其作为一个整体介绍not1改造的过程;
由于not1是个函数模板,通过实参推导得到类型Predicate,并将其指定为unary_negate class的模板参数,指定参数为pred(即bind2nd改造后的仿函数),调用unary_negate的构造函数将其保存在数据成员pred中;
等到算法count_if真正执行到pred(*first)时,调用unary_negate的重载的operator(),这时才使用保存在数据成员中的x,执行!pred(x)动作;
为了继续支持改造,unary_negate的operator()只接收一个参数,因此也要继承unary_function

在这里插入图片描述

  • 新版本应使用bind作参数绑定:
auto nf = bind(待改造的仿函数f, f的参数列表);//f被改造会得到一个新的仿函数nf;
f的参数列表按顺序表示f的参数;
用_1,_2等占位符表示调用nf时传入的参数,
想被绑定参数直接写在f的参数列表中想被替换的位置;

猜你喜欢

转载自blog.csdn.net/jiuri1005/article/details/114627327