如何定义不带中间字符的STL兼容输入迭代器?

时间:2019-07-13 14:02:19

标签: c++ inheritance types iterator

我正在尝试学习C ++,并且希望更好地了解迭代器。为此,我尝试为自定义类(称为StrBlob,它包含在美妙的C++ Primer中定义的字符串)编写与STL兼容的迭代器。最终,以下迭代器定义起作用了:

class StrBlob::iterator
    : public std::iterator<std::input_iterator_tag,  // iterator_category
                           std::string,              // value_type
                           std::string,              // difference_type
                           const std::string*,       // pointer
                           std::string               // reference
                           > {
   public:
    iterator() : curr(0) {}
    iterator(StrBlob& a, size_t sz = 0) : wptr(a.data), curr(sz) {}
    iterator& operator++();  // prefix operators
    iterator& operator--();
    iterator operator++(int);  // postfix operators
    iterator operator--(int);
    std::string& operator*() const;
    std::string* operator->() const;
    bool operator==(const iterator& b) const { return curr == b.curr; }
    bool operator!=(const iterator& b) const { return curr != b.curr; }

   private:
    std::shared_ptr<std::vector<std::string>> check(std::size_t,
                                                    const std::string&) const;
    std::weak_ptr<std::vector<std::string>> wptr;
    std::size_t curr;
};

最初,我花了很长时间尝试尝试自己设计具有正确类型定义的迭代器。这没有用,所以我只是向cppreference中提到的std::iterator提供了一个继承。

我可以编写完全不继承的类吗?如果是这样,我将如何重写上面的代码?

(我试图了解Stackoverflow对有关迭代器设计的相关问题的答案,但对我来说这些答案有些抽象。)

2 个答案:

答案 0 :(得分:2)

您的代码有错误,std::string不是合适的差异类型(difference_type是两个迭代器之间的差异,因此通常是std::ptrdiff_t),std::string也不合适引用类型(应为std::string&)。

这是正确的typedef,您可以使用它们代替继承。

typedef std::input_iterator_tag iterator_category;
typedef std::string value_type;
typedef std::ptrdiff_t difference_type;
typedef std::string* pointer;
typedef std::string& reference;

答案 1 :(得分:1)

  

我可以编写完全不继承的类吗?如果是这样,我该如何重写上面的代码?

是的std::iterator(在C ++ 17中已弃用)仅提供typedef。

因此,您可以自己添加这些typedef,而不必使用继承。

class StrBlob::iterator
{
public:
    using iterator_category = std::input_iterator_tag;
    using value_type = std::string;
    using difference_type = std::string;// should be `std::ptrdiff_t`
    using pointer = const std::string*; // const should probably be dropped, unless you do const_iterator
    using reference = std::string; // should be std::string&

// ...
};