I need a variant type that holds instances of any user-defined class. So I use void*:
typedef boost::variant<void*, int, float, std::string> Tvariant;
I’ve created a wrapper class with a map:
typedef std::map<std::string, Tvariant> Tvalues;
Example of usage:
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
There are 2 issues with this void* in variant class:
- Copying attributes with pointers to dynamically allocated memory is dangerous and error-prone.
- User can static_cast void* to WrongClass*, not to MyClass*. It compiles, but result is unpredicted.
Possible solutions:
- Use boost::shared_ptr< void* >.
- Remember typeid for all void* values (when they are added) in the
std::map<void*, typeid> typeid_map. When user requests for void* value, casting it to any TClass*, let’s evaluate an assertion:assert(typeid_from_typeid_map == typeid(TClass*)).
Questions:
1. Are there other solutions to hold values of any user-defined class?
2. May be you will recommend better solutions for mentioned issues and point some other issues?
Have you look at Boost::Any? This is something that carries with it compile time knowledge of the casting of the type while hiding what type it really is via the Any.