【问题标题】:Preparation for std::iterator Being Deprecated准备废弃 std::iterator
【发布时间】:2016-08-30 03:10:13
【问题描述】:

3 月 21 日st,标准委员会投票批准了在 P0174 中提出的 std::iterator 的弃用:

与在类定义本身中提供预期的typedefs 相比,长序列的 void 参数对读者来说不太清楚,这是当前工作草案采用的方法,遵循 中设置的模式

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

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

当我设计自定义迭代器时着眼于 兼容性时,有人能告诉我我应该期待哪些选项吗?

【问题讨论】:

  • @FirstStep 我希望得到一个不基于意见的答案。如果标准委员会正在弃用我明年所依赖的课程,我希望他们现在有一个引导我的方向。
  • 仅仅因为他们正在弃用它并不意味着你不能继续使用它一段时间。
  • 标准库中的迭代器已经选择了选项 1。
  • @LokiAstari - 它甚至比这更弱。从形式上讲,弃用是一种通知,表示将来某些东西可能会消失。就这样。请注意,自 1998 年以来,标准 C 标头已在 C++ 中弃用。
  • @JonathanMee - 我使用std::iterator 因为它很方便。我会继续使用它,直到我不能为止。

标签: c++14 c++17 c++17 c++ iterator standards deprecated c++17


【解决方案1】:

讨论的替代方案很清楚,但我觉得需要一个代码示例。

鉴于不会有语言替代品并且不依赖于 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;}
};

【讨论】:

  • @AmirKirsh operator* 应该返回 reference,你需要一个 operator-&gt; 返回一个 pointer,即使它对于 long 没有意义
  • 我也发现了一篇关于它的非常棒的文章here,其中概述了理由。
【解决方案2】:

选项 3 是选项 1 的严格意义上的更多类型版本,因为您必须编写所有相同的 typedefs 但另外包装 iterator_traits&lt;X&gt;

选项 2 作为解决方案是不可行的。你可以推导出一些类型(例如reference 就是decltype(*it)),但你不能推导出iterator_category。您不能仅仅通过操作的存在来区分input_iterator_tagforward_iterator_tag,因为您无法反身检查迭代器是否满足多遍保证。此外,如果迭代器产生可变引用,您无法真正区分这些和 output_iterator_tag。它们必须在某处明确提供。

剩下选项 1。猜想我们应该习惯于编写所有样板文件。我,一方面,欢迎我们新的腕管领主。

【讨论】:

  • 如果你真的喜欢std::iterator 所做的,你可以简单地编写你自己的版本。所以腕管的风险被夸大了。
  • @JonathanMee 这没有任何意义。
  • @JonathanMee Dude。 “迭代器”和“输入迭代器”不等价
  • @TemplateRex 这是个玩笑。无论如何,弃用std::iterator 以支持......现在每个人都编写自己的std::iterator 副本来解决这个问题似乎很愚蠢。
  • 相关:stackoverflow.com/q/29108958/819272 标准中删除仅包含 typedef(unary_function 等)的愚蠢基类是更普遍的趋势
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-04-20
  • 1970-01-01
  • 1970-01-01
  • 2019-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多