不推荐使用std :: iterator的准备


76

3月21,标准委员会投票通过了弃用P0174std::iterator提议的建议:

与读者typedef在类定义本身中简单地提供期望的s相比,冗长的void参数序列对读者而言并不十分清楚,这是当前工作草案采用的方法,遵循

之前 std::iterator鼓励从继承继承,以从迭代器样板实现中删除乏味。但是弃用将需要以下其中一项:

  1. 迭代器样板现在将需要包含所有必需的typedefs
  2. 使用迭代器的算法现在将需要使用auto而不是依赖迭代器来声明类型
  3. Loki Astari建议std::iterator_traits不继承的情况下进行更新以使其正常工作std::iterator

在设计自定义迭代器时,有人可以启发我应该选择哪些选项吗? 兼容性?


6
@FirstStep我希望得到一个不会基于观点的答案。如果标准委员会不赞成明年我要上的一堂课,我希望他们能有一个指导,让他们现在引导我。
乔纳森·梅

2
仅仅因为他们不赞成使用它并不意味着您不能暂时使用它。
Jesper Juhl

4
在标准库的迭代器已经走了选项1
博佩尔松

1
@LokiAstari-甚至比那还要弱。从形式上讲,弃用是将来可能会消失的通知。就这样。请注意,自1998
Pete Becker,

1
@JonathanMee-不,它没有白费。它不是必需的,但是有其优点。
皮特·贝克尔

Answers:


60

讨论的替代方案很明确,但我认为需要一个代码示例。

鉴于将没有语言替代品,并且不依赖boost或您自己的迭代器基类版本,因此下面使用std::iterator的代码将固定在下面的代码中。

std::iterator

template<long FROM, long TO>
class Range {
public:
    // member typedefs provided through inheriting from std::iterator
    class iterator: public std::iterator<
                        std::forward_iterator_tag, // iterator_category
                        long,                      // value_type
                        long,                      // difference_type
                        const long*,               // pointer
                        const long&                // reference
                                      >{
        long num = FROM;
    public:
        iterator(long _num = 0) : num(_num) {}
        iterator& operator++() {num = TO >= FROM ? num + 1: num - 1; return *this;}
        iterator operator++(int) {iterator retval = *this; ++(*this); return retval;}
        bool operator==(iterator other) const {return num == other.num;}
        bool operator!=(iterator other) const {return !(*this == other);}
        long operator*() {return num;}
    };
    iterator begin() {return FROM;}
    iterator end() {return TO >= FROM? TO+1 : TO-1;}
};

(获得原始作者许可的http://en.cppreference.com/w/cpp/iterator/iterator中的代码)。

不带 std::iterator

template<long FROM, long TO>
class Range {
public:
    class iterator {
        long num = FROM;
    public:
        iterator(long _num = 0) : num(_num) {}
        iterator& operator++() {num = TO >= FROM ? num + 1: num - 1; return *this;}
        iterator operator++(int) {iterator retval = *this; ++(*this); return retval;}
        bool operator==(iterator other) const {return num == other.num;}
        bool operator!=(iterator other) const {return !(*this == other);}
        long operator*() {return num;}
        // iterator traits
        using difference_type = long;
        using value_type = long;
        using pointer = const long*;
        using reference = const long&;
        using iterator_category = std::forward_iterator_tag;
    };
    iterator begin() {return FROM;}
    iterator end() {return TO >= FROM? TO+1 : TO-1;}
};

2
@AmirKirshoperator*应该返回reference,即使这对a没有意义,也需要operator->返回pointeralong
Ryan Haining

33

选项3是选项1的严格类型化版本,因为您必须编写所有相同的内容,typedefs但还要进行wrap iterator_traits<X>

选项2不可行。您可以推断出某些类型(例如reference,只是decltype(*it)),但不能推断出iterator_category。你不能区分之间input_iterator_tag,并forward_iterator_tag通过简单地操作的存在,因为你不能本能如果迭代满足检查多遍的保证。此外,您无法真正区分这些内容以及output_iterator_tag迭代器是否产生可变引用。必须在某处显式提供它们。

剩下的就是选项1。猜猜我们应该习惯于编写所有样板文件。首先,我欢迎我们新的腕管霸王。


3
如果您真的喜欢std::iterator它的功能,则可以轻松编写自己的版本。因此,腕管的风险过高。
TC

4
@JonathanMee这没有任何意义。
巴里

7
@乔纳森·米德 “ Iterator”和“ Input Iterator”不等效
巴里

7
@TemplateRex这是个玩笑。无论如何,过时std::iterator地赞成……似乎很愚蠢……现在每个人都写自己的副本std::iterator来解决该问题。
巴里(Barry)

3
相关:stackoverflow.com/q/29108958/819272在标准中,更普遍的趋势是删除仅包含typedef(傻瓜函数等)的愚蠢基类
TemplateRex
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.