how to overload << operator in c++ to use repeatedly?

Viewed 70

Sorry for the not clear title. Recently I started to learn C++ and I don't know how to overload operator << to make it repeatable.

Here's an example code.

class Foo{
private:
int* a;
int idx = 0;

public:
Foo(){a = new int[100];
void operator<< (int a) {arr[idx++] = a;}

What << does is basically class get integer number as an operand and save it into arr.(Ignore overflow case here)

For example, a << 100 will add 100 into array.

What I want to do is make << operator can be repeatedly used inline like a << 100 << 200 How should I fix above code to allow this function?

Thanks in advance :)

3 Answers

The overloaded Foo::operator<<() takes actually two arguments:

  1. The parameter int given as right-hand side
  2. The implicit this from left-hand side.

To allow chaining of this operator, it should return a reference to the left-hand-side (i.e. *this) to become usable at left-hand-side itself.

Sample code:

#include <iostream>

struct Foo {
  Foo& operator<<(int a)
  {
    std::cout << ' ' << a;
    return *this;
  }
};

int main()
{
  Foo foo;
  foo << 1 << 2 << 3;
}

Output:

 1 2 3

Live demo on coliru

Chaining is enabled by returning a reference to the instance so you can call another method:

class Foo{
private:
    std::vector<int> a;   
public:
    Foo(){}
    Foo& operator<< (int a) {
        arr.push_back(a);
        return *this;
    }
};

Now you can call f << 100 << 200 << 42;.

Note that I replaced the array with a std::vector to make Foo less broken (unless you have a descrutor that you did not show it was leaking memory, you could fix that, but then still copying would cause problems, in short you need to respect the rule of 3/5 when you own a resource, using a std::vector makes things much simpler).

PS: Same works for other methods. You simply call another method on the returned reference to this. Note that operators are just methods (with some syntactic sugar) and to see that you can write as well f.operator<<(100).operator<<(200).operator<<(42);.

Return a reference to *this. It's unrelated but you should use a vector to avoid memory leaks. Try to avoid raw new

class Foo{
private:
    std::vector<int> a;

public:
    Foo &operator<< (int a) {
        arr.push_back(a);
        return *this;
    }
};
Related