operator= function

R

Rahul

Hi Everyone,

I was just overloading operator = for a class and i have a problem in
one case...

class A
{
A& operator=(const A& obj)
{
return *this;
// please ignore the logic of this function
}
};

int main()
{
A a,b
a = b; //works fine
if(a=b) // causes compile time error as the operator=() returns a
reference to A and not a BOOL.
{
printf("both the objects are the same\n");
}
else
{
printf("both the objects are different\n");
}
}
return(0);
}

Now, i tried to overload operator=() function, but overloading just
based on the return type doesn't make sense.
So is there anyway to solve this problem, so that the user of the
class can get to work in both the cases just like any built in type?

Thanks in advance!!!
 
V

Victor Bazarov

Rahul said:
Hi Everyone,

I was just overloading operator = for a class and i have a problem in
one case...

class A
{
A& operator=(const A& obj)
{
return *this;
// please ignore the logic of this function
}
};

int main()
{
A a,b
a = b; //works fine
if(a=b) // causes compile time error as the operator=() returns a
reference to A and not a BOOL.
{
printf("both the objects are the same\n");
}
else
{
printf("both the objects are different\n");
}
}
return(0);
}

Now, i tried to overload operator=() function, but overloading just
based on the return type doesn't make sense.
So is there anyway to solve this problem, so that the user of the
class can get to work in both the cases just like any built in type?

A simple way would be to *also* provide a conversion function to type
'bool' in your 'A' class:

class A {
...
operator bool() const { return true; }
};

Or any other conversion function that yields a type that can be used
in a logical expression.

Now, let me ask you, why do you think you need assignment in the 'if'
expression

if (a = b)

instead of comparison

if (a == b)

? Or did you not know that those are two different operators?

V
 
R

Rahul

A simple way would be to *also* provide a conversion function to type
'bool' in your 'A' class:

class A {
...
operator bool() const { return true; }
};

Or any other conversion function that yields a type that can be used
in a logical expression.

Now, let me ask you, why do you think you need assignment in the 'if'
expression

if (a = b)

instead of comparison

if (a == b)

? Or did you not know that those are two different operators?

Yes i do. My point is to extend the support provided by c++ for
built-in types to custom types.
int a,b;
a=b; //works fine
if(a=b) // too works fine depending on the value of a.
 
T

Tadeusz B. Kopec

Hi Everyone,

I was just overloading operator = for a class and i have a problem in
one case...

class A
{
A& operator=(const A& obj)
{
return *this;
// please ignore the logic of this function
}
};

int main()
{
A a,b
a = b; //works fine
if(a=b) // causes compile time error as the operator=() returns a
reference to A and not a BOOL.
{
printf("both the objects are the same\n");
}
else
{
printf("both the objects are different\n");
}
}
return(0);
}

Now, i tried to overload operator=() function, but overloading just
based on the return type doesn't make sense. So is there anyway to solve
this problem, so that the user of the class can get to work in both the
cases just like any built in type?

First of all - for integer types statement
if (a=b)
tests if b is zero, not if a and b are the same (after executing this
they are for sure the same).
Second - possibility of assignment in 'if' expression is rather a
misfeature and I don't see any point in extending this possibility.
 
G

GArlington

Yes i do. My point is to extend the support provided by c++ for
built-in types to custom types.
int a,b;
a=b; //works fine
if(a=b) // too works fine depending on the value of a.

if() expects boolean value (or int at least), a=b (assignment) returns
new value of a (equals to b) - the chances of this being boolean or
int are not too good considering the number of different data types
AND objects.

So, what was your question?

If you are overloading the = (assignment) operator, what do you expect
it to return? And how do you expect this return value to be converted
to boolean? And why in hell do you want to overload = operator, unless
you want to clone the object?
So, maybe you ARE trying to overload == (compare) operator after all?
 
D

David Harmon

