Пользовательский итератор на основе диапазона для шаблонного вектора векторов
У меня есть задание, которое сводит меня с ума. Я изучал базовые концепции, чтобы расширить свои знания и попытался применить их к этой проблеме, но я немного застрял.
У нас есть файл 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
на первом месте.