Overload operator over and over

115 Views Asked by At

I've overloaded operator << in my own vector class that will work as follows

int main() {
    my_vector<int> vec;
    vec << 1 << 2 << 3;     // will add elements at end [ 1, 2, 3 ]

    display(vec);
}

This works perfectly fine as I want, but I wanted to make it more efficient I did this

    10 << vec;              // will add element at begin [ 10, 1, 2, 3 ]

But this goes wrong when I do it multiple times like

    20 << 10 << vec;        // this does [ 20480, 1, 2, 3 ];

that first does operation on 20 << 10, then 20480 << vec

I want to process it like [ 20, 10, 1, 2, 3];

3

There are 3 best solutions below

0
JohnFilleau On BEST ANSWER

One potential solution is to create a proxy object, or even a full-fledged vector object, that aggregates the elements to be inserted.

The interface would look approximately like:

vec_front_inserter(20) >> 10 >> my_vec;

Note that I recommend using the extraction operator (>>) to indicate front-insertion, as it reads better to me, but feel free to change back to the insertion operator (<<) if you don't like this.

Your implementation would require:

  1. Define an operator>>(const my_vector&, my_vector&) to represent front-inserting one vector into another.
  2. Create a proxy vec_front_inserter class that has operator>>(vec_front_inserter&, int) defined, and holds a my_vector internally.
  3. Define a operator>>(const vec_front_inserter&, my_vector&) to insert the elements at the front of my_vector.
class vec_front_inserter {
public:
    vec_front_inserter() {}
    vec_front_inserter(int seed) {
        _data.push_front(seed);
    }

    friend vec_front_inserter& operator>>(vec_front_inserter& proxy, int value);
    friend my_vector& operator>>(const vec_front_inserter& proxy, my_vector& vec);

private:
    my_vector _data;

};

vec_front_inserter& operator>>(vec_front_inserter& proxy, int value) {
    _data.push_back(value);
}

my_vector& operator>>(const vec_front_inserter& proxy, my_vector& vec) {
    vec.insert_front(proxy._data);
}

This feels similar to me to string concatenation.

You can do something like:

std::string concat = std::string("foo") + "bar" + "biz" + "baz";

But you can't do something like:

std::string fail = "foo" + "bar" + "biz" + "baz";
1
user107511 On

This happens because of operator precedence/associativity. The compiler first performs the << operation between 20 and 10, and then performs another << operation between the result and vec. That's because if you have more than a single << operator, they will be processed from left to right.

Using parenthesis should solve it:

20 << (10 << vec);

This tells the compiler to first perform the operation between 10 and vec and then perform another operation between the result and 20.

(Assuming you implemented the operator overloading correctly).

0
Marek R On

Side note:

Please do not overload operators in ways which is not expected. This will be confusing and will make hard to read/maintain your code. I can't imagine such overload in professional code, but it could be done just for fun.

On topic

Now you second approach didn't works since operators: << >> have left-to-right associativity. This means that when you write:

vec << 1 << 2 << 3;

this is equivalent to:

(((vec << 1) << 2) << 3);

and when you write:

20 << 10 << vec;

actual outcome is:

((20 << 10) << vec);

So it calculating 20 << 10 first and result of that is feed to your overloaded version of operator <<.

In theory you could overload other operators with have right-to-left associativity (for example <<=, >>=), to achieve your goal, but as I point out this is very bad practice and this would make it even worse.