C++ primer plus 第16章string 类和标准模板库, 自适应函数符和函数适配器

C++ primer plus 第16章string 类和标准模板库, 自适应函数符和函数适配器

C++ primer plus 第16章string 类和标准模板库, 自适应函数符和函数适配器


16.5.3自适应函数符和函数适配器

表16.12列出的预定义函数符都是自适应的。实际上STL有5个相关的概念:自适应生成器(adaptablegenerator)、自适应一元函数(adaptable unary function)、自适应二元函数(adaptable binary function)、自适应谓词(adaptable predicate)和自适应二元谓词(adaptable binary predicate)。

使函数符成为自适应的原因是,它携带了标识参数类型和返回类型的typedef成员。这些成员分别是result type、first argument type和 second argument type,它们的作用是不言自明的。例如,plus对象
的返回类型被标识为 plus::result type,这是 int 的typedef。

函数符自适应性的意义在于:函数适配器对象可以使用函数对象,并认为存在这些typedef成员。例如,接受一个自适应函数符参数的函数可以使用 result_type 成员来声明一个与函数的返回类型匹配的变量。

STL提供了使用这些工具的函数适配器类。例如,假设要将矢量gr8的每个元素都增加 2.5 倍,则需要使用接受一个一元函数参数的transform()版本,就像前面的例子那样:
transform(gr8,begin(),gr8.end(),out,sqrt);
multiplies()函数符可以执行乘法运行,但它是二元函数。因此需要一个函数适配器,将接受两个参数的函数符转换为接受1个参数的函数符。前面的TooBig2示例提供了一种方法,但STL使用 binderlst 和binder2nd 类自动完成这一过程,它们将自适应二元函数转换为自适应一元函数。
来看 binderlst。假设有一个自适应二元函数对象f2(),则可以创建一个 binderlst 对象,该对象与一个将被用作 f2()的第一个参数的特定值(val)相关联:
binderlst(f2,val)fl;这样,使用单个参数调用 f1(x)时,返回的值与将 val 作为第一参数、将 f()的参数作为第二参数调用12()返回的值相同。即 “(x)等价于f2(val,x),只是前者是一元函数,而不是二元函数。f2()函数被适配。
同样,仅当12()是一个自适应函数时,这才能实现。看上去有点麻烦。然而,STL提供了函数 bindlst(),以简化 binderlst 类的使用。可以问其提供用于构建 binderlst对象的函数名称和值,它将返回一个这种类型的对象。例如,要将二元函数 multiplies()转换为将参数乘以2.5的一元函数,则可以这样做:

bindlst(multipliessdouble>()2.5)

因此,将 gr8 中的每个元素与 2.5 相乘,并显示结果的代码如下:transform(gr8.begin(),gr8.end(),out,

bindlst(multiplies<double>()2.5));

binder2nd 类与此类似,只是将常数赋给第二个参数,而不是第一个参数。它有一个名为 bind2nd 的助手函数,该函数的工作方式类似于 bindlst。
程序清单16.16将一些最近的示例合并成了一个小程序。

程序清单16.16 funadap.cpp

// funadap.cpp -- using function adapters
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
#include <functional>

void Show(double);
const int LIM = 6;
int main()
{
    using namespace std;
    double arr1[LIM] = {28, 29, 30, 35, 38, 59};
    double arr2[LIM] = {63, 65, 69, 75, 80, 99};
    vector<double> gr8(arr1, arr1 + LIM);
    vector<double> m8(arr2, arr2 + LIM);
    cout.setf(ios_base::fixed);
    cout.precision(1);
    cout << "gr8:\t";
    for_each(gr8.begin(), gr8.end(), Show);
    cout << endl;
    cout << "m8: \t";
    for_each(m8.begin(), m8.end(), Show);
    cout << endl;

    vector<double> sum(LIM);
    transform(gr8.begin(), gr8.end(), m8.begin(), sum.begin(),
              plus<double>());
    cout << "sum:\t";
    for_each(sum.begin(), sum.end(), Show);
    cout << endl;

    vector<double> prod(LIM);
    transform(gr8.begin(), gr8.end(), prod.begin(),
              bind1st(multiplies<double>(), 2.5));
    cout << "prod:\t";
    for_each(prod.begin(), prod.end(), Show);
    cout << endl;
    // cin.get();
    return 0; 
}

void Show(double v)
{
    std::cout.width(6);
    std::cout << v << ' '; 
}

C++11提供了函数指针和函数符的替代品–lambda表达式,这将在第18章讨论。

  • 11
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值