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

Are implicit casts to void*& illegal?

P: n/a
I searched around but couldn't find any previous discussion on this, so...

I have a macro that implements a common memory disposal function, e.g.:

#define safe_free(void* pv) if(pv) { ::free(pv); (pv) = NULL; }

(Yes, its free() instead of operator delete, but I don't think using the
newer memory semantics matters in this case.)

Since another project might have an entity of the same name, and macros
are in the global namespace, to avoid namespace collision I thought an
inline function might be better:

namespace myspace
{
inline void safe_free(void*& pv) { ... }
}

(Having pv as a void*& lets pv be assigned to NULL).
However, calling code can no longer do this:

using namespace myspace;
char* p = (char*)::malloc(100);
safe_free(p); // error: char* cannot be
// converted to void*&.
Doing

safe_free((void*)p);

fails also (can't convert void* to void*&), which seems odd because

void* pv = (void*)p;
safe_free(pv);

works fine.

So to use the function, I wound up doing

safe_free((void*&)p);

which is not the end of the world but tragically inelegant considering
that references usually increase elegance. Implicit casts to void* are
legal, but not void*& -- strange.

This is happening in MSVC 6. I was wondering if others had the same
problem in other compilers or other versions of MSVC.

This template would work:

template <type T> void safe_free(T*& p)
{ ... }

but it seems like overkill to have to instantiate a template function
for all possible pointer types when the function only needs the
pointer's value, not the type of object being pointed to.

Ray
Apr 19 '06 #1
Share this Question
Share on Google+
3 Replies


P: n/a
Ray Gardener wrote:
I searched around but couldn't find any previous discussion on this,
so...
I have a macro that implements a common memory disposal function,
e.g.:
#define safe_free(void* pv) if(pv) { ::free(pv); (pv) = NULL; }
Actually, you need to drop the "void*" part. And there is no need to
check for its null-ness. 'free' does nothing if you pass a null pointer
to it.
(Yes, its free() instead of operator delete, but I don't think using
the newer memory semantics matters in this case.)
They may not, but only if the pointer is obtained from 'malloc' or
'realloc'. If you get the pointer from 'new', you can't 'free' it.
Since another project might have an entity of the same name, and
macros are in the global namespace, to avoid namespace collision I
thought an inline function might be better:

namespace myspace
{
inline void safe_free(void*& pv) { ... }
}

(Having pv as a void*& lets pv be assigned to NULL).
OK.
However, calling code can no longer do this:

using namespace myspace;
char* p = (char*)::malloc(100);
safe_free(p); // error: char* cannot be
// converted to void*&.
Make your 'safe_free' a template.
Doing

safe_free((void*)p);

fails also (can't convert void* to void*&), which seems odd because

void* pv = (void*)p;
safe_free(pv);

works fine.

So to use the function, I wound up doing

safe_free((void*&)p);

which is not the end of the world but tragically inelegant considering
that references usually increase elegance. Implicit casts to void* are
legal, but not void*& -- strange.
Yes, and it should be dropped.
This is happening in MSVC 6. I was wondering if others had the same
problem in other compilers or other versions of MSVC.

This template would work:

template <type T> void safe_free(T*& p)
{ ... }
That's right! It is perfect.
but it seems like overkill to have to instantiate a template function
for all possible pointer types when the function only needs the
pointer's value, not the type of object being pointed to.


It's not overkill. Declare it 'inline' and forget about it.

V
--
Please remove capital As from my address when replying by mail
Apr 19 '06 #2

P: n/a
Yes, you're right; I forgot that this is an inline function anyway.
Sigh... got so paranoid about template instantation bloat I've let it
get the better of me. :)

Thanks,
Ray
Victor Bazarov wrote:
Ray Gardener wrote:
I searched around but couldn't find any previous discussion on this,
so...
I have a macro that implements a common memory disposal function,
e.g.:
#define safe_free(void* pv) if(pv) { ::free(pv); (pv) = NULL; }


Actually, you need to drop the "void*" part. And there is no need to
check for its null-ness. 'free' does nothing if you pass a null pointer
to it.
(Yes, its free() instead of operator delete, but I don't think using
the newer memory semantics matters in this case.)


They may not, but only if the pointer is obtained from 'malloc' or
'realloc'. If you get the pointer from 'new', you can't 'free' it.
Since another project might have an entity of the same name, and
macros are in the global namespace, to avoid namespace collision I
thought an inline function might be better:

namespace myspace
{
inline void safe_free(void*& pv) { ... }
}

(Having pv as a void*& lets pv be assigned to NULL).


OK.
However, calling code can no longer do this:

using namespace myspace;
char* p = (char*)::malloc(100);
safe_free(p); // error: char* cannot be
// converted to void*&.


Make your 'safe_free' a template.
Doing

safe_free((void*)p);

fails also (can't convert void* to void*&), which seems odd because

void* pv = (void*)p;
safe_free(pv);

works fine.

So to use the function, I wound up doing

safe_free((void*&)p);

which is not the end of the world but tragically inelegant considering
that references usually increase elegance. Implicit casts to void* are
legal, but not void*& -- strange.


Yes, and it should be dropped.
This is happening in MSVC 6. I was wondering if others had the same
problem in other compilers or other versions of MSVC.

This template would work:

template <type T> void safe_free(T*& p)
{ ... }


That's right! It is perfect.
but it seems like overkill to have to instantiate a template function
for all possible pointer types when the function only needs the
pointer's value, not the type of object being pointed to.


It's not overkill. Declare it 'inline' and forget about it.

V

Apr 19 '06 #3

P: n/a

Ray Gardener wrote:
Yes, you're right; I forgot that this is an inline function anyway.
Sigh... got so paranoid about template instantation bloat I've let it
get the better of me. :)

Thanks,
Ray

[snip]

Actually i do not believe there is any reason to worry about template
bloat these days. Improvements in the linker and compiler have come a
far way - to an extent that code from different templates will be
merged if the code is the same. This happens for e.g.
std::vector::push_back which is the same code for int and unsigned int.
So even if your code was not inline, most probably all instantations
would fold to the same code.

/Peter

Apr 19 '06 #4

This discussion thread is closed

Replies have been disabled for this discussion.