2015-03-15 5 views
4

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

ParentStringList["somekey"] = "just a string value"; 
ParentStringList["anotherkey"] = SomeChildStringList; 

Вопрос в том, как я достичь того же самого в C++?

То, что я на данный момент:

typedef boost::variant< std::string, my_dictionary > my_variant; 
typedef std::map < std::string, my_variant > my_dictionary; 

... который явно круговым.

Могу ли я сделать это без обертывания вещей в structs (который я могу переслать объявление) или без использования указателей (которые компилятор знает о размере)?

+0

'struct X {X x; }; '- нет. –

+1

Ваше отвращение к указателям - очень хорошее отношение к C++, но в этом конкретном случае немного раздуто. Я предполагаю, что реализация Delphi также решит эту проблему с указателями внутри. Если бы я был вами, я бы использовал решение, основанное на указателях (возможно, с 'std :: unique_ptr') и прекрасно переносило все в класс с полностью свободным от указаний интерфейсом. –

ответ

3

Boost.Variant documentation охватывает этот точный случай. Вы не можете сделать это без использования указателей или другой подобной обертки.

-2

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

+0

Это неверно - 'std :: vector' не гарантированно разрешает рекурсивные структуры данных (хотя на практике это поддерживают все разумные реализации). Но, что еще хуже, это не помогает ОП, потому что они хотят использовать * динамические * значения типов. –

+0

Вы имеете в виду произвольные типы данных? Пожалуйста, объясните «динамический»? – user1973385

+0

Под «динамическим» я подразумеваю, что обычно подразумевается под «динамическим типом», т. Е. Используемый фактический тип известен только во время выполнения, еще не во время компиляции. Это не то же самое, что «произвольное», потому что тип все еще может быть статически привязан к четко определенному подмножеству всех возможных типов. –

0

Такой подход мог бы работать:

struct my_variant; 
typedef map<string,my_variant> my_dict; 
struct my_variant: variant<string, my_dict> 
{}; 

Есть несколько проблем с этим, хотя:

  • Это требует контейнеров (std::map специально), позволяющие аргументы шаблона, которые не полностью определены. Используя C++ 98, это явно запрещено, я не уверен, что это было снято в более поздних версиях на C++.
  • Публично вытекающие из контейнеров обычно не являются хорошей идеей, пожалуйста, изучите причины этого и как они применяются к вашей программе. Использование сдерживания вместо деривации было бы более безопасной альтернативой или средним способом частного деривации, но это нарушает полезную связь IS-A, которую обеспечивает этот подход.
Смежные вопросы