dimanche 26 juin 2016

C++ 'ifdef' for templates

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