This question has been asked before but not answered satisfactorily.
I have a class which is acting as an event handler and I would like to have a nice syntax for calling the event handler outside of an event. What this boils down to is overriding the () operator. I currently have
class EventHandler
{
public:
void Call(void* sender, EventArgs e);
void operator() (void* sender, EventArg e){ Call(sender, e); }
};
which works fine. I can call the event handler via
EventHandler EH;
EH(nullptr, EventArgs::Empty());
My problem lies in that I usually store the event handler on the heap so I need
EventHandler* EH;
EH(nullptr, EventArgs::Empty()); // error but this is the syntax I'm hoping for
but this can only be done with
EventHandler* EH;
(*EH)(nullptr, EventArgs::Empty()); // no error
How can I override the () operator to have it work with the pointer to the EventHandler object? I have seen some things that look like overloading the ->() operator instead of just the () operator but I haven't been able to make sense of it.
The operator ->() doesn't exists.
There are two ways to call the operator.
EventHandler* EH;
(*EH)(nullptr, EventArgs::Empty());
or
EventHandler* EH;
EH->operator()(nullptr, EventArgs::Empty());
This works in the same way as the operator= or any other operator
"My problem lies in that I usually store the event handler on the heap so I need"
Is there a reason for this? If the EH involves a large amount of state, then perhaps you could build a wrapper class that put the state on the heap but that itself was allocated as an object. This would allow overloading operator()() and getting the desired syntax, while forwarding to the underlying implementation. Basically refactor to a Pimpl in order to get the syntax you want in the objects that you use in your interface.
It is often a good idea to wrap your heap allocation details in a regular type, and use the regular type rather than a pointer.
class EventHandler_Impl {
public:
void Call(void* sender, EventArgs e);
void operator() (void* sender, EventArg e){ Call(sender, e); }
};
then we write:
struct EventHandler {
void operator()(void* sender, EventArg e){ (*pImpl)(sender, e); }
private:
std::unique_ptr<EventHandler_Impl> pImpl;
};
we have a "regular" type EventHandler that stores a pointer to the "actual" class. It has methods that forward to the pImpl.
The state of this class is just one pointer. It automatically deletes the pImpl when it goes out of scope. The std::unique_ptr has the overhead of a pointer (which you'd store instead), except it destroys the pImpl object when it goes out of scope.
You can make it move-only, or manually implement a copy constructor (adding to the _Impl interface the ability to clone itself).
It is a bit of boilerplate.
You can do away with writing methods in the _Impl by simply writing them in the regular type, and having them access only state through the pImpl pointer if you choose.
You can't. EventHandler* is a pointer to a type, which is simply not callable.
You could use another functor as a wrapper, you'd only need to call it in a slightly different way.
struct EventHandlerCaller
{
void operator() (EventHandler* eh, void* sender, EventArg& e)
{
eh->operator()(nullptr, sender, e);
}
}
static EventHandlerCaller caller;
EventHandler* EH;
caller(eh, nullptr, EventArgs::Empty());
Related
When I catch an exception, I want to emit a signal and pass that exception to a slot so it can be handled in a different thread. The signal and slot are connected using a Qt:QueuedConnection type.
I first tried this:
/*in .h*/
signals:
void exceptionOccured(const std::exception &e);
public slots:
void exceptionReceive(const std::exception &e);
/*in .cpp*/
connect(this,SIGNAL(exceptionOccured(const std::exception&)),this,SLOT(exceptionReceive(const std::exception&)),Qt::QueuedConnection);
try {
throw std::runtime_error("test");
} catch (std::exception &e) {
emit exceptionOccured(e);
}
This somewhat works, but as QT makes a copy of the referenced object to be placed on the queue, the exceptionReceived slot receives a std::exception type object and all additional information is lost.
I then tried to pass a pointer to the original exception object, but that gives me the problem that by the time the slot is called the actual object has disappeared.
How can I either tell QT to make a correct copy of the exception (the actually application has multiple levels of inheritance from std::exception) or turn the catch'ed exception into some safe pointer type (i.e. copy it from the stack to the heap or so).
P.S.
The object sends the message to itself because the try/catch statement is run from a lambda function using QtConcurrent::run();
std::exception_ptrwas added to the standard one C++11 in order to solve exactly this problem. std::current_exception() lets you get a handle to the current exception, and you can then pass it around and re-throw it in any thread you want.
Details at http://en.cppreference.com/w/cpp/error/exception_ptr.
If you insist on using the base exception type, then this is a C++ problem, not a Qt problem. You'd need to implement some type of a virtual copy constructor pattern. Once you do, Qt will do the right thing automagically.
One such pattern:
class clonable_exception : public std::exception {
protected:
virtual void clone_to(clonable_exception& dst) const = 0;
public:
clonable_exception() = default;
clonable_exception(const clonable_exception& src) {
src.clone_to(*this);
}
clonable_exception & operator=(const clonable_exception& src) {
src.clone_to(*this);
}
};
All signals and slots should use the clonable_exception type instead of std::exception.
My Event Manager
For a event manager I need to store many pointers to functions in a vector to call them when the event is triggered. (I will provide the source code of the EventFunction helper class at the end of this question.)
// an event is defined by a string name and a number
typedef pair<string, int> EventKey;
// EventFunction holds a pointer to a listener function with or without data parameter
typedef unordered_map<EventKey, vector<EventFunction>> ListEvent;
// stores all events and their listeners
ListEvent List;
Registering an listener could be done by calling the first or the second function, depending on if you want receive additional data or not. (This code is from my event manager class.)
public:
typedef void (*EventFunctionPointer)();
typedef void (*EventFunctionPointerData)(void* Data);
// let components register for events by functions with or without data parameter,
// internally simple create a EventFunction object and call the private function
void ManagerEvent::Listen(EventFunctionPointer Function, string Name, int State);
void ManagerEvent::Listen(EventFunctionPointerData Function, string Name, int State);
private:
void ManagerEvent::Listen(EventFunction Function, string Name, int State)
{
EventKey Key(Name, State);
List[Key].push_back(Function);
}
Member Function Pointers
That code doesn't work because I store function pointers but not member function pointers in my List. All these pointers should be member function pointers because a component like ComponentSound will listen to the event "PlayerLevelup" with on of its member functions ComponentSound::PlayerLevelup to play a nice sound if the event is triggered.
A member function pointer in C++ looks like this.
// ReturnType (Class::*MemberFunction)(Parameters);
void (ComponentSound::*PlayerLevelup)();
The problem is, any component class should be able to listen for events, but storing the member function pointers in the event manager requires me to specify the listening class. As you can see in the example, I need to specify ComponentSound but the event manager should simply have a vector of member function pointers to any class.
Question
An Answer to one of these question would help me a lot.
How can I store function pointers to any member function in a vector in my event manager? (Maybe it helps that all the listening functions are inherited from one abstract class Component.)
How can I design my event manager in another way to reach the aimed functionality? (I want to use string and int keys for messages.)
I tried to keep my question general but if you need more informations or code please comment.
Assignments
In my vector of member function pointers I use EventFunction instead of only a pointer to provide two message types. One with, and one without a data parameter.
class EventFunction
{
private: EventFunctionPointer Pointer; EventFunctionPointerData PointerData; bool Data;
public:
EventFunction(EventFunctionPointer Pointer) : Pointer(Pointer), PointerData(NULL), Data(false) { }
EventFunction(EventFunctionPointerData PointerData) : PointerData(PointerData), Pointer(NULL), Data(true) { }
EventFunctionPointer GetFunction() { return Pointer; }
EventFunctionPointerData GetFunctionData() { return PointerData; } bool IsData() { return Data; }
void Call(void* Data = NULL){ if(this->Data) PointerData(Data); else Pointer(); }
};
You will have to use std::function. This is the only way to achieve a generic callback. As soon as you involve function pointers instead of function objects, it is not generic, will never be generic, and can never be made to be generic.
unordered_map<string, vector<std::function<void()>>>
Function pointers are bad and should never be explicitly used in C++, only passed to templates like std::bind and std::function's constructor, and member function pointers are even worse.
You can use functors to achieve this. If you wrap a functor around your member functions you can make a vector out of functors. A functor looks like this:
template <class T> class MyFunctor
{
private:
T* ObjectPtr;
void (T::*MemberFunction) ();
public:
void operator () ()
{
return (*this->ObjectPtr.*this->MemberFunction)();
}
};
So basically a functor overrides the () operator and returns the member function stored in the functor class. Functors can be quite complex if you want them to work with different signatures but in this article you can get further information.
http://www.codeproject.com/Articles/7112/Pointers-to-Member-Functions-and-Functors
Not a direct response, so bear with me.
Before we start: This is generally referred to as the Observer pattern, you might find lots of confused information on the web about it, and many failed implementations, but who knows you might also strike gold.
Okay, so first the question has a fundamental flaw: it fails to consider that capturing object references is tricky, because object lifetimes are bounded.
Therefore, even before we delve into the specifics of an implementation we need to ask ourselves how to handle stale references. There are two basic strategies:
Not having stale references, this implies that registered objects unregister themselves automatically upon destruction. The mechanism can be factored out in a base class.
Having a way to tell good and stale references apart when inspecting them, and lazily collecting the stale ones. The mechanism can be enforced using a shared_ptr/weak_ptr pair and realizing that weak_ptr are observers of the shared_ptr.
Both solutions are viable and neither implementation is perfect. The base class mechanism assumes you can actually modify your class hierarchy while the weak_ptr trick assumes that all observes will be heap-allocated and their lifetime controlled by a weak_ptr.
I will make an example using shared_ptr (and make use of a number of C++11 facilities, though none is mandatory here):
class EventManager {
typedef std::unique_ptr<Observer> OPtr;
typedef std::vector<OPtr> Observers;
public:
// Callback observers of "name"
// Returns the number of observers so invoked
size_t signal(std::string const& name) const {
auto const it = _observers.find(name);
if (it == _observers.end()) { return 0; }
Observers& obs = it->second;
size_t count = 0;
auto invoker = [&count](OPtr const& p) -> bool {
bool const invoked = p->invoke();
count += invoked;
return not invoked; // if not invoked, remove it!
};
obs.erase(std::remove_if(obs.begin(), obs.end(), invoker), obs.end());
if (obs.empty()) { _observers.erase(it); }
return count;
}
// Registers a function callback on event "name"
void register(std::string const& name, void (*f)()) {
_observers[name].push_back(OPtr(new ObserverFunc(f)));
}
// Registers an object callback on event "name"
template <typename T>
void register(std::string const& name, std::shared_ptr<T> const& p, void (T::*f)()) {
_observers[name].push_back(OPtr(new ObserverMember<T>(p, f)));
}
private:
struct Observer { virtual ~Observer() {} virtual bool invoke() = 0; };
struct ObserverFunc: Observer {
ObserverFunc(void (*f)()): _f(f) {}
virtual bool invoke() override { _f(); return true; }
void (*_f)();
};
template <typename T>
struct ObserverMember: Observer {
ObserverT(std::weak_ptr<T> p, void (T::*f)()): _p(p), _f(f) {}
virtual bool invoke() override {
std::shared_ptr<T> p = _p.lock();
if (not p) { return false; }
p->*_f();
return true;
}
std::weak_ptr<T> _p;
void (T::*_f)();
};
// mutable because we remove observers lazily
mutable std::unordered_map<std::string, Observers> _observers;
}; // class EventManager
This is the typical case where you should use polymorphism instead of function (or member function) pointers.
As you noted, your component classes should inherit from a common class Component, which contains virtual method(s) representing the event(s):
class Component
{
public:
virtual void OnPlayerLevelUp()
{
}
};
class ComponentSound : public Component
{
public:
// override it
void OnPlayerLevelUp()
{
// do the actual work
}
};
Your ListEvent type will now look like this:
typedef unordered_map<EventKey, vector<Component*>> ListEvent;
As for the optional void* paramenter in event methods, you can specify it as an optional parameter, but the fact that it's a void* is a bad sign (use of void* can lead to loss of type safety), so I would suggest that you look for a different way to achieve what you want.
I have a framework function which expects an object and a member function pointer (callback), like this:
do_some_work(Object* optr, void (Object::*fptr)()); // will call (optr->*fptr)()
How can I pass a lambda expression to it? Want to do somethink like this:
class MyObject : public Object
{
void mystuff()
{
do_some_work(this, [](){ /* this lambda I want to pass */ });
}
};
The meaning of it all is to not clutter the interface of MyObject class with callbacks.
UPD
I can improve do_some_work in no way because I don't control framework and because actually it isn't one function, there're hundreds of them. Whole framework is based on callbacks of that type. Common usage example without lambdas:
typedef void (Object::*Callback)();
class MyObject : public Object
{
void mystuff()
{
do_some_work(this, (Callback)(MyClass::do_work));
}
void do_work()
{
// here the work is done
}
};
SOLUTION Here's my solution based on Marcelo's answer:
class CallbackWrapper : public Object
{
fptr fptr_;
public:
CallbackWrapper(void (*fptr)()) : fptr_(fptr) { }
void execute()
{
*fptr_();
}
};
class MyObject : public Object
{
void mystuff()
{
CallbackWrapper* do_work = new CallbackWrapper([]()
{
/* this lambda is passed */
});
do_some_work(do_work, (Callback)(CallbackWrapper::execute));
}
};
Since we create the CallbackWrapper we can control it's lifetime for the cases where the callback is used asynchonously. Thanks to all.
This is impossible. The construct (optr->*fptr)() requires that fptr be a pointer-to-member. If do_some_work is under your control, change it to take something that's compatible with a lambda function, such as std::function<void()> or a parameterised type. If it's a legacy framework that isn't under your control, you may be able to wrap it, if it's a function template, e.g.:
template <typename Object>
do_some_work(Object* optr, void (Object::*fptr)());
Then, you can implement a wrapper template:
template <typename F>
void do_some_work(F f) {
struct S {
F f;
S(F f) : f(f) { }
void call() { f(); delete this; }
};
S* lamf = new S(f);
do_some_work(lamf, &S::call);
}
class MyObject // You probably don't need this class anymore.
{
void mystuff()
{
do_some_work([](){ /* Do your thing... */ });
}
};
Edit: If do_some_work completes asynchronously, you must allocate lamf on the heap. I've amended the above code accordingly, just to be on the safe side. Thanks to #David Rodriguez for pointing this out.
There are deeper problems with the approach that you are trying to take than the syntactical mismatch. As DeadMG suggests, the best solution is to improve the interface of do_some_work to take a functor of some sort (std::function<void()> in C++11 or with boost, or even a generic F on which operator() is called.
The solution provided by Marcelo solves the syntactical mismatch, but because the library takes the first element by pointer, it is the responsibility of the caller to ensure that the object will be alive when the callback is executed. Assuming that the callback is asynchronous, the problem with his solution (and other similar alternatives) is that the object can potentially be destroyed before the callback is executed, causing undefined behavior.
I would suggest that you use some form of plimp idiom, where the goal in this case would be to hide the need for callbacks (because the rest of the implementation might not need to be hidden you could use just another class to handle the callbacks but store it by value, if you don't want do have to dynamically allocate more memory):
class MyClass;
class MyClassCallbacks {
MyClass* ptr;
public:
MyClassCallbacks( MyClass* ptr ) : ptr(ptr) {}
// callbacks that execute code on `ptr`
void callback1() {
// do some operations
// update *ptr
}
};
class MyClass {
MyClassCallbacks callbackHandler;
public:
void mystuff() {
do_some_work( &callbackHandler, &MyClassHandler::callback1 );
}
};
In this design, the two classes are separated but represent a unique single entity, so it is fine to add a friend declaration and let MyClassCallbacks access the internal data in MyClass (both of them are one single entity, divided only to provide a cleaner interface, but coupling is already high, so adding the extra coupling requiered by friend is no problem).
Because there is a 1-1 relationship between MyClass and MyClassCallbacks instances, their lifetimes are bound and there would be no lifetime issues, except during destruction. During destruction you must ensure that there is no callback registered that can kick in while the MyClass object is being destroyed.
Since you are at it, you might want to walk the extra mile and do a proper pimpl: move all of the data and implementation into a different type that is held by pointer, and offer a MyClass that stores a pointer and offers just the public functions, implemented as forwarders to the pimpl object. This could be somehow tricky as you are using inheritance, and the pimpl idiom is a bit cumbersome to implement on type hierarchies (if you need to extend MyClass, deriving from Object could be done in the pimpl object, rather than the interface type).
I don't think you can do that. Your do_some_work() is declared to accept pointer to methods of class Object, so such should be provided. Otherwise optr->*fptr is invalid since the lambda is not member of Object. Probably you should try using std::function and adding the needed members of Object in its closure.
You must use std::function<void()>. Both function and member function pointers are highly unsuited to being callbacks.
I have a class, Mouse, than handles mouse events. It consists of a number of static functions for simple "where is it, etc" calls, but it also has a few non-static members, namely some event-handling stuff when it's used as an object. I'm having trouble, however with how I can allow any object to subscribe to the events. In my Mouse.h file I have the follwing declarations: (excuse the syntax errors, this is from memory)
typedef void (*MouseEvent)(Point pos,MouseButton button)
class Mouse {
MouseEvent m_downEvent;
//...
void HookMouseDown(MouseEvent handler);
void OnMouseDown();
}
...and in the implemenation...
void Mouse::HookMouseDown(MouseEvent handler) {
if (handler != NULL) m_downEvent = handler;
}
void Mouse::OnMouseDown() {
if (m_downEvent != NULL) m_downEvent(m_pos,m_button);
}
Now in my subscriber's code, It seemed logical to hook up the event this way:
m_mouse.HookMouseDown(&MyClass::MouseDown);
But my compiler (MVC2008) doesn't like the fact that I'm passing it a pointer-to-member-function rather a pointer-to-free-function. After some research on here, I discovered that changing my typedef to
typedef void (MyClass::*MouseEvent)(Point pos,MouseButton button)
it won't complain and will work fine, but the problem is that this restricts subscribers to the event to only MyClass objects.
Will I have to get templates involved to allow any object to subscribe to these events? Or would it be bad design to allow anything to consume mouse events in the first place?
it won't complain and will work fine, but the problem is that this restricts subscribers to the event to only MyClass objects.
Nope, you will be able to 'invoke' that member through derived class instances as well.
Regardless, the problem has been solved many times over using std::mem_fun_ptr (c++03) std::function<> (c++0x), std::bind (c++0x) and boost::bind.
Here is a full sample, see it live on https://ideone.com/mut9V:
#include <iostream>
struct MyBase
{
virtual void DoStuff(int, float) { std::cout << "Base" << std::endl; }
};
struct MyDerived : MyBase
{
virtual void DoStuff(int, float) { std::cout << "Derived" << std::endl; }
};
int main()
{
typedef void (MyBase::*memfun)(int, float);
memfun event(&MyBase::DoStuff);
MyBase base;
MyDerived derived;
(base.*event)(42, 3.14);
(derived.*event)(42, 3.14);
}
To make the class Mouse handle pointers to member-functions of arbitrary classes, you could make it a template:
template<class T>
class Mouse {
typedef void (T::*MouseEvent)(Point pos,MouseButton button);
MouseEvent m_downEvent;
//...
void HookMouseDown(MouseEvent handler);
void OnMouseDown();
}
Or would it be bad design to allow anything to consume mouse events in the first place?
I think it is quite nice to use an event based design. On the other hand it is a pain in the ass to support both free functions and member functions. Especially if you have also to supply the instance which calls this function.
Coincidentally I stumbled upon a Delegate implementation which exactly deals with this matter. Have a look at this interesting article.
The HookMouseDown could now return a reference to an internal delegate, which then can be bound to either a free function or a member function:
mouse.HookMouseDown().Bind<MyClass, &MyClass::MyMember>(myinstance);
You really want std::function and std::bind/lambdas (function/bind also available in Boost). This more than adequately solves the problem.
I'd like to have a dynamic messaging system in my C++ project, one where there is a fixed list of existing events, events can be triggered anywhere during runtime, and where you can subscribe callback functions to certain events.
There should be an option for arguments passed around in those events. For example, one event might not need any arguments (EVENT_EXIT), and some may need multiple ones (EVENT_PLAYER_CHAT: Player object pointer, String with message)
The first option for making this possible is allowing to pass a void pointer as argument to the event manager when triggering an event, and receiving it in the callback function.
Although: I was told that void pointers are unsafe and I shouldn't use them.
How can I keep (semi) dynamic argument types and counts for my events whilst not using void pointers?
Since others have mentioned the visitor pattern, here is a slight twist using Boost.Variant. This library is often a good choice (or at least it has been for me) when you need a set of different behaviors based on a value. Compared to a void*, it has the benefit of static type checking: if you write a visitor class the misses one of the cases, your code will not compile rather than failing at run time.
Step 1: Define message types:
struct EVENT_EXIT { }; // just a tag, really
struct EVENT_PLAYER_CHAT { Player * p; std::string msg; };
typedef boost::variant<EVENT_EXIT,
EVENT_PLAYER_CHAT> event;
Step 2: Define a visitor:
struct event_handler : public boost::static_visitor<void> {
void operator()(EVENT_EXIT const& e) {
// handle exit event here
}
void operator()(EVENT_PLAYER_CHAT const& e) {
// handle chat event here
std::cout << e.msg << std::endl;
}
};
This defines an event handler that nicely separates out the code for each kind of event. The existence of all operator() overloads is checked at compile time (on template instantiation), so if you add an event type later, the compiler will force you to add corresponding handler code.
Note that event_handler subclasses boost::static_visitor<void>. This determines the return type for each of the operator() overloads.
Step 3: Use your event handler:
event_handler handler;
// ...
event const& e = get_event(); //variant type
boost::apply_visitor(handler, e); // will not compile unless handler
// implements operator() for each
// kind of event
Here, apply_visitor will call the appropriate overload for the 'actual' value of e. For example, if we define get_event as follows:
event get_event() {
return EXIT_EVENT();
}
Then the return value will be converted implicitly to event(EXIT_EVENT()). Then apply_visitor will call the corresponding operator()(EXIT_EVENT const&) overload.
Templates would allow you to write a type-safe event manager without it knowing the message types a-priori.
If the event types change at runtime, or you need to mix multiple types into a single container, you can use pointers to a common base class of all the message/event types.
Something I've done in the past is set up a delegate-based system not unlike what is in C#, using the (excellent) FastDelegate library: http://www.codeproject.com/Articles/7150/Member-Function-Pointers-and-the-Fastest-Possible
So with that in hand, I created some general-purpose Event classes to contain the lists of delegates, like so:
template <class T1>
class Event1 {
public:
typedef FastDelegate1<T1> Delegate;
private:
std::vector<Delegate> m_delegates;
public:
// ...operator() to invoke, operators += and -= to add/remove subscriptions
};
// ...more explicit specializations for diff arg counts (Event2, etc.), unfortunately
Then you can have the various sub-components expose their specific event objects (I used an interface-style but that's not necessary):
typedef Event2<Player*, std::string> PlayerChatEvent;
class IPlayerEvents {
public:
virtual PlayerChatEvent& OnPlayerChat() = 0;
virtual PlayerLogoutEvent& OnPlayerLogout() = 0; // etc...
};
Consumers of this interface can register like so:
void OtherClass::Subscribe(IPlayerEvent& evts) {
evts.OnPlayerChat() += MakeDelegate(this, &OtherClass::OnPlayerChat);
}
void OtherClass::OnPlayerChat(Player* player, std::string message) {
// handle it...
}
The result is is all individually static-typed per event type--no dynamic_casting. However it does decentralize the event system, which may or may not be an issue for your architecture.
You could use a base class, optionally abstract, and use dynamic_cast. The argument will be checked at run-time. A compile-time would probably be better, though.
class EventArgs
{
public:
virtual ~EventArgs();
};
class PlayerChatEventArgs : public EventArgs
{
public:
PlayerChatEventArgs(Player* player, const std::string& message);
virtual ~PlayerChatEventArgs();
Player* GetPlayer() const;
const std::string& GetMessage() const;
private:
Player* player;
std::string message;
};
class Event
{
public:
virtual ~Event() = 0;
virtual void Handle(const EventArgs& args) = 0;
};
class ExitEvent : public Event
{
public:
virtual ~ExitEvent();
virtual void Handle(const EventArgs& /*args*/)
{
// Perform exit stuff.
}
};
class PlayerChatEvent : public Event
{
public:
virtual ~PlayerChatEvent();
virtual void Handle(const EventArgs& args)
{
// this will throw a bad_cast exception if cast fails.
const PlayerChatEventArgs& playerchatargs =
dynamic_cast<const PlayerChatEventArgs&>(args);
// Perform player chat stuff.
}
};
I would think about having a base class for the messages, and then derive all the messages from that base class. You will then be passing pointers to the base class around the events.
You will, presumably, have some basic funcitonaliy in the base class, which may include a member saying what type of message it is. This will allow you to check the message type before casting to the version you need.
It is tempting to have the base class as the most basic type of message, but I would advise making it a virtual class so that every message has to be cast to be used. This symmetry makes it much less prone to bugs later when the complexity (inevitably) increases