On Tue, 4 Dec 2007 08:06:48 -0800 (PST) in comp.lang.c++, Rahul
Yes i do. My point is to extend the support provided by c++ for
built-in types to custom types.
int a,b;
a=b; //works fine
if(a=b) // too works fine depending on the value of a.

You should never write an assignment in an if statement. Write it
as
a=b;
if (a) ...

Now, what do you think if(a) should mean, when a is some complex
class you have defined?
 
K

Kira Yamato

Yes i do. My point is to extend the support provided by c++ for
built-in types to custom types.
int a,b;
a=b; //works fine
if(a=b) // too works fine depending on the value of a.

May not be a good idea. The syntax

if (a)
{
// do something
}

is not clear what you're testing for here. Code readability should be
highly sought for. Even with native data-types like integers, it's
better to write

if (n != 0) ...

than just

if (n) ...

unless you worry about performance, at which I would think a smart
compiler would generate equivalent codes for both cases anyway.

Also, don't overload the operator bool() just to support the if-test.
You might get yourself into trouble in other situations with this
implicit conversion.

My suggestion is to be explicit and have an method like
bool isValid() const;
so that your if statement reads more explicitly

if ((a=b).isValid()) ...
 
V

Victor Bazarov

Kira said:
[..] The syntax

if (a)
{
// do something
}

is not clear what you're testing for here.

Of course not! Who in their right mind would name a variable 'a'?
But imagine that the variable is 'statusIsValid' (and its type is not
necessarily 'bool'). What prevents me from writing

if (statusIsValid)
{
// do something
}

?
Code readability should be
highly sought for.

Sure. Don't name your variables 'a' or 'b'.
Even with native data-types like integers, it's
better to write

if (n != 0) ...

than just

if (n) ...

Now, with integers it may make sense. But with a class object
I would have to define non-equality comparison to 'int' in order
for 'if (n != 0)' to compile. OTOH, if I just define operator
bool() (known as type conversion function), both 'int' _and_ my
type would work in 'if (n)' beautifully.
unless you worry about performance, at which I would think a smart
compiler would generate equivalent codes for both cases anyway.

Also, don't overload the operator bool() just to support the if-test.
You might get yourself into trouble in other situations with this
implicit conversion.

Yes, that's why some folks define 'operator void*()' instead.
My suggestion is to be explicit and have an method like
bool isValid() const;
so that your if statement reads more explicitly

if ((a=b).isValid()) ...

Ouch. I still think that even

if (a=b, a.isValid())

is better. But nothing beats

a = b;
if (a.isValid())

V
 
K

Kira Yamato

Kira said:
[..] The syntax

if (a)
{
// do something
}

is not clear what you're testing for here.

Of course not! Who in their right mind would name a variable 'a'?
But imagine that the variable is 'statusIsValid' (and its type is not
necessarily 'bool'). What prevents me from writing

if (statusIsValid)
{
// do something
}

?

I was speaking from the OP's context. He's not likely to be using a
boolean flag. Instead, he's using some object of some class which he
also wants to test as a boolean also. He is trying to copy the
situation with the native type like the 'int'.

His code, which you ripped completely out so that the context is gone, was

class A
{
A& operator=(const A& obj)
{
return *this;
// please ignore the logic of this function
}
};

int main()
{
A a,b
a = b; //works fine
if(a=b) // causes compile time error as the operator=() returns a
reference to A and not a BOOL.
{
printf("both the objects are the same\n");
}
else
{
printf("both the objects are different\n");
}
}
return(0);
}

This is a bad idea on at least a couple of level.

First, the statement
if (a=b)
looks suspiciously a typo to
if (a==b).
Second,
if (someobject)
is never explicit in what you are trying to test for about the object.
In the case of 'int', it is tolerated because it is stipulated in the
standard what that means. But for a user-defined class, the meaning is
not obvious from that if statement alone.

This is what I was talking about.
Sure. Don't name your variables 'a' or 'b'.

