C++ STL 适配器

news2024/12/27 11:43:52

系列文章目录

模板特例化,偏特化,左右值引用 https://blog.csdn.net/surfaceyan/article/details/126794013
C++ STL 关联容器 https://blog.csdn.net/surfaceyan/article/details/127414434
C++ STL 序列式容器(二) https://blog.csdn.net/surfaceyan/article/details/127083966
C++ STL 序列式容器(一) https://blog.csdn.net/surfaceyan/article/details/126860166
C++STL迭代器iterator设计 https://blog.csdn.net/surfaceyan/article/details/126772555
C++11 标准库头文件模拟实现,无锁STL https://blog.csdn.net/surfaceyan/article/details/126772555


文章目录

  • 系列文章目录
  • 前言
  • 概念分类
    • 容器适配器
    • 迭代器适配器
      • 1. insert iterators
      • 2. reverse iterators
      • 3. stream iterators
  • function adapters
    • 4. 用于函数指针:ptr_fun
    • 5. 用于成员函数指针: mem_fun, mem_fun_ref
  • 总结


前言

适配器(adapters)在STL组件的灵活组合运用上扮演者重要角色。Adapter这个概念源于23个设计模式中的一个:将一个class的接口转换为以一个class接口,使原本因接口不兼容而不能合作的classes可以一起运作。

实际上就是在原有的接口上再套一层接口
或许叫接口适配器或者接口层也可


概念分类

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

queue和stack就是容器适配器。

容器适配器和迭代器适配器

#include <iterator>
#include <deque>
#include <algorithm>
#include <iostream>
using namespace std;

int main(int argc, char* argv[])
{
    ostream_iterator<int> outite(cout, " ");
    int ia[] = {0,1,2,3,4,5};
    deque<int> id(ia, ia+6);
    copy(id.begin(), id.end(), outite);
    cout << endl;
    
    copy(ia+1, ia+2, front_inserter(id));
    copy(ia+3, ia+4, back_inserter(id));
    copy(id.begin(), id.end(), outite);
    cout << endl;

    deque<int>::iterator ite = find(id.begin(), id.end(), 5);
    copy(ia+0, ia+3, inserter(id, ite));
    copy(id.begin(), id.end(), outite);
    cout << endl;

    copy(id.rbegin(), id.rend(), outite);
    cout << endl;

    istream_iterator<int> inite(cin), eos;  // end-of-stream
    copy(inite, eos, inserter(id, id.begin()));

    copy(id.begin(), id.end(), outite);
    cout << endl;
}

应用于函数的适配器
所有期望获取适配能力的组件,本事必须是可适配的,也就是说,一元仿函数必须继承自 unary_function,二元仿函数必须继承自 binary_function ,成员函数必须以mem_fun处理过,一般函数必须以 ptr_fun 处理过,一个未经ptr_fun处理的一般函数,虽然也可以函数指针的形式传递STL算法使用,却无法有任何适配能力

void print(int i)
{
    cout << i << ' ';
}
class Int
{
private:
    int m_i;
public:
    explicit Int(int i) : m_i(i) {}
    ~Int() {}
    void print1() const 
    {
        cout << '[' << m_i << ']';
    }
};

template<class Arg, class Result>
struct unary_function 
{
  typedef Arg     argument_type;
  typedef Result    result_type;
};

template <class Arg1, class Arg2, class Result>
struct binary_function
{
  typedef Arg1   first_argument_type;
  typedef Arg2  second_argument_type;
  typedef Result         result_type;
};

    stringstream scout;
    ostream_iterator<int> outite(scout, " ");
    int ia[6] = {2, 21, 12, 7, 19, 23};
    vector<int> iv(ia, ia+6);
    cout << count_if(iv.begin(), iv.end(), [](int a)->bool {return a>=12;});
    cout << endl;

    transform(iv.begin(), iv.end(), outite, [](int a)->int {return (a+2)*3;});
    cout << scout.str() << endl;

    copy(iv.begin(), iv.end(), outite);
    cout << scout.str() << endl;

    for_each(iv.begin(), iv.end(), print);
    cout << endl;

    for_each(iv.begin(), iv.end(), ptr_fun(print));
    cout << endl;

    for_each(iv.begin(), iv.end(), bind(print, placeholders::_1));
    cout << endl; 

    Int t1(3), t2(7), t3(20), t4(14), t5(68);
    vector<Int> Iv;
    Iv.push_back(t1);
    Iv.push_back(t2);
    Iv.push_back(t3);
    Iv.push_back(t4);
    Iv.push_back(t5);
    for_each(Iv.begin(), Iv.end(), mem_fun_ref(&Int::print1));  // 私有成员函数必须用指针
    cout << endl;

    for_each(Iv.begin(), Iv.end(), bind(&Int::print1, placeholders::_1));
    cout << endl;

