This code is taken from a discussion going on here.
someInstance.Fun(++k).Gun(10).Sun(k).Tun();
Is this code well-defined? Is ++k
in Fun() evaluated before k
in Sun()?
What if k
is user-defined type, not built-in type? And in what ways the above function calls order is different from this:
eat(++k);drink(10);sleep(k);
As far as I know, in both situations, there exists a sequence point after each function call. If so, then why can't the first case is also well-defined like the second one?
Section 1.9.17 of the C++ ISO standard says this about sequence points and function evaluation:
When calling a function (whether or not the function is inline), there is a sequence point after the evaluation of all function arguments (if any) which takes place before execution of any expressions or statements in the function body. There is also a sequence point after the copying of a returned value and before the execution of any expressions outside the function.
This depends on how Sun
is defined. The following is well-defined
struct A {
A &Fun(int);
A &Gun(int);
A &Sun(int&);
A &Tun();
};
void g() {
A someInstance;
int k = 0;
someInstance.Fun(++k).Gun(10).Sun(k).Tun();
}
If you change the parameter type of Sun
to int
, it becomes undefined. Let's draw a tree of the version taking an int
.
<eval body of Fun>
|
% // pre-call sequence point
|
{ S(increment, k) } <- E(++k)
|
E(Fun(++k).Gun(10))
|
.------+-----. .-- V(k)--%--<eval body of Sun>
/ \ /
E(Fun(++k).Gun(10).Sun(k))
|
.---------+---------.
/ \
E(Fun(++k).Gun(10).Sun(k).Tun())
|
% // full-expression sequence point
As can be seen, we have a read of k
(designated by V(k)
) and a side-effect on k
(at the very top) that are not separated by a sequence point: In this expression, relative to each other sub-expression, there is no sequence point at all. The very bottom %
signifies the full-expression sequence point.