Variadic template-based multiple inheritance for two interacting classes…

蹲街弑〆低调 提交于 2019-12-12 12:26:58

问题


In my current project, I need to be able to provide template-based multiple inheritance (Mixin pattern) and have two classes (with mirroring multiple-inheritance trees) that can interact together (i.e. one uses methods from the other one at the same inheritance level).

Long story short, I cannot seem to find an elegant way to build this. Below is a reduced testcase (you can run and edit it directly here).

Is there a pattern or trick that would let me have something similar to the commented line while keeping any subclasses relatively cruft-free?

Obviously, the nested Thing class would need to inherit from another class providing the necessary interface methods. However any attempt at fixing the inheritance problem (CRTP...) always seem to lead me to recursive inheritance or incomplete base type issues...

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;
}

回答1:


This is one of the options: http://ideone.com/KhLyfj (I just tell the base class what is its subclass to give _b a correct type). It won't work in some situations though. You can experiment with moving the template from Thing/add straight 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;
}


来源:https://stackoverflow.com/questions/27269603/variadic-template-based-multiple-inheritance-for-two-interacting-classes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!