其中std::bind是更易于使用更通用的方法,用它!

容器适配器

template<typename T, typename Sequence = deque<T>>
class stack{
protected:
  Sequence c;
  ...
};

迭代器适配器

由用户指定一个容器,在调用 迭代器适配器 时调用指定容器的对应方法

1. insert iterators

可细分为back insert iterator, front insert iterator和insert iterator,分别将对应类型的“指针解引用并赋值”(*p = value)操作修改为对应容器的方法

template<class Container>
class back_insert_iterator
{
protected:
    Container* container;
public:
    typedef std::output_iterator_tag iterator_category;
    typedef void                       value_type;
    typedef void                  difference_type;
    typedef void                          pointer;
    typedef void                        reference;

    explicit back_insert_iterator(Container& x) : container(&x) {};
    back_insert_iterator& operator=(const typename Container::value_type& value)
    {
        container->push_back(value);
        return *this;
    }
    back_insert_iterator& operator*() {return *this;}
    back_insert_iterator& operator++() {return *this;}
    back_insert_iterator& operator++(int) {return *this;}
};
template <class Container>
class front_insert_iterator
{
protected:
    Container* container;
public:
    typedef std::output_iterator_tag iterator_category;
    typedef void                       value_type;
    typedef void                  difference_type;
    typedef void                          pointer;
    typedef void                        reference;

    explicit front_insert_iterator(Container& c) : container(&c) {}
    front_insert_iterator& operator=(const typename Container::value_type& v)
    {
        container->push_front(v);
        return *this;
    }
    front_insert_iterator& operator*() {return *this;}
    front_insert_iterator& operator++() {return *this;}
    front_insert_iterator& operator++(int) {return *this;}
};
template <class Container>
class insert_iterator
{
protected:
    Container* container;
    typename Container::iterator iter;
public:
    typedef std::output_iterator_tag iterator_category;
    typedef void                       value_type;
    typedef void                  difference_type;
    typedef void                          pointer;
    typedef void                        reference;

    explicit insert_iterator(Container& c, typename Container::iterator i) : container(&c), iter(i) {}
    insert_iterator& operator=(const typename Container::value_type& v)
    {
        iter = container->insert(iter, v);
        ++iter;
        return *this;
    }
    insert_iterator& operator*() {return *this;}
    insert_iterator& operator++() {return *this;}
    insert_iterator& operator++(int) {return *this;}
};


template <class Container>
inline back_insert_iterator<Container> back_inserter(Container& x)
{
    return back_insert_iterator<Container>(x);
}
template <class Container>
inline front_insert_iterator<Container> front_inserter(Container& x)
{
    return front_insert_iterator<Container>(x);
}
template <class Container, class Iterator>
inline insert_iterator<Container> inserter(Container& x, Iterator i)
{
    typedef typename Container::iterator iter;
    return insert_iterator<Container>(x, iter(i));
}

int main()
{
    std::deque<int> v{1,2,3};
    auto bins = ::front_inserter(v);

    *bins = 4;
    *bins = 6;

    std::ostream_iterator<int> outite(std::cout, " ");
    std::copy(v.begin(), v.end(), outite); std::cout << std::endl;
}

2. reverse iterators

和reverse_iterator迭代器相关,将移动操作倒转
copy(v.rbegin(), v.rend(), ite)看似简单,实则暗藏玄机

typedef reverse_iterator<iterator> reverse_iterator;
reverse_iterator rbegin() {return reverse_iterator(end());}
reverse_iterator rend() {return reverse_iterator(begin());}

