C++编程思想 第2卷 第6章 通用算法 函数对象 编写自己的函数对象适配器

开发者福利!热门AI工具限时免费用 购周边即赠Coding Plan Lite,Claude Code、Cursor等20+工具畅享,效率翻倍! 阅读详情

编写一个把表示浮点数的字符串转化为相应实际数字值的程序
有个创建字符串的发生器
 

//: C06:NumStringGen.h
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
// A random number generator that produces
// strings representing floating-point numbers.
#ifndef NUMSTRINGGEN_H
#define NUMSTRINGGEN_H
#include <cstdlib>
#include <string>

class NumStringGen {
  const int sz; // Number of digits to make
public:
  NumStringGen(int ssz = 5) : sz(ssz) {}
  std::string operator()() {
    std::string digits("0123456789");
    const int ndigits = digits.size();
    std::string r(sz, ' ');
    // Don't want a zero as the first digit
    r[0] = digits[std::rand() % (ndigits - 1)] + 1;
    // Now assign the rest
    for(int i = 1; i < sz; ++i)
      if(sz >= 3 && i == sz/2)
        r[i] = '.'; // Insert a decimal point
      else
        r[i] = digits[std::rand() % ndigits];
    return r;
  }
};
#endif // NUMSTRINGGEN_H ///:~


使用NumStringGen来填写一个vector<string>
要使用标准C库函数atof()来把字符串转换为浮点数型
string类型对象必须首先转化为char类型指针
这是因为从string到char*没有自动类型转换

//: C06:MemFun3.cpp
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
// Using mem_fun().
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <functional>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
#include "NumStringGen.h"
using namespace std;

int main() {
  const int SZ = 9;
  vector<string> vs(SZ);
  // Fill it with random number strings:
  srand(time(0)); // Randomize
  generate(vs.begin(), vs.end(), NumStringGen());
  copy(vs.begin(), vs.end(),
    ostream_iterator<string>(cout, "\t"));
  cout << endl;
  const char* vcp[SZ];
  transform(vs.begin(), vs.end(), vcp,
    mem_fun_ref(&string::c_str));
  vector<double> vd;
  transform(vcp, vcp + SZ, back_inserter(vd),
    std::atof);
  cout.precision(4);
  cout.setf(ios::showpoint);
  copy(vd.begin(), vd.end(),
    ostream_iterator<double>(cout, "\t"));
  cout << endl;
  getchar();
} ///:~


输出
48.87   71.75   20.40   78.39   17.11   87.56   38.51   40.74   63.00
48.87   71.75   20.40   78.39   17.11   87.56   38.51   40.74   63.00
做了两个转换:一是将C++字符串转换成C风格字符串 字符数组
另一个是通过atof()将C风格的字符串转换成数值

用两个函数作为参数并按合适的顺序应用它们

//: C06:ComposeTry.cpp
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
// A first attempt at implementing function composition.
#include <cassert>
#include <cstdlib>
#include <functional>
#include <iostream>
#include <string>
using namespace std;

template<typename R, typename E, typename F1, typename F2>
class unary_composer {
  F1 f1;
  F2 f2;
public:
  unary_composer(F1 fone, F2 ftwo) : f1(fone), f2(ftwo) {}
  R operator()(E x) { return f1(f2(x)); }
};

template<typename R, typename E, typename F1, typename F2>
unary_composer<R, E, F1, F2> compose(F1 f1, F2 f2) {
  return unary_composer<R, E, F1, F2>(f1, f2);
}

int main() {
  double x = compose<double, const string&>(
    atof, mem_fun_ref(&string::c_str))("12.34");
  assert(x == 12.34);
} ///:~

无异常对话框
unary_composer对象存储函数指针atof和string::c_str
在调用该对象的operator()时首先要应用后面的函数如果无需提供任何模板参数就更好了
这是对合适的函数对象坚持类型定义转换来完成

