By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
459,366 Members | 1,366 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 459,366 IT Pros & Developers. It's quick & easy.

operator= function

P: n/a
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!!!
Dec 4 '07 #1
Share this Question
Share on Google+
24 Replies


P: n/a
Rahul wrote:
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
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Dec 4 '07 #2

P: n/a
On Dec 4, 8:46 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
Rahul wrote:
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?
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.
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Dec 4 '07 #3

P: n/a
On Tue, 04 Dec 2007 07:41:52 -0800, Rahul wrote:
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.

--
Tadeusz B. Kopec (tk****@NOSPAMPLEASElife.pl)
How many "coming men" has one known! Where on earth do they all go to?
-- Sir Arthur Wing Pinero
Dec 4 '07 #4

P: n/a
On Dec 4, 4:06 pm, Rahul <sam_...@yahoo.co.inwrote:
On Dec 4, 8:46 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
Rahul wrote:
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?

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.
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
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?
Dec 4 '07 #5

P: n/a
On Tue, 4 Dec 2007 08:06:48 -0800 (PST) in comp.lang.c++, Rahul
<sa*****@yahoo.co.inwrote,
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?
>
Dec 4 '07 #6

P: n/a
On 2007-12-04 11:06:48 -0500, Rahul <sa*****@yahoo.co.insaid:
On Dec 4, 8:46 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
>Rahul wrote:
>>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?

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()) ...

--

-kira

Dec 4 '07 #7

P: n/a
On Dec 4, 5:06 pm, Rahul <sam_...@yahoo.co.inwrote:
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.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Dec 5 '07 #8

P: n/a
On Dec 4, 8:44 pm, Kira Yamato <kira...@earthlink.netwrote:
On 2007-12-04 11:06:48 -0500, Rahul <sam_...@yahoo.co.insaid:
[...]
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.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Dec 5 '07 #9

P: n/a
Victor Bazarov wrote:
>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.
So that things like:

int i = std::cout + 3;

don't work, since it would be so dangerous if it did...
>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())
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.

Dec 5 '07 #10

P: n/a
On Dec 4, 11:53 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
Kira Yamato wrote:
On 2007-12-04 14:56:17 -0500, "Victor Bazarov"
<v.Abaza...@comAcast.netsaid:
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.
Dec 5 '07 #11

P: n/a
On Dec 5, 7:06 pm, Rolf Magnus <ramag...@t-online.dewrote:
Victor Bazarov wrote:
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.

So that things like:

int i = std::cout + 3;

don't work, since it would be so dangerous if it did...
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())

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.
Dec 5 '07 #12

P: n/a
terminator wrote:
On Dec 4, 11:53 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
>[..]
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
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Dec 5 '07 #13

P: n/a
On Dec 5, 5:06 pm, Rolf Magnus <ramag...@t-online.dewrote:
Victor Bazarov wrote:
[...]
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())
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.)
}
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.
No way. It hides an important change of state (and declaration)
in the middle of a condition.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Dec 6 '07 #14

P: n/a
On Dec 5, 10:31 pm, terminator <farid.mehr...@gmail.comwrote:
On Dec 5, 7:06 pm, Rolf Magnus <ramag...@t-online.dewrote:
[...]
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){
....
};
};
And writing clean code, without outlandishly long functions,
eliminates the need for the functionality completely.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Dec 6 '07 #15

P: n/a
On Dec 6, 12:52 am, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
terminator wrote:
On Dec 4, 11:53 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
[..]
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.
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).
why do you insist on 'void*'?

regards,
FM.
Dec 6 '07 #16

P: n/a
terminator wrote:
On Dec 6, 12:52 am, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
>terminator wrote:
>>On Dec 4, 11:53 pm, "Victor Bazarov" <v.Abaza...@comAcast.net>
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.
>>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).

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
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Dec 6 '07 #17

