Are implicit casts to void*& illegal?

Discussion in 'C++' started by Ray Gardener, Apr 19, 2006.

  1. Ray Gardener

    Ray Gardener Guest

    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
     
    Ray Gardener, Apr 19, 2006
    #1
    1. Advertising

  2. 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
     
    Victor Bazarov, Apr 19, 2006
    #2
    1. Advertising

  3. Ray Gardener

    Ray Gardener Guest

    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
     
    Ray Gardener, Apr 19, 2006
    #3
  4. Ray Gardener

    peter koch Guest

    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
     
    peter koch, Apr 19, 2006
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Simon Ford
    Replies:
    4
    Views:
    431
    tom_usenet
    Sep 23, 2003
  2. Ollej Reemt
    Replies:
    7
    Views:
    547
    Jack Klein
    Apr 22, 2005
  3. Stig Brautaset

    `void **' revisited: void *pop(void **root)

    Stig Brautaset, Oct 25, 2003, in forum: C Programming
    Replies:
    15
    Views:
    794
    The Real OS/2 Guy
    Oct 28, 2003
  4. Replies:
    5
    Views:
    842
    S.Tobias
    Jul 22, 2005
  5. Replies:
    1
    Views:
    413
    Victor Bazarov
    May 23, 2007
Loading...

Share This Page