problems declaring operators in gcc

J

Jim Michaels

friend fraction& operator+=(const fraction& rhs);

fraction.h(64) Error: error: 'fraction& operator+=(const fraction&)'
must take exactly two arguments


I practically pulled this out of a C++ book (except for the "friend").
can someone explain why GCC is giving me problems here?
for a += or similar operator, what does a proper declaration look like
and what are its arguments for?


fraction.h:64: error: 'fraction& operator+=(const fraction&)' must take
exactly two arguments
fraction.h:65: error: 'fraction& operator+=(const char*)' must have an
argument of class or enumerated type
fraction.h:65: error: 'fraction& operator+=(const char*)' must take
exactly two arguments
fraction.h:66: error: 'fraction& operator+=(const long int&)' must have
an argument of class or enumerated type
fraction.h:66: error: 'fraction& operator+=(const long int&)' must take
exactly two arguments
fraction.h:72: error: 'fraction& operator-=(const fraction&)' must take
exactly two arguments
fraction.h:73: error: 'fraction& operator-=(const char*)' must have an
argument of class or enumerated type
fraction.h:73: error: 'fraction& operator-=(const char*)' must take
exactly two arguments
fraction.h:74: error: 'fraction& operator-=(const long int&)' must have
an argument of class or enumerated type
fraction.h:74: error: 'fraction& operator-=(const long int&)' must take
exactly two arguments
fraction.h:80: error: 'fraction& operator*=(const fraction&)' must take
exactly two arguments
fraction.h:81: error: 'fraction& operator*=(const char*)' must have an
argument of class or enumerated type
fraction.h:81: error: 'fraction& operator*=(const char*)' must take
exactly two arguments
fraction.h:82: error: 'fraction& operator*=(const long int&)' must have
an argument of class or enumerated type
fraction.h:82: error: 'fraction& operator*=(const long int&)' must take
exactly two arguments
fraction.h:88: error: 'fraction& operator/=(const fraction&)' must take
exactly two arguments
fraction.h:89: error: 'fraction& operator/=(const char*)' must have an
argument of class or enumerated type
fraction.h:89: error: 'fraction& operator/=(const char*)' must take
exactly two arguments
fraction.h:90: error: 'fraction& operator/=(const long int&)' must have
an argument of class or enumerated type
fraction.h:90: error: 'fraction& operator/=(const long int&)' must take
exactly two arguments
fraction.h:96: error: 'fraction& operator%=(const fraction&)' must take
exactly two arguments
fraction.h:97: error: 'fraction& operator%=(const char*)' must have an
argument of class or enumerated type
fraction.h:97: error: 'fraction& operator%=(const char*)' must take
exactly two arguments
fraction.h:98: error: 'fraction& operator%=(const long int&)' must have
an argument of class or enumerated type
fraction.h:98: error: 'fraction& operator%=(const long int&)' must take
exactly two arguments
 
I

Ian Collins

Jim said:
friend fraction& operator+=(const fraction& rhs);

fraction.h(64) Error: error: 'fraction& operator+=(const fraction&)'
must take exactly two arguments


I practically pulled this out of a C++ book (except for the "friend").
can someone explain why GCC is giving me problems here?
for a += or similar operator, what does a proper declaration look like
and what are its arguments for?
The error says it all, these operators require two arguments, the left
and right hand sides of the expression:

lhs += rhs.
 
J

Jim Michaels

Ian said:
The error says it all, these operators require two arguments, the left
and right hand sides of the expression:

lhs += rhs.
friend fraction& operator~=(const fraction&, const fraction&); //no op
friend fraction& operator~=(const fraction&, const char *); //no op
friend fraction& operator~=(const fraction&, const long int&); // no op

