Boost logo

Boost Users :

From: Chris Newbold (Chris.Newbold_at_[hidden])
Date: 2007-07-16 10:57:41


Greetings. I've been wrestling with some legacy C code which makes heavy
use of raw arrays of pointers-- typically pointers to quasi-OO C
structures which have specific "constructor" and "destructor" functions.
Here's a contrived example:

        struct OldStuff
        {
                ...
        };
        
        OldStuff* CreateOldStuff();
        void DestroyOldStuff(OldStuff*);
        
Then there are functions which return zero or more of these structures
as output via an array of pointers:

        bool FiddleWithStuff(OldStuff** output, size_t count, ...);
        
It's the callers responsibility to properly dispose of the results
returned in 'output' by calling DestroyOldStuff() on each element.

What I'd like to be able to do is provide a wrapper for functions like
this which provide automatic management for the output values. Here's an
example using ptr_vector:

        struct OldStuff_Destroyer
        {
                // What's up with the const pointer to deallocate?!?
                static void deallocate_clone(const OldStuff* p) {
                        DestroyOldStuff(const_cast<OldStuff*>(p));
                }
        };
        
        typedef boost::ptr_vector<
                boost::nullable<OldStuff>,
                OldStuff_Destroyer>
        StuffVec_t;
        
        bool Wrapper(StuffVec_t& output, size_t count, ...);
        
The pointer containers like ptr_vector seem to be a good fit,
particularly given the customizable cloning behavior and is a very
natural transition from an array of pointers.

The problem I'm having is how to couple ptr_vector to the legacy code
which expects to use arrays of pointers. Here's what I'd like to do:

        bool Wrapper(StuffVec_t& output, size_t count, ...)
        {
                // Won't work: resize() isn't supported
                output.resize(count);
                // Won't work: no way to get to raw storage
                return FiddleWithStuff(&output[0], count, ...);
        }
        
As noted, this won't work for a couple of reasons. The pointer
containers have an aversion to containing NULL pointers, which is why I
imagine resize() isn't supported. And there's no way to get a pointer to
the raw storage for the pointers to provide a buffer for the legacy code
to write into.

I do understand why the pointer containers don't support what I'm trying
to do here, and the restrictions are entirely reasonable to provide
additional safety. But...

Using a container of smart pointers isn't an option, either, for the
same reason: the need to have legacy code write into the storage as if
it were an array.

Does anyone have any suggestions on how to encapsulate a collection of
pointers and some associated deletion logic? Obviously I could write my
own pointer collection that satisfies my requirements, but I was hoping
to use off-the-shelf bits.

Thanks for any ideas.

-Chris


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net