一:适配器简介

  1. C++中有三类适配器,分别是容器适配器迭代器适配器函数适配器,这里主要介绍函数适配器

(一)函数适配器简介

  1. STL中已经定义了大量的函数对象,但是有时候需要对函数返回值进行进一步的简单计算,或者填上多余的参数,
    才可以带入其他的算法中进行下一步数据处理,不能直接带入算法。
  1. 函数适配器就实现了这一功能:将一种函数对象转化为另外一种符合要求的函数对象
  1. 函数适配器可以分为4大类:
    绑定适配器(bind adaptor),
    组合适配器(composite adaptor),
    指针函数适配器(pointer adaptor),
    成员函数适配器(member function adaptor

(二)绑定适配器(bind adaptor)

(三)组合适配器(composite adaptor)

(四) 指针函数适配器(pointer adaptor)

(五)成员函数适配器(member function adaptor)

二:函数适配器辅助函数

  1. 直接构造STL中的函数适配器通常会导致冗长的类型声明。---->之前说过模板函数和STL中类型是严格定义的,需要我们显式写出
  2. 为了简化函数适配器的构造,
    STL还提供了函数适配器辅助函数,借助于泛型自动推断技术,无需显式的类型声明便可以实现函数适配器的构造。

三:常用函数适配器

  1. 标准库提供一组函数适配器,用来特殊化或者扩展一元和二元函数对象。

(一)绑定器(binder): 将二元函数对象转一元函数对象

  1. binder通过把二元函数对象的一个实参绑定到一个特殊的值上,将其转换成一元函数对象。
    C++标准库提供两种预定义的binder适配器(适配器辅助函数)
    bind1stbind2nd,前者把值绑定到二元函数对象的第一个实参上,后者绑定在第二个实参上

(二)取反器(negator) : 操作谓词函数

  1. negator是一个将函数对象的值翻转的函数适配器
    标准库提供两个预定义的ngeator适配器(适配器辅助函数)
    not1翻转一元预定义函数对象的真值,而not2翻转二元谓词函数的真值。

(三)常用函数适配器案例:《重点》

1.使用绑定器和预定义函数对象

  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>
  4. #include <functional> //由于要使用到预定义函数对象,所以引入
  5.  
  6. using namespace std;
  7.  
  8. template<typename T>
  9. void ShowEle(const T& t) //用于打印容器数据
  10. {
  11. cout << t << " ";
  12. }
  1. int main()
  2. {
  3. vector<int> v1, v2, v3;
  4.  
  5. for (int i = ; i < ;i++)
  6. v1.push_back(rand() % ); //v1数据插入
  7.  
  8. //打印数据
  9. for_each(v1.begin(), v1.end(), ShowEle<int>);
  10. cout << endl;
  11.  
  12. int num = count_if(v1.begin(), v1.end(), bind2nd(greater<int>(), 2));
  13. cout << num << endl;
  14.  
  15. system("pause");
  16. return ;
  17. }

补充:count和count_if

  1. 1)count(first,last,value):first是容器的首迭代器,last是容器的末迭代器,value是询问的元素,整个函数返回int型。count函数的功能是:统计容器中等于value元素的个数。
  2.  
  3. 2)count_if(first,last,comp) (在comp为true的情况下计数) 或者 count_if(first,last,value,comp) (这个是在comp为true的情况下统计容器中等于value的元素):first为首迭代器,last为末迭代器,value为要查询的元素,comp为比较bool函数,为true则计数,函数返回型是int。
  4.  
  5. 注:此两个函数复杂度是线性的,适用于小规模运算。count_if更加灵活

