Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Callbacks with different parameter types and storing the type

I have a communication library, that should invoke callbacks (or handlers) based on a received command type. I am storing handlers in a std::map (command as a key, handler as a value).

These handlers need to have different parameter types. There is always only one handler parameter, and this parameter inherits fromBaseType. So I have following typedefs and handlers:

class Comm {
    typedef std::function<void(BaseType*)> Handler;
    typedef std::map<Command, Handler> Handlers;

    void HandleHandshake(IntType*); // IntType inherits from BaseType
};

Unfortunately I cannot store handler HandleHandshake in the Handlers type. I can only store a handler that has parameter of type BaseType*. I cannot use std::function<void()> to bind different arguments since I need to have access to its argument_type (Otherwise I wouldn't be able to pass proper data type when invoking the handler.).

Is there any way of achieving what I want to achieve? (Storing handlers of different parameter types, and also storing the type for further use.)

To show example of calling the handler:

// I parsed a command. Handler of this command should take IntType as a parameter.
m_Handlers[cmd](IntType(some_data));
// But, I don't really know that it is IntType, I only have my map of handlers.
// I want something like this:
m_Handlers[cmd](m_Handlers[cmd]::argument_type(some_data));
like image 972
Tomáš Ondruš Avatar asked Oct 18 '25 10:10

Tomáš Ondruš


2 Answers

You could always store a lambda that does a static_cast. For example:

template <typename T=BaseType, typename F>
void store(Command c, F function)
{
     Handlers[c] = [function](BaseType* obj){
         function(static_cast<T*>(obj));
     });
}
like image 165
Barry Avatar answered Oct 21 '25 01:10

Barry


I've worked on something similar before. This is what I would do:

typedef std::function<void(BaseType*)> Handler;
typedef std::map<Command, Handler> Handlers;

Then I would have each handler take a pointer to BaseType* so that I can store it in my map.

void MyIntHandler(BaseType* b)
{
    // we know what kind of information should be passed into this method
    // so we can just cast to the correct type
    auto data = static_cast<IntType*>(b);

    // do something with data
}

void MyStringHandler(BaseType* b)
{
    auto data = static_cast<StringType*>(b);
    // ...
}

You can't store a type object like you can in C# and then use it to create objects of that type. You can use typeinfo to get some information about a particular type at runtime.

like image 32
Mohamad Elghawi Avatar answered Oct 21 '25 02:10

Mohamad Elghawi