Lets say I have a class Handler with some subclasses like stringhandler, SomeTypeHandler, AnotherTypeHandler. The class Handler defines a method "handle" as a common interface for all the subclasses. The logic to "handle" is ofcourse completely different for the different handlers.
So what I need to do is pass a value of anything to the handle method. The specific classes can then cast the "anything" to the type they expect.
Basically what I need is something like the java class Object :D
The first thing I tried was a void*
, but apparently you can not do B* someB = dynamic_cast<B*>(theVoidPointer)
, so no luck there.
My second idea was to use boost::any
. however, the requirement to use boost::any is that the value must be copy cunstructable, which is not the case for my data.
Any ideas to get this to work?
Thanks
EDIT: Note that I know I could use a SomeData class with no members at all, and let my data be subclasses of that, but I am looking for a more generic approach which does not require me to make my own wrapper class.
You can for example define a base class:
class BaseHandlerData {
...
};
Then derive your specific data classes, which are expected by your handlers:
class StringData: public BaseHandlerData {
...
};
class SomeData: public BaseHandlerData {
...
};
Then you should be able to pass a BaseHandlerData* argument to the handle method, and use something like:
void handle(BaseHandlerData *data) {
StringData* stringData = dynamic_cast<StringData*>(...);
// handle your string data here ...
}
to safely cast to your expected data type.
Gerald
Okay, here is a simple approach using boost::any to hold pointers to your datatypes. However, beware that boost::any adds some overhead code decreasing performance slightly (in most cases neglectible).. consider using boost::spirit::hold_any instead, or void* if you don't need type safety.
class Handler {
public:
void handle( boost::any value ) {
do_handle( value );
}
private:
virtual void do_handle( boost::any& value ) = 0;
};
template<class T>
class HandlerBase : public Handler {
private:
void do_handle( boost::any& value ) {
// here you should check if value holds type T*...
handle_type( *(boost::any_cast<T*>( value )) );
}
void handle_type( const T& value ) = 0;
};
class StringHandler : HandlerBase<std::string> {
private:
void handle_type( const std::string& value ) {
// do stuff
}
};
Now you can write lots of handler classes, deriving from HandlerBase, without assuming that the handled types have a common base class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With