tags:

views:

84

answers:

1

I want to do something like this: I want the user to provide a return type and an argument (there will always only be one) then I want the user to be able to provide the pointer of a function that matches this criteria. I will be using this to create a timed event. The issue here is that usually with templates you must provide T and make a new class instance, however in this case I need it kind of a runtime. ex:

TimeEvent *explode  = new TimeEvent(int (the return type),data (the argument), explodeFunc (the function pointer);

This would then create and set the function pointer. Then the caller simply does explode.call() to call it. How could I achieve something like this?

Thanks

+3  A: 

Well boost.function + boost.bind is something you can use for this:

int explodeFunc( std::string const & someString ) {
     std::cout << someString << " exploded" << std::endl;
     return 1;
}

and later...

boost::function< int() > timeEvent = boost::bind(explodeFunc, "The world"); 
int retVal = timeEvent();

But I am not sure if this is what you are looking for

Here a simple version without boost:

#include <iostream>
#include <string>

template< typename R >
struct TimeEvent {
    virtual ~TimeEvent(){}
    virtual R call() = 0;
};

template< typename R, typename ParamType >
struct TimeEventT : TimeEvent<R> {
    typedef R (*callback_type)( ParamType const & );
    typedef ParamType param_type;
    TimeEventT( param_type const & param, callback_type cb )
        : TimeEvent<R>()
        , callback_( cb )
        , param_( param )
    {}

    R call() {
        return callback_( param_ );
    }

protected:
    callback_type callback_;
    param_type param_;
};

template< typename R, typename ParamType, typename ParamValueT >
TimeEvent<R> * create_time_event( 
    R (*cb)(ParamType const &),
    ParamValueT const & param
) {
    return new TimeEventT<R, ParamType>( param, cb );
}

int explodeFunc( std::string const & param ) { 
    std::cout << param << " exploded" << std::endl;
    return 1;
}

std::string explodeFuncString( std::string const & param ) { 
    return param + " really exploded this time";    
}

int main(){
    std::string param = "The world";
    TimeEvent<int> * timeEvent1 = create_time_event( explodeFunc, param );
    if( timeEvent1 ) {
        timeEvent1->call();
        delete timeEvent1;
    }
    TimeEvent<std::string> * timeEvent2 = create_time_event( explodeFuncString, param );
    if( timeEvent2 ) {
        std::cout << timeEvent2->call() << std::endl;
        delete timeEvent2;
    }
    return 0;
}

I hope you get the idea and can make it fit your needs.

HTH

Edit: Updated with templated return type. * Made create_time_event a bit more user friendly

Vinzenz
`timeEvent` will never be null.
GMan
@GMan true because I did not use std::nothrow, I am so used to use that at work, that I always check it -.-
Vinzenz
@Vinzenz but isn't there a way to specify the return value too as a template arg?
Milo
@Milo added the example with ReturnType as template parameter
Vinzenz