Вот сценарий: я хотел бы иметь класс хоста, который может иметь переменное количество mixins (не слишком трудно с шаблонами variadic - см., например, http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.103.144). Однако я также хотел бы, чтобы mixins был параметризован классом хоста, так, чтобы они могли обратиться к его открытым типам (использующий идиому CRTP). Проблема возникает при попытке смешать два - правильный синтаксис неясен мне. Например, следующему коду не удается скомпилировать с g ++ 4.4.1:
template class... Mixins>
class Host : public Mixins>... {
public:
template
Host(Args&&... args) : Mixins(std::forward(args))... {}
};
template struct Mix1 {};
template struct Mix2 {};
typedef Host TopHost;
TopHost *th = new TopHost(Mix1(), Mix2());
С ошибкой:
tst.cpp: In constructor ‘Host::Host(Args&& ...) [with Args = Mix1 >, Mix2 >, Mixins = Mix1, Mix2]’:
tst.cpp:33: instantiated from here
tst.cpp:18: error: type ‘Mix1 >’ is not a direct base of ‘Host’
tst.cpp:18: error: type ‘Mix2 >’ is not a direct base of ‘Host’
У кого-либо есть успешный опыт при смешивании variadic шаблонов с CRTP?
Похоже, работает следующее. Я добавил Mixins ...
в унаследованные классы примесей, которые расширяют пакет параметров на месте. Вне тела шаблона 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>());
}