By harrbharry


2012-01-17 19:20:42 8 Comments

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 comments

@James Kanze 2012-01-17 20:07:12

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.

@Bo Persson 2012-01-17 19:27:38

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.

@harrbharry 2012-01-17 19:50:51

I forgot to ask why the compiler output messages differ, any ideas on that? This is also what led to this entire question.

@James Kanze 2012-01-17 20:09:50

Even with printf, the compiler can evaluate the arguments in any order it pleases, or even interleave the evaluations. On a stack based machine, the first argument is likely to be the last pushed, but there's also a good chance that the compiler just reserves the necessary space on the stack, and stores each argument where it belongs using sp-relative addressing. And doing so in whatever order it finds convenient.

Related Questions

Sponsored Content

5 Answered Questions

[SOLVED] What is the lifetime of a static variable in a C++ function?

  • 2008-10-29 12:14:03
  • Motti
  • 165429 View
  • 356 Score
  • 5 Answer
  • Tags:   c++ static lifetime

36 Answered Questions

[SOLVED] Difference between static class and singleton pattern?

8 Answered Questions

[SOLVED] Difference between static and shared libraries?

10 Answered Questions

[SOLVED] What is a "static" function?

  • 2009-02-17 18:26:02
  • Slava V
  • 540525 View
  • 452 Score
  • 10 Answer
  • Tags:   c function static

4 Answered Questions

[SOLVED] How can I get sizeof a vector::value_type?

1 Answered Questions

[SOLVED] How to pass an implemented virtual member function as a parameter

15 Answered Questions

[SOLVED] Can I call a constructor from another constructor (do constructor chaining) in C++?

  • 2008-11-21 09:43:08
  • Stormenet
  • 419420 View
  • 852 Score
  • 15 Answer
  • Tags:   c++ constructor

3 Answered Questions

[SOLVED] Error to use of static and static function in C++

2 Answered Questions

[SOLVED] Function argument evaluation order

0 Answered Questions

std::atomic_is_lock_free(shared_ptr<T>*) didn't compile

  • 2014-02-10 05:32:27
  • 大宝剑
  • 1061 View
  • 6 Score
  • 0 Answer
  • Tags:   c++ c++11

Sponsored Content