If a function has multiple arguments, it is unspecified what order they are evaluated in. The following code could print x = 1, y = 2
or x = 2, y = 1
but it is unspecified which.
int f(int x, int y) {
printf("x = %d, y = %d\n", x, y);
}
int get_val() {
static int x = 0;
return ++x;
}
int main() {
f(get_val(), get_val());
}
In C++17, the order of evaluation of function arguments remains unspecified.
However, each function argument is completely evaluated, and the calling object is guaranteed evaluated before any function arguments are.
struct from_int {
from_int(int x) { std::cout << "from_int (" << x << ")\n"; }
};
int make_int(int x){ std::cout << "make_int (" << x << ")\n"; return x; }
void foo(from_int a, from_int b) {
}
void bar(from_int a, from_int b) {
}
auto which_func(bool b){
std::cout << b?"foo":"bar" << "\n";
return b?foo:bar;
}
int main(int argc, char const*const* argv) {
which_func( true )( make_int(1), make_int(2) );
}
this must print:
bar
make_int(1)
from_int(1)
make_int(2)
from_int(2)
or
bar
make_int(2)
from_int(2)
make_int(1)
from_int(1)
it may not print bar
after any of the make
or from
's, and it may not print:
bar
make_int(2)
make_int(1)
from_int(2)
from_int(1)
or similar. Prior to C++17 printing bar
after make_int
s was legal, as was doing both make_int
s prior to doing any from_int
s.