Created
June 19, 2014 13:45
-
-
Save cout/e98b5ffda20beb5c61fb to your computer and use it in GitHub Desktop.
hi teckla
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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