Микшины, вариативные шаблоны и 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?
Ответы
Ответ 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>());
}