//: C06:ComposeFinal.cpp {-edg}
// From "Thinking in C++, Volume 2", by Bruce Eckel & Chuck Allison.
// (c) 1995-2004 MindView, Inc. All Rights Reserved.
// See source code use permissions stated in the file 'License.txt',
// distributed with the code package available at www.MindView.net.
// An adaptable composer.
#include <algorithm>
#include <cassert>
#include <cstdlib>
#include <functional>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
#include "NumStringGen.h"
using namespace std;

template<typename F1, typename F2> class unary_composer
: public unary_function<typename F2::argument_type,
                        typename F1::result_type> {
  F1 f1;
  F2 f2;
public:
  unary_composer(F1 f1, F2 f2) : f1(f1), f2(f2) {}
  typename F1::result_type
  operator()(typename F2::argument_type x) {
    return f1(f2(x));
  }
};

template<typename F1, typename F2>
unary_composer<F1, F2> compose(F1 f1, F2 f2) {
  return unary_composer<F1, F2>(f1, f2);
}

int main() {
  const int SZ = 9;
  vector<string> vs(SZ);
  // Fill it with random number strings:
  generate(vs.begin(), vs.end(), NumStringGen());
  copy(vs.begin(), vs.end(),
    ostream_iterator<string>(cout, "\t"));
  cout << endl;
  vector<double> vd;
  transform(vs.begin(), vs.end(), back_inserter(vd),
    compose(ptr_fun(atof), mem_fun_ref(&string::c_str)));
  copy(vd.begin(), vd.end(),
    ostream_iterator<double>(cout, "\t"));
  cout << endl;
  getchar();
} ///:~


输出
67.40   94.88   84.55   87.11   82.76   14.23   52.16   95.76   38.92
67.4    94.88   84.55   87.11   82.76   14.23   52.16   95.76   38.92

再次使用typename来使编译器知道涉及的成员是一个嵌套类型

一些实现将函数对象的组合作为一个扩展来支持
 

STL算法——函数对象适配器 函数适配器bind1st bind2nd 现在我有这个需求 在遍历容器的时候,我希望将容器中的值全部加上100之后显示出来,怎么做? 我们直接给函数对象绑定参数 编译阶段就会报错 for_each(v.begin(), v.end(), bind2nd(myprint(),100)); 如果我们想使用绑定适配器,需要我们自己的函数对象继承binary_function或者 unary_function 根据我们函数对象是一元函数对象 还是二元函数对象 class MyPrint :public bina 阅读详情

相关推荐

C++,STL 六大组件:容器、迭代器、算法函数对象适配器、分配器

C++ 标准模板库(Standard Template Library, STL)是泛型编程的典范,其核心思想是通过高度抽象的组件实现数据结构和算法的解耦。STL 的成功离不开其六大核心组件的协同工作:容器(Containers)、迭代器(Iterators)、算法(Algorithms)、函数对象(Functors)、适配器(Adapters)和分配器(Allocators)。这些组件各司其职,共同构建了一个高效、灵活且通用的编程框架。本文将深入解析这六大组件的功能、用法及其相互关系。

汽车电子软件领域知识分享 1469

关于cpp中copy的用法

