c++vectoriteratorreverse-iteratorspdlog

In custom reverse vector iterator don't see first element


The other day I wanted to try writing my own iterators for a vector, of course, the most primitive example, since there is a lot of confusing code in the c++ standards. So the usual iterator for a vector in the forward direction works fine, but there was a problem with the reverse iterator. I have it completely built on the base iterator, only I changed / inverted the operators specifically for the reverse iterator.

template<typename Vector>
class VectorRevIterator : public VectorIterator<Vector> //This is normal (work) vector iterator
{
public:
    using Base = VectorIterator<Vector>;

    VectorRevIterator(PointerType ptr) noexcept : Base(ptr) {};

    VectorRevIterator(const VectorRevIterator& other) : Base(other) { *this = other; };

    VectorRevIterator& operator++()
    {
        Base::operator--(); //--ptr;
        return *this;
    }

    VectorRevIterator operator++(int)
    {
        VectorRevIterator itr = *this;
        Base::operator--(); //--*this;
        return itr;
    }

    VectorRevIterator& operator--()
    {
        Base::operator++(); //++ptr;
        return *this;
    }

    VectorRevIterator operator--(int)
    {
        VectorRevIterator itr = *this;
        Base::operator++(); //++*this;
        return itr;
    }

    VectorRevIterator& operator+=(const PointerType otherPtr)
    {
        Base::operator-=(otherPtr); //ptr -= otherPtr;
        return *this;
    }

    VectorRevIterator operator+(const PointerType otherPtr)
    {
        VectorRevIterator itr = *this;
        Base::operator-(otherPtr); // itr -= otherPtr
        return *this;
    }

    VectorRevIterator& operator-=(const PointerType otherPtr) { return Base::operator+=(otherPtr); }
    VectorRevIterator operator-(const PointerType otherPtr) { Base::operator+(otherPtr); }
    ReferenceType operator*() const { return *ptr; }
    PointerType operator->() const { return std::_Const_cast(Base::operator->()); }
};

Access to iterator from Vector:

template<typename T>
class Vector
{
public:
        using ValueType = T;
        using PointerType = ValueType*;
        using ReferenceType = ValueType&;
        
        using ReverseIterator = VectorRevIterator<Vector<T>>;
public:
       T* data;
       size_t size;
       size_t capacity;
...

// construct/destructor
// custom allocator
// index operators

...

ReverseIterator rBegin() { return ReverseIterator(data + size); }
ReverseIterator rEnd() { return ReverseIterator(data); }

};

The problem itself is that when I try to go through all the elements in the opposite direction VectorRevIterator. When trying to output all this to the console, it seems to shift one element forward and does not see/cannot read the characters of the first element. But then output all the elements, only without the last one.

Here a example:

Vector<String> values;
values.emplaceBack("1");
values.emplaceBack("2");
values.emplaceBack("3");
values.emplaceBack("4");
values.emplaceBack("5");

Vector<String>::ReverseIterator revIt = values.rBegin();

// output with spdlog
for (revIt; revIt != values.rEnd(); ++revIt)
        INFO(*revIt); // error on first iteration, but print only 1, 2, 3, 4

// ouput with std::cout
for (revIt; revIt != values.rEnd(); ++revIt)
        std::cout << *revIt << std::endl; // doesn't print anything

How solve this problem? To make reverse iterator it just need to revert operators ++ -- += -= and rBegin rEnd functions. Or maybe im forgotten about something?


Solution

  • rBegin() returns an iterator to the first element:

    ReverseIterator rBegin() { return ReverseIterator(data + size); }
    

    But it's pointing one element beyond the end and can't be dereferenced. You need to dereference the element before it.

    You could therefore adjust the dereference operator in the VectorRevIterator version:

    ReferenceType operator*() const { return *std::prev(ptr); }