Multiple inheritance based on Variadic templates for two interacting classes ...

In my current project, I need to provide template based multiple inheritance (Mixin pattern) and have two classes (mirroring multiple inheritance trees) that can interact with each other (i.e. use methods from another to the same inheritance level ).

In short, I cannot find an elegant way to build this. Below is the test file (you can run and edit it directly here ).

Is there a pattern or trick that would allow me to have something like a commented out line while keeping any subclasses relatively crack free?

Obviously, the nested class Thing

would have to inherit from another class, providing the necessary interface methods. However, any attempt to fix the inheritance problem (CRTP ...) always seems to lead me to recursive inheritance or incomplete base type problems ...

class Base {
public:

    class Thing {
    public:
        Thing(Base& b) : _b(b) {};

        Thing& operator+= (const Thing p) { _b.add(*this, p); return *this; };

        int k;
    protected:
        Base& _b;
    };

    void add(Thing &d, const Thing s) { d.k += s.k; }
};

template <class... Interfaces>
class Extensible : virtual public Base, virtual public Interfaces... {

    class Thing : virtual public Base::Thing, virtual public Interfaces::Thing... {

    };
};

class SomeInterface : Base {
    void multiply(Thing &d, const Thing s) { d.k *= s.k; }

    class Thing : public Base::Thing {
        Thing& operator*= (const Thing p) {
            //_b.multiply(*this, p); return *this; // <-- won't work of course
        };

    };

};

int main() {
    Extensible<SomeInterface> a;
    return 0;
}

      

+3


source to share


1 answer


This is one of the options: http://ideone.com/KhLyfj (I just tell the base class to subclass it to give the _b

correct type). However, in some situations this will not work. You can experiment with moving the template from Thing

/ add

directly to Base

.



class Base {
public:

    template<typename Outer>
    class Thing {
    public:
        Thing(Base& b) : _b(b) {};

        Thing& operator+= (const Thing p) { _b.add(*this, p); return *this; };

        int k;
    protected:
        Outer& _b;
    };

    template<typename Outer>
    void add(Thing<Outer> &d, const Thing<Outer> s) { d.k += s.k; }
};

template <class... Interfaces>
class Extensible : virtual public Base, virtual public Interfaces... {

    class Thing : virtual public Base::Thing<Base>, virtual public Interfaces::template Thing<Base>... {

    };
};

class SomeInterface : Base {
    void multiply(Thing<SomeInterface> &d, const Thing<SomeInterface> s) { d.k *= s.k; }

    class Thing : public Base::Thing<SomeInterface> {
        Thing& operator*= (const Thing p) {
            _b.multiply(*this, p); return *this; // <-- will work of course
        };

    };

};

int main() {
    Extensible<SomeInterface> a;
    return 0;
}

      

+1


source







All Articles