Список аргументов шаблона переменной длины? - PullRequest
10 голосов
/ 03 октября 2009

Я помню, что видел что-то вроде этого:

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

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

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

Ответы [ 4 ]

23 голосов
/ 03 октября 2009

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

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, но пропускаете первый параметр. Так что все они скользят по одному месту. В конечном итоге все они будут иметь значения по умолчанию, и специализация начнется, которая ничего не наследует, и тем самым прекратит рекурсию.

Обновление: просто было странное ощущение, что я публиковал что-то подобное раньше, и угадайте, что ...

19 голосов
/ 03 октября 2009

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

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

template <typename...T>
class X : public T... {};
4 голосов
/ 03 октября 2009

Как уже отвечали другие, вариационные шаблоны являются частью следующего стандарта, но могут быть эмулированы в текущем C ++. Одним из удобных инструментов для этого является использование библиотеки 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
{
...
};
2 голосов
/ 03 октября 2009

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

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

...