在这里插入图片描述


template <class Iterator>
class reverse_iterator
{
protected:
    Iterator current;  // 记录对应之正向迭代器
public:
    typedef typename std::iterator_traits<Iterator>::iterator_category  iterator_category;
    typedef typename std::iterator_traits<Iterator>::value_type                value_type;
    typedef typename std::iterator_traits<Iterator>::difference_type      difference_type;
    typedef typename std::iterator_traits<Iterator>::pointer                      pointer;
    typedef typename std::iterator_traits<Iterator>::reference                  reference;
    typedef Iterator          iterator_type;
    typedef reverse_iterator<Iterator> self;

    reverse_iterator() {}
    explicit reverse_iterator(iterator_type x) : current(x) {}
    reverse_iterator(const self& x): current(x.current) {}
    iterator_type base() const {return current;}
    reference operator*() const
    {
        Iterator tmp = current;
        return *--tmp;  // key point
    }
    pointer operator->() const 
    {
        return &(operator*());
    }
    self& operator++()
    {
        --current;
        return *this;
    }
    self operator++(int)
    {
        self tmp = *this;
        --current;
        return tmp;
    }
    self& operator--()
    {
        ++current;
        return *this;
    }
    self operator--(int)
    {
        self tmp = *this;
        ++current;
        return tmp;
    }
    self operator+(difference_type n) const
    {
        return self(current - n);
    }
    self& operator+=(difference_type n)
    {
        current -= n;
        return *this;
    }
    self operator-(difference_type n) const
    {
        return self(current + n);
    }
    self& operator-=(difference_type n)
    {
        current += n;
        return *this;
    }
    difference_type operator-(const self& second) const
    {
        return second.current - current;
    }
    reference operator[](difference_type n) const 
    {
        return *(*this+n);
    }
};


int main()
{
    std::deque<int> v{1,2,3};
    ::reverse_iterator<std::deque<int>::iterator> rbegin(v.end()), rend(v.begin());


    std::ostream_iterator<int> outite(std::cout, " ");
    // copy到outite迭代器所指的位置
    std::copy(rbegin, rend, outite); std::cout << std::endl;
}

3. stream iterators

就是将迭代器绑定到一个stream对象身上。绑定到istream(std::cin)身上叫istream_iterator,拥有输入能力;绑定到ostream(std::cout)身上的叫ostream_iterator, 拥有输出能力。
所谓绑定是指,在iterator内部维护一个stream成员,客户端对该iterator的所有操作都转换成该stream成员的操作。

template <typename T, typename Distance = std::ptrdiff_t>
class istream_iterator
{
friend bool operator==(const istream_iterator<T, Distance>& x, const istream_iterator<T, Distance>& y);

protected:
    std::istream* stream;
    T value;
    bool end_marker;
    void read()
    {
        end_marker = (*stream) ? true : false;
        if (end_marker) *stream >> value;
        end_marker = (*stream) ? true : false;
    }
public:
    typedef std::input_iterator_tag  iterator_category;
    typedef T                               value_type;
    typedef Distance                   difference_type;
    typedef const T*                           pointer;
    typedef const T&                         reference;

    istream_iterator() : stream(&std::cin), end_marker(false) {}
    explicit istream_iterator(std::istream& s) : stream(&s) { read(); }
    reference operator*() const { return value; }
    pointer operator->() const { return &(operator*()); }
    istream_iterator& operator++()
    {
        read();
        return *this;
    }
    istream_iterator operator++(int)
    {
        istream_iterator<T, Distance> tmp = *this;
        read();
        return tmp;
    }
}; 
template <typename T>
class ostream_iterator
{
protected:
    std::ostream* stream;
    const char* string;
public:
    typedef std::output_iterator_tag  iterator_category;
    typedef void                             value_type;
    typedef void                        difference_type;
    typedef void                                pointer;
    typedef void                              reference;

    explicit ostream_iterator(std::ostream& s) : stream(&s), string(0) {}
    ostream_iterator(std::ostream& s, const char* c) : stream(&s), string(c) {}
    ostream_iterator operator=(const T& value)
    {
        *stream << value;
        if (string) *stream << string;
        return *this;
    }
    ostream_iterator& operator*() {return *this;}
    ostream_iterator& operator++() {return *this;}
    ostream_iterator& operator++(int) {return *this;}
}; 

