Подтвердить что ты не робот

Микшины, вариативные шаблоны и CRTP в С++

Здесь сценарий: я хотел бы иметь класс хоста, который может иметь переменное количество mixins (не слишком сложно с вариативными шаблонами - см., например, http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.103.144). Тем не менее, мне также хотелось бы, чтобы mixins были параметризованы классом хоста, чтобы они могли ссылаться на свои общедоступные типы (используя идиому CRTP). Проблема возникает при попытке смешать два - правильный синтаксис для меня непонятен. Например, следующий код не скомпилирован с g++ 4.4.1:

template <template<class> class... Mixins>
class Host : public Mixins<Host<Mixins>>... {
  public:
    template <class... Args>
    Host(Args&&... args) : Mixins<Host>(std::forward<Args>(args))... {}
};

template <class Host> struct Mix1 {};

template <class Host> struct Mix2 {};

typedef Host<Mix1, Mix2> TopHost;
TopHost *th = new TopHost(Mix1<TopHost>(), Mix2<TopHost>());

С ошибкой:

tst.cpp: In constructor ‘Host<Mixins>::Host(Args&& ...) [with Args = Mix1<Host<Mix1, Mix2> >, Mix2<Host<Mix1, Mix2> >, Mixins = Mix1, Mix2]’:

tst.cpp:33:   instantiated from here

tst.cpp:18: error: type ‘Mix1<Host<Mix1, Mix2> >’ is not a direct base of ‘Host<Mix1, Mix2>’

tst.cpp:18: error: type ‘Mix2<Host<Mix1, Mix2> >’ is not a direct base of ‘Host<Mix1, Mix2>’

У кого-нибудь есть успешный опыт смешивания вариативных шаблонов с CRTP?

4b9b3361

Ответ 1

Кажется, что работает следующее. Я добавил Mixins... в унаследованные классы mixin, который расширяет пакет параметров inplace. Вне тела шаблона Host должны быть указаны все параметры шаблона Host, поэтому Mixins... служит для этой цели. Внутри тела просто Host достаточно не нужно указывать все его параметры шаблона. Вид короткой руки.

#include <utility>

template <template<class> class... Mixins>
class Host : public Mixins<Host<Mixins...>>...
{
  public:
    Host(Mixins<Host>&&... args) : Mixins<Host>(std::forward<Mixins<Host>>(args))... {}
};

template <class Host> struct Mix1 {};
template <class Host> struct Mix2 {};

int main (void)
{
  typedef Host<Mix1, Mix2> TopHost;
  delete new TopHost(Mix1<TopHost>(), Mix2<TopHost>());
}