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?
terminology - Name of Property: The Order Of Parameters in a Function Does Not Matter - Mathematics Stack Exchange.
3. Positional Arguments. During a function call, values passed through arguments should be in the order of parameters in the function definition. This is called positional arguments.
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
.
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