Search code examples
c++operator-overloadingostream

Is it possible to overload the ostream operator for arithmetic expressions?


Is it possible to create an overload for the ostream operator that does an arithmetic operation (addition for example) and then streams out the result? The standard ostream overload that can be found all over the web can only stream from a single variable. I need something that does the following:

std::cout << x+y << std::endl;

or even more complex expressions like:

std::cout << x*y+(3*z)^2 << std::endl;

where x, y, and z are instances of a simple custom-made struct where arithmetic operations are already defined (overloaded).

EDIT:

Here is my code:

struct scalar //complex scalar data structure
{
friend scalar operator^(const scalar&, int); //integer power operator overload
friend scalar exp(const scalar&); //exponential power function
std::ostream& operator<<(std::ostream&, const scalar&)
protected:
  double re;
  double im;
public:
  double real() {return re;} //returns the real part
  double imag() {return im;} //returns the imaginary part
  scalar(double _re, double _im) {re=_re;im=_im;} //constructor 1
  scalar(double _re) {re=_re;im=0.0;} //constructor 2
  scalar(const scalar& s): re(s.re), im(s.im) {} //copy constructor
  scalar& operator=(const scalar& rhs) //assignment operator overload
  {
    if (&rhs==this) return *this; //checks for self-assignment
    re=rhs.re; //sets real parts equal
    im=rhs.im; //sets imaginary parts equal
    return *this;
  }
  scalar& operator+=(const scalar& rhs) //compound addition-assignment operator overload
  {
    if (&rhs==this) return *this; //checks for self-assignment
    re=re+rhs.re; //adds real parts
    im=im+rhs.im; //adds imaginary parts
    return *this;
  }
  scalar& operator*=(const scalar& rhs) //compound multiplication-assignment operator overload
  {
    if (&rhs==this) return *this; //checks for self-assignment
    double x1=re; double x2=rhs.re; double y1=im; double y2=rhs.im;
    re=x1*x2-y1*y2; //multiplies real parts
    im=x1*y2+x2*y1; //multiplies imaginary parts
    return *this;
  }
  scalar& operator-=(const scalar& rhs) //compound subtraction-assignment operator overload
  {
    if (&rhs==this) return *this; //checks for self-assignment
    re=re-rhs.re; //adds real parts
    im=im-rhs.im; //adds imaginary parts
    return *this;
  }
  scalar& operator/=(const scalar& rhs) //compound division-assignment operator overload
  {
    if (&rhs==this) return *this; //checks for self-assignment
    double x1=re; double x2=rhs.re; double y1=im; double y2=rhs.im;
    double n;
    n =pow(x2,2)+pow(y2,2);
    if (n==0) throw(1);
    re=(x1*x2+y1*y2)/n; //multiplies real parts
    im=(x2*y1-x1*y2)/n; //multiplies imaginary parts
    return *this;
  }
  const scalar operator+(const scalar& b) //addition operator overload
  {
    scalar c = *this;
    c+=b;
    return c;
  }
  const scalar operator*(const scalar& b) //addition operator overload
  {
    scalar c = *this;
    c*=b;
    return c;
  }
  const scalar operator-(const scalar& b) //addition operator overload
  {
    scalar c = *this;
    c-=b;
    return c;
  }
  const scalar operator/(const scalar& b) //addition operator overload
  {
    scalar c = *this;
    c/=b;
    return c;
  }
};

scalar i(0.0,1.0);
scalar j(0.0,1.0);

std::ostream& operator<<(std::ostream& out, const scalar& s)
{
  out << s.re << '+' << s.im << 'i';
  return out;
}

scalar operator^(scalar a, int b) //integer power operator overload
{
  double x=a.real(); double y=a.imag();
  if (x==0) throw(1);
  int r=sqrt(pow(x,2)+pow(y,2));
  int arg=atan2(y,x);
  scalar c(r*cos(arg),r*sin(arg));
  return c;
}

scalar exp(const scalar& s) //exponential power function
{
  double x=s.re; double y=s.im;
  scalar c(exp(x)*cos(y),exp(x)*sin(y));
  return c;
}

Here is my main function:

int main()
{
  scalar x(3,4);
  scalar y=2;
  cout << x*y << endl;
  return 0;
}

This is is the output it is supposed to give:

6+8i

And this is the errors it gives instead:

In function 'std::ostream& operator<<(std::ostream&, const scalar&)':|
error: passing 'const scalar' as 'this' argument of 'double scalar::real()' 
discards qualifiers|

And if I remove the const as the compiler says, I will get the following error:

error: no match for 'operator<<' in 'std::cout << scalar::operator*(const scalar&)
(((const scalar&)((const scalar*)(& y))))'|

Solution

  • The error is because functions scalar::real and scalar::imag are not const - you can only call const member functions when you've got a reference to a constant scalar.

       double real() const {return re;}
       double imag() const {return im;}