C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

enforcing a literal 0 as an parameter

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Joe
Guest





PostPosted: Tue Nov 22, 2005 4:35 pm    Post subject: enforcing a literal 0 as an parameter Reply with quote



I have been adapting our smart pointers to use the safe bool idiom.
Previously, our smartpointer had a casting operator to return the raw
pointer. Therefore, we have a lot of code which looks like "if (0 !=
smartpointer) blah". To keep from having to rewrite all these
statements, I added some binary == and != operators. I would really
like to be able to enforce that the smart pointer only be comparable
with 0 and get compile time messages for violations of this. Is this
possible, or is an assert the best I can do?

joe


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

Back to top
Bob Hairgrove
Guest





PostPosted: Tue Nov 22, 2005 7:30 pm    Post subject: Re: enforcing a literal 0 as an parameter Reply with quote



On 22 Nov 2005 11:35:58 -0500, "Joe" <jgreer (AT) nsisoftware (DOT) com> wrote:


Quote:
I have been adapting our smart pointers to use the safe bool idiom.
Previously, our smartpointer had a casting operator to return the raw
pointer. Therefore, we have a lot of code which looks like "if (0 !=
smartpointer) blah". To keep from having to rewrite all these
statements, I added some binary == and != operators. I would really
like to be able to enforce that the smart pointer only be comparable
with 0 and get compile time messages for violations of this. Is this
possible, or is an assert the best I can do?


I don't see a way to do this (i.e. compile-time assertions) without
rewriting the statements. In general, though, all you need to do is
overload operator! like the standard stream classes do, then take away
the comparisons.

--
Bob Hairgrove
[email]NoSpamPlease (AT) Home (DOT) com[/email]

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


Back to top
Pete Becker
Guest





PostPosted: Tue Nov 22, 2005 7:33 pm    Post subject: Re: enforcing a literal 0 as an parameter Reply with quote



Joe wrote:

Quote:
I have been adapting our smart pointers to use the safe bool idiom.
Previously, our smartpointer had a casting operator to return the raw
pointer. Therefore, we have a lot of code which looks like "if (0 !=
smartpointer) blah". To keep from having to rewrite all these
statements, I added some binary == and != operators. I would really
like to be able to enforce that the smart pointer only be comparable
with 0 and get compile time messages for violations of this. Is this
possible, or is an assert the best I can do?



struct incomplete;
bool operator==(const incomplete*, const smartpointer&);

You may also want to consider not using comparison with 0, but instead
providing a conversion to a boolean type:

if(smartptr)
--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)

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


Back to top
Alf P. Steinbach
Guest





PostPosted: Tue Nov 22, 2005 7:34 pm    Post subject: Re: enforcing a literal 0 as an parameter Reply with quote

* Joe:

Quote:
I have been adapting our smart pointers to use the safe bool idiom.


The safest bool idiom is to _not_ provide implicit conversion: provide a
suitably named member function instead (and that really is an idiom).

Complicating things in the extreme to save one keystroke in the client
code and make that client code more difficult to understand is, well, I
don't think it's especially good engineering practice.

The "safe bool idiom" should IMHO better be known as the "the really
overly unsafe bool little evil", which makes for a nice acronym!



Quote:
Previously, our smartpointer had a casting operator to return the raw
pointer. Therefore, we have a lot of code which looks like "if (0 !=
smartpointer) blah".


By allowing conversion to raw pointer the stage is set for all the bugs
and bad things that the smart pointer is meant to prevent.



Quote:
To keep from having to rewrite all these
statements, I added some binary == and != operators.


I suggest adding a "!" operator to cater for idiomatic usage.



Quote:
I would really
like to be able to enforce that the smart pointer only be comparable
with 0 and get compile time messages for violations of this. Is this
possible, or is an assert the best I can do?


It's possible.

Off the cuff:

struct MustBeZero; // Not defined anywhere.

template< typename T >
bool operator==( MustBeZero*, SmartPtr<T> const& p ){ return !p; }

template< typename T >
bool operator==( SmartPtr<T> const& p, MustBeZero* ){ return !p; }

And so on.

Hope this helps,

- Alf

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

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


Back to top
Peter Dimov
Guest





PostPosted: Wed Nov 23, 2005 1:46 pm    Post subject: Re: enforcing a literal 0 as an parameter Reply with quote

Joe wrote:
Quote:
I have been adapting our smart pointers to use the safe bool idiom.
Previously, our smartpointer had a casting operator to return the raw
pointer. Therefore, we have a lot of code which looks like "if (0 !=
smartpointer) blah". To keep from having to rewrite all these
statements, I added some binary == and != operators. I would really
like to be able to enforce that the smart pointer only be comparable
with 0 and get compile time messages for violations of this. Is this
possible, or is an assert the best I can do?

You can use a pointer to member.

struct X
{
};

typedef int X::* Pm;

void f( Pm pm )
{
}

int main()
{
f( 0 );
}

Since X doesn't have any members, a Pm can only be constructed from a
null pointer constant (technically you can also construct one with a
reinterpret_cast).


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


Back to top
Joe Gottman
Guest





PostPosted: Wed Nov 23, 2005 1:51 pm    Post subject: Re: enforcing a literal 0 as an parameter Reply with quote


"Alf P. Steinbach" <alfps (AT) start (DOT) no> wrote

Quote:
The "safe bool idiom" should IMHO better be known as the "the really
overly unsafe bool little evil", which makes for a nice acronym!


By allowing conversion to raw pointer the stage is set for all the bugs
and bad things that the smart pointer is meant to prevent.


I think of the safe-bool idiom as conversion to member pointer or member
function pointer. For example, consider this code from the
boost::shared_ptr implementation:

