I understand that when I call a function such as
a(b(),c());
then the behavior of this may be undefined in <= C++14, and unspecified in >= C++17, in the sense that it is up to the compiler to determine whether to evaluate b
or c
first.
I would like to know the best way to force an evaluation order. I will be compiling as C++14.
The thing that immediately comes to mind is something like this:
#include <iostream>
int count = 5;
auto increment(){
return count++;
}
template <typename A, typename B>
auto diff(A && a, B && b){
return a - b;
}
int main() {
auto && a = increment();
auto && b = increment();
auto c = diff(a,b);
}
Am I in undefined behavior land? Or is this how one is "supposed" to force evaluation order?
The semi-colon that separates statements imposes a "happens before" relation.
auto && a = increment()
must be evaluated first. It is guaranteed. The returned temporary will be bound to the reference a
(and its lifetime extended) before the second call to increment
.
There is no UB. This is the way to force an evaluation order.
The only gotcha here is if increment
returned a reference itself, then you'd need to worry about lifetime issues. But if there was no lifetime issues, say if it returned a reference to count
, there still would not be UB from the imposed evaluation of a
and then b
.