正在弃用的std :: iterator的准备工作

时间:2016-05-04 15:15:21

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

3月21日 st 标准委员会投票赞成批准std::iterator中提议的P0174的弃用:

  

对于读者而言,很长的void参数序列不仅仅是简单地在类定义本身中提供预期的typedef s,这是当前工作草案采用的方法,遵循{中设置的模式{3}}

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

  1. 迭代器样板现在需要包含所有必需的typedef s
  2. 使用迭代器的算法现在需要使用auto而不是依赖于迭代器来声明类型
  3. Loki Astari has suggested可以更新为工作而不继承std::iterator
  4. 有人可以告诉我我应该期待哪些选项,因为我设计的自定义迭代器着眼于std::iterator_traits兼容性?

2 个答案:

答案 0 :(得分:31)

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

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

答案 1 :(得分:30)

选项3是选项1的严格打字版本,因为您必须编写所有相同的typedefs,但另外包装iterator_traits<X>

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

留下选项1.猜猜我们应该习惯于编写所有样板文件。我是一个人,欢迎我们新的腕管道领主。