I wrote a template class to allow a C#-like events in C++. It takes a typename EVENT_ARGS
that serves as the parameter passed by the raised event. And using a typename HOSTING_CLASS
to have the raise()
function private and only allow raise from the class that exposes the event.
template<typename HOSTING_CLASS, typename EVENT_ARGS>
class Event
{
friend HOSTING_CLASS;
public:
int Subscribe(const std::function<void(EVENT_ARGS)>& func)
{
//add to map
}
bool Unsubscribe(int token)
{
//remove from map
}
int operator+=(const std::function<void(EVENT_ARGS)>& func)
{
return Subscribe(func);
}
bool operator-=(int token)
{
return Unsubscribe(token);
}
private:
void Raise(EVENT_ARGS t)
{
for (auto pair : m_subscribers)
{
pair.second(t);
}
}
void operator()(EVENT_ARGS t) { Raise(t); }
std::map<int, std::function<void(EVENT_ARGS)>> m_subscribers;
};
[I'm not using an inheritance of EventArgs to support raise by value.]
[Please don't suggest using boost\Signal]
The problem I have is that I want to support raising events without arguments but I can't pass void
as the EVENT_ARGS
because void Raise(EVENT_ARGS t) {...}
will not compile (and of course also the operator()
). I can't overload it without arguments as well for the same reason.
So my question is- is there a way to hace some sort of ifdef void
or something like that so that when someone uses Event<MyClass, void>
(or Event<MyClass>
) the compiler will create a class with void raise() {...}
(i.e without arguments) so that I can call pair.second();
(and not pair.second(t);
) ?
I wish to get an elegant solution to this problem. I don't want to duplicate the class or have a specification which duplicates the entire class as well.
Aucun commentaire:
Enregistrer un commentaire