Список аргументов шаблона переменной длины?

Я помню, как это делалось:

template <ListOfTypenames>
class X : public ListOfTypenames {};

то есть X наследует из списка переменных длины имен имен, переданных в качестве аргументов шаблона. Разумеется, этот код гипотетический.

Я не могу найти никаких ссылок для этого. Является ли это возможным? Это С++ 0x?

Ответ 1

Вы можете сделать это в текущем С++. Вы даете шаблону "достаточно большое" количество параметров, и вы даете им значения по умолчанию:

class nothing1 {};
class nothing2 {};
class nothing3 {};

template <class T1 = nothing1, class T2 = nothing2, class T3 = nothing3>
class X : public T1, public T2, public T3 {};

Или вы можете получить более сложную и использовать рекурсию. Сначала вы переходите к объявлению шаблона:

class nothing {};

template <class T1 = nothing, class T2 = nothing, class T3 = nothing>
class X;

Затем вы специализируетесь на случай, когда все параметры по умолчанию:

template <>
class X<nothing, nothing, nothing> {};

Затем вы правильно определяете общий шаблон (который ранее вы только прокручивали вперед):

template <class T1, class T2, class T3>
class X : public T1, public X<T2, T3>

Обратите внимание, как в базовом классе вы наследуете X, но пропустите первый параметр. Поэтому все они скользят по одному месту. В конце концов все они будут по умолчанию, и специализация начнет работать, что не наследует ничего, тем самым заканчивая рекурсию.

Обновление: просто странное чувство, что я разместил что-то вроде этого раньше, и угадаю, что...

Ответ 2

Похоже, вы ссылаетесь на С++ 0x Variadic Templates. Вы также можете добиться такого же эффекта, используя Alexandrescu TypeList из Loki.

Я полагаю, что рассматриваемый вариант синтаксиса вариационного шаблона будет выглядеть следующим образом.

template <typename...T>
class X : public T... {};

Ответ 3

Как уже говорили другие, вариативные шаблоны являются частью следующего стандарта, но могут быть эмулированы в текущем С++. Одним из удобных инструментов для этого является использование библиотеки Boost.MPL. В вашем коде вы пишете один параметр шаблона (пусть его называют "Typelist" ), а пользователи вашего шаблона завершают список типов в последовательности MPL. Пример:

#include "YourType.h"
#include "FooBarAndBaz.h"
#include <boost/mpl/vector.hpp>

YourType<boost::mpl::vector<Foo, Bar, Baz> > FooBarBaz;

В реализации "YourType" вы можете получить доступ к элементам в Typelist с различными метафайлами. Например, at_c<Typelist, N> - это N -й элемент списка. В качестве другого примера, класс "X" в вашем вопросе может быть записан с помощью inherit_linearly как:

//Warning: Untested
namespace bmpl = boost::mpl;
template<class Typelist>
class X : bmpl::inherit_linearly<Typelist, bmpl::inherit<bmpl::_1, bmpl::_2> >::type
{
...
};

Ответ 4

Изменчивое количество шаблонов является частью следующего стандарта С++. Однако вы можете попробовать его, если используете GCC (начиная с версии 4.3). Здесь список доступных функций С++ 0x в GCC. Вы ищете шаблоны Variadic.

Кстати, если вам нужна формальная ссылка о том, как добиться механизма наследования, описанного Earwicker, он в книге С++ Templates.