Я хотел лучше понять расширения пакета параметров , поэтому я решил немного исследовать и, что когда-то казалось мне очевидным, перестал быть настолько очевидным после попытки понять, что именно происходит. Давайте рассмотрим стандартное расширение пакета параметров с помощью std::forward
:
template <typename... Ts>
void foo(Ts&& ... ts) {
std::make_tuple(std::forward<Ts>(ts)...);
}
Здесь я понимаю, что для любого пакета параметров Ts
, std::forward<Ts>(ts)...
приведет к разделенному запятыми списку перенаправленных аргументов с их соответствующего типа, например, для ts
, равного 1, 1.0, '1'
, тело функции будет расширено до:
std::make_tuple(std::forward<int&&>(1), std::forward<double&&>(1.0), std::forward<char&&>('1'));
И это имеет смысл для меня. Расширение пакета параметров, используемое с вызовом функции, приводит к разделенному запятыми списку вызовов этой функции с соответствующими аргументами.
Что меня беспокоит, так это то, почему тогда нам иногда нужно вводить оператор запятой (operator,
), если мы хотим вызвать несколько функций подобным образом? Видя этот ответ , мы можем прочитать этот код:
template<typename T>
static void bar(T t) {}
template<typename... Args>
static void foo2(Args... args) {
(bar(args), ...); // <- notice: comma here
}
int main() {
foo2(1, 2, 3, "3");
return 0;
}
с последующей информацией о том, что это приведет к следующему расширению:
(bar(1), bar(2), bar(3), bar("3"));
Справедливо, имеет смысл , но ... почему ? Почему вместо этого:
template<typename... Args>
static void foo2(Args... args) {
(bar(args)...); // <- notice: no comma here
}
не работает? Согласно моей логи c (« Расширение пакета параметров, используемое с вызовом функции, приводит к разделенному запятыми списку вызовов этой функции с соответствующими аргументами »), оно должно расшириться до:
(bar(1), bar(2), bar(3), bar("3"));
Это из-за bar()
возврата void
? Что ж, изменение bar()
на:
template<typename T>
static int bar(T t) { return 1; }
ничего не меняет. Я предположил бы, что он просто расширится до списка разделенных запятыми 1
с (возможно, с некоторыми побочными эффектами, если bar()
был задуман как таковой). Почему это ведет себя по-другому? Где моя логика c с недостатками?