简体   繁体   English

同一容器的多个自定义迭代器

[英]Multiple custom iterators for same container

I have a created a dynamic container for storing bytes as uint8_t and have implemented an iterator class inside the container class.我创建了一个用于将字节存储为uint8_t的动态容器,并在容器 class 内实现了迭代器 class。 The iterator traverses through the bytes as expected.迭代器按预期遍历字节。 But these bytes are formatted with headers so I want to implement another iterator to skip through the byte array based on byte headers.但是这些字节是用标题格式化的,所以我想实现另一个迭代器来跳过基于字节标题的字节数组。 Is it possible to have both iterator classes run when used with for(auto &x: container) based on which class is declared first?for(auto &x: container)一起使用时,是否可以同时运行两个迭代器类,基于哪个 class 首先声明? or is there some other way to do this?还是有其他方法可以做到这一点?

Current iterator and container当前迭代器和容器

class container {

public:

    container() : s(0), c(2), data(new uint8_t[2]) {};
    container(size_t reserve) : s(0), c(reserve + 1), data(new uint8_t[reserve + 1]) {};
    ~container();

    // container insert, operators etc...

    // iterator class

    class Iterator {

    public:

        uint8_t* ptr;

        using iterator_category = std::forward_iterator_tag;
        using difference_type = std::ptrdiff_t;
        using value_type = uint8_t;
        using pointer = uint8_t*;
        using reference = uint8_t&;

        Iterator(pointer m_ptr) : ptr(m_ptr) { std::cout << "In iterator 1" << std::endl; }
        reference operator*() const;
        pointer operator->();
        Iterator& operator++();
        Iterator operator++(int);
        Iterator& operator+=(int const& lhs);
        Iterator operator+(int const& lhs);
        friend bool operator== (const Iterator& a, const Iterator& b);
        friend bool operator!= (const Iterator& a, const Iterator& b);

    };

    Iterator begin() const;
    Iterator end() const;

private:

    uint8_t* data;
    size_t s;
    size_t c;

};

No, range iteration syntax is what it is: a proxy for calling the container's begin() and end() ;不,范围迭代语法就是这样:调用容器的begin()end()的代理; and then iterating over the returned sequence.然后遍历返回的序列。 That's the only way it works.这是它工作的唯一方式。

C++20 adds the ranges library which can be used to combine two separate iterator sequences together. C++20 添加了范围库,可用于将两个单独的迭代器序列组合在一起。 Until C++20 the most common option in this kind of a situation is to declare a third iterator class that proxies over the combined sequence of the two underlying iterator classes, and then use this proxy iterator class with begin() and end() .在 C++20 之前,这种情况下最常见的选择是声明第三个迭代器 class 代理两个底层迭代器类的组合序列,然后使用这个代理迭代器 class 与begin()end() . The basic approach is fairly straightforward:基本方法相当简单:

  1. begin() returns the third iterator class initialized with the beginning and the ending iterator values of both underlying iterator classes, end() returns the third iterator class initialized with the ending iterator values of both underlying iterator classes for both the proxied, internal beginning and ending iterator values (ie begin=end for both of them). begin()返回第三个迭代器 class 用两个底层迭代器类的开始和结束迭代器值初始化, end()返回第三个迭代器 class 用两个底层迭代器类的结束迭代器值初始化,用于代理、内部开始和结束迭代器值(即它们两个的开始=结束)。

  2. The * and/or the -> operator overloads check if the first iterator class's proxied beginning iterator value already reached its ending value. *和/或->运算符重载检查第一个迭代器类的代理开始迭代器值是否已经达到其结束值。 If not then use it to implement * and -> , otherwise use the second proxied beginning iterator value.如果不是,则使用它来实现*-> ,否则使用第二个代理的开始迭代器值。

  3. The various forward/increment overloads advance the first iterator class's proxied beginning iterator value.各种前向/增量重载会推进第一个迭代器类的代理起始迭代器值。 If it's already at its iterator class's ending iterator value then the second iterator class's proxied beginning iterator value gets advanced.如果它已经在其迭代器类的结束迭代器值处,则第二个迭代器类的代理开始迭代器值将被推进。

You can't make iteration behave differently based on declaration order.您不能根据声明顺序使迭代行为不同。 What would that even mean?这甚至意味着什么? Somehow, that's like asking for the same class to behave differently based on context or perhaps randomly.不知何故,这就像要求相同的 class 根据上下文或可能随机地表现不同。

However, what you can do is implement code like this:但是,您可以做的是实现如下代码:

for (auto x: my_container.raw()) { ... }
for (auto x: my_container.rows()) { ... }
for (auto x: my_container.columns()) { ... }
for (auto x: my_container.pixels()) { ... }

Note: I'm just guessing that the header you mention is a bitmap header and that you're processing an image file.注意:我只是猜测您提到的 header 是 bitmap header 并且您正在处理图像文件。

BTW: There's a bunch of things wrong with your code that are not catastrophic, but still good opportunities to improve, like eg using raw new[] memory allocation which should be a std::vector instead.顺便说一句:你的代码有很多问题不是灾难性的,但仍然有很好的改进机会,比如使用原始new[] memory 分配,它应该是一个std::vector代替。 Consider posting your working (.) code on codereview.stackexchange.com.考虑在 codereview.stackexchange.com 上发布您的工作 (.) 代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM