Skip to content

Instantly share code, notes, and snippets.

@cout
Created June 19, 2014 13:45
Show Gist options
  • Save cout/e98b5ffda20beb5c61fb to your computer and use it in GitHub Desktop.
Save cout/e98b5ffda20beb5c61fb to your computer and use it in GitHub Desktop.
hi teckla
#include <iostream>
#include <boost/variant.hpp>
class Message
{
public:
virtual ~Message() { }
};
class Message1 : public Message { };
class Message2 : public Message { };
class Message3 : public Message { };
class Message4 : public Message { };
// ...
using Message_Variant = boost::variant<
Message1,
Message2,
Message3,
Message4
// ...
>;
class Message_Handler_Base
{
public:
virtual ~Message_Handler_Base() { }
// What I want is this:
//
// template<typename Message_T>
// virtual void handle(Message_T const & msg);
//
// but there is no such thing as a virtual template function.
// Solution 1: provide dynamic dispatch for every message type that
// I'm interested in:
virtual void handle(Message1 const &) { }
virtual void handle(Message2 const &) { }
virtual void handle(Message3 const &) { }
virtual void handle(Message4 const &) { }
// ...
// Solution 2: provide dynamic dispatch via a variant type. The
// derived class can override this method, then do static dispatch
// on the variant (which is basically a giant switch statement)
virtual void handle(Message_Variant const &) { }
// Solution 3: do static dispatch on the handler type (see below),
// then use a visitor to dispatch the message.
};
class My_Message_Handler
: public Message_Handler_Base
{
// provide a specialization for one of the handler functions above
};
class My_Other_Message_Handler
: public Message_Handler_Base
{
// provide a specialization for one of the handler functions above
};
char const * read_message()
{
// for demonstration purposes only
return "";
}
template<typename Message_Handlers, typename Message_T>
void dispatch(Message_Handlers & handlers, Message_T const & message)
{
// Somehow I need to dispatch this message to a function in the
// handler derived class, but the function is going to need static
// type information
}
template<typename Message_Handlers>
void event_loop(Message_Handlers & handlers)
{
while(true)
{
char const * message = read_message();
// first character in the message is the message type. Yes, I know
// I'm not doing a length check. This is for demonstation purposes
// only.
switch(message[0])
{
case 'A': dispatch(handler, Message1()); break;
case 'B': dispatch(handler, Message2()); break;
case 'C': dispatch(handler, Message3()); break;
case 'D': dispatch(handler, Message4()); break;
// ...
}
}
}
int main()
{
// Solutions 1 and 2:
{
std::vector<Message_Handler_Base *> handlers;
handlers.push_back(new My_Message_Handler);
handlers.push_back(new My_Other_Message_Handler);
event_loop(handlers);
}
// Solution 3:
{
using Handler_Variant = boost::variant<
My_Message_Handler,
My_Other_Message_Handler
// ...
>;
handlers.push_back(Handler_Variant(My_Message_Handler()));
handlers.push_back(Handler_Variant(My_Other_Message_Handler()));
event_loop(handlers);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment