Function call priority in output stream

Viewed 112

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?

2 Answers

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.

Put value also in << overloaded function like

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

Now

#include<iostream>

using namespace std;

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;
    }
    friend ostream& operator<<(ostream &out,const Ratio &R){return (out<<"R = "<<R.num<<':'<<R.den<<"\tvalue = "<<R.val);}
};

int main()
{
    Ratio R;

    cout<<R.update(2,1)<<endl;

}

Output:

  R = 2:1 value = 2

  Process returned 0 (0x0)   execution time : 0.382 s
  Press any key to continue.
Related