Spencer Michaels
Spencer Michaels

Reputation: 3

Overloading when inheriting from two differently-templated copies of the same class

I'm writing an input-handling system for a game that I'd like to make extensible to arbitrary event types. I'd like to design an interface-like specification that allows me to enforce that certain objects are expected to handle certain events; for instance via something like class Player : public EventHandler<KeyboardEvent>. My proposed design for such a thing is as follows.

template <class T>
class EventHandler {
public:
    void handleEvent(T event) { doHandleEvent(event); };
private:
    virtual void doHandleEvent(T event) {};
};

class InputHandler : public EventHandler<Action>, public EventHandler<CursorEvent> {};

However, at the point where I call InputHandler::handle(), the above produces the following errors. It appears that handleEvent() for both templated versions of EventHandler is treated as the same function. I was under the impression that since the two versions of handleEvent have different argument types, the result should be as if InputHandler had one overloaded function with the two possible argument types.

Why doesn't C++ allow this, and what are some better alternatives to what I'm trying to do? I suspect the above may not be good practice.

/Users/smichaels/Projects/danmaku/src/SDL/Input.cpp:35:34: error: member 'handleEvent' found in multiple base classes
      of different types
                if (act) handler.handleEvent(act.get());
                                 ^
/Users/smichaels/Projects/danmaku/src/SDL/../Input/InputHandler.hpp:15:14: note: member found by ambiguous name lookup
        void handleEvent(T event) { doHandleEvent(event); };
             ^
/Users/smichaels/Projects/danmaku/src/SDL/../Input/InputHandler.hpp:15:14: note: member found by ambiguous name lookup

Upvotes: 0

Views: 36

Answers (1)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275760

class InputHandler :
  public EventHandler<Action>,
  public EventHandler<CursorEvent>
{
public:
  using EventHandler<Action>::handleEvent;
  using EventHandler<CursorEvent>::handleEvent;
};

in you can instead write:

template<class...Bases>
struct ManyHandler:Bases...{
  using Bases::handleEvent...;
};
template<class...Events>
using EventsHandler=ManyHandler< EvendHandler<Events>...>;

then

class InputHandler : public EventsHandler<Actions, CursorEvent >{};

and if you also have

class OutputHandler : public EventsHandler< Messages, Sounds >{};

we can write

class IoHandler : public ManyHandler< InputHandler, OutputHandler > {};

Upvotes: 1

Related Questions