У меня есть структура, которая содержит векторы разных типов. Я хотел бы создать один итератор, который будет перебирать каждый элемент каждого вектора и в соответствии с конкретными правилами предоставлять конкретное значение с помощью оператора *
. Я уже создал игрушечный пример для итератора итераторов:
/*--------------------------------------------------------------------*/
/* Copyright (C) Inria 2014
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Project: MixtComp
* Created on: Feb 20, 2014
* Author: Vincent KUBICKI <[email protected]>
**/
#include <iostream>
#include <iterator>
#include <vector>
class MyIterator : public std::iterator<std::input_iterator_tag, int>
{
typedef std::vector<int>::const_iterator it ;
typedef std::vector<it> vecit;
typedef std::vector<it>::iterator itit ;
public:
MyIterator(it itA ,
it itB ,
it endA,
it endB)
{
vec_it_.push_back(itA);
vec_it_.push_back(itB);
vec_end_.push_back(endA);
vec_end_.push_back(endB);
it_vec_it_ = vec_it_.begin();
it_vec_end_ = vec_end_.begin();
if (itA == endA)
{
++it_vec_it_;
++it_vec_end_;
}
}
MyIterator(const MyIterator& mit) :
vec_it_(mit.vec_it_),
vec_end_(mit.vec_end_),
it_vec_it_(mit.it_vec_it_),
it_vec_end_(mit.it_vec_end_)
{}
MyIterator& operator++()
{
if (*it_vec_it_ != *it_vec_end_)
{
++(*it_vec_it_);
if (*it_vec_it_ == *it_vec_end_)
{
++it_vec_it_;
++it_vec_end_;
}
}
return *this;
}
MyIterator operator++(int)
{
MyIterator tmp(*this);
operator++();
return tmp;
}
bool operator==(const MyIterator& rhs)
{
return (*it_vec_it_ == *(rhs.it_vec_it_));
}
bool operator!=(const MyIterator& rhs)
{
return (*it_vec_it_ != *(rhs.it_vec_it_));
}
const int operator*()
{
return *(*it_vec_it_);
}
private:
vecit vec_it_; // vector of current iterators
vecit vec_end_; // vector of end iterators
itit it_vec_it_; // iterator on vec_it_
itit it_vec_end_; // iterator on vec_end_
};
int main () {
std::vector<int> dataA {1, 3, 4, 9};
std::vector<int> dataB {11, 34, 43};
MyIterator from(dataA.begin(),
dataB.begin(),
dataA.end(),
dataB.end());
MyIterator until(dataA.end(),
dataB.end(),
dataA.end(),
dataB.end());
for (MyIterator it = from; it != until; ++it)
{
std::cout << *it << std::endl;
}
return 0;
}
Однако в этой реализации оба dataA
и dataB
являются векторами того же типа. Предположим, что я хотел бы иметь разные типы векторов, например std::vector<std::pair<int, int>>
и std::vector<std::pair<int, std::vector<int>>>
.
Есть ли разумный (и простой) способ достичь этого?
Мои первые мысли заключались в замене it
типа комбинацией Base
и Derived
итераторов. itit
будет итератором на std::vector<Base>
. Чтобы сравнить Base
итераторы, я бы использовал указатели void
для сравнения адресов их соответствующих объектов, указывающих на объект. operator*()
будет определяться в классах Derived
и будет обеспечивать одинаковый результат, например int
.
Мы сделаем замену itit
структурой switch/case
. Целое число, таким образом, Виль отслеживать "текущий" it
объект.
boost::variant
.