Need to work around g++ 'NULL' warning

N

Neil

I've constructed a custom smart pointer, and for various reasons I'm
in the situation where I'd like to make the raw-pointer ctor for it
explicit.

However, this then disallows assignment from NULL (and implicit
creation, e.g., for 'return NULL' returning a smart pointer). I've
gone out of my way to try to make this smart pointer as drop-in-
replacement friendly as possible, so losing the ability to easily
assign NULL is a bit of a blow.


I *thought* I had a nice work-around by defining an implicit (int)
ctor, and while VS accepts this, g++ (-Wall -pedantic; probably quite
rightly for most cases) reports a warning:

warning: passing NULL to non-pointer argument ...


Can anyone think of a clever way of working around this (even if
it's g++-specific)?

A point of interest may be that '#pragma GCC system_header' can
disable that warning, but only if the actual conversion from NULL to
smart-ptr is in a header with the pragma, and I couldn't figure out
how to wangle that.


Here's a really basic example:

#include <iostream>

template <typename T>
struct Ptr
{
Ptr( const Ptr & ) {} // copy ctor
explicit Ptr( T * ) {} // only explicit from c-ptr
Ptr( int ) {} // to catch NULL (don't care about non 0)
};

int main()
{
float f1 = 0.0;

Ptr<float> p1(&f1); // OK
Ptr<float> p2(NULL); // warning :-(

return 0;
}
 
R

Ron Natalie

You cranked up the G++ warning level and you gripe about valid warnings?
If G++ doesn't have a pragma to disable warnings on a specific line like
VC++ does, then you'll have to live with it.

One option is to have an IMPLICIT conversion from some UNLIKLEY type
that you can convert NULL to that won't interfere.

For example:


template <class T> struct Ptr {
class ThisIsNeverUsed;
explicit Ptr(T*);
Ptr(ThisIsNeverUsed*);
};
 
A

Alf P. Steinbach

* Neil:
I've constructed a custom smart pointer, and for various reasons I'm
in the situation where I'd like to make the raw-pointer ctor for it
explicit.

However, this then disallows assignment from NULL (and implicit
creation, e.g., for 'return NULL' returning a smart pointer). I've
gone out of my way to try to make this smart pointer as drop-in-
replacement friendly as possible, so losing the ability to easily
assign NULL is a bit of a blow.


I *thought* I had a nice work-around by defining an implicit (int)
ctor, and while VS accepts this, g++ (-Wall -pedantic; probably quite
rightly for most cases) reports a warning:

warning: passing NULL to non-pointer argument ...


Can anyone think of a clever way of working around this (even if
it's g++-specific)?

A point of interest may be that '#pragma GCC system_header' can
disable that warning, but only if the actual conversion from NULL to
smart-ptr is in a header with the pragma, and I couldn't figure out
how to wangle that.


Here's a really basic example:

#include <iostream>

template <typename T>
struct Ptr
{
Ptr( const Ptr & ) {} // copy ctor
explicit Ptr( T * ) {} // only explicit from c-ptr
Ptr( int ) {} // to catch NULL (don't care about non 0)
};

int main()
{
float f1 = 0.0;

Ptr<float> p1(&f1); // OK
Ptr<float> p2(NULL); // warning :-(

return 0;
}

struct NullPtr
{
template< typename T >
operator T* () const { return 0; }

// More stuff if you want it.
};

NullPtr const nullPtr = NullPtr();

template< typename T >
struct Ptr
{
Ptr( Ptr const& ) {}
explicit Ptr( T* ) {}
};

int main()
{
float f1 = 0;
Ptr<float> p1( &f1 );
Ptr<float> p2( nullPtr );
// Ignore g++ warning of non-usage, or use.
}


Note: C++0x will introduce some support for typed nullpointers, and it
might be an idea to try to be forward-compatible. If possible.
However, I don't have time to look up the details.


Cheers, & hth.,

- Alf
 
F

FNX

Around about 25/01/08 12:17, Ron Natalie scribbled ...
You cranked up the G++ warning level and you gripe about valid warnings?

Yeah, we're awkward like that :)

One option is to have an IMPLICIT conversion from some UNLIKLEY type
that you can convert NULL to that won't interfere.
explicit Ptr(T*);
Ptr(ThisIsNeverUsed*);

Ah! That was what I was getting wrong in all my tests. I'd tried a
number of interim class solutions, but all my Ptr members took
const-refs; making them take const pointers to the interim class does
the trick!

The only loss is that I can't 'Ptr p(NULL)', but that's no great loss
as NULL's the default.

I think I can breath easy now! That's been bugging me; I can try it
out with the full s/w first thing Monday. Certainly my test case (now
extended to more match the real thing) is happy.

I *knew* there was going to be some straightforward solution I was
missing.

Thanks!
 
F

FNX

Around about 25/01/08 12:44, Alf P. Steinbach scribbled ...
NullPtr const nullPtr = NullPtr();
Ptr<float> p2( nullPtr );

As it happens, after failing to figure out a solution initially, I
(a) tried to redefine NULL (effective C++, 2nd, edition [dropped from
3rd!]) which would've solved it in a similar fashion† then (b) decided
to go down your route and define a global 'null'.

But I started hitting *so* much code that needed NULL changing to
null I got scared off it (we have a no. of next-level users with code
based on ours that would *not* have been happy with having to ripple
through that mod.).

Although I might have to go back to it if my current possible
solution (prior post) falls over in the real thing.

Note: C++0x will introduce some support for typed nullpointers, and it
might be an idea to try to be forward-compatible. If possible. However,
I don't have time to look up the details.

That's interesting; I'll have to remember to look into that.
Certainly, my smart pointer code is due to go through a couple of
further revisions in the future and it's certainly worth bearing c++0x
in mind as a probable end target. Thanks.
 
J

James Kanze

You cranked up the G++ warning level and you gripe about valid
warnings? If G++ doesn't have a pragma to disable warnings on
a specific line like VC++ does, then you'll have to live with
it.
One option is to have an IMPLICIT conversion from some
UNLIKLEY type that you can convert NULL to that won't
interfere.

You can do better than just "unlikely".
For example:

template <class T> struct Ptr {
class ThisIsNeverUsed;
explicit Ptr(T*);
Ptr(ThisIsNeverUsed*);
};

Make the class type private, and user code can't possibly create
a pointer to it, other than through the implicit conversion of
0.

This solution has the added advantage that it only allows using
null pointer constants, and not any integral value---Ptr( NULL )
works, but Ptr( 43 ) fails to compile.
 

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,982
Messages
2,570,185
Members
46,736
Latest member
AdolphBig6

Latest Threads

Top