Palace Chan
Palace Chan

Reputation: 9183

How to avoid duplicating code with static polymorphism

I have an interface like this (except much much lengthier than this in the real library code)

struct IFoo
{
    virtual void onA(A& a) = 0;
    virtual void onB(A& a) = 0;
    virtual void onC(A& a) = 0;
};

and it is common for me to implement different listeners of IFoo. Because of this, I designed a helper class like this one:

template <class T>
struct IFooHelper {
    virtual void onA(A& a) { static_cast<T*>(this)->onGeneric(a); }
    virtual void onB(B& b) { static_cast<T*>(this)->onGeneric(b); }
    virtual void onC(C& c) { static_cast<T*>(this)->onGeneric(c); }
};

so now, when I have a lot of common behavior in a listener, rather than having to provide a virtual override of every single IFoo function, I can do something like:

struct Fox : public IFooHelper<Fox>
{
    template <class T> void onGeneric(T& t) { //do something general }
    void onD(D& d) { //special behavior only for a type D }
};

This has worked fantastically well but now I am implementing a listener for which I want some common behavior, and then update a counter, say, of which type of call it was. In other words, assuming I only have types A,B,C as above, my listener would be:

struct Ugly : public IFooHelper<Ugly>
{
    void onA(A& a) { //8 lines of common code; //update some counter for type A objs; }
    void onB(B& b) { //8 lines of common code; //update some counter for type B objs; }
    void onC(C& c) { //8 lines of common code; //update some counter for type C objs; }
};

In here, the calls have to be very fast (so no lookups) and ideally I would be able to exploit the IFooHelper to hoist the common behavior into the template method, and then somehow still be able to distinguish the types. I was thinking something like a template specialized struct with offsets into a static cons char* array..or with values themselves which are char* depending on T..is there a better way?

Upvotes: 4

Views: 201

Answers (1)

Daniel Frey
Daniel Frey

Reputation: 56863

Not sure if I fully understand what you are looking for, but I'll give it a shot. As a first step, consider this:

struct NotSoUgly : public IFooHelper<NotSoUgly>
{
    void updateCounter(A& a) { //update some counter for type A objs; }
    void updateCounter(B& b) { //update some counter for type B objs; }
    void updateCounter(C& c) { //update some counter for type C objs; }

    template <class T> void onGeneric(T& t) {
        //8 lines of common code;
        updateCounter(t);
    }
};

Further improvements are possible if you'd show us the content of the updateCounter() methods to we could come up with a single generic implementation for that as well, but without seeing the code, it's hard to guess.

Upvotes: 1

Related Questions