Каковы правила для токена " ... " в контексте вариативных шаблонов?
в C++11 есть вариативные шаблоны, такие как этот:
template< class T, class... Args >
unique_ptr<T> make_unique( Args&&... args )
{
return unique_ptr<T>(new T(std::forward<Args>(args)...));
}
есть некоторые курьезы об этом: выражение std::forward<Args>(args)... использует Args и args но только один ... маркер. Кроме того std::forward - это не вариативная функция шаблона, принимающая только один параметр шаблона и один аргумент. Каковы синтаксические правила для этого (грубо)? Как его можно обобщить?
также в реализации функции с многоточием (...) находится в конце выражение заинтересованности. Есть ли причина, что в списке аргументов шаблона и списке параметров многоточие находится посередине?
2 ответа:
в контексте вариативного шаблона, многоточие
...используется для распаковки пакета параметров шаблона, если он отображается в правой части выражения (вызовите это выражение pattern на мгновение). Правило таково, что бы ни pattern находится на левой стороне...повторяется-распакованные шаблоны (назовите их выражения теперь) разделяются запятой,.это лучше всего можно понять на некоторых примерах. Предполагать у вас есть этот шаблон функции:
template<typename ...T> void f(T ... args) { g( args... ); //pattern = args h( x(args)... ); //pattern = x(args) m( y(args...) ); //pattern = args (as argument to y()) n( z<T>(args)... ); //pattern = z<T>(args) }теперь, если я вызываю эту функцию передачи
Tкак{int, char, short}, затем каждый вызов функции расширяется как:g( arg0, arg1, arg2 ); h( x(arg0), x(arg1), x(arg2) ); m( y(arg0, arg1, arg2) ); n( z<int>(arg0), z<char>(arg1), z<short>(arg2) );в коде, который вы разместили,
std::forwardследует четвертому шаблону, проиллюстрированномуn()вызов функции.обратите внимание на разницу между
x(args)...иy(args...)выше!
можно использовать
...для инициализации массива, также как:struct data_info { boost::any data; std::size_t type_size; }; std::vector<data_info> v{{args, sizeof(T)}...}; //pattern = {args, sizeof(T)}который расширяется до этого:
std::vector<data_info> v { {arg0, sizeof(int)}, {arg1, sizeof(char)}, {arg2, sizeof(short)} };
я только что понял, что шаблон может даже включать спецификатор доступа, такой как
public, как показано в следующем примере:template<typename ... Mixins> struct mixture : public Mixins ... //pattern = public Mixins { //code };в этом примере шаблон расширяется следующим образом:
struct mixture__instantiated : public Mixin0, public Mixin1, .. public MixinNто есть
mixtureвыводит публично из всех базовых классов.надеюсь, что это поможет.
следующее взято из разговора "шаблоны с переменным числом аргументов является Funadic" Андрей Александреску на GoingNative 2012. Я могу рекомендовать его для хорошего введения в вариативные шаблоны.
есть две вещи, которые можно сделать с вариативным пакет. Это можно применить
sizeof...(vs)чтобы получить количество элементов и развернуть его.правила расширения
Use Expansion Ts... T1, ..., Tn Ts&&... T1&&, ..., Tn&& x<Ts,Y>::z... x<T1,Y>::z, ..., x<Tn,Y>::z x<Ts&,Us>... x<T1&,U1>, ..., x<Tn&,Un> func(5,vs)... func(5,v1), ..., func(5,vn)расширение продолжается внутрь наружу. При расширении двух списков в замок-шаг, они должны иметь одинаковый размер.
примеры:
gun(A<Ts...>::hun(vs)...);расширяет все
Tsв списке аргументов шаблонаAа потом функцияhunрасширяется со всеvs.gun(A<Ts...>::hun(vs...));расширяет все
Tsв списке аргументов шаблонаAиvsв качестве аргументов функцииhun.gun(A<Ts>::hun(vs)...);расширяет функции
hunСTsиvsin стоп-шаг.Примечание:
Ts- это не тип, аvs- это не ценность! Они являются псевдонимами для списка типов / значений. Любой список может быть потенциально пустым. Оба подчиняются только определенным действиям. Так как не представляется возможным:typedef Ts MyList; // error! Ts var; // error! auto copy = vs; // error!локусов расширения
аргументов функции
template <typename... Ts> void fun(Ts... vs)списки инициализатора
any a[] = { vs... };база спецификаторы
template <typename... Ts> struct C : Ts... {}; template <typename... Ts> struct D : Box<Ts>... { /**/ };инициализатора списки
// Inside struct D template <typename... Us> D(Us... vs) : Box<Ts>(vs)... {}список аргументов шаблона
std::map<Ts...> m;будет компилироваться только в том случае, если есть возможное совпадение для Аргументов.
списки захват
template <class... Ts> void fun(Ts... vs) { auto g = [&vs...] { return gun(vs...); } g(); }списки атрибутов
struct [[ Ts... ]] IAmFromTheFuture {};он находится в спецификации, но пока нет атрибута, который может быть выражен как тип.