【问题标题】:Variadic template-based multiple inheritance for two interacting classes...两个交互类的基于可变模板的多重继承...
【发布时间】:2015-01-31 21:23:03
【问题描述】:

在我当前的项目中,我需要能够提供基于模板的多重继承(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;
}

【问题讨论】:

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


    【解决方案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;
    }
    

    【讨论】:

    • 感谢您的建议:这听起来是一个很有前途的方向(必须为其添加一些内容才能让我实例化Thing 对象)。除非这会导致无法在主类中使用_b 的钻石问题:ideone.com/YrrpBn
    • 试试这个,然后:ideone.com/TOKP8b。我添加了SomeInterface 的前向声明,BaseExtensible 的虚拟基类,SomeInterface::Thing 有一个显式构造函数,Extensible::Thing 的构造函数显式调用Base::Thing&lt;SomeInterface&gt;::Thing(e)。这是一个非常好的谜题:)。
    • 非常感谢您的努力...不幸的是,前向声明(并在 Extensible 内部使用)有点违背了接口模式的目的(要求我们抢先继承我们拥有的所有接口) .我设法让一些代码工作在:ideone.com/sblnfM 无论如何,我将您的答案标记为已接受。随意将其与此代码合并。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-15
    • 1970-01-01
    • 2014-09-12
    • 2019-04-25
    相关资源
    最近更新 更多