Решение проблемы конструктора mixin в C ++ с использованием шаблонов с переменными числами - PullRequest
5 голосов
/ 31 июля 2010

Я недавно решил проблему конструктора , где различные классы миксинов, которые украшают друг друга (и самый верхний хост-класс), имеют разные сигнатуры конструктора. Чтобы сохранить единый конструктор в результирующем декорированном классе и без добавления функций инициализации, я нашел следующее решение. Единственное ограничение, которое он накладывает на класс 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) В частности, действительно ли нужны кортежи?

Ответы [ 2 ]

4 голосов
/ 31 июля 2010

Вам нужно что-то вроде кортежей, только если у вас есть несколько конструкторов с разной арностью для миксинов (и, следовательно, неоднозначности).

Если нет, вы можете просто обработать параметры для миксина как обычно:

template <class... A>
M2(const char* p, double d, short s, const A&... a)
  : B(a...), p_(p), d_(d), s_(s) {}
0 голосов
/ 31 июля 2010

Вы можете создать базовую структуру и передать ее в качестве параметра конструктора M1 и M2, чтобы они могли вызвать конструктор копирования b:

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

Вы действительно уверены, что вам нужно наследование? Композиция более элегантна и ремонтопригодна.

...