在百度知道里面看到的一个关于copy回答: ---------------------------------------------------------------------------------------------------------------------------------------------------- ostream_iterator output(c

追求无止尽 2124

FPGA中Verilog HDL/VHDL实现NCO(数字控制振荡器)的查表法优化与性能分析

本文深入探讨了在FPGA中使用Verilog HDL/VHDL实现数字控制振荡器(NCO)的查表法优化与性能分析。文详细解析了NCO的核心工作原理,包括相位累加器、查找表(ROM)的设计,并重点介绍了利用波形对称性压缩ROM、相位抖动注入等关键优化技巧,以提升无杂散动态范围(SFDR)并平衡速度、精度与资源消耗。

vscode6remote的博客 444

STL学习(19):排序及相关操作

排序 第n个元素 二分检索 归并 序结构上的集合操作 堆操作 最大和最小 词典比较 排列生成器 数值算法 自定义STL函数 主要函数如下所示。 序号 功能 函数名称 说明 1 排序 Sort 以很好的平均效率排序 ...

QQ2558030393的博客 276

C++函数对象operator()

函数对象:定义了调用操作符()的类对象。当用该对象调用此操作符时,其表现形式如同普通函数调用一般,因此取名叫函数对象。举个最简单的例子: class A { public: int operator() ( int val ) { return val > 0 ? val : -val; } }; 类A中定义了操作符 ( ),A

summer 3万+

C++】STL 算法 ⑩ ( 函数适配器 | 函数适配器概念 | 函数适配器分类 | 函数适配器辅助函数 | std::bind2nd 函数原型及示例 | std::bind 函数原型及示例 )

一、函数适配器简介 1、函数适配器概念 2函数适配器分类 3、函数适配器辅助函数 二、函数适配器使用示例 - std::bind2nd 函数 1、std::bind2nd 函数原型 2、代码示例 - std::bind2nd 函数 三、函数适配器使用示例 - std::bind 函数 1、std::bind 函数原型 2、代码示例 - std::bind 函数

让 学习 成为一种 习惯 ( 韩曙亮 の 技术博客 ) 2858

c++ STL 仿函数适配器算法常用)

stl谓词理解,结合容器、算法、以及函数适配器的使用

hutaotaotao的博客 1588

C++编程思想26 通用算法 函数对象 函数指针适配器

算法无论在什么地方都要求一个类似函数的实体 系统可以提供一个指向普通函数或是一个函数对象的指针 当算法通过函数指针调用时 就启用了本地的函数调用机制用ptr_fun() 来封装一个一元函数 //: C06:PtrFun1.cpp // From "Thinking in C++, Volume 2", by Bruce Eckel &amp; Chuck Allison. // (c) 199...

eyetired的博客 311

c++中的函数适配器

函数适配器 函数适配器概念 STL中定义了大量的函数对象,但是有时候需要对函数返回值进行进一步的简单计算,或者填上多余的参数,不能直接代入算法函数适配器实现了这一功能,将一种函数对象转化为另一种符合要求的函数对象函数适配器可以分为4大类,绑定适配器,组合适配器,指针函数适配器和成员函数适配器 直接构造STL中的函数适配器通常会导致冗长的类型声明。为简化安徽念书适配器的构造,STL还提供了函数...

LXY的博客 2511

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

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

zhyjhacker的博客 1019

C++深入学习之STL:2适配器、迭代器与算法部分

迭代器是一种设计模式,用于遍历容器中的元素而不需要知道容器的底层表示方式。C++标准模板库(STL)中的迭代器允许程序员通过迭代器来访问和操作容器中的元素,而不是直接使用指针。迭代器具有以下特性:1、双向访问:迭代器允许你通过++和–运算符向前或向后遍历容器中的元素。2、随机访问:某些迭代器(如std::vector::iterator)还允许你通过索引操作符([])直接访问特定位置的元素。3、关联容器:关联容器(如std::map和std::set)的迭代器通常也支持基于键的访问。

qq_53324833的博客 1349

[STL]容器小结+函数对象+谓词+内建函数对象+函数对象适配器+算法(汇总)

总结了1 各容器的特点总结及使用场景 2 各个容器的使用场景3 函数对象4 谓词5 内建函数对象 6 函数对象适配器 7 算法几大部分

weixin_44972997的博客 1546

C++ STL(十一):适配器函数对象适配器、取反适配器函数指针适配器、成员函数适配器

目录1 函数对象适配器 1 函数对象适配器 作用:修饰函数对象/仿函数,提供适配功能。 问题案例: 使用for_each算法函数对象/仿函数遍历容器的元素时: ①若希望原容器元素经某种运算(如与给定值100进行加法运算)后,再输出运算结果; ②给定值可作为operator()函数的参数传递(如由用户键盘输入,而非在operator()函数体内使用固定值100); ③for_each(iterator begin, iterator end, _Fn _Func)函数只支持3个参数,且第3个参数需传入

NewsomTech 1273

【第九天】C++函数对象/仿函数、谓词、适配器及常见algorithm算法

