2017-09-05 95 views
3

折叠表达式似乎是将函数应用于元组的每个元素的好方法。但是,如果应用函数有副作用,那么函数调用的顺序可能是一个重要的问题。折叠表达式的评估顺序

考虑:

#include <iostream> 

template<typename... Ts> 
void printStuff(Ts... args) 
{ 
    (([](auto&& v) { std::cout << v << " "; })(args), ...); 
    std::cout << '\n'; 
} 

int main() 
{ 
    printStuff("hello", 42, 1.5f); 
    // expected output: hello 42 1.5 
} 

seems to work

但是,在这里保证的lambda表达式的评估顺序还是可以最终在输出中翻转值?如果我使用不同的操作员来一起链接命令,答案会改变吗?

+3

您使用逗号运算符,该运算符已排序。 – Jarod42

回答

9

操作符的右侧展开如下所示:... (arg0 op (arg1 op arg2))。所以,虽然这些人的帮助,但他们不保证任何有关各个元素的顺序。

因此,这全部留给op。而comma operator(与逗号分隔函数参数不同),甚至是pre-C++ 17,都是一个很难的序列点。它确保从左到右的评估不会出现串扰。

如果您改为使用+,则不会有序列保证。这取决于您使用的操作员。 C++ 17增加了几个具有严格排序保证的运算符(例如,<<)。

+1

仅供参考:在C++ 17中为我们提供了更严格的时序保证的建议是[P0145r3](https://wg21.link/P0145r3)。这也保证了重载逗号操作符不会消除顺序保证。 – ComicSansMS

+0

OP正在使用正确的折叠。 –

+0

@ T.C:你知道,你有完整的编辑权限。你可以自己修复它。 –