Я новичок в расширении пакета параметров C++, и меня долгое время смущало положение ... (многоточие), например:
template <typename... Args>
void func(Args&&... args) {
// ...
std::forward<Args>(args)...;
// ...
}
Почему нет std::forward<Args>(args...)? Какому правилу мне следует следовать?
@user12002570 user12002570 хороший чувак. Я не смог его найти, потому что у него не было пака-расширения. Я думаю, нам следует чаще применять этот тег, чтобы упростить дедупликацию в будущем.
@JanSchultke Спасибо, я искал фразу «куда должно идти многоточие в расширении пакета std::forward», и Google не разочаровал. Обычно я сначала ищу в Google, а затем ищу SO (если Google не может найти ничего подходящего) на основе тегов и т. д. (как вы это сделали). Я согласен с применением этого тега немного больше.





Грамматически std::forward<Args>(args)...; не имеет смысла.
Вы можете использовать расширение пакета только в круглых или фигурных скобках.
Если бы вы вызвали функцию, скажем foo, вы бы написали:
foo(std::forward<Args>(args)...)
Это будет постфиксное-выражение foo(/* ... */), которое содержит список-выражений , который представляет собой список-инициализаторов с единственным предложением-инициализатором std::forward<Args>(args) и ....
Другими словами, ... не является частью выражения; это часть списка выражений.
Следовательно, ... является «самым внешним» элементом, поскольку он имеет более низкий приоритет, чем любое выражение.
*args... и args()... будут применяться * и () к каждому аргументу в args соответственно.
Вы можете воспринимать X... как инструкцию, в которой говорится:
Сделайте
Xдля каждого элемента в наборе.
std::forward<Args>(args...) неверно, потому что ... здесь относится к списку инициализаторов аргументов при вызове std::forward, но std::forward не является шаблоном функции с переменным числом аргументов.
Вместо пересылки каждого аргумента он пытается вызвать std::forward с переданным всем пакетом.
См. также Как можно вызвать std::forward для всех аргументов в вариативной функции?
Посетите https://en.cppreference.com/w/cpp/language/parameter_pack, особенно раздел «Расширение пакета».
По сути, «...» в расширении пакета почти похож на макрос: в некотором смысле он создает больше исходного кода. Все, что находится перед «...», просто повторяется для каждого аргумента (и имя пакета заменяется указанным аргументом), поэтому что-то вроде func(args...) будет расширено как «func(a, b, c)», а func(args)... превратится в «func(a), func(b), func(c)».
std::forward просто принимает один аргумент и создает один пересылаемый элемент: func(std::forward(args)...) превратится в список отдельных пересылаемых элементов: func(std::forward(a), std::forward(b), std::forward(c)). Итак, он принимает список аргументов и создает список перенаправленных аргументов.
Я читаю главу. Это ясно в сочетании с вашим объяснением. Большое спасибо!
для меня странно, что cppprefrence не может отображать синтаксис для расширения пакета. Это намного более гибко, чем они показывают.
Exact Dupe: Каковы правила для токена «...» в контексте вариативных шаблонов?