P: n/a
On Dec 6, 6:10 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
terminator wrote:
[...]
why do you insist on 'void*'?
I don't. It's just another option, which is considered better.
Better than what? iostream continues to use it, for historical
reasons, but I think that the generally approved solution today
is either HiddenClass* (where HiddenClass is a private member),
or some sort of pointer to member of HiddenClass; both make it
extremely difficult (and the pointer to member makes it
impossible) for the user to recover an apparently usable pointer
to anything, and thus reduce the chance of mis-use even more.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Dec 7 '07 #18

P: n/a
On 2007-12-07 07:15:59 -0500, James Kanze <ja*********@gmail.comsaid:
On Dec 6, 6:10 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
>terminator wrote:

[...]
>>why do you insist on 'void*'?
>I don't. It's just another option, which is considered better.

Better than what? iostream continues to use it, for historical
reasons, but I think that the generally approved solution today
is either HiddenClass* (where HiddenClass is a private member),
or some sort of pointer to member of HiddenClass; both make it
extremely difficult (and the pointer to member makes it
impossible) for the user to recover an apparently usable pointer
to anything, and thus reduce the chance of mis-use even more.
Specifically, the primary justification for returning a
pointer-to-member rather than a pointer to a class type (or to void*,
for that matter) is that you can't delete it. I haven't seen or heard
of any studies indicating that either of these is a significant
problem, however.

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

Dec 7 '07 #19

P: n/a
James Kanze wrote:
On Dec 6, 6:10 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
>terminator wrote:

[...]
>>why do you insist on 'void*'?
>I don't. It's just another option, which is considered better.

Better than what?
Better than 'bool'. Better than 'int'.
iostream continues to use it, for historical
reasons, but I think that the generally approved solution today
is either HiddenClass* (where HiddenClass is a private member),
or some sort of pointer to member of HiddenClass; both make it
extremely difficult (and the pointer to member makes it
impossible) for the user to recover an apparently usable pointer
to anything, and thus reduce the chance of mis-use even more.
Yes, that's better still.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Dec 7 '07 #20

P: n/a
On Dec 7, 3:06 pm, Pete Becker <p...@versatilecoding.comwrote:
On 2007-12-07 07:15:59 -0500, James Kanze <james.ka...@gmail.comsaid:
On Dec 6, 6:10 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
terminator wrote:
[...]
>why do you insist on 'void*'?
I don't. It's just another option, which is considered better.
Better than what? iostream continues to use it, for historical
reasons, but I think that the generally approved solution today
is either HiddenClass* (where HiddenClass is a private member),
or some sort of pointer to member of HiddenClass; both make it
extremely difficult (and the pointer to member makes it
impossible) for the user to recover an apparently usable pointer
to anything, and thus reduce the chance of mis-use even more.

Specifically, the primary justification for returning a
pointer-to-member rather than a pointer to a class type (or to void*,
for that matter) is that you can't delete it. I haven't seen or heard
of any studies indicating that either of these is a significant
problem, however.
I've seen it happen at least once. The conversion was always to
false,
so delete 0 didn't complain (crashing the application would have saved
a lot of debugging).
It took us a while to track the bug.

The (not) fun thing is that our operator safe-bool was actually
using the proper pointer to member function idiom but we were
using a broken gcc version (3.3.5 IIRC) that had a regression
that allowed that illegal code to compile (it was fixed in gcc 3.3.6).

HTH,

--
gpd

Dec 7 '07 #21

P: n/a
On Dec 7, 5:39 pm, gpderetta <gpdere...@gmail.comwrote:
On Dec 7, 3:06 pm, Pete Becker <p...@versatilecoding.comwrote:


