2013-04-18 3 views
2

Я новичок в STL и хотел узнать, как это сделать: Я хотел в гнездо контейнеров с элементами разных типов. Моя идея была набором, элементами которого могли быть либо векторы, либо карты.Вложенные контейнеры разных типов

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

Будет ли альтернатива для реализации чего-то подобного?

+0

Итак, вам нужен 'std :: set >'? –

+2

На самом деле не имеет смысла. Набор упорядочен, что означает, что вам нужно заказывать векторы относительно карт. – MSalters

ответ

2

Вы не можете поместить два разных вида объектов в стандартный контейнер. То, что вам нужно сделать, это «обернуть» контейнер в другом объекте, который «знает», какой именно объект он фактически удерживает. boost::variant<T1, T2 ... > - относительно стандартный способ сделать это. Если вы не можете использовать библиотеку наддува, то вы можете найти что-то вроде этого работает нормально:

struct wrapper 
{ 
    int type; // or enum 
    union { 
     vector v; 
     map m; 
    } content; 
}; 
+1

Обратите внимание, что подход в коде действителен только в C++ 11, и вам нужно будет предоставить некоторый дополнительный код в 'wrapper', чтобы он работал (в частности, чтобы установить соединение для обращения к одному типу или другому, требуется вызов соответствующий конструктор/деструктор, чтобы избежать утечек памяти. –

+0

Спасибо за предложение boost :: variant. Я думаю, что я сначала попытаюсь использовать более быстрый подход с одним вложенным типом, а затем погрузиться в boost. –

1

То, что вы пытаетесь сделать, это на самом деле не поддерживается языком, и в то время как вы можете заставить его работать, это не будет простым или изящным. Подход, предложенный sftrabbit (после того, как вы исправите синтаксис :)), может получить вас на полпути, но для итерации потребуется создание посетителя, возможно, с помощью функтора, который будет применяться к элементам; чтобы иметь возможность использовать его внутри заказанного контейнера, вам нужно будет обернуть его типом, который обеспечивает заказ ...

Другая проблема с вашим предполагаемым дизайном заключается в том, что std::set не позволяет изменять вложенные элементы, которые в основном означает, что после добавления контейнеров в std::set они становятся неизменными. Если это нормально, вы можете использовать другой подход и просто поддерживать std::vector<ElementType*>, чтобы указать на все существующие элементы после включение во внешний std::set. Это позволит вам выполнять более простую линейную настройку по всем элементам.

Более простое решение может быть создание класса, который заменяет внешний контейнер и внутри имеет две разные std::set (опять же при условии, что неизменность не является проблемой, или другой контейнер, если это необходимо), один для каждого вложенного контейнера:

class Container { 
    std::set<std::vector<Type>> d_vectors; 
    std::set<std::map<Key,Type>> d_maps; 
... 

Тогда тип Container может содержать функции, которые проходят через внутренние контейнеры.

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

+0

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

Смежные вопросы