2009-10-02 5 views
10

Я помню Seing что-то вроде этого делается:Список аргументов шаблона переменной длины?

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

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

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

ответ

23

Вы можете сделать это в текущем 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> {}; 

Тогда вы правильно определить общий шаблон (который ранее вы только вперед -declared):

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

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

Update: просто было странное ощущение, что я отвечал что-то подобное раньше, and guess what...

+0

вы также можете использовать только один «ничего» класс – sellibitze

+0

@sellibitze - я использую использовать только один «ничего» класс в рекурсивная версия. Вы не можете использовать один и тот же класс для значений по умолчанию в нерекурсивной версии, потому что вы получите ошибки «ничего уже не является прямым базовым классом». –

+0

Я не понимаю: почему вы пропустили первый параметр при наследовании от X? – Gili

19

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

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

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

Если я не ошибаюсь, вам также нужно будет распаковать тип: 'public T ... {};' – UncleBens

2

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

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

4

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