Hmm... This is somewhat controversial, but I actually prefer single
letter variable names for local variables. Perhaps this is because of
my math background.

I would think that in a clean program, most functions should not be
more than 100 lines of code anyway. So, it's ok for local variables to
be single letter and not get lost in just 100 lines of code.

But I'm not holding my breath on this one.
Now, with integers it may make sense. But with a class object
I would have to define non-equality comparison to 'int' in order
for 'if (n != 0)' to compile. OTOH, if I just define operator
bool() (known as type conversion function), both 'int' _and_ my
type would work in 'if (n)' beautifully.

Like I said before, just because you could, should you? For integer
variables, the standard says very clearly what
if (n)
means, but for objects, what can you really tell from the code below
if (my_car_engine)
what it means? Now, consider the alternative
if (my_car_engine.isReady()).

This was my point in my last post.
Yes, that's why some folks define 'operator void*()' instead.

I don't get your point here.
Ouch. I still think that even

if (a=b, a.isValid())

is better.
Agree.

But nothing beats

a = b;
if (a.isValid())

Definitely agree.
 
V

Victor Bazarov

Kira said:
Kira said:
[..] The syntax

if (a)
{
// do something
}

is not clear what you're testing for here.

Of course not! Who in their right mind would name a variable 'a'?
But imagine that the variable is 'statusIsValid' (and its type is not
necessarily 'bool'). What prevents me from writing

if (statusIsValid)
{
// do something
}

?

I was speaking from the OP's context. He's not likely to be using a
boolean flag. Instead, he's using some object of some class which he
also wants to test as a boolean also. He is trying to copy the
situation with the native type like the 'int'.

His code, which you ripped completely out so that the context is
gone, was
class A
{
A& operator=(const A& obj)
{
return *this;
// please ignore the logic of this function
}
};

int main()
{
A a,b
a = b; //works fine
if(a=b) // causes compile time error as the operator=() returns a
reference to A and not a BOOL.
{
printf("both the objects are the same\n");
}
else
{
printf("both the objects are different\n");
}
}
return(0);
}

This is a bad idea on at least a couple of level.

First, the statement
if (a=b)
looks suspiciously a typo to
if (a==b).
Second,
if (someobject)
is never explicit in what you are trying to test for about the object.
In the case of 'int', it is tolerated because it is stipulated in the
standard what that means. But for a user-defined class, the meaning
is not obvious from that if statement alone.

This is what I was talking about.

Now, you ripped my code completely out and jerked us back to the OP's
example which doesn't really present _any_ context simply because there
is no design intent recognisable in it. It's OK, I'll try to gently
nudge us back to the discussion on merits of the original syntax.

Imagine (and that will require you to think outside the box, I *am*
holding my breath for this one) that the OP wants to check the success
of the assignment operation. The OP could then define

class A {
bool operator=(const A& other);
};

so that the assignment could be either checked

if (a = b) ...

or

bool success = a = b;
if (success)

Yes, I agree that it's not the idiomatic use of the assignment operator.
But it's possible the OP wanted exactly that! I am simply showing how
those things _can_ be done.
Hmm... This is somewhat controversial, but I actually prefer single
letter variable names for local variables. Perhaps this is because of
my math background.
Perhaps.

I would think that in a clean program, most functions should not be
more than 100 lines of code anyway. So, it's ok for local variables
to be single letter and not get lost in just 100 lines of code.

Those two things are orthogonal. The meaning of the object in the
program should *not* have to be deducible from the code in which it
is involved (10 lines or 10000 lines), but from its name!
But I'm not holding my breath on this one.

Good idea.
Like I said before, just because you could, should you? For integer
variables, the standard says very clearly what
if (n)
means, but for objects, what can you really tell from the code below
if (my_car_engine)
what it means?

Right, for 'my_car_engine' it probably doesn't mean anything specific.
Now, consider the alternative
if (my_car_engine.isReady()).

