STL之适配器(adapter)

C++ STL函数适配器详解
本文深入探讨C++ STL中的函数适配器,包括bind()、mem_fn()、not1()、not2()和ptr_fun()的功能与用法。通过示例代码解释如何改变函数对象接口,使算法能调用成员函数,以及如何转换函数指针为函数对象。


一、适配器

定义

适配器是标准库中的一个通用概念。容器、迭代器和函数都有适配器。本质上,一个适配器是一种机制,能使某种事物的行为看起来像另外一种事物一样。

改变函数对象接口的称为 function adapter,改变容器接口的称为 container adapter,改变迭代器接口的称为 iterator adapter。

二、容器适配器

STL定义了3个顺序容器适配器:stack、queue和priority_queue。有关容器适配器的内容请参看STL之顺序容器

三、函数适配器

3.1、bind()

bind()接受一个可调用对象,生成一个新的可调用对象来"适应"原对象的参数列表。

调用bind的一般形式为:auto newCallable = bind(callable,arg_list);
其中,newCallable 本身是一个可调用对象,arg_list 是一个逗号分隔的参数列表,对应给定的 callable 的参数。即,当我们调用 newCallable 时,newCallable 会调用 callable,并传递给它 arg_list 中的参数。

arg_list 中的参数可能包含形如 _n 的名字,其中 n 是一个整数。这些参数是“占位符”,表示 newCallable 的参数,它们占据了传递给 newCallable 的参数的“位置”。数值 n 表示生成的可调用对象中参数的位置:_1 为 newCallable 的第一个参数,_2 为第二个参数,依此类推。

3.1.1、示例

例如: auto f2 = bind(f1,a,b,_2,_1);
这个bind调用会将 f2(_1,_2) 映射为 f1(a,b,_2,_1)。即对 f2 的调用会调用 f1,用f2的参数代替占位符,再加上绑定的参数a、b。

#include <iostream>
#include <functional>
using namespace std;
using namespace placeholders;

void fun1(string &str, int &i)
{
   
   
  cout << str << ' ' << i << endl;
}

auto fun2 = bind(fun1, _1, _2);

int main()
{
   
   
  string str("hello");
  int i = 0;
  fun2(str, i); //输出为:hello 0

  return 0;
}

3.1.2、重载函数

为了绑定重载函数的参数,必须显式说明绑定的是哪个版本的函数。
在这里插入图片描述

3.1.3、绑定引用参数

默认情况下,bind 的那些不是占位符的参数被拷贝到 bind 返回的可调用对象中。如果希望传递给 bind 一个对象而又不拷贝它,例如当参数为一个ostream,就必须使用标准库的 ref 函数。函数 ref 返回一个对象,包含给定的引用,此对象是可以拷贝的。标准库中还有一个 cref 函数,生成一个保存const引用的类。

使用方式: auto f2 = bind(f1,ref(os),_1);

3.2、mem_fn()

3.2.1、类的成员函数指针

对于类的成员函数指针,若想通过一个指向成员函数的指针进行函数调用,必须首先利用.* 运算符或 ->*运算符将该指针绑定到特定的对象上。因此与普通的函数指针不同,成员指针不是一个可调用对象,这样的指针不支持函数调用运算符

因为成员指针不是可调用对象,所以我们不能直接将一个指向成员函数的指针传递给算法。例如,如果我们想在一个 string 的 vector 中找到第一个空 string,不能使用下面的语句:

auto  fp = &string::empty;//fp指向string的empty函数
find_if(svec.begin(), svec.end(), fp);//错误,必须使用.*或->*调用成员指针

find_if 算法需要一个可调用对象,但我们提供给它的是一个指向成员函数的指针fp。因此在 find_if 的内部将执行如下形式的代码,从而导致无法通过编译:

if(fp(*it))    //错误:要想通过成员指针调用函数,必须使用->*运算符

显然该语句试图调用的是传入的对象,而非函数。

3.2.2、使用mem_fn生成一个可调用对象

mem_fn(mf) 生成一个函数对象,可以作为非成员函数调用。mem_fn()的主要用途是服务与需要非成员函数的算法。通过使用 mem_fn 可以从成员指针生成一个可调用对象,mem_fn 可以根据成员指针的类型推断可调用对象的类型,而无须用户显式地指定:

find_if(svec.begin(), svec.end(), 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Spring_24

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值