2010-03-17 3 views
11

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

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>’ 

Кто-нибудь есть успешный опыт смешивания VARIADIC шаблоны с CRTP?

ответ

6

Следующие, похоже, работают. Я добавил 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>()); 
} 
+0

Я пересмотрел его, чтобы включить templatized constructor. template <класс ... Args> Host (Args && ... args): Mixins (std: forward > (args)) ... {} – Sumant

+0

Спасибо, суман. Ваше предложение имеет смысл, но мне как-то не удается работать. Какую версию компилятора вы используете? Я скопировал и вставил этот код и при компиляции получил: tst2.cpp: В функции 'int main()': tst2.cpp: 16: ошибка: нет соответствующей функции для вызова на «Host : : Host (Mix1 >, Mix2 >) ' tst2.cpp: 7: примечание: кандидаты: Host :: Host (Mixins > && ...) [с Mixins = Mix1, Mix2] tst2.cpp: 5: note: Host :: Host (const Host &) – Eitan

+0

О, я пропустил вашу ревизию. Это исправляет ошибку «отсутствие соответствия», но взрывается с «внутренней ошибкой компилятора» :) Итак, какой компилятор вы используете? – Eitan