Even for a self-contained code base, it's a pain compared to a type that just works with any current or future derived class.
Even for a self-contained code base, it's a pain compared to a type that just works with any current or future derived class.
enum EventType {
...,
EVENT_USER_START = 0xF0000000,
};
struct UserEventData { uint8 placeholder[64]; }
struct Event {
EventType type;
union {
UserEventData user;
};
}
That aside, have you ever felt the need to implement your own Win32 event, or SDL event, or X11 event, or epoll_event, or a custom DOM event or whatever?If you're writing a good library, give the user the data they need, and let them handle it however they wish, don't force them int your framework.
Typically with your pattern, you'd use a switch statement on the event type, but what do you do if it's in the user-defined space (type>=EVENT_USER_START)? You could add mandatory function pointers for relevant handlers in a header prefix, but now you're just reimplementing virtual methods. As is common in C, you end up making your own object-oriented language, only with more effort and not as good.
-or- in places where you simply want to maintain a compilation firewall, for compile times, or encapsulation... i.e. you don't want to update the "visitor" in a pile of unrelated files each time you come up with a new Event.