发送模板参数包到 std::basic_ostream

Sending a template parameter pack to std::basic_ostream

cppreference page 上有一个代码示例 std::integer_sequence:

template<typename T, T... ints>
void print_sequence(std::integer_sequence<T, ints...> int_seq)
{
    std::cout << "The sequence of size " << int_seq.size() << ": ";
    ((std::cout << ints << ' '),...);
    std::cout << '\n';
}

我不太明白 ((std::cout << ints << ' '),...) 语法。我没有看到 std::basic_ostream::operator<<` 的任何重载版本,它们会采用可变参数模板的参数包。

这里到底发生了什么,它是如何工作的?

I don't quite understand the ((std::cout << ints << ' '),...) syntax. I don't see any overloaded versions of std::basic_ostream::operator<< that would take a variadic template's parameter pack in.

What exactly is happening here, and how does it work?

如果我没记错的话,它叫做 "fold expression",但您也可以将其称为“模板折叠”或简称为“折叠”。

从 C++17 开始可用。

我们的想法是对可变值包应用一个运算符。

经典例子:求和。

如果您想要 ints 的总和,您可以按如下方式应用 + 运算符

( ints + ... );

在您的例子中,折叠表达式应用于逗号运算符。

因此,如果 ints... 是(例如)2, 3, 5, 7,您的表达式:

((std::cout << ints << ' '),...);

等同于

(std::cout << 2 << ' '), (std::cout << 3 << ' '), (std::cout << 5 << ' '), (std::cout << 7 << ' ');

operator<< 不需要接受可变参数包就可以工作。这里实际发生的是,例如,对于 3 个整数,该行将扩展为如下所示:

(
  (std::cout << int1 << ' '),
  (std::cout << int2 << ' '),
  (std::cout << int3 << ' ')
);

运算符,保证从左到右的执行顺序。