Search code examples
c++iostreamostreaminsertion

C++ insertion operator for class method


In C++ is there a way to use the insertion operator for a class method?

This operator<< overload is working:

class Complex {
public:
  //Normal overload:
  friend std::ostream& operator<<(std::ostream &out, const Complex &o) {
    out << "test overload";
    return out;
  }

  Complex() {};
  ~Complex() {};
};

I can do this:

int main()
{
  Complex* o = new Complex();

  std::cout << "This is test: " << *o << "." << std::endl; // => This is test: test overload.
}

I know about stream manipulators, like this:

std::ostream& welcome(std::ostream& out)
{
    int data = 1;
    out << "WELCOME " << data << "\r\n";
    return out;
}

int main()
{
  std::cout << "Hello " << welcome; // => "Hello WELCOME 1\r\n"
}

How can I put the welcome method into the Complex class and then how shall I call it from cout (please note that welcome method must access some class member variables)?

My trial:

class Complex {
public:
  //Normal overload:
  friend std::ostream& operator<<(std::ostream &out, const Complex &o) {
    out << "test overload";
    return out;
  }

  std::ostream& welcome(std::ostream& out) {
    out << "WELCOME " << data << "\r\n";
    return out;
  }

  Complex() { data = 1; };
  ~Complex() {};
private:
  int data;
};

int main()
{
  Complex* o = new Complex();

  std::cout << "This is test2: " << o->welcome << std::endl; // compile error
}

Solution

  • One easy way to pick a different << overload is to use a different type.

    #include <iostream>
    
    class Complex {
    public:
      //Normal overload:
      friend std::ostream& operator<<(std::ostream &out, const Complex &o) {
        out << "test overload";
        return out;
      }
    
      struct extra_info {
          const Complex& parent;
          extra_info(const Complex& p) : parent(p) {}
          friend std::ostream& operator<<(std::ostream& out, const extra_info& ei){
            int i = 1;
            out << "extrainfo " << i;
            return out;
          }
      };
      extra_info extrainfo() {
          return {*this};
      }
    
      Complex() {};
      ~Complex() {};
    };
    
    
    int main() {
        Complex c;
        std::cout << c << "\n";
        std::cout << c.extrainfo();
    }
    

    Output:

    test overload
    extrainfo 1
    

    I suppose in your real code you are using members. Hence the helper type must hold a reference to the Complex instance.