указатели boost::variant и void*

Мне нужен вариантный тип, который содержит экземпляры любого определяемого пользователем класса. Поэтому я использую void*:

typedef boost::variant<void*, int, float, std::string> Tvariant;

Я создал класс-оболочку с картой:

typedef std::map<std::string, Tvariant> Tvalues;

Пример использования:

int x = 123;
attributes.set("int_var", x);
x = attributes.get<int>("int_var");

MyClass* obj = new MyClass();
attributes.set("void*_var", obj);
obj = static_cast<MyClass*>( attributes.get<void*>("void*_var") );
obj = attributes.cast<MyClass*>("void*_var"); // the same

Есть 2 проблемы с этим void* в классе вариантов:

  1. Копирование атрибутов с указателями на динамически выделенную память опасно и чревато ошибками.
  2. Пользователь может static_cast void* использовать WrongClass*, а не MyClass*. Он компилируется, но результат непредсказуем.

Возможные решения:

  1. Используйте boost::shared_ptr‹ void* >.
  2. Запомните typeid для всех значений void* (при их добавлении) в файле std::map<void*, typeid> typeid_map. Когда пользователь запрашивает значение void*, приводя его к любому TClass*, давайте оценим утверждение: assert(typeid_from_typeid_map == typeid(TClass*)).

Вопросы:
1. Существуют ли другие решения для хранения значений любого определяемого пользователем класса?
2. Может быть, вы порекомендуете лучшие решения для упомянутых проблем и укажете на некоторые другие проблемы?


person topright gamedev    schedule 07.02.2011    source источник


Ответы (1)


Вы смотрели Boost::Any? Это то, что несет в себе информацию о приведении типа во время компиляции, скрывая, какой это тип на самом деле, через Any.

person wheaties    schedule 07.02.2011
comment
Да, но boost::any не обеспечивает проверки во время компиляции и работает медленнее, чем boost::variant. Обеспечивает ли boost::any безопасность типов при приведении любого значения к пользовательскому классу? - person topright gamedev; 07.02.2011
comment
@topright Поскольку вы уже используете Boost, boost::any кажется подходящим вариантом. - person karlphillip; 07.02.2011
comment
@topright: boost::any обеспечивает проверку типа во время выполнения, а any_cast требует от вас указать тип, который вы хотите получить, например. Myclass* c = any_cast<MyClass*>(myMap["myClassObj"]), который выдает bad_any_cast, если вы ошиблись с типом. Поскольку вы будете искать значения на карте, я сомневаюсь, что накладные расходы boost::any будут иметь для вас значение. Boost any синтаксически очень чистый и очень безопасный. - person Alexandre C.; 07.02.2011
comment
@topright gamedev Мне жаль, что у меня не было времени изложить свой ответ более подробно. Обычно я публикую только тогда, когда мне нужно несколько минут простоя, выходные или нерабочее время. - person wheaties; 07.02.2011
comment
@wheaties, все в порядке, я уже знал о boost::any и просто изменил свою реализацию, чтобы использовать ее. Что меня беспокоило, так это производительность и безопасность типов. - person topright gamedev; 07.02.2011