以上两个迭代器在应用上非常重要,说明了如何为自己量身定制一个迭代器。可以完成一个绑定到 Internet Explorer 身上的迭代器,也可以完成一个绑定到磁盘目录上的迭代器······

function adapters

std::bind

4. 用于函数指针:ptr_fun

@deprecated Deprecated in C++11, no longer in the standard since C++17.

5. 用于成员函数指针: mem_fun, mem_fun_ref

在这里插入图片描述
@deprecated Deprecated in C++11, no longer in the standard since C++17. Use mem_fn instead.

std::mem_fn


总结

algorithm里存放各种算法如accumulate,sort等
functional里存各种xx函数如std::move, less, greater等

适配器一般要和泛型算法配合使用方可体现其强大之处

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2116524.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

项目实战系列三: 家居购项目 第四部分

购物车 &#x1f333;购物车&#x1f346;显示购物车&#x1f346;更改商品数量&#x1f346;清空购物车&&删除商品 &#x1f333;生成订单 &#x1f333;购物车 需求分析 1.会员登陆后, 可以添加家居到购物车 2.完成购物车的设计和实现 3.每添加一个家居,购物车的数量…

比较顺序3s1,3s2,4s1之间的关系

(A,B)---6*30*2---(0,1)(1,0) 分类A和B&#xff0c;让B全是0。当收敛误差为7e-4&#xff0c;收敛199次取迭代次数平均值&#xff0c;3s1为 3s2为 4s1为 3s1&#xff0c;3s2&#xff0c;4s1这3个顺序之间是否有什么联系 &#xff0c; 因为4s1可以按照结构加法 变换成与4s1内在…

Linux相关概念和重要知识点(2)(用户、文件和目录、inode、权限)

1.root和普通用户 在Windows里面&#xff0c;管理员Administrator是所有用户里面权限最高的&#xff0c;很多文件都会提示请使用管理员打开等。但在整个Windows系统中&#xff0c;管理员的权限并不是最大的&#xff0c;System优先级更高&#xff0c;因此我们系统中的某些文件是…

谈谈ES搜索引擎

一 ES的定义 ES 它的全称是 Elasticsearch&#xff0c;是一个建立在全文搜索引擎库Lucene基础上的一个开源搜索和分析引擎。ES 它本身具备分布式存储&#xff0c;检索速度快的特性&#xff0c;所以我们经常用它来实现全文检索功能。目前在 Elastic 官网对 ES 的定义&#xff0c…

模拟实现vector中的常见接口