2.使用自定义谓词和绑定器《重点》

  1. template<typename T>
  2. void ShowEle(const T& t) //用于打印容器数据
  3. {
  4. cout << t << " ";
  5. }
  6.  
  7. template<typename T>
  8. class Mygreater :public binary_function<T, T, bool>  //1.自定义谓词需要继承binary_function
  9. {
  10. public:
  11. bool operator() (const T& iLeft, const T& iRight) const  //2.重载()函数需要加上const,变为常函数
  12. {
  13. return (iLeft > iRight);//如果是实现less<int>的话,这边是写return (iLeft<iRight);
  14. }
  15. };
  16.  
  17. int main()
  18. {
  19. vector<int> v1, v2, v3;
  20.  
  21. for (int i = ; i < ;i++)
  22. v1.push_back(rand() % ); //v1数据插入
  23.  
  24. //打印数据
  25. for_each(v1.begin(), v1.end(), ShowEle<int>);
  26. cout << endl;
  27.  
  28. int num = count_if(v1.begin(), v1.end(), bind2nd(Mygreater<int>(), ));
  29. cout << num << endl;
  30.  
  31. system("pause");
  32. return ;
  33. }

  1. template<class _Ty = void>
  2. struct greater
  3. : public binary_function<_Ty, _Ty, bool>
  4. { // functor for operator>
  5. bool operator()(const _Ty& _Left, const _Ty& _Right) const
  6. { // apply operator> to operands
  7. return (_Left > _Right);
  8. }
  9. };

参照预定义函数greater

3.使用自定义二元函数对象和绑定器《重点》

  1. template<typename T>
  2. void ShowEle(const T& t) //用于打印容器数据
  3. {
  4. cout << t << " ";
  5. }
  6.  
  7. //自定义二元函数对象---数据相加
  8. template<typename T>
  9. class MySumAdd :public binary_function<T, T, int>
  10. {
  11. public:
  12. int operator()(const T& t1, const T& t2) const
  13. {
  14. return t1 + t2;
  15. }
  16. };
  17. int main()
  18. {
  19. vector<int> v1, v2, v3;
  20.  
  21. for (int i = ; i < ;i++)
  22. v1.push_back(rand() % ); //v1数据插入
  23.  
  24. //打印数据
  25. for_each(v1.begin(), v1.end(), ShowEle<int>);
  26. cout << endl;
  27.  
  28. v2.resize(10);
  29. //将v1中所有数据加2
  30. transform(v1.begin(), v1.end(), v2.begin(), bind2nd(MySumAdd<int>(), 2));
  31. //打印数据
  32. for_each(v2.begin(), v2.end(), ShowEle<int>);
  33. cout << endl;
  34.  
  35. system("pause");
  36. return ;
  37. }

总之:自定义的仿函数和函数配接器搭配使用时,要继承自template <...> unary_function    or   template <...> binary_function

  1. unary_function可以作为一个一元函数对象的基类,他定义了两个模板参数,分别是函数参数类型argument_type和返回值类型result_type,本身并不重载函数符(),由派生类去完成()操作符的重载工作。
  2. binary_function可以作为一个二元函数对象的基类,他定义了三个模板参数,两个函数参数类型first_argument_typesecond_argument_type,以及返回值类型result_type,本身并不重载函数符(),由派生类去完成()操作符的重载工作

