В 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
, это невариная шаблонная функция, принимающая только один параметр шаблона и один аргумент. Каковы правила синтаксиса для этого (примерно)? Как это можно обобщить?
Также: в реализации функции многоточие ( ...
) находится в конце интересующего выражения. Есть ли причина, по которой в списке аргументов шаблона и списке параметров многоточие находится посередине?
c++
c++11
variadic-templates
Ральф Тандецки
источник
источник
...
предшествует вводимому идентификатору. При использовании одного или обоих типов пакетов...
символ расширения следует после шаблона выражения.Ответы:
В контексте вариативного шаблона многоточие
...
используется для распаковки пакета параметров шаблона, если он появляется в правой части выражения (вызовите этот шаблон выражения на мгновение). Правило состоит в том, что любой шаблон в левой части...
повторяется - распакованные шаблоны (назовите их выражениями ) разделяются запятыми,
.Лучше всего это можно понять на нескольких примерах. Предположим, у вас есть этот шаблон функции:
Теперь, если я вызываю эту функцию, передавая
T
как{int, char, short}
, тогда каждый вызов функции расширяется как:В опубликованном вами коде
std::forward
следует четвертый шаблон, проиллюстрированныйn()
вызовом функции.Обратите внимание на разницу между
x(args)...
иy(args...)
выше!Вы также можете использовать
...
для инициализации массива как:который расширяется до этого:
Я только что понял, что шаблон может даже включать спецификатор доступа, например
public
, как показано в следующем примере:В этом примере шаблон раскрывается как:
То есть,
mixture
происходит публично от всех базовых классов.Надеюсь, это поможет.
источник
x+args...
следует расширить доx+arg0,x+arg1,x+arg2
, а неx+arg0,arg1,arg2
....
применяется ко всем расширяемым объектам в шаблоне.x+args...
должен расширяться доx+arg0,x+arg1,x+arg2
, а не доx+arg0,arg1,arg2
.sizeof...(T)
не нужен. Вы можете просто написать:int a[] = { ___ };
Следующее взято из выступления Андрея Александреску на GoingNative 2012 «Шаблоны с вариативными шаблонами» . Я могу порекомендовать его для хорошего введения в вариативные шаблоны.
С вариативным пакетом можно сделать две вещи. Можно подать заявку,
sizeof...(vs)
чтобы получить количество элементов и расширить его.Правила расширения
Расширение происходит внутрь наружу. При одновременном расширении двух списков они должны иметь одинаковый размер.
Еще примеры:
Раскрывает все
Ts
в списке аргументов шаблона,A
а затем функцияhun
расширяется на всеvs
.Раскрывает все
Ts
в списке аргументов шаблонаA
и всеvs
как аргументы функции дляhun
.Расширяет функцию
hun
с помощьюTs
иvs
синхронно.Примечание:
Ts
не тип иvs
не значение! Это псевдонимы для списка типов / значений. Любой список может быть потенциально пустым. Оба подчиняются только определенным действиям. Таким образом, следующее невозможно:Локусы расширения
Аргументы функции
Списки инициализаторов
Базовые спецификаторы
Списки инициализаторов членов
Списки временных аргументов
Будет компилироваться, только если есть возможное совпадение аргументов.
Списки захвата
Списки атрибутов
Он есть в спецификации, но пока нет атрибута, который мог бы быть выражен как тип.
источник