insert void insert(iterator pos, const T& x) {if (_finish _endofstorage){int n pos - _start;size_t newcapacity capacity() 0 ? 2 : capacity() * 2;reserve(newcapacity);pos _start n;//防止迭代器失效}int end _finish-1;while (end > pos){*(end 1…

PMBOK® 第六版 规划进度管理

目录 读后感—PMBOK第六版 目录 规划进度管理主要关注为整个项目期间的进度管理提供指南和方向。以下是两个案例&#xff0c;展示了进度管理中的复杂性和潜在的冲突&#xff1a; 案例一&#xff1a;近期&#xff0c;一个长期合作的客户因政策要求&#xff0c;急需我们为多家医…

SQL的增删改查CRUD练习知识点(day27)

1 学习目标 重点掌握插入单条记录的语法了解全表插入记录的语法重点掌握修改记录的语法重点掌握删除记录的语法重点掌握主键约束、外键约束了解检查约束、非空约束、唯一约束 2 数据类型 MySQL支持多种数据类型&#xff0c;大致可以分类三类&#xff1a;数值、日期和字符串。…

【JavaEE初阶】多线程(3)

欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 目录 线程状态 线程安全 代码示例 解释 总结原因 解决方案-->加锁 t1和t2都加锁 且 同一个锁对象 t1和t2中只有一个加锁了 t1和t2都加锁,但锁对象不同 加锁 与线程等待…

我给孩子请了个AI老师,省掉了1999元的报名费

大家好&#xff0c;我是凡人。 最近老婆想给儿子在线报个书法班&#xff0c;要价1999元&#xff0c;本来是个好事情&#xff0c;但一向勤俭持家的我&#xff0c;怎能让她花这个冤枉钱&#xff0c;经过我三七二十一个小时的上网&#xff0c;还真让我找出一套利用AI学习的万能命…

图片无损放大编辑PhotoZoom Pro 9.0.4多版本软件2024年最新安装包下载含安装教程

PhotoZoom Pro 9.0.4是一款非常流行的图像放大软件&#xff0c;它可以让你将低分辨率的图像放大到高分辨率的尺寸&#xff0c;同时保持高质量的图像细节和清晰度。 PhotoZoom Pro 9.0.4采用了一种称为S-Spline技术的算法&#xff0c;这是一种能够保持图像细节的高级插值算法。…

Web3 详解

1. 使用 Web3 库 Web3 是一个 JavaScript 库&#xff0c;可用于通过 RPC 通信与以太坊节点通信。 Web3 的工作方式是&#xff0c;公开已通过 RPC 启用的方法&#xff0c;这允许开发利用 Web3 库的用户界面&#xff0c;以便与部署在区块链上的合约进行交互。 一旦 Geth JavaScri…

25届计算机专业选题推荐-基于python的线上拍卖会管理系统【python-爬虫-大数据定制】

&#x1f496;&#x1f525;作者主页&#xff1a;毕设木哥 精彩专栏推荐订阅&#xff1a;在 下方专栏&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; 实战项目 文章目录 实战项目 一、基于python的线上拍卖会管理…

Window下编译OpenJDK17

本文详细介绍Window下如何编译OpenJDK17&#xff0c;包含源码路径&#xff0c;各工具下载地址&#xff0c;严格按照文章中的步骤来操作&#xff0c;你将获得一个由自己亲手编译出的jdk。 一、下载OpenJDK17源码 下载地址&#xff1a;GitHub - openjdk/jdk at jdk-1735 说明&a…

碰撞检测 | 详解矩形AABB与OBB碰撞检测算法(附ROS C++可视化)

引言 在复杂的人工智能系统和机器人应用中,碰撞检测(Collision Detection)作为一项基础技术,扮演着至关重要的角色。无论是在自动驾驶车辆中防止车祸的发生,还是在机器人导航中避免障碍物,碰撞检测的精度和效率都直接决定了系统的可靠性和安全性。在游戏开发、虚拟现实、…

USART—串口通讯

USART—串口通讯 大纲 串口通讯协议简介STM32 的 USART 简介USART 功能框图USART 初始化结构体详解 具体案例 串口通讯协议简介 物理层 串口通讯的物理层有很多标准及变种&#xff0c;我们主要讲解 RS-232 标准&#xff0c;RS-232 标准主要规定了信号的用途、通讯接口以及…

SpringCache之本地缓存

针对不同的缓存技术&#xff0c;需要实现不同的cacheManager&#xff0c;Spring定义了如下的cacheManger实现。 CacheManger 描述 SimpleCacheManager 使用简单的Collection来存储缓存&#xff0c;主要用于测试 ConcurrentMapCacheManager 使用ConcurrentMap作为缓存技术&…

spring揭秘20-spring事务02-编程式事务与声明式事务管理

文章目录 【README】【1】编程式事务管理【1.1】使用PlatformTransactionManager进行编程式事务管理【1.2】使用TransactionTemplate进行编程式事务管理【1.3】基于Savepoint的嵌套事务 【2】声明式事务管理【2.1】基于xml的声明式事务【2.1.1】使用ProxyFactory&#xff08;Pr…

【基础篇】应届毕业生必备:机器学习面试题指南【1】

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发…

【软件工程】软件开发模型

三、瀑布模型 四、几种软件开发模型的主要特点 题目 判断题 选择题 小结

房贷计算及比较

本博客主要介绍&#xff1a; 1. 等额本金计算公式 2. 等额本息计算公式 3. 对比两种还款方式 4. 本示例:贷款金额为35万&#xff0c; 期限12年&#xff0c;年利率4.9% 等额本金计算 import matplotlib.pyplot as plt import matplotlib matplotlib.rcParams[font.sans-s…