两个交互类的基于变量模板的多重继承......

时间:2014-12-03 10:43:21

标签: c++ inheritance c++11 variadic-templates

在我当前的项目中,我需要能够提供基于模板的多重继承(Mixin模式)有两个类(带有镜像多重继承树)可以一起交互(即一个在同一继承级别使用另一个方法。)

长话短说,我似乎无法找到一种优雅的方式来构建它。下面是一个简化的测试用例(您可以直接运行和编辑here)。

是否有一种模式或技巧可以让我拥有类似于注释行的东西,同时保持任何子类相对无瑕疵?

显然,嵌套的Thing类需要从提供必要接口方法的另一个类继承。但是,任何修复继承问题的尝试(CRTP ......)似乎总是导致递归继承或不完整的基类型问题......

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 个答案:

答案 0 :(得分:1)

这是其中一个选项:http://ideone.com/KhLyfj(我只是告诉基类它的子类是什么,为_b提供正确的类型)。但它在某些情况下不会工作。您可以尝试将模板从Thing / add直接移至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;
}