1

This line: "friend ostream& operator<<(ostream& os, Fraction&& obj)" It works on Visual Studio,But on CodeBlocks it doesn't work. and the error is "expected ',' or '...' before '&&' token|"

#include <iostream>
#include <cstdio>
using namespace std;
int lcf(int n, int m)
{
    if (n < m)
    {
        int tmp = n;
        n = m;
        m = tmp;
    }
    if (n % m == 0)
        return m;
    else
        return lcf(m, n % m);
}
class Fraction
{
private:
    int fenzi, fenmu;
public:
    Fraction(int a, int b) :fenzi(a), fenmu(b) {}
    Fraction operator+(Fraction& another)
    {
        fenzi += another.fenzi;
        fenmu += another.fenmu;
        return *this;
    }
    Fraction operator*(Fraction& another)
    {
        fenzi *= another.fenzi;
        fenmu *= another.fenmu;
        return *this;
    }
    operator double()
    {
        return 1.0* fenzi / fenmu;
    }
    friend istream& operator>>(istream& is, Fraction& obj)
    {
        is >> obj.fenzi;
        getchar();
        is >> obj.fenmu;
        return is;
    }
    friend ostream& operator<<(ostream& os, Fraction&& obj)
    {
        int t = lcf(obj.fenzi, obj.fenmu);
        obj.fenzi /= t;
        obj.fenmu /= t;
        os << obj.fenzi << "/" << obj.fenmu;
        return os;
    }
    Fraction& operator++()
    {
        fenzi++;
        fenmu++;
        return *this;
    }
    Fraction operator++(int)
    {
        Fraction tmp(fenzi, fenmu);
        fenzi++;
        fenmu++;
        return tmp;
    }
};
int main()
{
    Fraction a1(9, 11), a2(1, 2);
    cout << double(a2) << endl;
    cout << ++a1 << endl;
    cout << a2++ << endl;
    cout << a1 * a2 << endl;
    return 0;
}

if the code is: "friend ostream& operator<<(ostream& os, Fraction& obj)" in the main function,"cout << a1 * a2 << endl" will strangely call the "operator double()" function instead of "friend ostream& operator<<()". So I add an "&"(Fraction&& obj),and successfully work on Visual Studio as what I expected.But CodeBlocks has error.How can I solve it.

  • `&&` is required because `a1*a2` returns r-value which cannot bind to non-const reference. It could bind to `const T&`, which would solve the problems but your operator requires non-const. Please reconsider having side-effects inside print, it's unexpected and dangerous. Make sure CodeBlocks is set to c++11 or newer. Also with `&&` `cout<<++a1` should not work. – Quimby May 10 '19 at 10:12

1 Answers1

3
cout << ++a1 << endl;//(1)
cout << a2++ << endl;//(2)
cout << a1 * a2 << endl;//(3)
  1. Results in Fraction& so it can bind to Fraction& or const Fraction& but not Fraction&&. Compiler is allowed one implicit user-defined conversion, so as a last attempt to make the code compile it converts to double and uses operator<<(ostream&,double&&) or operator<<(ostream&,double) not sure which is defined but the output is the same.
  2. cout << a2++ << endl; Results in Fraction so it can bind to Fraction&& or const Fraction& but not Fraction&. operator<<(ostream&,Fraction&&) is called.
  3. cout << a1 * a2 << endl; Results in Fraction so same as previous.

You should almost never have print with side-effects. Certainly not the ones that modify the object you passed. Then someone will write a code like this and the poor soul will spend unnecessary time with a debugger:

Fraction a;
Fraction b = a;
if(debug_build)
  cout <<"LOG:"<<a<<'\n';
assert(a==b);

My solution would be:

friend ostream& operator<<(ostream& os, const Fraction& obj)
{
    int t = lcf(obj.fenzi, obj.fenmu);
    os << obj.fenzi/t << "/" << obj.fenmu/t;
    return os;
}

Eveything can bind to const Fraction& and it's const as it should be. (1),(2),(3) will work and none will call double(). I would even consider making double() explicit as it will forbid these unexpected calls that got you confused. Unless you have good reason not to and some extra typing might not qualify. The last thing would be to really encourage you to be const-correct and not make unnecessary copies.

  • Fraction& operator+(const Fraction& another)
  • Fraction& operator+(const Fraction& another)
  • Fraction operator++(int) const

Not sure what's tripping CodeBlocks as you did not post the error message. I would guess that you must enable c++11.

Quimby
  • 17,735
  • 4
  • 35
  • 55