Topic: How to distinguish between a zero value and a NULL pointer? [was: Comparing...]
Author: David R Tribble <david@tribble.com>
Date: 2000/08/16 Raw View
David R Tribble wrote:
>> I didn't get to see Scott's code. But I will quote code that was
>> proposed previously on this NG (I forget the name of the original
>> author):
>>
>> class Null_
>> {
>> public:
>> template <class T>
>> operator T *() const
>> {
>> return ((T *) 0);
>> }
Niels Dekker wrote:
> Are you sure it says ((T *) 0)? AFAIK, ((T *) 0) is not a portable
> null-pointer, but instead, just a pointer to the address zero.
> (Please correct me if I'm wrong!)
Converting 0 to any pointer type always results in a null pointer.
> Here is the NULL-object posted by Scott Meyers on Tue, 11 July 2000
> (subject: "Who's pathetic, me or C++ compilers?"):
>>
>> const // this is a const object...
>> class {
>> public:
>> template<class T> // convertible to any type
>> operator T*() const // of null non-member
>> { return 0; } // pointer...
>>
>> template<class C, class T> // or any type of null
>> operator T C::*() const // member pointer...
>> { return 0; }
>>
>> private:
>> void operator&() const; // whose address can't be
>> // taken (see Item 27)...
>>
>> } NULL; // and whose name is NULL
Meyer's code is identical to what I posted, with the useful addition
of a pointer-to-member conversion operator.
Dennis Yelle wrote:
>> Is something missing???
> Well, the Standard requires any const POD object to have an
> initializer, so it should read "NULL = {};", as William M. Miller
> pointed out.
Such a rule would make the following illegal:
int x; // int is a POD type
Non-auto POD types do have initializers, but they are allowed to
be implicit.
> But whether with or without initializer, I still get compile errors
> when I use this NULL as follows:
> const char *const ptr = true ? NULL : "";
> Borland 5.5 says:
> Two operands must evaluate to the same type
> GCC-2.95.2 says:
> ambiguous overload for `bool ? const {anonymous class} & : const
> char[1]'
> candidates are:
> operator ?:(bool, T C::*, const char *) <builtin>
> operator ?:(bool, const char *, const char *) <builtin>
>
> If these compilers are right, yes, there is still something missing!
> Any idea how to get it working?
The problem is in trying to cast both "" and NULL into the same type.
The "" constant is given a type of char[1] by the Borland compiler,
and there is no conversion of NULL to that type.
Perhaps we could add an explicit conversion operator for 'char*' to
the NULL class:
class
{
public:
... as above ...
operator char *() const
{
return 0;
}
} NULL;
--
David R. Tribble, mailto:david@tribble.com, http://david.tribble.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Michiel Salters <salters@lucent.com>
Date: 2000/08/17 Raw View
David R Tribble wrote:
[ long thread about alternative NULL snipped ]
> > Well, the Standard requires any const POD object to have an
> > initializer, so it should read "NULL = {};", as William M. Miller
> > pointed out.
> Such a rule would make the following illegal:
>
> int x; // int is a POD type
> Non-auto POD types do have initializers, but they are allowed to
> be implicit.
I think you missed the "const" qualifier.
Surely the following is illegal:
const int x; // const int is a const POD type;
whether x is or is not an auto var.
Michiel Salters
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: James Kuyper <kuyper@wizard.net>
Date: 2000/08/11 Raw View
Niels Dekker wrote:
...
> David R Tribble wrote:
...
> > operator T *() const
> > {
> > return ((T *) 0);
> > }
>
> Are you sure it says ((T *) 0)? AFAIK, ((T *) 0) is not a portable
> null-pointer, but instead, just a pointer to the address zero.
> (Please correct me if I'm wrong!)
0 is a null pointer constant. Any null pointer constant, when converted
to a pointer type, is guaranteed to result in a null pointer. It's NOT
guaranteed to point to address 0. The standard provides no method that
is guaranteed to produce a pointer to address 0. If there is any way to
create such a pointer, it's implementation-defined. It's also likely to
be this method.
...
> > operator T*() const // of null non-member
> > { return 0; } // pointer...
This performs an implicit conversion to T*, with the same consequences.
I prefer implicit conversions where they're adequate; the restrictions
on implicit conversions are stronger than those on explicit ones, so
they're correspondingly safer. Unfortunately, I'm currently working
under an official set of programming standards and guidelines that
prohibit implicit conversions.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Dennis Yelle <dennis51@jps.net>
Date: 2000/08/09 Raw View
David R Tribble wrote:
[...]
> I didn't get to see Scott's code. But I will quote code that was
> proposed previously on this NG (I forget the name of the original
> author):
>
> class Null_
> {
> public:
> template <class T>
> operator T *() const
> {
> return ((T *) 0);
> }
> private:
> Null_(const Null_ &r);
> void operator &();
> };
>
> const Null_ null; // Generic null pointer const
>
> // Optional:
> #define NULL null // Generic null pointer const
>
> This requires a compiler that supports template member functions.
I don't understand how that is supposed to work.
Is something missing???
Dennis Yelle
--
I am a computer programmer and I am looking for a job.
There is a link to my resume here: http://table.jps.net/~vert
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Niels Dekker <ndekker@REMOVETHISnki.nl>
Date: 2000/08/11 Raw View
Valentin Bonnard wrote:
> > Does your compiler complain about the following?
> > int i = NULL; // Bug!
>
> gcc does (in GNU mode, not in ANSI mode (rightly, because it's
> nonconforming behaviour ([...])))
This is really great, thanks! :-) We have just installed GCC-2.95.2 at
our institute and we have found some NULL-related bugs already!
David R Tribble wrote:
>
> I didn't get to see Scott's code. But I will quote code that was
> proposed previously on this NG (I forget the name of the original
> author):
>
> class Null_
> {
> public:
> template <class T>
> operator T *() const
> {
> return ((T *) 0);
> }
Are you sure it says ((T *) 0)? AFAIK, ((T *) 0) is not a portable
null-pointer, but instead, just a pointer to the address zero.
(Please correct me if I'm wrong!)
Here is the NULL-object posted by Scott Meyers on Tue, 11 July 2000
(subject: "Who's pathetic, me or C++ compilers?"):
>
> const // this is a const object...
> class {
> public:
> template<class T> // convertible to any type
> operator T*() const // of null non-member
> { return 0; } // pointer...
>
> template<class C, class T> // or any type of null
> operator T C::*() const // member pointer...
> { return 0; }
>
> private:
> void operator&() const; // whose address can't be
> // taken (see Item 27)...
>
> } NULL; // and whose name is NULL
Dennis Yelle wrote:
>
> Is something missing???
Well, the Standard requires any const POD object to have an initializer,
so it should read "NULL = {};", as William M. Miller pointed out. But
whether with or without initializer, I still get compile errors when I
use this NULL as follows:
const char *const ptr = true ? NULL : "";
Borland 5.5 says:
Two operands must evaluate to the same type
GCC-2.95.2 says:
ambiguous overload for `bool ? const {anonymous class} & : const char[1]'
candidates are: operator ?:(bool, T C::*, const char *) <builtin>
operator ?:(bool, const char *, const char *)<builtin>
If these compilers are right, yes, there is still something missing!
Any idea how to get it working?
Niels Dekker
ndekker "at" nki "dot" nl
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Valentin Bonnard <Bonnard.V@wanadoo.fr>
Date: 2000/08/08 Raw View
Niels Dekker wrote:
> Valentin Bonnard wrote:
> > > Well, I just hope that C++ will provide me a more convenient way to
> > > distinguish between an integral zero expression and a null pointer...
> >
> > We already have a reserved spelling for that, it's NULL (not a keyword,
> > but very close). So just write NULL and use a good compiler.
>
> What do you mean by "a good compiler"? All compilers I have seen so far
> allow NULL to be used as an integral value. Does your compiler complain
> about the following?
> int i = NULL; // Bug!
gcc does (in GNU mode, not in ANSI mode (rightly, because it's
nonconforming behaviour (I haven't found how to re-activate it in
-ansi -pedantic mode))):
quatramaran bonnard ~/C++/core $ cat > NULL-is-not-an-int.cc
#include <stdlib.h>
int main()
{
int i = NULL;
}
quatramaran bonnard ~/C++/core $ gcc NULL-is-not-an-int.cc
NULL-is-not-an-int.cc: In function `int main()':
NULL-is-not-an-int.cc:5: warning: initialization to `int' from `{unknown
type} *' lacks a cast
quatramaran bonnard ~/C++/core $ gcc -ansi NULL-is-not-an-int.cc
quatramaran bonnard ~/C++/core $
> If so, how does your compiler define NULL?
You don't want to know that.
> (Scott Meyers published a
> wonderful template-based NULL object in the first edition of his book
> Effective C++. Unfortunately it was rejected by most compilers, as you
> might have read last month in the discussion "Who's pathetic, me or C++
> compilers?")
Not only I have read it, but I remember the Scott Meyers' code. And I
remember that was rejected... because it was incorrect.
--
Valentin Bonnard
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: David R Tribble <david@tribble.com>
Date: 2000/08/09 Raw View
Niels Dekker wrote:
>> [...]
>> All compilers I have seen so far allow NULL to be used as an
>> integral value. Does your compiler complain about the following?
>> int i = NULL; // Bug!
That's because ISO C++ defines 0 as a null pointer constant, and
specifically allows NULL to be defined as 0.
Valentin Bonnard wrote:
> gcc does (in GNU mode, not in ANSI mode (rightly, because it's
> nonconforming behaviour (I haven't found how to re-activate it in
> -ansi -pedantic mode))):
>[...]
IIRC, GCC (in non-ISO mode) defines NULL to something like __null__,
which is a reserved name known to the compiler to mean "null pointer
constant". This is a prime example of the compiler going beyond the
ISO requirements and providing more rational semantic behavior.
Niels:
>> (Scott Meyers published a wonderful template-based NULL object in
>> the first edition of his book Effective C++. Unfortunately it was
>> rejected by most compilers, as you might have read last month in
>> the discussion "Who's pathetic, me or C++ compilers?")
Valentin:
> Not only I have read it, but I remember the Scott Meyers' code. And
> I remember that was rejected... because it was incorrect.
I didn't get to see Scott's code. But I will quote code that was
proposed previously on this NG (I forget the name of the original
author):
class Null_
{
public:
template <class T>
operator T *() const
{
return ((T *) 0);
}
private:
Null_(const Null_ &r);
void operator &();
};
const Null_ null; // Generic null pointer const
// Optional:
#define NULL null // Generic null pointer const
This requires a compiler that supports template member functions.
--
David R. Tribble, mailto:david@tribble.com, http://david.tribble.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Niels Dekker <ndekker@REMOVETHISnki.nl>
Date: 2000/08/07 Raw View
Valentin Bonnard wrote:
>
> For zero() we already have T(0) and T().
Unfortunately from the replies so far I understand that both char(0) and
char() are allowed to be used as a null-pointer. So the following is
legal C++, even though it's clearly a bug:
char *ptr = char(); // Buggy but legal! :-(
I'm glad about the reply William M. Miller gave us, saying he will check
with the Committee whether this is an issue.
> > Well, I just hope that C++ will provide me a more convenient way to
> > distinguish between an integral zero expression and a null pointer...
>
> We already have a reserved spelling for that, it's NULL (not a keyword,
> but very close). So just write NULL and use a good compiler.
What do you mean by "a good compiler"? All compilers I have seen so far
allow NULL to be used as an integral value. Does your compiler complain
about the following?
int i = NULL; // Bug!
If so, how does your compiler define NULL? (Scott Meyers published a
wonderful template-based NULL object in the first edition of his book
Effective C++. Unfortunately it was rejected by most compilers, as you
might have read last month in the discussion "Who's pathetic, me or C++
compilers?")
James Kanze wrote:
>
> In practice, however, I find numeric_limits invaluable when writing
> template code for numeric types. In this context, I could very well
> imagine using it to get a zero value of the correct type.
Thanks for your support.
> Which is less verbose: numeric_limits<T>.zero(), or static_cast<T>( 0 )?
Personally I'd rather avoid using any explicit casts. But more
importantly, I *think* static_cast<char>(0) is an integral constant
expression as described in 5.19p1. (Please correct me if I'm wrong!)
If I'm right, this implies that static_cast<char>(0) can be used as a
null-pointer, and the following bug won't get rejected by a
Standard-conforming compiler:
char *ptr = static_cast<char>(0);
On the other hand, numeric_limits<char>::zero() would not be an integral
constant expression because it is a function call. So the following
line would get rejected, preventing an unnecessary bug.
char *ptr = numeric_limits<char>::zero(); // Illegal C++! :-)
Niels Dekker
ndekker "at" nki "dot" nl
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]