STL函数适配器的更多相关文章

  1. STL 函数适配器(function adapter)

    函数适配器(function adapter):通过不同函数适配器的绑定,组合和修饰能力,可以实现强大的功能,配合STL泛型算法完成复杂功能. 绑定(bind) template <class ...

  2. C++STL 预定义函数对象和函数适配器

    预定义函数对象和函数适配器 预定义函数对象基本概念:标准模板库STL提前定义了很多预定义函数对象,#include <functional> 必须包含. 1使用预定义函数对象: void ...

  3. STL算法设计理念 - 函数适配器

    1)函数适配器的理论知识 2)常用函数函数适配器 标准库提供一组函数适配器,用来特殊化或者扩展一元和二元函数对象.常用适配器是: 1.绑定器(binder): binder通过把二元函数对象的一个实参 ...

  4. function adapter(函数适配器)和迭代器适配器

    所谓function adapter(函数适配器)是指能够将不同的函数对象(或是和某值或某寻常函数)结合起来的东西,它自身也是个函数对象. 迭代器适配器  运用STL中的迭代器适配器,可以使得算法能够 ...

  5. ###STL学习--适配器

    点击查看Evernote原文. #@author: gr #@date: 2014-08-24 #@email: forgerui@gmail.com STL中的适配器. ###stl学习 |--迭代 ...

  6. 函数适配器bind2nd 、mem_fun_ref 源码分析、函数适配器应用举例

    一.适配器 三种类型的适配器: 容器适配器:用来扩展7种基本容器,利用基本容器扩展形成了栈.队列和优先级队列 迭代器适配器:(反向迭代器.插入迭代器.IO流迭代器) 函数适配器:函数适配器能够将仿函数 ...

  7. 二分优化lis和STL函数

    LIS:最长上升子序列: 这个题我们很显然会想到使用dp, 状态设计:dp[i]代表以a[i]结尾的LIS的长度 状态转移:dp[i]=max(dp[i], dp[j]+1) (0<=j< ...

  8. C++11之function模板和bind函数适配器

    在C++98中,可以使用函数指针,调用函数,可以参考之前的一篇文章:类的成员函数指针和mem_fun适配器的用法.   简单的函数调用   对于函数: void foo(const string &a ...

  9. ----堆栈 STL 函数库 ----有待补充

    #include<cstdio> #include<string> #include<vector> #include<iostream> using ...

随机推荐

  1. Vue外卖的学习之路

    用Vue打造外卖项目 一.项目前整理思绪 (1)项目所需的技术栈 (2)项目分布 (3)整体项目文件介绍

  2. 《ABCD组》实验十一 团队作业7:团队项目设计完善&编码

    <ABCD组>实验十一 团队作业7:团队项目设计完善&编码 项目 内容 这个作业属于哪个课程 http://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在 ...

  3. 去除chrome网站https的安全检测

    chrome://net-internals/#hsts  访问该网址,把要禁止检测的网址放在下面:

  4. test20181102 空间复杂度 和 test20181030 数独

    空间复杂度 考场做法 前有时间复杂度,后有空间复杂度. 但是这题不会有CE情况,所以较为好写. 就用map存复杂度,单层循环就搞定了. 至于判断维度的方法,我是用快读从字符串中读入. 然后不管常数,把 ...

  5. Git报错:Please tell me who you are.

    Git在提交的时候报错 Please tell me who you are. 报错 Please tell me who you are. 具体如下: 原因:明确报错.请告诉我你是谁.意思是你在提交 ...

  6. JavaSctipt 常用字符串 方法及使用方式

    1. charAt(x) charAt(x)返回字符串中x位置的字符,下标从 0 开始. //charAt(x) var myString = 'jQuery FTW!!!'; console.log ...

  7. 学习了武沛齐讲的Day10-完

    int       整形 int     将字符串转换为数字 x.bit_length()  ===== 当前数字的二进制,至少用n位表示 str       字符串 x.capitalize()== ...

  8. 采用非常规方法(非gprecoverseg) 恢复greenplum数据库

    greenplum数据库中mirror的作用就是作为primary的备份存在.那么恢复down掉的mirror或primary时,是否可以直接复制文件从primary或mirror到对应的mirror ...

  9. MySQL Multi-Range Read(MRR 索引多范围查找) 原理与解析

    原理: 如果基表很大,数据没有被缓存,在二级索引上使用范围扫描读取行可能会导致大量的随机磁盘访问.使用Multi-Range Read新特性,mysql可以减少对磁盘的随机读的次数:首先,mysql只 ...

  10. 设计一个树型目录结构的文件系统,其根目录为 root,各分支可以是目录,也可以是文件,最后的叶子都是文件。

    设计一个树型目录结构的文件系统,其根目录为 root,各分支可以是目录,也可以是文件,最后的叶子都是文件. 我实现的功能是提供父目录(兄弟目录),输入文件名,创建树型目录结构,文本文件不可以再有子目录 ...