typedef T * this_type::*unspecified_bool_type;

operator unspecified_bool_type() const //never throws
{
return px == 0 ? 0 : &this_type::px;
}

Returning a member pointer is much safer than returning a regular pointer,
for example:
1) It is a compile error to delete a member pointer.
2) It is a compile error to perform <, >, <=, and >= on member pointers.
3) It is a compile error to perform == or != on member pointers into
different classes.

This removes most of the bugs that are caused by automatic conversion to a
pointer-type. Most of the rest can be removed by declaring operator<<,
operator== and operator!= and either giving them reasonable semantics or
else declaring them as private members and not defining them.

The main advantage of the safe-bool is that it makes it possible to declare
a variable inside an if statement

shared_ptr ...
if (shared_ptr<Derived> pd = dynamic_pointer_cast<Derived>(pb)) {
// Do something with pd.
}

Note that in the above, pd is only in scope inside the body of the if
statement.

Joe Gottman


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


Back to top
kanze
Guest





PostPosted: Wed Nov 23, 2005 5:55 pm    Post subject: Re: enforcing a literal 0 as an parameter Reply with quote

Pete Becker wrote:
Quote:
Joe wrote:

I have been adapting our smart pointers to use the safe
bool idiom. Previously, our smartpointer had a casting
operator to return the raw pointer. Therefore, we have a
lot of code which looks like "if (0 != smartpointer) blah".
To keep from having to rewrite all these statements, I
added some binary == and != operators. I would really like
to be able to enforce that the smart pointer only be
comparable with 0 and get compile time messages for
violations of this. Is this possible, or is an assert the
best I can do?

struct incomplete;
bool operator==(const incomplete*, const smartpointer&);

You may also want to consider not using comparison with 0, but instead
providing a conversion to a boolean type:

if(smartptr)

If you're providing a generic tool to the general public (e.g.
like Boost does), you have to provide both.

If you're providing a generic tool for internal use, and you
have coding guidelines, you only have to provide forms allowed
by the coding guidelines. (This generally means == and != with
0/NUL, but not conversion to bool and the ! operator.)

If you're working in a context where people know that they will
be dealing with a smart pointer, a member function isValid() is
probably the best solution. No unexpected conversions, and no
problems about the type of the other side for comparisons.

In one green fields project, I adopted the idiom of using a
global (templated) function isValid -- the generic template
called a member function with the same name, and a partial
specialization for pointers compared with NULL. *I* liked this,
but it has a major drawback: know one else even knows about it,
which means one more thing someone reading my code has to learn
first.

--
James Kanze GABI Software
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


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


Back to top
Alf P. Steinbach
Guest





PostPosted: Wed Nov 23, 2005 8:41 pm    Post subject: Re: enforcing a literal 0 as an parameter Reply with quote

* Joe Gottman:

Quote:

"Alf P. Steinbach" <alfps (AT) start (DOT) no> wrote in message
news:43834be8.1080286406 (AT) news (DOT) individual.net...

The "safe bool idiom" should IMHO better be known as the "the really
overly unsafe bool little evil", which makes for a nice acronym!


By allowing conversion to raw pointer the stage is set for all
the bugs
and bad things that the smart pointer is meant to prevent.



I think of the safe-bool idiom as conversion to member pointer or
member
function pointer. For example, consider this code from the
boost::shared_ptr implementation:

typedef T * this_type::*unspecified_bool_type;

operator unspecified_bool_type() const //never throws
{
return px == 0 ? 0 : &this_type::px;
}


It's a bit more than that, namely adding comparision operations.

<url: http://www.artima.com/cppsource/safebool.html>

Where the author contends that "!" is difficult to understand compared
to that implicit conversion.



Quote:
Returning a member pointer is much safer than returning a regular
pointer,
for example:
1) It is a compile error to delete a member pointer.
2) It is a compile error to perform <, >, <=, and >= on member
pointers.
3) It is a compile error to perform == or != on member pointers
into
different classes.

This removes most of the bugs that are caused by automatic
conversion to a
pointer-type. Most of the rest can be removed by declaring operator<<,
operator== and operator!= and either giving them reasonable
semantics or
else declaring them as private members and not defining them.


Note that _all_ of the bugs caused by implicit conversion are removed by
not having implicit conversion, and, that's much simpler and causes less
bugs, as evidenced by the bugs caused by implicit conversion.



Quote:
The main advantage of the safe-bool is that it makes it possible to
declare
a variable inside an if statement

shared_ptr ...
if (shared_ptr<Derived> pd = dynamic_pointer_cast<Derived>(pb)) {
// Do something with pd.
}


First, you have that anyway, and second, to many programmers side-effect
based code isn't desirable.



Quote:
Note that in the above, pd is only in scope inside the body of the if
statement.


Note that in the above, if you add an 'else' branch then pd is still in
scope in the 'else' branch.

To introduce a local scope, just add braces (that's what they're for),
or a function call.

A local class is a handy device for introducing small local functions.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

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


Back to top
Joe
Guest





PostPosted: Mon Nov 28, 2005 4:29 pm    Post subject: Re: enforcing a literal 0 as an parameter Reply with quote

The company has had these smart pointers for a long time. I was
dissatified with them, so I got permission to modify the classes as
long as I didn't break too much code in the process. I am sure that
you know how these things go... Unfortunately, it is the style here to
compare pointers with 0 and rather than fight that battle now, I wanted
to allow that, but in a safe manner. Your suggestion works
beautifully. I should have thought of that myself, but I somehow got
trapped into trying all sorts of wierd template overloading things that
went no where and ended up not being able to see the forest for all the
trees that were in the way. Thanks for pointing the way. :)

joe


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

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.