如何实现"解除引用和后增量"用于C ++中的输入迭代器?

时间:2016-02-02 23:30:35

标签: c++ stl iterator input-iterator

InputIterator的

Requirements包含*i++,其等效表达式为

value_type x = *i;
++i;
return x;

如何在不实现标准后增量i++的情况下声明这样的运算符,返回非void值(InputIterators不需要这样做)?

2 个答案:

答案 0 :(得分:3)

您可以使用代理进行后期增量:

#include <iostream>

class input_iterator
{
    private:
    class post_increment_proxy
    {
        public:
        post_increment_proxy(int value) : value(value) {}
        int operator * () const { return value; }

        private:
        int value;
    };

    public:
    post_increment_proxy operator ++ (int) {
        post_increment_proxy result{value};
        ++value;
        return result;
    }

    private:
    int value = 0;
};


int main() {
    input_iterator i;
    std::cout << *i++ << '\n';
    std::cout << *i++ << '\n';
    std::cout << *i++ << '\n';
}

答案 1 :(得分:1)

首先,迭代器是可复制的,即使在InputIterator的情况下,复制更像是一个移动(具体地说,在你递增迭代器的任何一个副本之后,你不应该取消引用任何其他副本它)。

尽管如此,复制迭代器应该没有任何问题 - 事实上,大多数库(以及许多其他代码)都假定迭代器是“轻量级”对象;复制它们很便宜,所以(对于一个明显的例子)它们通常是按值传递的,而不是通过引用传递的。

因此,一个稍微简化的流迭代器可能看起来像这样:

template <class T>
class istream_iterator {
    std::istream *is;
    T data;
public:
    istream_iterator(std::istream &is) : is(&is) { ++(*this); }
    istream_iterator() : is(nullptr) { }

    istream_iterator &operator++() { (*is) >> data; return *this; }

    // So here's the post-increment: it just saves a copy of itself, then
    // reads the next item (which increments the iterator), and finally
    // returns the copied object, which will return the previously-read item
    // from the stream when/if dereferenced.
    istream_iterator operator++(int) { 
        // Note: this uses the compiler-generated copy constructor. Assuming
        // a `T` is copy-constructible, this works fine--other than a T,
        // we're only copying a pointer.
        istream_iterator temp = *this; 
        (*is) >> data; 
        return temp; 
    }

    T const &operator*() const { return data; }

    bool operator !=(istream_iterator &end) { return (*is).good(); }
    bool operator ==(istream_iterator &end) { return !(*is).good(); }
};

这会在一些相当小的点上“欺骗” - 例如,两个默认构造的迭代器应该相互比较相等,这不需要实现(实际上没有人使用或关心) 。在正常使用中,您从流中创建一个迭代器,而默认构造另一个迭代器。当且仅当第一个已经到达输入流的末尾时(或者由于某种原因读取失败,无论如何),两者之间的比较应该返回true。同样,这省略了实现operator->,以及标准迭代器类型(value_type,traits_type,istream_type等)所需的一些typedef。这些都与手头的问题无关虽然(并且所有都是添加所需代码的问题,而不是对已经存在的代码进行任何实质性更改。)

代码的快速演示可能如下所示:

int main() {
    istream_iterator<char> i(std::cin), end;

    while (i != end)
        std::cout << *i++;
}

这会将字符从标准输入复制到标准输出,跳过空格,因为默认情况下operator>>会跳过空格(但如果需要,可以使用noskipws删除它。)