On 2007-12-07 07:15:59 -0500, James Kanze <james.ka...@gmail.comsaid:
On Dec 6, 6:10 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
>terminator wrote:
[...]
>>why do you insist on 'void*'?
>I don't. It's just another option, which is considered better.
Better than what? iostream continues to use it, for historical
reasons, but I think that the generally approved solution today
is either HiddenClass* (where HiddenClass is a private member),
or some sort of pointer to member of HiddenClass; both make it
extremely difficult (and the pointer to member makes it
impossible) for the user to recover an apparently usable pointer
to anything, and thus reduce the chance of mis-use even more.
Specifically, the primary justification for returning a
pointer-to-member rather than a pointer to a class type (or to void*,
for that matter) is that you can't delete it. I haven't seen or heard
of any studies indicating that either of these is a significant
problem, however.

I've seen it happen at least once. The conversion was always to
false,
so delete 0 didn't complain (crashing the application would have saved
a lot of debugging).
It took us a while to track the bug.

The (not) fun thing is that our operator safe-bool was actually
using the proper pointer to member function idiom but we were
using a broken gcc version (3.3.5 IIRC) that had a regression
that allowed that illegal code to compile (it was fixed in gcc 3.3.6).
casting to pointer to a type that defines delete can fix that too:

class none_delete{
void operator delete(void *)//can become public
{/*empty*/};
}

operator A::none_delete*()
{
....
return reinterpreit_cast<none_delete *>(result);
};

regards,
FM.
Dec 7 '07 #22

P: n/a
On Dec 6, 8:10 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
terminator wrote:
On Dec 6, 12:52 am, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
terminator wrote:
On Dec 4, 11:53 pm, "Victor Bazarov" <v.Abaza...@comAcast.net>
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.
>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).
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?
I was not just sure if it was the best,Now I know it was not.

regards,
FM.

Dec 7 '07 #23

P: n/a
On Dec 7, 3:06 pm, Pete Becker <p...@versatilecoding.comwrote:
On 2007-12-07 07:15:59 -0500, James Kanze <james.ka...@gmail.comsaid:
On Dec 6, 6:10 pm, "Victor Bazarov" <v.Abaza...@comAcast.netwrote:
terminator wrote:
[...]
>why do you insist on 'void*'?
I don't. It's just another option, which is considered better.
Better than what? iostream continues to use it, for historical
reasons, but I think that the generally approved solution today
is either HiddenClass* (where HiddenClass is a private member),
or some sort of pointer to member of HiddenClass; both make it
extremely difficult (and the pointer to member makes it
impossible) for the user to recover an apparently usable pointer
to anything, and thus reduce the chance of mis-use even more.
Specifically, the primary justification for returning a
pointer-to-member rather than a pointer to a class type (or to
void*, for that matter) is that you can't delete it.
Adding a private operator delete to HiddenClass would solve that
as well:-).

I'm not that much of a purist. I might use HiddenClass*,
because it only takes one extra line, and it will solve the most
obvious abuses (static_cast, or passing it to a legacy C
function which takes a void*). But quite frankly...
I haven't seen or heard of any studies indicating that either
of these is a significant problem, however.
I've never had (nor heard of) any problems with misuse of the
void* in iostream either. I use HiddenClass in my smart
pointers, as an argument for == and !=, so that the user can
only pass NULL, but that's really about it in practice.

But he said "better":-). And it's a sort of a challenge to
think of how you could detect as many user errors as possible,
even if you'd never actually do it in practice, because the work
involved largely outweighs the actual gain.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Dec 7 '07 #24

P: n/a
On 2007-12-07 11:14:50 -0500, James Kanze <ja*********@gmail.comsaid:
>
But he said "better":-). And it's a sort of a challenge to
think of how you could detect as many user errors as possible,
even if you'd never actually do it in practice, because the work
involved largely outweighs the actual gain.
The problem is that these exercises tend to become enshrined. The
current WD for C++0x has half a dozen places that advise returning a
pointer-to-member as the implementation-specific return type of a
conversion operator that's intended for testing the state of an object.
Fortunately, most of those are going away, and being replaced with
explict conversion operators.

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

Dec 7 '07 #25

This discussion thread is closed

Replies have been disabled for this discussion.