重载了函数调用运算符()的类 实例化的对象函数对象,也叫仿函数。 如果函数对象 有一个参数 叫:一元函数对象/仿函数 如果函数对象 有二个参数 叫:二元函数对象/仿函数 如果函数对象 有三个及以上参数 叫:多元函数对象/仿函数

m0_75045191的博客 1065

35 C++ STL模板库4-函数适配器

本文介绍了C++ STL中的函数适配器,重点讲解了三种绑定器:bind1st、bind2nd和bind。前两者已弃用,用于将二元函数对象转换为一元函数对象;bind更灵活,可绑定任意参数位置和类型,支持函数、成员函数和Lambda。文详细说明了bind的用法,包括占位符(_1,_2等)的使用、参数绑定规则和注意事项,特别强调了函数重载时需显式指定类型。通过多个代码示例展示了不同绑定方式的输出结果,帮助理解参数绑定和占位符的工作机制。

17208955的博客 1102

C++函数对象适配器及其底层原理

函数对象适配器 bind1st bind2nd 函数对象适配器用于扩展函数对象的功能,提供额外传入参数的方法。 例如,我现在有一个一元谓词: class Pred { public: bool operator()(int a) { // ... } }; 现在调用某算法,该算法会使用这个一元谓词。 algorithm(..., ..., Pred()); 但与此同时,我们希望这个谓词可以额外实现一个功能,而这个功能依赖一个临时传入的参数。 于是改了谓词的实现: b

高厉害 0w0 432

STL之函数对象适配器、取反适配器函数指针适配器、成员函数适配器的讲解运用

​ 简述: 对于 适配器函数对象适配器、取反适配器函数指针适配器、成员函数适配器,做一个讲解和小例子的应用,并且简单地探究一下原理。 文目录本博文的简述or解决问题?讲解大纲:函数对象适配器初始代码:使用步骤:代码演示:运行演示:细节方面:心得思考:取反适配器:初始代码:使用步骤:代码演示:运行演示:细节方面:心得思考:函数指针适配器:初始代码:使用步骤:代码演示:运行演示:细节方面:...

1572

C++迭代器、函数对象、STL算法

erase函数会返回一个新的迭代器,该迭代器指向被删除元素之后的第一个元素。如果被删除的是最后一个元素,则会返回end(),这样就保证了迭代器在整个循环过程中的有效性。bind是一种通用绑定机制,它可以将一个可调用对象(如函数函数指针、lambda表达式等)的参数进行绑定,生成一个新的可调用对象。end()返回一个指向超尾位置的迭代器,即最后一个元素的下一个位置。同样的,insert函数也会返回一个迭代器,该迭代器指向插入序列的第一个元素。C++的STL中提供了一系列的算法,用于执行各种常见的数据操作。

2301_82023822的博客 1281

[C++]STL-函数对象适配器

函数对象适配器是完成一些配接工作,这些配接包括绑定(bind),否定(negate),以及对一般函数或成员函数的修饰,使其成为函数对象 bind1st:将参数绑定为函数对象的第一个参数 bind2nd:将参数绑定为函数对象的第二个参数 not1:对一元函数对象取反 not2:对二元函数对象取反 ptr_fun:将普通函数修饰成函数对象 mem_fun:修饰成员函数 mem_fun_ref:修饰成员...

renboyu010214的博客 395

函数对象函数适配器

函数对象函数适配器标准库还提供了一组函数适配器用来特殊化或者扩展一元和二元函数对象适配器是一种特殊的类它被分成下面两类1 绑定器binder binder 通过把二元函数对象的一个实参绑定到一个特殊的值上将其转换成一元函数对象例如为了计数一个容器中小于或等于10 的元素的个数我们可能会向count_if()传递一个less_equal 函数对象以及一个被绑定为10 的实参在下一节中我们将了解怎样

DX 1116
上一篇: C++编程思想 第2卷 第6章 通用算法 函数对象 函数指针适配器
下一篇: C++编程思想 第2卷 第6章 通用算法 STL算法目录 实例创建的支持工具
eyetired
博客等级 码龄8年 52粉丝 931原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值