Проблемы с созданием итератора

221
10 сентября 2018, 19:40

Выполняю вот это задание. Необходимо написать итератор на лист векторов. Вылетает

Failed. Runtime error Segmentation fault (core dumped)

Прогнал тесты: похоже, что проблема в реализации операторов инкремента и декремента, но я не могу понять, что я упускаю.

Заранее спасибо.

UPD Теперь тут правильный код

#include <vector>
#include <list>
#include <iterator>
template<class T>
class VectorList
{
private:
    using VectT = std::vector<T>;
    using ListT = std::list<VectT>;
    ListT data_;
public:
    using value_type = T;
    VectorList() = default;
    VectorList(VectorList const &) = default;
    VectorList(VectorList &&) = default;
    VectorList & operator=(VectorList &&) = default;
    VectorList & operator=(VectorList const &) = default;
    // метод, который будет использоваться для заполнения VectorList
    // гарантирует, что в списке не будет пустых массивов
    template<class It>
    void append(It p, It q); // определена снаружи
                              //{
                            // if (p != q)
                            // data_.push_back(VectT(p,q));
                            // }

    bool empty() const { return size() == 0; }
    // определите метод size
    size_t size() const
    {
        size_t ans = 0;
        for (auto &v : data_)
        {
            ans += v.size();
        }
        return ans;
    }
    // определите const_iterator
    struct const_iterator : std::iterator<std::bidirectional_iterator_tag, const T>
    {
        typename ListT::const_iterator ItL;
        typename VectT::const_iterator ItV;
        const ListT* ptr;
        const_iterator() = default;
        ~const_iterator() = default;
        const_iterator(const const_iterator& It) = default;
        const_iterator& operator=(const const_iterator&) = default;
        const_iterator(const ListT* ptr_) :
            ItL(ptr_->cbegin()), ItV(ItL->cbegin()), ptr(ptr_){};
        const_iterator& in_end()
        {
            ItL = --(ptr->cend());
            ItV = ItL->cend();
            return *this;
        }
        const T& operator*() const { return *ItV; };
        const_iterator& operator++()
        {
            if (ItV == std::prev((*ItL).cend()))
            {
                ++ItL;
                if (ItL != ptr->cend()) {
                    ItV = ItL->cbegin();
                } else {++ItV; --ItL; }
            }
            else
            {
                ++ItV;
            }
            return *this;
        }
        const_iterator operator++(int)
        {
            auto tmp = *this;
            ++(*this);
            return tmp;
        }
        const_iterator& operator--()
        {
            if (ItV == (*ItL).cbegin())
            {
                if (ItL != ptr->cbegin())
                {
                    --ItL;
                    ItV = std::prev((*ItL).cend());
                }
            }
            else
            {
                --ItV;
            }
            return *this;
        }
        const_iterator operator--(int)
        {
            auto tmp = *this;
            --(*this);
            return tmp;
        }
        bool operator== (const const_iterator& right) const
        {
            return (ItL==right.ItL && ItV==right.ItV);
        }
        bool operator!= (const const_iterator& right) const
        {
            return !(ItL==right.ItL && ItV==right.ItV);
        }
        const T* operator->() const { return &(*ItV); }
    };
    // определите методы begin / end
    const_iterator begin() const 
    { 
        return !data_.empty() ? const_iterator(&data_) : const_iterator(); 
    }
    const_iterator end()   const 
    {
        if (!data_.empty())
        {
            return const_iterator(&data_).in_end();
        }
        return const_iterator();
    }
    // определите const_reverse_iterator
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;
        // определите методы rbegin / rend
    const_reverse_iterator rbegin() const 
    { 
        return !data_.empty() ? const_reverse_iterator(end()) : const_reverse_iterator(); 
    }
    const_reverse_iterator rend()   const 
    { 
        return !data_.empty() ? const_reverse_iterator(begin()) : const_reverse_iterator();
    }

}; 
Answer 1

1) Операторы сравнения итераторов:

bool operator== (const const_iterator& it) const
    {
        return *ItV == *it;
    }
  • сравнение данных по значениям вместо итераторов?

  • ItV имеет тип vector::const_iterator, а it имеет тип ListVector::const_iterator Решение (аналогично для operator!=):

    bool operator== (const const_iterator& it) const { return ItV == it.ItV; }

2) Оператор инкремента (наверно и декремента, не смотрел):

  • не хватает проверки для ItL != end перед разыменованием
  • не хватает проверки для ItL != end после фактического инкремента (кстати тут и крылась ошибка)

3) По соглашению все постфиксные формы инкремента/декремента должны реализовываться через префиксную форму. Т.е. все постфиксные операции должны выглядеть следующим образом:

const_iterator operator++(int)
{
    auto tmp = *this;
    ++(*this);
    return tmp;
}
READ ALSO
бинарное дерево с негативными числами

бинарное дерево с негативными числами

Как написать код для binary tree с негативными числами ? Может есть примеры ?

214
Не работает h:commandButton в JSF

Не работает h:commandButton в JSF

Есть обычная JSF страница с 2-мя формами:

217