zoukankan      html  css  js  c++  java
  • C++坑点集合

    之前写了一个char32_iterator,简单说就是封装一个string::const_iterator,在operator*的时候将它引用的utf-8序列转为utf-32编码的单个字符返回——这看上去很简单。平时各位在编程的过程中一定会遇到类似的需求:实现一个惰性的transform,在一个容器的每一个元素上应用一个转换函数,但不是立即应用,而是等到使用它的时候即时转换。这听起来就像C#的Linq或者Java的Stream API。熟悉C++的你,一定会想到封装一个迭代器,就像我前面的char32_iterator一样,对引用的原始序列进行一个变换——这个变换还多半是纯函数,在operator*被调用的时候返回这个变换后的值。

    思考起来没什么问题,等到编写的时候,你会遇到一个问题,那就是,这个被封装过一层的迭代器——我们以后叫他proxy iterator——应该属于哪种iterator category呢?是继承被封装的迭代器的category吗?如果这个变换函数是纯函数,那么是否说明这个迭代器可以重复扫描整个序列而使返回结果不变,满足Multipass Guarantee从而至少可以是一个Forward Iterator呢?

    结果很残酷,这个proxy iterator,不管它封装的迭代器是什么category,它只能是一个Input Iterator,也就是最弱的那个迭代器。为什么呢?因为它不满足Multipass Guarantee。

    Multipass Guarantee的定义在这里

    简单说,Multipass Guarantee不仅仅要求迭代器允许拷贝和在解引用后原位置仍有效,同时它还要求相同的两个迭代器,解引用后得到的对象应该是同一对象,进一步说,同一对象指的是相同地址。这也就要求,我们的迭代器至少要指向一个确定存在的序列,才能拥有满足Multipass Guarantee的必要条件。像上面所说的proxy iterator,在解引用的时候即时返回变换的结果,是个右值,就算你提前算好保存在了迭代器内部,返回它的引用,也不满足相同迭代器指向同一对象的要求,所以这就不满足Multipass Guarantee。

    最后我们的proxy iterator的category不得不回退到了Input Iterator上,最后一个问题是,迭代器的operator*要求返回引用,而我们的迭代器解引用时返回的是右值,这可以吗?可以,cppreference又说了,不是Forward Iterator的Input Iterator,operator*的返回值可以不是引用——可以是右值,或者一个proxy类什么的随你的便——这个洞开的好啊,不然真不知道怎么实现cpplinq。

    p.s. 这篇文章翻译腔很重,我也不知道为什么,但是文章确实是我原创的。

  • 相关阅读:
    通过WebService跨平台上传大文件到服务器
    C# 委托、Lambda表达式和事件——学习总结
    WIN8、WIN7访问Windows Server 2003服务器的数据库速度很慢、远程速度很慢的解决方法
    C#中接口与抽象类的区别
    DataGridView重查后,返回原来所在行
    需要开拓的领域
    FTP使用心得
    VS的几个实用快捷键
    C#中窗体、MDI的使用心得
    水晶报表使用心得
  • 原文地址:https://www.cnblogs.com/pointer-smq/p/6348050.html
Copyright © 2011-2022 走看看