2

I need to add multiple objects using operator overloading such as below:

ex1 operator+(const ex1 &c1, const ex1 &c2, more++){
    return ex1(c1 + c2 + more++);
}

This function adds two objects, however I want to add multiple objects. Is that possible?

int main(){
  // first for example I want to add 3 objects
  ex1 ob1, ob2, ob3;
  ob1 + ob2 + ob3;

  code..
  code..

  // and after that I want to add for example 10 or more objects  
  ex1 ob1, ob2, ob3,..., ob10;
  ob1 + ob2 + ob3 +....+ ob10;
}
11
  • 1
    It doesn't matter how many "values" (or objects) you want to add together, the operator function still only takes one (for member functions) or two (for non-member functions) arguments. The compiler will cascade the calls for you. Commented Jan 9, 2016 at 18:21
  • can you explain more your reply? you said that i can call the operator+ with any number of argument's? Commented Jan 9, 2016 at 18:26
  • No the compiler will generate the correct number of calls of your operator function. The function will always only be called with one or two arguments (depending on where it's declared), but the number of calls will increase as you add more values. Commented Jan 9, 2016 at 18:29
  • Just to experiment, why don't you write a simple operator+ functions which does nothing but print something and return a default-constructed object, of course with only two arguments to make it work. That way you can easily see that the function gets called two times for e.g. a + b + c, three times for a + b + c + d etc. Commented Jan 9, 2016 at 18:35
  • 1
    Also, just think about it like that: Addition (the + operator) is a binary operator, meaning it has two operands: A left hand side and a right hand side. This is how addition works, in C++ as well as in real life. That the left hand side is the result of another addition doesn't really matter, the operator still has only two operands. Commented Jan 9, 2016 at 18:38

4 Answers 4

2

Just define

ex1 operator+(const ex1 &c1, const ex1 &c2){
    return ex1(c1.inner_value + c2.inner_value);
}

And then

a + b + c

Will be interpreted as

operator+(  operator+(a,b) , c )

So it should work

Sign up to request clarification or add additional context in comments.

4 Comments

i want multiple class objects .. not 3 but multiple,3 was an example
While the operator function signature is correct and the calling order, the function will actually not work as the operator+ function would be called recursively.
Right. I fixed the operator+ definition to not be recursive.
Can you please check my update with a similar question?
2

You need only overload + for two objects. It will then automagically work if you try to add three or more objects, because a + b + c is equivalent to (a+b)+c, or in terms of operator-function calls:

 operator+(operator+(a, b), c)

As long as you return an appropriate type from your + routine, you should be fine.

If you have an array of objects and want to sum all of them up, once again, you only need to overload operator + for two objects and then you can use the std::accumulate function from <numeric> header:

std::vector<ex1> objects = {/*...lots of objects*/};
ex1 sum = std::accumulate(objects.begin(), objects.end(), ex1());

re update: By overloading operators in C++ you can change the return type and semantics of what an operator does, but you cannot change any of the following:

  • the precedence of the operator (i.e. you cannot make a+b*c be equivalent to (a+b)*c
  • the arity of the operator (i.e. you cannot overload a unary operator to take 2 operands and vice versa. You can't for example, make % work liks %a or a%
  • you can't change if the (unary) operator is postfix or prefix, so you can't make the syntax a- or a+ work

So the answer to your second question is no.

3 Comments

can you give me an example for multiple objects?
@therealp: a+b+c+d+e is equivalent to (((a+b)+c)+d)+e
Can you please check my update with a similar question??
1

If you want your overloaded operator to work for multiple objects, what you need is chaining*, this could be ensured when you return your result by reference:

ex1& operator+(const ex1 &c1, const ex1 &c2){

    return ex1.var = c1.var + c2.var;
}

or if the operator is a class member:

ex1& operator+(const ex1 &rhs) {

    return ex1.var = this.var + rhs.var; 
}

once you have the above definition, you can add multiple objects as follows:

ex1 + ex2 + ex3

which will be equivalent to:

(ex1 + ex2) + ex3 => sum(ex1,ex2) + ex3 => sum(sum(ex1,ex2), ex3)

i.e. it is always reduced to binary operation between two operands.

To answer your updated question, here is a list of all the operators that could be overloaded, regardless of their arity (unary, binary) or affix (prefix, postfix). In the case of your updated question you are looking for postfix, unary operator overload.

*Multiple method calls, where each method returns an object, allowing the calls to be chained together in a single statement without requiring variables to store the intermediate results

7 Comments

Glad that I could help! :)
Can you please check my update with a similar question?
@therealp I would kindly advice you to accept the answer which satisfy the first part of the question and then ask a new question with the new topic. :)
thanks for help im new in this community but the system doesn't allowed me to create a new thread :(
@simplicis veritatis You are returning a local variable by reference. Anyone that calls your operator+ will be looking at undefined behavior.
|
0

With one exception, C++ only has unary operators and binary operators. The one exception is the ternary operator, exemplified by x = condition ? 0 : 42;. With regard to operator+, that is either a unary operator (e.g., +42) or a binary operator (40+2).

You can easily create a custom function that takes three ex1 objects as input and somehow computes the sum of those three objects. However, you cannot call this function operator+. There's no place in C++ for an operator+ that takes three arguments.

There are a number of ways around this restriction. The simplest is to create an overload of binary operator+ that computes the sum of a pair of ex1 objects, creating a new ex1 object as output. The statement ex1 d=a+b+c; will result in two calls to ex1 operator+(const ex1&, const ex1&). Both will create a temporary objects of type ex1. The temporary that represents the value of a+b+c is then passed to ex1::operator= to assign the value of that expression to d.

If you are doing this over and over and over, the creation of those temporary objects might well represent a performance bottleneck. If you are only doing this a few times, that performance bottleneck is a non-issue. The only time you need to worry is if this is an issue, and determining whether that's the case is an issue for you to resolve.

One way of overcoming this performance bottleneck is to create a function (or functions) that take more than two objects as input and creating a sum from those multiple objects. The downside is that you cannot name this function operator+, and hence you cannot use d=a+b+c. You'd instead have to use something like ex1::add_three(ex1&d, const ex1&a, const ex1&b, const ex1&c).

Another approach is to use expression templates as a means for implementing lazy evaluation. Your operator+(const ex1& a, constex1& b) doesn't actually calculate a+b. It instead creates an object that eventually will calculate a+b. The expression a+b+c in turn creates another object that eventually will calculate that result. Finally, the expression d=a+b+c evaluates that expression and assigns it to d, and (if implemented correctly) does so without creating any temporaries.

This approach has also its downsides. Sometimes it is better to create a temporary. The Eigen package does a very good job of determining when its better to create a temporary as opposed to using expression templates that defer calculation.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.