Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

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

My questions are:
1) Is there a better, more elegant way of solving this problem with C++0X?
2) Specifically, are tuples really necessary?

like image 738
Eitan Avatar asked Oct 15 '22 02:10

Eitan


1 Answers

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) {}
like image 87
Georg Fritzsche Avatar answered Nov 15 '22 09:11

Georg Fritzsche