C++17 折叠表达式
(f(args), ...);
如果您调用可能返回带有重载逗号运算符的对象的内容:
((void)f(args), ...);
C++17 之前的解决方案
这里的典型方法是使用哑列表初始化器并在其中进行扩展:
{ print(Args)... }
在 curly 初始化程序中,评估顺序保证从左到右。
但是print 返回void,所以我们需要解决这个问题。那么让我们把它变成一个 int。
{ (print(Args), 0)... }
不过,这不会直接用作语句。我们需要给它一个类型。
using expand_type = int[];
expand_type{ (print(Args), 0)... };
只要Args 包中始终存在一个元素,此方法就有效。零大小的数组是无效的,但我们可以通过使其始终具有至少一个元素来解决这个问题。
expand_type{ 0, (print(Args), 0)... };
我们可以通过宏使这个模式可重用。
namespace so {
using expand_type = int[];
}
#define SO_EXPAND_SIDE_EFFECTS(PATTERN) ::so::expand_type{ 0, ((PATTERN), 0)... }
// usage
SO_EXPAND_SIDE_EFFECTS(print(Args));
但是,要使其可重用,需要更多地关注一些细节。我们不希望在这里使用重载的逗号运算符。逗号不能用 void 的参数之一重载,所以让我们利用它。
#define SO_EXPAND_SIDE_EFFECTS(PATTERN) \
::so::expand_type{ 0, ((PATTERN), void(), 0)... }
如果你偏执害怕编译器分配大量的零数组,你可以使用一些其他类型,可以像这样进行列表初始化但什么都不存储。
namespace so {
struct expand_type {
template <typename... T>
expand_type(T&&...) {}
};
}