fraction.h(128) Error: error: declaration of 'operator~' as non-function
fraction.h(129) Error: error: expected primary-expression before 'const'
fraction.h(129) Error: error: expected `)' before 'const'

I'm confused by the error messages. is this saying I'm supposed to do this?

friend fraction& operator~=(); //no op
friend fraction& operator~=(); //no op
friend fraction& operator~=(); // no op
then I get
fraction.h(128) Error: error: expected primary-expression before ')' token
fraction.h(128) Error: error: declaration of 'operator~' as non-function


I want to disable those operators. can I do that by just not using them?
 
I

Ian Collins

Jim said:
friend fraction& operator~=(const fraction&, const fraction&); //no op

I want to disable those operators. can I do that by just not using them?

There isn't an operator ~=.
 
J

Jim Michaels

Ian said:
There isn't an operator ~=.

fraction& operator+(const fraction& lhs, const fraction& rhs) {
mpq_add(frac, lhs.frac, rhs.frac);
return *this;
}

this is a friend function of the fraction class. for some reason, the
compiler chokes when I put this in the class definition.
it only works as a friend function. and now it complains
In function 'fraction& operator+(const fraction&, const fraction&)':
fraction.h(173) Error: error: 'frac' was not declared in this scope
fraction.h(174) Error: error: invalid use of 'this' in non-member function


I wish I could get it to work as a regular class member.


for a class member method (not template), what declaration would you use
for the following?
operator+, int as lhs, fraction as rhs, returning fraction
operator+, fraction as rhs, int as rhs, returning fraction
or am I totally misunderstanding the problem?

how would you overload unary + and -?

(I think maybe I can google this one, unless you know of a really good URL)
how would you overload << and >> for iostreams?

and for that, how do you output a char* kind of string to a stream?
 
I

Ian Collins

Jim said:
fraction& operator+(const fraction& lhs, const fraction& rhs) {
mpq_add(frac, lhs.frac, rhs.frac);
return *this;
}

this is a friend function of the fraction class. for some reason, the
compiler chokes when I put this in the class definition.

Because binary operator can't be class members, it would not make sense.
it only works as a friend function. and now it complains
In function 'fraction& operator+(const fraction&, const fraction&)':
fraction.h(173) Error: error: 'frac' was not declared in this scope
fraction.h(174) Error: error: invalid use of 'this' in non-member function
Exactly, only class members have a this pointer. You have to define a
temporary object, do the maths and return the temp.
I wish I could get it to work as a regular class member.
Why, how would you use it?
for a class member method (not template), what declaration would you use
for the following?
operator+, int as lhs, fraction as rhs, returning fraction
operator+, fraction as rhs, int as rhs, returning fraction
or am I totally misunderstanding the problem?
It looks like you are. A binary operator requires two parameters, the
lhs and rhs. Consider

c = a+b;

Which object does the operator modify? There isn't one, the operator
creates a new object which is the sum of a and b.

Now consider

a += b;

Here it is clear that a is the object being modified, so it does make
sense for the unary operator += to be a class member which requires one
parameter, the rhs.
how would you overload unary + and -?

How would you define them? There isn't a unary operator + or -.
 
M

Mumia W.

fraction& operator+(const fraction& lhs, const fraction& rhs) {
mpq_add(frac, lhs.frac, rhs.frac);
return *this;
}

this is a friend function of the fraction class. for some reason, the
compiler chokes when I put this in the class definition.
it only works as a friend function. and now it complains
In function 'fraction& operator+(const fraction&, const fraction&)':
fraction.h(173) Error: error: 'frac' was not declared in this scope
fraction.h(174) Error: error: invalid use of 'this' in non-member function


I wish I could get it to work as a regular class member.


for a class member method (not template), what declaration would you use
for the following?
operator+, int as lhs, fraction as rhs, returning fraction
operator+, fraction as rhs, int as rhs, returning fraction
or am I totally misunderstanding the problem?

I doubt you can do that. Operator+ must only have one argument.

how would you overload unary + and -?
[...]

That's probably impossible too. I don't think that unary operator+ and
operator- exist.

As member functions, binary operator+ and operator- should work.

I'm not a C++ expert, but this should help you:


#include <cstdio>
#include <cstdlib>

class fraction {
int num;
int denom;

public:
fraction (int n = 0, int d = 1) : num(n), denom(d) { }

fraction & operator+(const fraction & other) {
fraction scopy = *this;
num = (scopy.num*other.denom + scopy.denom*other.num);
denom = scopy.denom * other.denom;
return *this;
}

char * c_str() {
char * temp = new char [20];
sprintf(temp,"%d/%d", num, denom);
return temp;
}

};



int main (void) {
int sp = 0;
char * strs[10];
char * string;

fraction fraa = fraction(12,3);
string = strs[sp++] = fraa.c_str();
puts(string);

fraction frab = fraa + fraction(1,3);
string = strs[sp++] = frab.c_str();
puts(string);

frab+1;
string = strs[sp++] = frab.c_str();
puts(string);

for (int n = 0; n < sp; n++) {
delete[] strs[n];
}
return 0;
}
 
M

Mumia W.

[...]
fraction & operator+(const fraction & other) {
fraction scopy = *this;
num = (scopy.num*other.denom + scopy.denom*other.num);
denom = scopy.denom * other.denom;
return *this;
}
[...]

I apologize for the slightly non-intuitive behavior of my operator+
function. This is probably more to the norm:

fraction operator+(const fraction & other) {
fraction sf;
sf.num = (num*other.denom + denom*other.num);
sf.denom = denom * other.denom;
return sf;
}
 
J

James Kanze

Jim Michaels wrote:
Because binary operator can't be class members, it would not make sense.

Since when? I regularly define binary operators are members.

It is usual for classes to define binary operators as free
functions in the case where the class supports implicit
conversions, so that the right hand operator supports the same
set of conversions as the left hand side, e.g. (supposing a
conversion of int to Decimal):

Decimal a,b,c ;
a = b + c ; // OK, global or member...
a = b + 1 ; // OK, global or member...
a = 1 + b ; // OK if global, not if member...

(Note that it is also usual in such cases to define += as a
member, and to define + in terms of +=, so that it doesn't even
need to be a friend.)

If the class in question doesn't have any converting
constructors (e.g. most iterators), then there's no real
argument against making the binary operators members (and my
iterators usually have operator==() and operator!=() as a
member).

And of course, some binary operators *must* be members---don't
forget that the assignment operator is a binary operator.
It looks like you are. A binary operator requires two parameters, the
lhs and rhs. Consider
Which object does the operator modify? There isn't one, the operator
creates a new object which is the sum of a and b.
Now consider
Here it is clear that a is the object being modified, so it does make
sense for the unary operator += to be a class member which requires one
parameter, the rhs.

There is no unary operator+=.

A binary operator may or may not be a member. If it is a
member, this points to the left argument, and it takes one
declared parameter for the right argument. If it is not a
member, it takes two parameters, the first for the left
argument, and the second for the right.

Special rules require that the binary operators = and [] be
members. (The n-ary operator () must also be a member.)
How would you define them? There isn't a unary operator + or -.

Of course, there is. Generally, unary operators can be either
members, with this pointing to the argument, and no declared
parameters, or free functions, with a single declared parameter
for the argument. Again, some special rules: operator->,
operator& and operator* must be members, and post-fix operator++
and operator-- are declared as binary operators, with an int as
the second parameter. (The compiler will pass a 0 when they are
invoked using the operator syntax; normally, this value will be
ignored.)

(All of the above is from memory, so I may have missed some of
the special cases.)
 
J

James Kanze

On Apr 21, 10:39 am, "Mumia W."

[...]
I doubt you can do that. Operator+ must only have one argument.

Binary operator+ must have exactly two arguments. If it's a
member, the first is the implicit this argument, and only the
second is declared. If it's a free function, both must be
explicitly declared. Thus:

class MyClass
{
public:
// Either:
MyClass operator+( MyClass const& rhs ) const ;
} ;
// or:
MyClass operator+( MyClass const& lhs, MyClass const& rhs ) ;

For user defined arithmetic types (which typically support
conversion from int or double):

MyClass
operator+(
MyClass const& lhs,
MyClass const& rhs )
{
MyClass result( lhs ) ;
result += rhs ;
return result ;
}

is a classical implementation: operator+ is a free function, and
not even a friend. (Actually, they are often declared as
friends to allow the use of the Barton and Nackman trick. See
the documentation for the file Operators.hh in
http://kanze.james.neuf.fr/doc/en/Basic/html/index.html, for
example. But learn to overload operators correctly first:);
this is a more or less advanced technique.)

Operators which modify the left operand, such as +=, are more
typically members.
how would you overload unary + and -?
[...]
That's probably impossible too. I don't think that unary operator+ and
operator- exist.

Are you kidding? (I've never actually used unary +, but unary
minus is frequent:
int minusOne = -1 ;
..)
As member functions, binary operator+ and operator- should work.

Or as free functions. Single declared argument as a free
function, implicit this and no declared argument as a member.
I'm not a C++ expert, but this should help you:

#include <cstdio>
#include <cstdlib>
class fraction {
int num;
int denom;
public:
fraction (int n = 0, int d = 1) : num(n), denom(d) { }
fraction & operator+(const fraction & other) {
fraction scopy = *this;
num = (scopy.num*other.denom + scopy.denom*other.num);
denom = scopy.denom * other.denom;
return *this;
}

So:

1) operator+ actually has the semantics of +=, and not those of
+, and
2) "fraction( 1, 2 ) + 3" is legal, but "3 + fraction( 1, 2 )"
isn't (which is normal given 1).

Better:

fraction& operator+=( fraction const& other )
{
num = other.denom * num + denom * other.num ;
denom *= other.denom ;
return *this ;
}

(Except that you need some logic for renormalizing, and handling
the inevitable overflows.)

With a free function:

fraction
operator+( fraction const& lhs, fraction const& rhs )
{
fraction result( lhs ) ;
result += rhs ;
return result ;
}

(As it stands, I'd probably make this a friend, and construct
the return value immediately. But the above will leverage
automatically off the error checking and normalization in
operator+=, once it gets added.)
char * c_str() {
char * temp = new char [20];
sprintf(temp,"%d/%d", num, denom);
return temp;
}

Never, never. You return a pointer, and count on the caller to
free it?

For such things, a friend
std::eek:stream& operator<<( ostream& dest, fraction const& src) ;
is the normal solution.
 
J

Jim Michaels

Ian said:
There isn't an operator ~=.

I think I have everything worked out now. thanks.

--

------------------------------------
Jim Michaels
for email, edit the address

RAM Disk is *not* an installation method.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top