【问题标题】:Solving the mixin constructor problem in C++ using variadic templates使用可变参数模板解决 C++ 中的 mixin 构造函数问题
【发布时间】:2010-07-31 15:48:12
【问题描述】:

我最近处理了the constructor problem,其中各种相互装饰的混合类(以及最顶层的宿主类)具有不同的构造函数签名。为了在生成的装饰类中维护单个构造函数,并且不添加初始化函数,我找到了以下解决方案。它对 mixin 类的唯一限制是,如果它的构造函数接受多个参数,则它们都应该封装在一个元组中。 (使用 g++ 编译此代码需要 -std=c++0x 标志)

#include <boost/tuple/tuple.hpp>

// Base class for all mixins
struct Host {
    float f_;
    int i_;

    Host(float f, int i) : f_(f), i_(i) {}
};

// First mixin--constructs with 1 parameter
template <class B>
struct M1 : public B {
    char c_;

    template <class... A>
    M1(char c, const A&... a) : B(a...), c_(c) {}
};

// Second mixin--constructs with 3 parameters
template <class B>
struct M2 : public B {
    double d_;
    short s_;
    const char* p_;

    template <class... A>
    M2(boost::tuple<const char*, double, short> t, const A&... a)
    : B(a...), p_(t.get<0>()), d_(t.get<1>()), s_(t.get<2>()) {}
};


int main() {
    // ctor parameters go in this order, from most derived to base:
    M2<M1<Host>> tst(boost::make_tuple("test", 46.1, (short)-1), (char)5, 4.2f, 2);
  return 0;
}

我的问题是:
1) 有没有更好、更优雅的方法来用 C++0X 解决这个问题?
2) 具体来说,元组真的有必要吗?

【问题讨论】:

    标签: c++ templates mixins variadic boost-tuples


    【解决方案1】:

    如果您有多个构造函数具有不同的混合参数(因此有歧义),则只需要元组之类的东西。

    如果没有,你可以像往常一样处理 mixin 的参数:

    template <class... A>
    M2(const char* p, double d, short s, const A&... a)
      : B(a...), p_(p), d_(d), s_(s) {}
    

    【讨论】:

    • 没错,但我试图解决最一般的情况,对未来的 mixin 施加尽可能少的限制。在我的具体情况下,arity 确实有所不同。
    • @eit:你的意思是你的意思是你需要在一个mixin中有多个具有不同arities的构造函数?那将是我能想到的唯一有问题的案例。除此之外,我看不出它可以如何更优雅地完成。
    • 也许我不清楚。每个 mixin 只需要一个构造函数,但可以采用不同的编号。来自其他 mixin 的 args,如示例中所示。
    • @eit:如果每个 mixin 只有一个构造函数,那么不使用元组应该没有任何问题。或者你有什么特别的想法?
    • 你是对的。它适用于这个简单的示例,但不适用于我的实际代码。我会尝试重现。
    【解决方案2】:

    您可以构造基础结构并将其作为 M1 和 M2 的构造函数参数传递,因此它们可以调用 b 的复制构造函数:

    M2(const B &b, ....) : B(b), ....
    

    你确定你需要继承吗?组合更加优雅和可维护。

    【讨论】:

    • 使用复制构造函数作为替代方法是对的(虽然有点浪费)。 C++ 没有内置的方式来添加 mixins,并且在这个例子中使用 CRTP 是一种常见的解决方法。使用组合获得与此示例类似的功能意味着我必须定义 D2 以具有 D1 类型的成员,并定义 D1 以具有 Host 成员。它更丑(在我看来),但更重要的是,它增加了耦合。 Mixin 不再像装饰器那样相互独立。使用当前结构,我可以同时拥有 M1> 和 M1。使用作曲,我不能。
    猜你喜欢
    • 1970-01-01
    • 2016-01-02
    • 1970-01-01
    • 1970-01-01
    • 2019-05-30
    • 2018-05-18
    • 1970-01-01
    • 1970-01-01
    • 2016-09-02
    相关资源
    最近更新 更多