Пользовательский итератор на основе диапазона для шаблонного вектора векторов

У меня есть задание, которое сводит меня с ума. Я изучал базовые концепции, чтобы расширить свои знания и попытался применить их к этой проблеме, но я немного застрял.

У нас есть файл main.cpp, который тестирует класс VectorOfVectors с таким синтаксисом:

for( int num : intVov )
{
     printf( "%d ", num );
}

Мы создаем наш собственный класс VectorOfVectors с шаблонными векторами в качестве элементов.

Мы должны заставить основную функцию работать должным образом, создав собственный настраиваемый итератор, который перебирает все значения, как показано главной функцией. Я исследовал основанные на диапазоне итераторы, но меня немного смущает вопрос о том, как создавать свои собственные, и, поскольку это вектор векторов, синтаксис не очень хорошо согласуется с некоторыми онлайн-примерами.

Я хотел бы получить руководство относительно того, как я могу создать этот итератор. Я знаю, что мне нужна функция begin() и end(), а также переопределить функцию operator++, чтобы заставить ее работать. Будет ли мой итератор использовать значения int в качестве указателей, которые я увеличиваю в operator++? Нужны ли мне два указателя? Что будут возвращать begin() и end(), итераторы или целые числа, или значения T, или векторы? Как мне построить итератор и какие данные мне нужны для него? Будет ли конструктор итератора принимать два указателя в качестве значений, или один, или как это будет работать? Нужна ли итератору его собственная копия VectorOfVectors для итерации (и она будет установлена ​​в конструкторе)?

Как бы я пошел на увеличение указателей? Любая помощь, общие знания или даже советы будут с благодарностью!

Вот то, что я возился, просто как ссылка.

#include <vector>

using std::vector;


template< typename T > class VectorOfVectors
{
public:

    class iterator
    {
        public:
            //Constructor
            iterator(const VectorOfVectors<T> * vov, int pos_vov, int pos_v)
            {
                _pos_vov = pos_vov;
                _pos_v = pos_v;
                _vov = vov;
            }

            bool operator!= (const iterator & other) const
            {
                return pos != other._pos;
            }

            int operator* () const;

            const iterator operator++ ()
            {
                _pos_v++;
                if (_pos_v == _pos_vov->end())
                {
                    _pos_vov++;
                    if (_pos_vov == _vov.end())
                    {
                        --_pos_vov;
                        _pos_v = _pos_vov->end();
                        --_pos_v;
                        return (*this);
                    }
                    else
                    {
                        _pos_v = _pos_vov->begin();
                        return (*this);
                    }
                }
                else
                {
                    return (*this);
                }
            }

    private:
        int _pos_v;
        int _pos_vov;
        const VectorOfVectors<T> * _vov;
    };

    void AddEmptyVector()
    {
        vectorOfVectors.push_back(new vector<T>());
    }

    int GetVectorCount() const
    {
        return vectorOfVectors.size();
    }

    vector<T> GetVectorAtIndex(int index)
    {
        return vectorOfVectors.at(index);
    }

    void AddCopyOfVector(vector<T> & toBeAdded)
    {
        vectorOfVectors.push_back(toBeAdded);
    }

    iterator begin() const
    {
        return iter(this, 0, 0);
    }

    iterator end() const
    {
        return iterator(this, 4, 3);
    }

private:
    vector< vector<T> > vectorOfVectors = new vector< vector<T> >();

};

1 ответ

От for Похоже, что в цикле, который вы разместили, инструктор хочет, чтобы итератор выполнял итерации по отдельным элементам вектора векторов (а не, например, по субвекторам).

begin() а также end() всегда должен возвращать итераторы, а не элементы, на которые указывают итераторы (например, не необработанные intв этом случае). В некоторых особых случаях может быть возможно сделать эти необработанные указатели (например, я думаю, что некоторые реализации STL std::vector::iterator сделать это), но, как правило, они должны быть маленькими structСодержит достаточно информации для навигации по родительской структуре данных.

Смотрите эту страницу для хорошего описания того, что for (var : collection) синтаксис на самом деле переводится как. Это говорит о том, что вам нужно спроектировать тип итератора Iter который имеет следующие свойства:

  • *Iter возвращает Tили что-то конвертируемое в T (лайк T&). Вы в настоящее время имеете это неправильно - ваш int operator* () const; (который, кажется, не определен?) возвращает intпо какой-то причине.
  • ++Iter перемещает итератор к следующему элементу.
  • Iter1 != Iter2 возвращается false когда два итератора указывают на один и тот же элемент.

Как вы на самом деле создаете Iter Тип полностью зависит от вас. Использование 2-х целочисленных индексов и проверка на "wraparound" на ++ как ты сейчас делаешь мне кажется здоровым.

Другие заметки:

  • Ваш begin() в настоящее время звонки return iter(this, 0, 0);, который даже не скомпилируется.
  • Пожалуйста, не размещайте указатели динамически std::vector, как вы делаете в декларации vectorOfVectors И в AddEmptyVector(), Для начала ни один из них не скомпилируется, потому что для их компиляции вам нужно объявить vectorOfVectors как указатель на вектор указателей на векторы, и вы не хотите этого делать, потому что std::vector внутренне управляет собственным динамическим распределением памяти - избегая необходимости когда-либо вызывать new а также delete является основной причиной, по которой вы используете std::vector на первом месте.
Другие вопросы по тегам