I keep finding more idioms that lend themselves to std::exchange.
Today I found myself writing this in an answer:
do {
path.push_front(v);
} while (v != std::exchange(v, pmap[v]));
I like it a lot more than, say
do {
path.push_front(v);
if (v == pmap[v])
break;
v= pmap[v];
} while (true);
Hopefully for obvious reasons.
However, I'm not big on standardese and I can't help but worry that lhs != rhs doesn't guarantee that the right-hand side expression isn't fully evaluated before the left-hand-side. That would make it a tautologous comparison - which would by definition return true.
The code, however, does run correctly, apparently evaluating lhs first.
Does anyone know
- whether the standard guarantees this evaluation order
- if it has changed in recent standards, which standard version first specified it?
PS. I realize that this is a special case of f(a,b) where f is operator!=. I've tried to answer my own query using the information found here but have failed to reach a conclusion to date:
C++17 introduced rules on sequences. What was UB before is now well defined. This applies to arguments to function calls as well as a select assortment of operators:
The built-in
!=however is not sequenced (see link above). A function call would be sequenced but the order of evaluation is not guaranteed:(emphasis added)
To my reading, even if you wrote a wrapper function, your compiler would not be required to evaluate
vfirst, thenstd::exchange(v, pmap[v])and finallyequal(..). And reversing the evaluation order, I believe, would change semantics in your example.So sadly, as nice as
std::exchangeis, in this case, it is not guaranteed to do what you need it to.