Reputation: 791
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.
Upvotes: 2
Views: 192
Reputation: 275976
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.
Upvotes: 1
Reputation: 4367
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());
Upvotes: 0
Reputation: 7303
"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.
Upvotes: 2
Reputation: 646
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
Upvotes: 7
Reputation: 304162
You can't. EventHandler*
is a pointer to a type, which is simply not callable.
Upvotes: 0