2011-02-07 2 views
2

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

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 проблемы, связанные с этой пустотой * в варианте:

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

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

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

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

ответ

6

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

+0

Да, но boost :: any не обеспечивает проверку времени компиляции и медленнее, чем boost :: variant. Поддерживает ли boost :: any обеспечить безопасность типа при литье любого значения в пользовательский класс? –

+0

@topright Поскольку вы уже используете Boost, boost :: any похоже на способ. – karlphillip

+2

@topright: 'boost :: any' обеспечивает проверку типа времени выполнения, а' any_cast' требует указать тип, который вы хотите получить, например. 'Myclass * c = any_cast (myMap [" myClassObj "])', который вызывает «bad_any_cast», если вы ошибались в отношении типа. Поскольку вы будете искать значения на карте, я сомневаюсь, что накладные расходы 'boost :: any' будут иметь отношение к вам. Boost any синтаксически очень чист и очень безопасен. –

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