Argument evaluation order between chained static function calls

580 views Asked by At

I am curious why there is a difference in the argument evaluation order between chained static functions and member functions. From the answers at this question I can see it is unspecified what the argument evaluation order is between such chained function calls. Take for example the following snippet:

#include <iostream>
class test {
public:
    static test& chain_s(test& t, int i) {
        std::cout << i << " ";
        return t;
    }

    test& chain(test& t, int i) {
        std::cout << i << " ";
        return *this;
    }
};

int main(int, char**) {
    int x = 2;
    test t;
    t.chain(t,++x).chain(t,++x).chain(t,++x);
    x = 2; std::cout << std::endl;
    t.chain_s(t,++x).chain_s(t,++x).chain_s(t,++x);

    return 0;
}

In the case of GCC 4.6.2 and CL 15.00.30729.01 (MSVC 9) the resulting output is for me

5 5 5
3 4 5

However, I was wondering if there is any reason in the specification or if it is otherwise known why the static function are evaluated left-to-right (with their arguments), and for the non-static function all the arguments first (right-to-left from what I've seen in other tests).

The reason I'm asking this is because I first noticed this difference in behavior when trying to get similar behavior in C (using a struct and a function pointer) and failed. I strongly suspect this is some optimization implemented both in GCC and MSVC for member functions, but I hope someone here can shed a little more light on this.

Edit:
I forgot to mention one crucial bit of information which strikes me as odd: GCC will only warn on unspecified behavior on the chained non-static function, but not the static functions:

a.cpp: In function 'int main(int, char**)':
a.cpp:18:45: warning: operation on 'x' may be undefined [-Wsequence-point]

GCC is not obligated to provide such warnings so it could miss the second expression, but this is what leads me to believe something interesting is going on.

2

There are 2 answers

0
James Kanze On

Your code has undefined behavior, but I suppose you know that. Also, you could easily see a difference depending on optimization flags. But in this case, one likely reason is that the non-static functions require three arguments, including the results of the previous call, where as the static functions only require two, and the results of the previous call are ignored.

2
Bo Persson On

No reason. Like you say, the order is unspecified by the language.

One reason for using right to left order is that functions with a variable number of parameters, like printf, will then always have the first parameter on top. Otherwise it doesn't matter.