Где... (многоточие) должно быть размещено в расширении пакета параметров C++? Внутри или снаружи скобок для std::forward?

Я новичок в расширении пакета параметров C++, и меня долгое время смущало положение ... (многоточие), например:

template <typename... Args> 
void func(Args&&... args) {
    // ...
    std::forward<Args>(args)...;
    // ...
}

Почему нет std::forward<Args>(args...)? Какому правилу мне следует следовать?

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

Jan Schultke 24.05.2024 13:36

@JanSchultke Спасибо, я искал фразу «куда должно идти многоточие в расширении пакета std::forward», и Google не разочаровал. Обычно я сначала ищу в Google, а затем ищу SO (если Google не может найти ничего подходящего) на основе тегов и т. д. (как вы это сделали). Я согласен с применением этого тега немного больше.

user12002570 24.05.2024 15:34
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
3
105
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Грамматически 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)). Итак, он принимает список аргументов и создает список перенаправленных аргументов.

Я читаю главу. Это ясно в сочетании с вашим объяснением. Большое спасибо!

Ethan 24.05.2024 10:56

для меня странно, что cppprefrence не может отображать синтаксис для расширения пакета. Это намного более гибко, чем они показывают.

Swift - Friday Pie 24.05.2024 12:15

Другие вопросы по теме