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&&...) {}
};
}