0

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;

};
0

2 Answers 2

1

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 e.g. using raw new[] memory allocation which should be a std::vector instead. Consider posting your working (!) code on codereview.stackexchange.com.

Sign up to request clarification or add additional context in comments.

2 Comments

I'm using new because I don't want to use the standard doubling etc. that std::vector uses (or is there a way to extend(inherit) from std::vector?
What doubling? Are you referring to the allocation strategy to always double the capacity to achieve amortized constant-time insertions? If you know the exact size you need, use reserver() or resize() (read the docs!) to prevent useless allocations.
1

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 (i.e. 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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.