Использование итераторов для скрытия внутреннего контейнера и выполнения общих операций над базовым контейнером - PullRequest
3 голосов
/ 03 февраля 2010

Я в основном хочу иметь базовый контейнерный класс, который может возвращать универсальный итератор, который можно использовать для обхода экземпляра контейнерного класса, без необходимости указывать шаблоны итератора.Я думаю, что не могу реализовать базовый контейнер над шаблоном класса, который затем потребовал бы алгоритм обхода, основанный на классах шаблона, которые не известны заранее.Базовый контейнер может быть унаследован и реализован с использованием любого (пользовательского или стандартного) типа / реализации контейнера внутри.Вот несколько примеров кода, чтобы прояснить это:

struct MyObject {
  int myInt;
}

// an abstract container
class BaseContainer {
public:
  virtual void insertMyObject(MyObject& obj) = 0;
  virtual iterator getFirst(); // the iterator type is for demonstration purposes only
  virtual iterator getLast();  // the iterator type is for demonstration purposes only
}

// Sample container class that uses a std::vector instance to manage objects
class BaseContainer_Vector : public BaseContainer {
public:
  void insertMyObject(MyObject& obj); // e.g. just pushes back to the vector
  iterator getFirst(); // needs to override the iterator?
  iterator getLast();  // needs to override the iterator?
private:
  std::vector<MyObject> objectContainer;
}

Затем у меня будет список объектов-контейнеров, и я хочу перебрать и эти контейнеры, и сохраненные объекты.

std::vector<MyContainer*> containers;
for(int i=0 ; i<containers.size() ; i++){
  iterator i    = containers[i]->getFirst();
  iterator iend = containers[i]->getLast();
  for(; i != iend ; i++) {
    std::cout << (*i).myInt << std::endl;
  }
}

Кроме того, я хотел бы получить поддержку для выражения макроса boost foreach.Он поддерживает расширения до тех пор, пока функции range_begin и range_end работают правильно.Но пример в boost doc использует std :: string :: iterator в качестве возвращаемого типа, в то время как мне нужен общий класс итераторов, и я пока не могу понять, как это сделать.

std::vector<MyContainer*> containers;
for(int i=0 ; i<containers.size() ; i++){
  BOOST_FOREACH(MyObject obj, *(containers[i])) {
    std::cout << obj.myInt << std::endl;
  }
}
* 1009Я думаю, что могу определить свой собственный класс итераторов, тогда каждый класс, который расширяет BaseContainer, должен определить свой собственный итератор, расширяющий этот базовый итератор.Тем не менее, я бы предпочел использовать стандартные итераторы (stl или boost) для поддержки этой структуры, а не писать свои собственные итераторы.Я думаю, что этот подход будет работать, но я открыт для комментариев относительно его эффективности.

Есть ли выполнимый подход, который может элегантно решить эту проблему?Или я упускаю простой момент, который может решить эту проблему безо всякой боли?

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

1 Ответ

1 голос
/ 03 февраля 2010

Это будет сложно.

Как уже говорилось, сначала вам нужно, чтобы ваши итераторы имели значение семантическое, потому что, поскольку они обычно копируются, в противном случае это приведет к нарезке объектов.

class BaseContainer
{
protected:
  class BaseIteratorImpl; // Abstract class, for the interface

public:
  class iterator
  {
  public:
    iterator(const BaseIteratorImpl& impl);
  private:
    BaseIteratorImpl* m_impl;
  };

  iterator begin();
  iterator end();
}; // BaseContainer

Затем BaseIterator перенаправляет все методы на m_impl.

Таким образом, вы получаете семантический синтаксис значения с полиморфным ядром.

Очевидно, вам придется обращаться с семантикой глубокого копирования и надлежащим уничтожением.

Некоторые заметки:

  • публикует iterator и const_iterator класс
  • Назовите ваши методы empty, size, begin, end и т. Д. ... для совместимости с алгоритмами STL

Вы можете проверить SGI Iterators для получения справки о концепциях и операциях, которые ваши операторы должны поддерживать для максимальной совместимости.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...