Fold expressions seem to be a nice way to apply a function to each element of a tuple. However, if the applied function has side effects, the order of function invocations might be an important concern.
Consider:
#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
}
This seems to work.
But is the order of evaluation for the lambdas guaranteed here or could I end up with the values being flipped around in the output? Does the answer change if I used a different operator for chaining the commands together?
Order of evaluation refers to the operator precedence and associativity rules according to which mathematical expressions are evaluated.
Only the sequential-evaluation ( , ), logical-AND ( && ), logical-OR ( || ), conditional-expression ( ? : ), and function-call operators constitute sequence points, and therefore guarantee a particular order of evaluation for their operands.
The order of evaluation of function arguments is unspecified. Consequently, parameters of a function shall not be used in a default argument, even if they are not evaluated. The same verbiage is used by C++14 standard as well, and is found under the same section. Save this answer.
You can combine two or more conditional expressions on the IF statement. ISPF evaluates the conditional expressions on the IF statement from left to right, starting with the first expression and proceeding to the next and subsequent expressions on the IF statement until processing is complete.
A right-fold over an operator expands like this: ... (arg0 op (arg1 op arg2))
. So while the parens help, they don't guarantee anything about the order of the individual elements.
Therefore, it's all left up to op
. And the comma operator (which is distinct from commas separating function arguments), even pre-C++17, is a hard sequence point. It ensures left-to-right evaluation with no cross-talk.
If you had instead used +
, there would be no sequencing guarantees. So it depends on the operator you use. C++17 added a few more operators that have strict sequencing guarantees (<<
, for example).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With