Search code examples
c++classstreammember

Function call priority in output stream


So, I have the following class:

typedef double decimal;

class Ratio {
  int num, den;
  decimal val;

public:
  Ratio() { num = 1, den = 1, val = (decimal)num / den; }

  Ratio update(int a, int b) {
    num *= a, den *= b;
    val = (decimal)num / den;
    return *this;
  }

  decimal v(void) { return val; }

  friend ostream &operator<<(ostream &out, const Ratio &R) {
    return (out << R.num << ':' << R.den);
  }
};

When I use the member functions in the output stream as:

cout<<"R = "<<R.update(2,1)<<"\tvalue = "<<R.v();

where R is of type Ratio, the function to the right end is called first so it displays the updated ratio but the non-updated value:

R = 2:1    value = 1

I overcame this by splitting the stream in two:

cout<<"R = "<<R.update(2,1), cout<<"\tvalue = "<<R.v();

so that I "force" .update() to be called first. Is there another way to achieve this, using only one stream for output?


Solution

  • As there is no guaranteed evaluation order in c++, it won't work without splitting it into separate parts, as you did in your fix.

    Quoting from cppreference

    There is no concept of left-to-right or right-to-left evaluation in C++. This is not to be confused with left-to-right and right-to-left associativity of operators: the expression a() + b() + c() is parsed as (a() + b()) + c() due to left-to-right associativity of operator+, but the function call to c may be evaluated first, last, or between a() or b() at run time

    As user @super pointed out, starting from c++17 the evaluation order of shift operators is now defined. It's hidden in bullet 19) of the rules on the page I linked above. So if you can c++17, you're done.