开发者

Solving the mixin constructor problem in C++ using variadic templates

开发者 https://www.devze.com 2023-01-09 22:23 出处:网络
I\'ve recently tackled the constructor problem, where various mixins classes that decorate each other (and a topmost host class) have different constructor signatures. To maintain a single constructor

I've recently tackled the constructor problem, where various mixins classes that decorate each other (and a topmost host class) have different constructor signatures. To maintain a single constructor in the resulting decorated class, and without adding init functions, I've found the following solution. The only restriction it places on a mixin class is that if its constructor takes more than one parameter, they should all be encapsulated in a single tuple. (Compiling this code with g++ requires the -std=c++0x flags)

#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_;

    te开发者_JS百科mplate <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;
}

My questions are:

1) Is there a better, more elegant way of solving this problem with C++0X?

2) Specifically, are tuples really necessary?


You only need something like tuples if you have multiple constructors with differing arity for the mixins (and thus ambiguities).

If not you could just handle the parameters for the mixin as usual:

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


You could construct the base struct and pass it as constructor parameter of M1 and M2, so they can call a copy constructor of b:

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

Are you really sure you need inheritance? Composition is more elegant and maintainable.

0

精彩评论

暂无评论...
验证码 换一张
取 消