Миксины, вариационные шаблоны и CRTP в C ++ - PullRequest
11 голосов
/ 17 марта 2010

Вот сценарий: я хотел бы иметь хост-класс, который может иметь переменное количество миксинов (не слишком сложно с вариадическими шаблонами - см., Например, 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 Ответ

8 голосов
/ 17 марта 2010

Следующее похоже на работу. Я добавил Mixins... в унаследованные классы mixin, которые расширяют пакет параметров на месте. За пределами тела шаблона 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>());
}
...