This was my point in my last post.

I get your point. However, if it does make sence for 'bool', why
shouldn't you be _able_ to have a wrapper, an object with more than
one state, of which some would be "true" and some "false", when used
in an 'if' statement? Again, you need to be able to think outside
of the car... ahem!.. box.
I don't get your point here.

The point is that if you don't want an implicit conversion to 'int'
or any other arithmetic type (that 'bool' provides), use something
that has an explicit conversion to 'bool' instead. Use 'void*'.
Non-null value (like the object's address) would mean 'true', and
a null pointer value would mean 'false'.

V
 
J

James Kanze

Yes i do. My point is to extend the support provided by c++ for
built-in types to custom types.
int a,b;
a=b; //works fine
if(a=b) // too works fine depending on the value of a.

For what definition of "works"? For historical reasons, it's
formally legal (although there have been proposals to deprecate
it). It's only intentional use in real code is obfuscation,
however, and good compilers will generally warn if you do it.
the correct way of writing this is in two statements:

a = b ;
if ( a != 0 ) { /* ... */ }

Add the necessary == and != operators to your class, and this
will work.
 
J

James Kanze

On 2007-12-04 11:06:48 -0500, Rahul <[email protected]> said:

[...]
is not clear what you're testing for here. Code readability
should be highly sought for. Even with native data-types like
integers, it's better to write
if (n != 0) ...
than just
if (n) ...

Support for the "if (n)" notation is really just a historical
abherition. Originally, C didn't have a boolean type; you had
to simulate it with int. And of course, "if ( n )" *is* the
correct way to write a test of a boolean variable.

When bool was added to C++, the original proposal was also to
deprecate the implicit conversions of int to bool. In the end,
this was dropped, because it was felt that it would break way
too much code.
unless you worry about performance, at which I would think a
smart compiler would generate equivalent codes for both cases
anyway.

Even a dumb compiler. Even before bool, the compiler needs some
sort of boolean value to make a binary test. Internally, you
generally cannot simply make a conditional jump on an integral
value. (This wasn't necessarily true for older processors.)
The result is that if an expression is used in a boolean
context, and the top node is not a comparison (which sets the
processor's condition codes), the compiler inserts a node with
the comparison. Whether you write "if ( n )" or "if ( n != 0
)", the expression trees used to generate the code are normally
identical.
Also, don't overload the operator bool() just to support the
if-test. You might get yourself into trouble in other
situations with this implicit conversion.
My suggestion is to be explicit and have an method like
bool isValid() const;
so that your if statement reads more explicitly
if ((a=b).isValid()) ...

Don't do that either. With very few exceptions, a single
statement should to one, and only one thing, if you want your
code to be readable. An if statement is flow control, and so
shouldn't modify state.
 
R

Rolf Magnus

Victor said:
Yes, that's why some folks define 'operator void*()' instead.

So that things like:

int i = std::cout + 3;

don't work, since it would be so dangerous if it did...
Ouch. I still think that even

if (a=b, a.isValid())

is better. But nothing beats

a = b;
if (a.isValid())

As long as you want a to exist outside the if scope.

if (MyType a = somefunc())
{
}

I sometimes use that when I need to use dynamic_cast to handle things
differently based on the dynamic type (Using some external libraries that
give me no other choice):

BaseClass* base = somefunc();
// ...
if (Derived1* d1 = dynamic_cast<Derived1*>(base))
{
// do something
}
else if (Derived2* d2 = dynamic_cast<Derived2*>(base))
{
// do something else
}

vs:

BaseClass* base = somefunc();
// ...
Derived1* d1 = dynamic_cast<Derived1*>(base);
if (d1 != 0)
{
// do something
}
else
{
Derived1* d2 = dynamic_cast<Derived2*>(base);
if (d2 != 0)
{
// do something else
}
}

If you have a loop, you might even need to duplicate things:

while (MyType a = somefunc())
{
// do something with a
}

vs:

MyType a = somefunc();
while (a)
{
a = somefunc();
// do something with a
}

I consider the first variant more readable.
 
T

terminator

Kira said:
Kira Yamato wrote:
[..] The syntax
if (a)
{
// do something
}
is not clear what you're testing for here.
Of course not! Who in their right mind would name a variable 'a'?
But imagine that the variable is 'statusIsValid' (and its type is not
necessarily 'bool'). What prevents me from writing
if (statusIsValid)
{
// do something
}
?
I was speaking from the OP's context. He's not likely to be using a
boolean flag. Instead, he's using some object of some class which he
also wants to test as a boolean also. He is trying to copy the
situation with the native type like the 'int'.
His code, which you ripped completely out so that the context is
gone, was
class A
{
A& operator=(const A& obj)
{
return *this;
// please ignore the logic of this function
}
};
int main()
{
A a,b
a = b; //works fine
if(a=b) // causes compile time error as the operator=() returns a
reference to A and not a BOOL.
{
printf("both the objects are the same\n");
}
else
{
printf("both the objects are different\n");
}
}
return(0);
}
This is a bad idea on at least a couple of level.
First, the statement
if (a=b)
looks suspiciously a typo to
if (a==b).
Second,
if (someobject)
is never explicit in what you are trying to test for about the object.
In the case of 'int', it is tolerated because it is stipulated in the
standard what that means. But for a user-defined class, the meaning
is not obvious from that if statement alone.
This is what I was talking about.

Now, you ripped my code completely out and jerked us back to the OP's
example which doesn't really present _any_ context simply because there
is no design intent recognisable in it. It's OK, I'll try to gently
nudge us back to the discussion on merits of the original syntax.

Imagine (and that will require you to think outside the box, I *am*
holding my breath for this one) that the OP wants to check the success
of the assignment operation. The OP could then define

class A {
bool operator=(const A& other);
};

so that the assignment could be either checked

you will lose the ability to chain:

{
int a, b, c;
a=b=c;//ok
}{
A a, b, c;
a=b=c;//error
}

I prefere a conversion operator to an intrinsic type ,or at least a
checker function like 'auto_ptr::get' or 'some_STL_container::empty'.

regards,
FM.
 
T

terminator

So that things like:

int i = std::cout + 3;

don't work, since it would be so dangerous if it did...






As long as you want a to exist outside the if scope.

if (MyType a = somefunc())
{

}

I sometimes use that when I need to use dynamic_cast to handle things
differently based on the dynamic type (Using some external libraries that
give me no other choice):

BaseClass* base = somefunc();
// ...
if (Derived1* d1 = dynamic_cast<Derived1*>(base))
{
// do something}

else if (Derived2* d2 = dynamic_cast<Derived2*>(base))
{
// do something else

}

vs:

BaseClass* base = somefunc();
// ...
Derived1* d1 = dynamic_cast<Derived1*>(base);
if (d1 != 0)
{
// do something}

else
{
Derived1* d2 = dynamic_cast<Derived2*>(base);
if (d2 != 0)
{
// do something else
}

}

If you have a loop, you might even need to duplicate things:

while (MyType a = somefunc())
{
// do something with a

}

vs:

MyType a = somefunc();
while (a)
{
a = somefunc();
// do something with a

}

I consider the first variant more readable.

enclosing the loop/conditional statement in an extra pair of braces
gives similar functionality(I do not discuss readabilty for now):

{//extra braces
class X* xptr=whatever;
while (xptr){
....
};
};

regards,
FM.
 
V

Victor Bazarov

terminator said:
[..]
Imagine (and that will require you to think outside the box, I *am*
holding my breath for this one) that the OP wants to check the
success of the assignment operation. The OP could then define

class A {
bool operator=(const A& other);
};

so that the assignment could be either checked

you will lose the ability to chain:

{
int a, b, c;
a=b=c;//ok
}{
A a, b, c;
a=b=c;//error
}


Chaining is not necessarily a good idea. Neither is the assignment
operator that can fail, of course. In that case it would probably
be best to have a member function that would return 'bool'.
I prefere a conversion operator to an intrinsic type ,or at least a
checker function like 'auto_ptr::get' or 'some_STL_container::empty'.

Well, as we discussed elsethread, conversion to an integral type may
not be the right choice, but conversion to 'void*' could work (like
it does for streams).

V
 
J

James Kanze

Victor Bazarov wrote:

[...]
As long as you want a to exist outside the if scope.

I'd say that if it matters, your function is too big.
if (MyType a = somefunc())
{
}
I sometimes use that when I need to use dynamic_cast to handle
things differently based on the dynamic type (Using some
external libraries that give me no other choice):
BaseClass* base = somefunc();
// ...
if (Derived1* d1 = dynamic_cast<Derived1*>(base))
{
// do something}

else if (Derived2* d2 = dynamic_cast<Derived2*>(base))
{
// do something else

You mean, something like:

d1->xxx ;

You might as well move the declaration out of the if, so that
it's readable.

(If I had to chain the tests, of course, I'd probably put each
case in a separate function, with its test.)
}

BaseClass* base = somefunc();
// ...
Derived1* d1 = dynamic_cast<Derived1*>(base);
if (d1 != 0)
{
// do something}

else
{
Derived1* d2 = dynamic_cast<Derived2*>(base);
if (d2 != 0)
{
// do something else

}
If you have a loop, you might even need to duplicate things:
while (MyType a = somefunc())
{
// do something with a
}

MyType a = somefunc();
while (a)
{
a = somefunc();
// do something with a
}
I consider the first variant more readable.

No way. It hides an important change of state (and declaration)
in the middle of a condition.
 
T

terminator

terminator said:
[..]
Imagine (and that will require you to think outside the box, I *am*
holding my breath for this one) that the OP wants to check the
success of the assignment operation. The OP could then define
class A {
bool operator=(const A& other);
};
so that the assignment could be either checked
you will lose the ability to chain:
{
int a, b, c;
a=b=c;//ok
}{
A a, b, c;
a=b=c;//error
}

Chaining is not necessarily a good idea. Neither is the assignment
operator that can fail, of course. In that case it would probably
be best to have a member function that would return 'bool'.

as long as OP needs a type that follows the syntax for intrisic
types ,chaining must not be dropped.But generally you are right of
course.
Well, as we discussed elsethread, conversion to an integral type may
not be the right choice, but conversion to 'void*' could work (like
it does for streams).

why do you insist on 'void*'?

regards,
FM.
 
V

Victor Bazarov

terminator said:
terminator said:
On Dec 4, 11:53 pm, "Victor Bazarov" <[email protected]>
wrote:
[..]
Imagine (and that will require you to think outside the box, I *am*
holding my breath for this one) that the OP wants to check the
success of the assignment operation. The OP could then define
class A {
bool operator=(const A& other);
};
so that the assignment could be either checked
you will lose the ability to chain:
{
int a, b, c;
a=b=c;//ok
}{
A a, b, c;
a=b=c;//error
}

Chaining is not necessarily a good idea. Neither is the assignment
operator that can fail, of course. In that case it would probably
be best to have a member function that would return 'bool'.

as long as OP needs a type that follows the syntax for intrisic
types ,chaining must not be dropped.But generally you are right of
course.
Well, as we discussed elsethread, conversion to an integral type may
not be the right choice, but conversion to 'void*' could work (like
it does for streams).

why do you insist on 'void*'?

I don't. It's just another option, which is considered better.
You seem to not like it. Why?

V
 

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
474,183
Messages
2,570,965
Members
47,513
Latest member
JeremyLabo

Latest Threads

Top