简体   繁体   中英

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. 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? 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() ; 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. 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() . 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).

  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.

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.

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. Consider posting your working (.) code on codereview.stackexchange.com.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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