2010-07-09 5 views
6

Мне нужно сохранить ряд точек данных в виде (имя, значение), где значение может принимать разные типы.C++ Как создать гетерогенный контейнер

Я пытаюсь использовать шаблон класса для каждой точки данных. Затем для каждой точки данных, которую я вижу, я хочу создать новый объект и вернуть его обратно в вектор. Для каждого нового типа мне нужно сначала создать новый класс из шаблона. Но я не могу хранить объекты, созданные в любом векторе, поскольку векторы ожидают того же типа для всех записей. Типы, которые мне нужно хранить, не могут быть установлены в иерархии наследования. Они не связаны. Также в будущем может быть больше типов, и я не хочу менять службу хранения для каждого нового типа. Есть ли способ создать гетерогенный контейнер для хранения этих записей? Спасибо!

+0

Это показывает один из способов борьбы с полиморфизмом во время выполнения. Наверное, это связано. https://youtu.be/vxv74Mjt9_0?t=16m8s –

+0

Возможный дубликат [Как хранить объекты разных типов в контейнере C++?] (Https://stackoverflow.com/questions/4738405/how-can- i-store-objects-of-different-types-in-ac-container) –

ответ

7

У библиотеки ускорения, вероятно, есть то, что вы ищете (boost :: any). Если вы не можете использовать boost ...

+1

Спасибо! Я думаю, что «любой» будет работать! Я также нашел учебник по этому вопросу, основанный на boost :: any. Вот оно, если кому-то это нужно! http://www.devx.com/cplus/10MinuteSolution/29757/1954 – Abhi

0

Я думал, что вы можете просто иметь пару (тип, void *) и написать свою собственную функцию pop, которая отличает void * в зависимости по типу, описанному в паре, а затем засуньте их в любой контейнер, попавший в глаза.

+0

, как упоминал Нил, хотя, подверженный ошибкам и неэффективный, я бы тоже не рекомендовал этого. Либо следуйте предложению Нила, либо просто используйте наследование или посмотрите на boost :: any, как упомянуто выше, 6502. – cjh

4

Проблема с контейнерами, подобная этому, заключается в том, что, когда вы хотите получить доступ к чему-либо в контейнере, вы должны определить его тип, а затем каким-то образом применить его к фактическому типу. Это уродливое, неэффективное и подверженное ошибкам, поэтому выбор # 1 на C++ заключается в использовании наследования, если у вас нет оснований для этого - я никогда не сталкивался с карьерой на C++.

+0

Спасибо Neil! ... Итак, эти типы данных в основном повсюду, это набор ручек, если вам нравится , Они могут быть длинными int, string, bool и т. Д .:(Нельзя использовать наследование .. – Abhi

+1

Проблема с векторами и классами C++ заключается в том, что вы не можете объявить вектор базы и затем поместить экземпляры Derived внутри. Из-за (или любой другой std :: container) должен использовать указатели (в конечном итоге завернутые). – 6502

+1

@Abhi Фактически вы можете использовать наследование, то есть как boost :: any works, он стирает тип в частную базу, которая имеет тип шаблона, который содержит значения, все это скрыто внутри boost :: any, где оператор-конструктор/присваивание выполняет стирание типа (это шаблоны). Однако я предлагаю вам пересмотреть свой дизайн, действительно нужно это. –

9

boost::any было рекомендовано, но это для всех, поэтому вы не можете ожидать от него многого.

Если вы знаете различные типы загодя, вам лучше использовать boost::variant.

typedef boost::variant<Foo, Bar, Joe> variant_type; 

struct Print: boost::static_visitor<> 
{ 
    void operator()(Foo const& f) const { f.print(std::cout); } 

    template <class T> 
    void operator()(T const& t) const { std::cout << t << '\n'; } 
}; 

void func(variant_type const& v) // not template 
{ 
    boost::apply_visitor(Print(), v); // compile-time checking 
            // that all types are handled 
} 

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

  • Нет связанных вопросов^_^