Общий контейнер в C ++ - PullRequest
       7

Общий контейнер в C ++

10 голосов
/ 31 декабря 2010

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

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

Может кто-нибудь направить меня в лучшем направлении, чем приведенный ниже пример кода?

template<class C, typename I>
class Container
{
 public:
 //...

    void push(const I& item)
    {
        if(typeid(C) == typeid(std::priority_queue<I>))
        {
           std::priority_queue<I>* container = (std::priority_queue<I>*)&_container;
           container->push(item);
        }
        if(typeid(C) == typeid(std::list<I>))
        {
           std::list<I>* container = (std::list<I>*)&_container;
           container->push_back(item);
        }
        else
        {
           //error!
        }
     };

  private:
     C _container;
 //...
}

Спасибо

Ответы [ 3 ]

7 голосов
/ 31 декабря 2010

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

Пусть ваши плагины предоставляют итераторы begin и end в свои коллекции элементов, а затем используют диапазон по своему усмотрению.

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

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

0 голосов
/ 31 декабря 2010

Начните с класса, как указано выше, предоставьте минимальный интерфейс, необходимый для ваших плагинов. Затем реализуйте его в терминах контейнера, который вы собираетесь использовать. Это называется контейнерным адаптером, и именно так реализован std :: stack.

Если вам действительно нужен адаптер для более чем одного контейнера STL с шаблоном, взгляните на std :: stack, он покажет, как это сделать.

Не включайте typeid, зачем вам это нужно?

Кстати, придерживайтесь того, что предлагает Джеймс, если нет необходимости выставлять сам контейнер.

0 голосов
/ 31 декабря 2010

Знаете, когда вы писали "общий интерфейс", я был уверен, что вы собираетесь показать что-то в стиле Java с абстрактным классом и подклассами, которые обертывают стандартные контейнеры. Я был удивлен, увидев кучу звонков типа ...

Но тогда, почему вы хотите это сделать? Большинство контейнеров имеют общий интерфейс, и с мощью SFINAE вам даже не нужно писать специальный код! Просто используйте шаблоны и вызывайте метод напрямую.

РЕДАКТИРОВАТЬ: забыл, что стандартные контейнеры не имеют виртуальных методов и, следовательно, не может быть dynamic_cast ред.

...