It depends.
First, let's assume that x++
by itself does not invoke undefined behavior. Think about signed overflow, incrementing a past-the-end-pointer, or the postfix-increment-operator might be user-defined).
Further, let's assume that invoking f()
and g()
with their arguments and destroying the temporaries does not invoke undefined behavior.
That are quite a lot of assumptions, but if they are broken the answer is trivial.
Now, if the comma is the built-in comma-operator, the comma in a braced-init-list, or the comma in a mem-initializer-list, the left and right side are sequenced either before or after each other (and you know which), so don't interfere, making the behavior well-defined.
struct X {
int f, g;
explicit X(int x) : f(x++), g(x++) {}
};
// Demonstrate that the order depends on member-order, not initializer-order:
struct Y {
int g, f;
explicit Y(int x) : f(x++), g(x++) {}
};
int y[] = { f(x++), g(x++) };
Otherwise, if x++
invokes a user-defined operator-overload for postfix-increment, you have indeterminate sequencing of the two instances of x++
and thus unspecified behavior.
std::list<int> list{1,2,3,4,5,6,7};
auto x = begin(list);
using T = decltype(x);
void h(T, T);
h(f(x++), g(x++));
struct X {
X(T, T) {}
}
X(f(x++), g(x++));
And in the final case, you get full-blown undefined behavior as the two postfix-increments of x
are unsequenced.
int x = 0;
void h(int, int);
h(f(x++), g(x++));
struct X {
X(int, int) {}
}
X(f(x++), g(x++));
,
operator. No if the,
operator is user defined. see: en.cppreference.com/w/cpp/language/… (this changes with C++17) – Irrigationabort();
but that's not very helpful, is it? – Iataoperator,
still has a sequencing guarantee? – Iataoperator,( f(x++), g(x++) );
is not UB, and (say x == 0 beforehand) will either callf(0)
theng(1)
, or callg(0)
thenf(1)
; and leavex == 2
afterwards. It was proposed that function calls have strict left-right evaluation, but so far as I know, that didn't happen – Statuary