Вместо NonZeroIter
проверки явно по end()
и rend()
, конструктор должен проверить направление итерации и выбрать начало (begin()
или rbegin()
) и конец (end()
или rend()
) , Они могут быть сохранены как локальные переменные и проверены по.
Вместо проверки по "rend" в operator--()
, вы можете проверить по "begin" (индекс, представленный begin()
, совпадает с rend() - 1
) .
Все итераторы стандартных контейнеров основаны на std::reverse_iterator
, поэтому вы можете использовать эти знания, чтобы найти направление _it
.
Примерно так:
template<typename T>
struct is_reverse_iterator : std::false_type {};
template<typename T>
struct is_reverse_iterator<std::reverse_iterator<T>> : std::true_type {};
template<class Container, class Iter>
struct NonZeroIter: public Iter
{
using Parent = Iter;
using Parent::Parent;
using iterator_category = std::bidirectional_iterator_tag;
private:
Parent begin, end;
bool is_valid() const { return *(*this) != 0; }
bool is_end() const { return *this == end; }
bool is_begin() const { return *this == begin; }
public:
NonZeroIter(Container& c, const Iter& _it):
Parent(_it),
begin(is_reverse_iterator<Parent> ? c.rbegin() : c.begin()),
end(is_reverse_iterator<Parent> ? c.rend() : c.end()),
{ if (!is_end() && !is_valid()) ++(*this); }
NonZeroIter& operator++()
{
if (!is_end()){
do{
Parent::operator++();
} while(!is_end() && !is_valid());
}
return *this;
}
NonZeroIter& operator--()
{
// Smallest possible value is begin, but you could also make that begin - 1
if (!is_begin()){
do{
Parent::operator--();
} while(!is_begin() && !is_valid());
}
return *this;
}
NonZeroIter& operator++(int) { NonZeroIter tmp(*this); ++(*this); return tmp; }
NonZeroIter& operator--(int) { NonZeroIter tmp(*this); --(*this); return tmp; }
};