Search code examples
c++pointersboost-any

How can I pass "Any kind of data" to a function in C++


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.


Solution

  • 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.