c++boostauto-ptrexception-safe

Why does `myvector.push_back(autoPtr.release())` provide the strong exception safety guarantee?


EDIT: I should've mentioned, I was looking at the documentation for Boost's ptr_sequence_adapter and it claims that their adapter for template< class U > void push_back( ::std::auto_ptr<U> x ); is equivalent to doing vec.push_back(autoPtr.release()); and also provides the strong exception guarantee. And then I realized I was confusing their description of the effect of the implementation for what the implementation actually was, and so this question is semi-nonsensical. I'm just leaving it here for posterity.

To me, it seems the call to std::auto_ptr<t> would succeed, and then the call to std::vector<t*>::push_back could throw an exception, and the pointer would be leaked.

It seems like you'd have to do this instead:

vec.push_back(0); //Attempts to allocate space in vector, could throw bad_alloc
vec.back() = autoPtr.release(); //Provides nothrow

Solution

  • This is specifically a feature of the Boost pointer containers library.

    The base push_back member function is defined as:

    void push_back( value_type x )  // strong               
    {
        this->enforce_null_policy( x, "Null pointer in 'push_back()'" );
    
        auto_type ptr( x );           // notrow
        this->base().push_back( x );  // strong, commit
        ptr.release();                // nothrow
    }
    

    (from the ptr_sequence_adapter.hpp header)

    So, the push_back function itself takes ownership of the pointer and if reallocation fails, it takes responsibility for deleting the pointer.

    The push_back overload that takes an auto_ptr is defined in terms of the base push_back function:

    template< class U >
    void push_back( std::auto_ptr<U> x )
    {
        push_back( x.release() );
    }
    

    The pointer is released before the call to the base push_back, which is okay because the base push_back function has a strong guarantee that it will delete the pointer if an exception is thrown.