From: Dominic Chandar on
Hi,

I would like to add multiple objects of a class with integers/
floats. Need some basic help in fixing an error

Eg:

#include<iostream>
using namespace std;
class Test
{
public:
Test(float _code){ code = _code;}
Test(){}
float code;
friend Test operator+(Test & ob, float val);
friend Test operator+(float val, Test & ob);
Test operator+(Test & ob);
};
Test Test::operator+(Test & ob)
{
Test temp;
temp.code = this->code + ob.code;
return temp;
}
Test operator+(Test & ob, float val)
{
Test temp;
temp.code = ob.code + val;
return temp;
}
Test operator+(float val, Test & ob)
{
Test temp;
temp.code = ob.code + val;
return temp;
}
int main()
{
Test ob1(1.0), ob2(2.0), ob3(3.0), ob4(0.0);
float c1=100.5 ;

ob4 = ob1+ob2+ob3 ; // This works
ob4 = ob1+c1; // This works
ob4 = ob1 + ob2 + c1 ;// Does not work... why ?
ob4 = ob1 + c1 + ob2 ;// This works...


return 0;
}

My question is : why does the third operation ob4 = ob1 + ob2 + c1
fail ?

-Dominic

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Pete Becker on
On 2010-07-13 12:43:44 -0400, Dominic Chandar said:

> Hi,
>
> I would like to add multiple objects of a class with integers/
> floats. Need some basic help in fixing an error
>
> Eg:
>
> #include<iostream>
> using namespace std;
> class Test
> {
> public:
> Test(float _code){ code = _code;}
> Test(){}
> float code;
> friend Test operator+(Test & ob, float val);
> friend Test operator+(float val, Test & ob);
> Test operator+(Test & ob);
> };
> Test Test::operator+(Test & ob)
> {
> Test temp;
> temp.code = this->code + ob.code;
> return temp;
> }
> Test operator+(Test & ob, float val)
> {
> Test temp;
> temp.code = ob.code + val;
> return temp;
> }
> Test operator+(float val, Test & ob)
> {
> Test temp;
> temp.code = ob.code + val;
> return temp;
> }
> int main()
> {
> Test ob1(1.0), ob2(2.0), ob3(3.0), ob4(0.0);
> float c1=100.5 ;
>
> ob4 = ob1+ob2+ob3 ; // This works
> ob4 = ob1+c1; // This works
> ob4 = ob1 + ob2 + c1 ;// Does not work... why ?
> ob4 = ob1 + c1 + ob2 ;// This works...
>
>
> return 0;
> }
>
> My question is : why does the third operation ob4 = ob1 + ob2 + c1
> fail ?
>

Presumably "fail" here means "doesn't compile and produces error
messages that haven't been included in this message". Error messages
are your friend! Read them!

Off hand, it looks like ob1 + ob2 is returning a Test object, and since
operator+ takes a non-const Test object, it can't be called with a
temporary. Both free functions should take their Test object by const
reference or by value, and the member operator+ should be marked const.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: mingze zhang on
On Jul 14, 6:43 am, Dominic Chandar <dominic.chan...(a)gmail.com> wrote:
> Hi,
>
> I would like to add multiple objects of a class with integers/
> floats. Need some basic help in fixing an error
>
> Eg:
>
> #include<iostream>
> using namespace std;
> class Test
> {
> public:
> Test(float _code){ code = _code;}
> Test(){}
> float code;
> friend Test operator+(Test & ob, float val);
> friend Test operator+(float val, Test & ob);
> Test operator+(Test & ob);
> };
> Test Test::operator+(Test & ob)
> {
> Test temp;
> temp.code = this->code + ob.code;
> return temp;}
>
> Test operator+(Test & ob, float val)
> {
> Test temp;
> temp.code = ob.code + val;
> return temp;
> }
> Test operator+(float val, Test & ob)
> {
> Test temp;
> temp.code = ob.code + val;
> return temp;}
>
> int main()
> {
> Test ob1(1.0), ob2(2.0), ob3(3.0), ob4(0.0);
> float c1=100.5 ;
>
> ob4 = ob1+ob2+ob3 ; // This works
> ob4 = ob1+c1; // This works
> ob4 = ob1 + ob2 + c1 ;// Does not work... why ?
> ob4 = ob1 + c1 + ob2 ;// This works...
>
> return 0;
>
> }
>
> My question is : why does the third operation ob4 = ob1 + ob2 + c1
> fail ?
>
> -Dominic
>


change
Test operator+(Test & ob, float val);
to
Test operator+(const Test & ob, float val);

A temp variable (ob1+ob2) cannot be passed to non-const reference.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Seungbeom Kim on
On 2010-07-13 19:48, Pete Becker wrote:
>
> Off hand, it looks like ob1 + ob2 is returning a Test object, and since
> operator+ takes a non-const Test object, it can't be called with a
> temporary. Both free functions should take their Test object by const
> reference or by value, and the member operator+ should be marked const.

I found something interesting when the member operator+ is not const.
A minimal example:

struct A
{
A(int);
friend A operator+(const A&, int);
A operator+(const A&);
};

int main()
{
A(1)+2;
}

Comeau C++ gives an error for this:

error: more than one operator "+" matches these operands:
function "operator+(const A &, int)"
function "A::operator+(const A &)"
operand types are: A + int
A(1)+3;
^

So, apparently, it is trying converting 2 into an A and using the friend
function, and that is ambiguous with using the member function directly.
Making the constructor explicit solves the problem, even without marking
the member operator+ const.

That means the temporary can be bound to *this in the non-const member
operator+. Then why do we have an ambiguity in the first place, when
choosing the member does require a conversion from int to A but choosing
the friend does not? Can anyone explain what is going on here?

--
Seungbeom Kim

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Nick Hounsome on
On 13 July, 23:43, Dominic Chandar <dominic.chan...(a)gmail.com> wrote:
> Hi,
>
> I would like to add multiple objects of a class with integers/
> floats. Need some basic help in fixing an error
>
> Eg:
>
> #include<iostream>
> using namespace std;
> class Test
> {
> public:
> Test(float _code){ code = _code;}
> Test(){}
> float code;
> friend Test operator+(Test & ob, float val);
> friend Test operator+(float val, Test & ob);
> Test operator+(Test & ob);
> };

Short answer: change to take const references.

Longer answer:
The preferred way to do this sort of thing is to provide member Test&
operator +=(XXXXX) and the define all the operator + as free functions
in terms of these.
Secondly rely on constructors wherever possible:

class Test
{
public:
Test(float _code){ code = _code;}
Test(A a) {....}
Test(B b) {....}
....
Test& operator+= (const Test& other) { .... }
};

Test operator+(Test a, cons Test& b) { return a += b; }

This will handle addition of instances of Test,A,B,float in any
combination and only requires a new ctor to add a new type OR,
if you want to freeze Test then new type C can be added by adding 2
free operators without any need to add them as friends provided only
that you can convert them to Test.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]