epoc32/include/stdapis/boost/ptr_container/detail/reversible_ptr_container.hpp
author William Roberts <williamr@symbian.org>
Wed, 31 Mar 2010 12:33:34 +0100 (2010-03-31)
branchSymbian3
changeset 4 837f303aceeb
permissions -rw-r--r--
Current Symbian^3 public API header files (from PDK 3.0.h)
This is the epoc32/include tree with the "platform" subtrees removed, and
all but a selected few mbg and rsg files removed.
williamr@2
     1
//
williamr@2
     2
// Boost.Pointer Container
williamr@2
     3
//
williamr@2
     4
//  Copyright Thorsten Ottosen 2003-2005. Use, modification and
williamr@2
     5
//  distribution is subject to the Boost Software License, Version
williamr@2
     6
//  1.0. (See accompanying file LICENSE_1_0.txt or copy at
williamr@2
     7
//  http://www.boost.org/LICENSE_1_0.txt)
williamr@2
     8
//
williamr@2
     9
// For more information, see http://www.boost.org/libs/ptr_container/
williamr@2
    10
//
williamr@2
    11
/*
williamr@2
    12
 * © Portions copyright (c) 2006-2007 Nokia Corporation.  All rights reserved.
williamr@2
    13
*/
williamr@2
    14
williamr@2
    15
#ifndef BOOST_PTR_CONTAINER_DETAIL_REVERSIBLE_PTR_CONTAINER_HPP
williamr@2
    16
#define BOOST_PTR_CONTAINER_DETAIL_REVERSIBLE_PTR_CONTAINER_HPP
williamr@2
    17
williamr@2
    18
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
williamr@2
    19
# pragma once
williamr@2
    20
#endif
williamr@2
    21
williamr@2
    22
#include <boost/ptr_container/detail/throw_exception.hpp>
williamr@2
    23
#include <boost/ptr_container/detail/scoped_deleter.hpp>
williamr@2
    24
#include <boost/ptr_container/detail/static_move_ptr.hpp>
williamr@2
    25
#include <boost/ptr_container/exception.hpp>
williamr@2
    26
#include <boost/ptr_container/clone_allocator.hpp>
williamr@2
    27
#include <boost/ptr_container/nullable.hpp>
williamr@2
    28
williamr@2
    29
#ifdef BOOST_NO_SFINAE
williamr@2
    30
#else
williamr@2
    31
#include <boost/range/functions.hpp>
williamr@2
    32
#endif
williamr@2
    33
williamr@2
    34
#include <boost/config.hpp>
williamr@2
    35
#include <boost/iterator/reverse_iterator.hpp>
williamr@2
    36
#include <boost/range/iterator.hpp>
williamr@2
    37
#include <boost/utility/enable_if.hpp>
williamr@2
    38
#include <boost/type_traits/is_pointer.hpp>
williamr@2
    39
#include <boost/type_traits/is_integral.hpp>
williamr@2
    40
#include <boost/serialization/split_member.hpp>
williamr@2
    41
#include <algorithm>
williamr@2
    42
#include <exception>
williamr@2
    43
#include <memory>
williamr@2
    44
#include <typeinfo>
williamr@2
    45
#ifdef __SYMBIAN32__
williamr@2
    46
#include <boost/range/begin.hpp>
williamr@2
    47
#include <boost/range/end.hpp>
williamr@2
    48
#endif
williamr@2
    49
williamr@2
    50
namespace boost
williamr@2
    51
{
williamr@2
    52
    
williamr@2
    53
namespace ptr_container_detail
williamr@2
    54
{
williamr@2
    55
williamr@2
    56
    template< class T >
williamr@2
    57
    inline T const& serialize_as_const( T const& r )
williamr@2
    58
    {
williamr@2
    59
        return r;
williamr@2
    60
    }
williamr@2
    61
williamr@2
    62
    template< class CloneAllocator >
williamr@2
    63
    struct clone_deleter
williamr@2
    64
    {
williamr@2
    65
        template< class T >
williamr@2
    66
        void operator()( const T* p ) const
williamr@2
    67
        {
williamr@2
    68
            CloneAllocator::deallocate_clone( p );
williamr@2
    69
        }
williamr@2
    70
    };
williamr@2
    71
williamr@2
    72
    template< class T >
williamr@2
    73
    struct is_pointer_or_integral
williamr@2
    74
    {
williamr@2
    75
        BOOST_STATIC_CONSTANT(bool, value = is_pointer<T>::value || is_integral<T>::value );
williamr@2
    76
    };
williamr@2
    77
williamr@2
    78
    struct is_pointer_or_integral_tag {};
williamr@2
    79
    struct is_range_tag {};
williamr@2
    80
williamr@2
    81
    
williamr@2
    82
    
williamr@2
    83
    template
williamr@2
    84
    < 
williamr@2
    85
        class Config, 
williamr@2
    86
        class CloneAllocator
williamr@2
    87
    >
williamr@2
    88
    class reversible_ptr_container 
williamr@2
    89
    {
williamr@2
    90
    private:
williamr@2
    91
#ifdef  __MWERKS__
williamr@2
    92
        enum { allow_null = Config::allow_null };
williamr@2
    93
#else
williamr@2
    94
        BOOST_STATIC_CONSTANT( bool, allow_null = Config::allow_null );
williamr@2
    95
#endif        
williamr@2
    96
        
williamr@2
    97
        typedef BOOST_DEDUCED_TYPENAME Config::value_type Ty_;
williamr@2
    98
williamr@2
    99
        template< bool allow_null_values >
williamr@2
   100
        struct null_clone_allocator
williamr@2
   101
        {
williamr@2
   102
            template< class Iter >
williamr@2
   103
            static Ty_* allocate_clone_from_iterator( Iter i )
williamr@2
   104
            { 
williamr@2
   105
                return allocate_clone( Config::get_const_pointer( i ) );
williamr@2
   106
            }
williamr@2
   107
            
williamr@2
   108
            static Ty_* allocate_clone( const Ty_* x )
williamr@2
   109
            {
williamr@2
   110
                if( allow_null_values )
williamr@2
   111
                {
williamr@2
   112
                    if( x == 0 )
williamr@2
   113
                        return 0;
williamr@2
   114
                }
williamr@2
   115
                else
williamr@2
   116
                {
williamr@2
   117
                    BOOST_ASSERT( x != 0 && "Cannot insert clone of null!" );
williamr@2
   118
                }
williamr@2
   119
williamr@2
   120
                Ty_* res = CloneAllocator::allocate_clone( *x );
williamr@2
   121
                BOOST_ASSERT( typeid(*res) == typeid(*x) &&
williamr@2
   122
                              "CloneAllocator::allocate_clone() does not clone the "
williamr@2
   123
                              "object properly. Check that new_clone() is implemented"
williamr@2
   124
                              " correctly" );
williamr@2
   125
                return res;
williamr@2
   126
            }
williamr@2
   127
            
williamr@2
   128
            static void deallocate_clone( const Ty_* x )
williamr@2
   129
            {
williamr@2
   130
                if( allow_null_values )
williamr@2
   131
                {
williamr@2
   132
                    if( x == 0 )
williamr@2
   133
                        return;
williamr@2
   134
                }
williamr@2
   135
williamr@2
   136
                CloneAllocator::deallocate_clone( x );
williamr@2
   137
            }
williamr@2
   138
        };
williamr@2
   139
williamr@2
   140
        typedef BOOST_DEDUCED_TYPENAME Config::void_container_type  Cont;
williamr@2
   141
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))    
williamr@2
   142
        typedef  null_clone_allocator<reversible_ptr_container::allow_null> 
williamr@2
   143
                                                                    null_cloner_type;
williamr@2
   144
#else
williamr@2
   145
        typedef null_clone_allocator<allow_null>                    null_cloner_type;
williamr@2
   146
#endif        
williamr@2
   147
        typedef clone_deleter<null_cloner_type>                     Deleter;
williamr@2
   148
williamr@2
   149
        Cont      c_;
williamr@2
   150
williamr@2
   151
    public:
williamr@2
   152
        Cont& c_private()                { return c_; }
williamr@2
   153
        const Cont& c_private() const    { return c_; }
williamr@2
   154
williamr@2
   155
    public: // typedefs
williamr@2
   156
        typedef  Ty_*          value_type;
williamr@2
   157
        typedef  Ty_*          pointer;
williamr@2
   158
        typedef  Ty_&          reference;
williamr@2
   159
        typedef  const Ty_&    const_reference;
williamr@2
   160
        
williamr@2
   161
        typedef  BOOST_DEDUCED_TYPENAME Config::iterator 
williamr@2
   162
                                   iterator;
williamr@2
   163
        typedef  BOOST_DEDUCED_TYPENAME Config::const_iterator
williamr@2
   164
                                   const_iterator;
williamr@2
   165
        typedef  boost::reverse_iterator< iterator > 
williamr@2
   166
                                   reverse_iterator;  
williamr@2
   167
        typedef  boost::reverse_iterator< const_iterator >     
williamr@2
   168
                                   const_reverse_iterator;
williamr@2
   169
        typedef  BOOST_DEDUCED_TYPENAME Cont::difference_type
williamr@2
   170
                                   difference_type; 
williamr@2
   171
        typedef  BOOST_DEDUCED_TYPENAME Cont::size_type
williamr@2
   172
                                   size_type;
williamr@2
   173
        typedef  BOOST_DEDUCED_TYPENAME Config::allocator_type
williamr@2
   174
                                   allocator_type;
williamr@2
   175
williamr@2
   176
        typedef ptr_container_detail::static_move_ptr<Ty_,Deleter> 
williamr@2
   177
                                   auto_type;
williamr@2
   178
            
williamr@2
   179
    protected: 
williamr@2
   180
            
williamr@2
   181
        typedef ptr_container_detail::scoped_deleter<Ty_,null_cloner_type>
williamr@2
   182
                                   scoped_deleter;
williamr@2
   183
        typedef BOOST_DEDUCED_TYPENAME Cont::iterator
williamr@2
   184
                                   ptr_iterator; 
williamr@2
   185
        typedef BOOST_DEDUCED_TYPENAME Cont::const_iterator
williamr@2
   186
                                   ptr_const_iterator; 
williamr@2
   187
    private:
williamr@2
   188
williamr@2
   189
        template< class InputIterator >  
williamr@2
   190
        void copy( InputIterator first, InputIterator last ) 
williamr@2
   191
        {
williamr@2
   192
            std::copy( first, last, begin() );
williamr@2
   193
        }
williamr@2
   194
        
williamr@2
   195
        void copy( const reversible_ptr_container& r )
williamr@2
   196
        { 
williamr@2
   197
            copy( r.begin(), r.end() );
williamr@2
   198
        }
williamr@2
   199
        
williamr@2
   200
        void copy_clones_and_release( scoped_deleter& sd ) // nothrow
williamr@2
   201
        {
williamr@2
   202
            BOOST_ASSERT( size_type( std::distance( sd.begin(), sd.end() ) ) == c_.size() );
williamr@2
   203
            std::copy( sd.begin(), sd.end(), c_.begin() );
williamr@2
   204
            sd.release(); 
williamr@2
   205
        }
williamr@2
   206
        
williamr@2
   207
        void insert_clones_and_release( scoped_deleter& sd ) // strong
williamr@2
   208
        {
williamr@2
   209
            c_.insert( sd.begin(), sd.end() );
williamr@2
   210
            sd.release();
williamr@2
   211
        }
williamr@2
   212
williamr@2
   213
        template< class ForwardIterator >
williamr@2
   214
        void clone_assign( ForwardIterator first, 
williamr@2
   215
                           ForwardIterator last ) // strong 
williamr@2
   216
        {
williamr@2
   217
            BOOST_ASSERT( first != last );
williamr@2
   218
            scoped_deleter sd( first, last );      // strong
williamr@2
   219
            copy_clones_and_release( sd );         // nothrow
williamr@2
   220
        }
williamr@2
   221
williamr@2
   222
        template< class ForwardIterator >
williamr@2
   223
        void clone_back_insert( ForwardIterator first,
williamr@2
   224
                                ForwardIterator last )
williamr@2
   225
        {
williamr@2
   226
            BOOST_ASSERT( first != last );
williamr@2
   227
            scoped_deleter sd( first, last );
williamr@2
   228
            insert_clones_and_release( sd, end() );
williamr@2
   229
        }
williamr@2
   230
        
williamr@2
   231
        void remove_all() 
williamr@2
   232
        {
williamr@2
   233
            remove( begin(), end() ); 
williamr@2
   234
        }
williamr@2
   235
williamr@2
   236
    protected:
williamr@2
   237
williamr@2
   238
        void insert_clones_and_release( scoped_deleter& sd, 
williamr@2
   239
                                        iterator where ) // strong
williamr@2
   240
        {
williamr@2
   241
            //
williamr@2
   242
            // 'c_.insert' always provides the strong guarantee for T* elements
williamr@2
   243
            // since a copy constructor of a pointer cannot throw
williamr@2
   244
            //
williamr@2
   245
            c_.insert( where.base(), 
williamr@2
   246
                       sd.begin(), sd.end() ); 
williamr@2
   247
            sd.release();
williamr@2
   248
        }
williamr@2
   249
williamr@2
   250
        template< class I >
williamr@2
   251
        void remove( I i )
williamr@2
   252
        { 
williamr@2
   253
            null_policy_deallocate_clone( Config::get_const_pointer(i) );
williamr@2
   254
        }
williamr@2
   255
williamr@2
   256
        template< class I >
williamr@2
   257
        void remove( I first, I last ) 
williamr@2
   258
        {
williamr@2
   259
            for( ; first != last; ++first )
williamr@2
   260
                remove( first );
williamr@2
   261
        }
williamr@2
   262
williamr@2
   263
        static void enforce_null_policy( Ty_* x, const char* msg )
williamr@2
   264
        {
williamr@2
   265
            if( !allow_null )
williamr@2
   266
            {
williamr@2
   267
                BOOST_PTR_CONTAINER_THROW_EXCEPTION( 0 == x && "null not allowed", 
williamr@2
   268
                                                     bad_pointer, msg );
williamr@2
   269
            }
williamr@2
   270
        }
williamr@2
   271
williamr@2
   272
        static Ty_* null_policy_allocate_clone( const Ty_* x )
williamr@2
   273
        {
williamr@2
   274
            return null_cloner_type::allocate_clone( x );
williamr@2
   275
        }
williamr@2
   276
williamr@2
   277
        static void null_policy_deallocate_clone( const Ty_* x )
williamr@2
   278
        {
williamr@2
   279
            null_cloner_type::deallocate_clone( x );
williamr@2
   280
        }
williamr@2
   281
williamr@2
   282
    private:
williamr@2
   283
        template< class ForwardIterator >
williamr@2
   284
        ForwardIterator advance( ForwardIterator begin, size_type n ) 
williamr@2
   285
        {
williamr@2
   286
            ForwardIterator iter = begin;
williamr@2
   287
            std::advance( iter, n );
williamr@2
   288
            return iter;
williamr@2
   289
        }
williamr@2
   290
        
williamr@2
   291
    private:
williamr@2
   292
        reversible_ptr_container( const reversible_ptr_container& );
williamr@2
   293
        void operator=( const reversible_ptr_container& );
williamr@2
   294
        
williamr@2
   295
    public: // foundation! should be protected!
williamr@2
   296
        explicit reversible_ptr_container( const allocator_type& a = allocator_type() ) 
williamr@2
   297
         : c_( a )
williamr@2
   298
        {}
williamr@2
   299
        
williamr@2
   300
        template< class PtrContainer >
williamr@2
   301
        explicit reversible_ptr_container( std::auto_ptr<PtrContainer> clone )
williamr@2
   302
          : c_( allocator_type() )                
williamr@2
   303
        { 
williamr@2
   304
            swap( *clone ); 
williamr@2
   305
        }
williamr@2
   306
williamr@2
   307
    private:
williamr@2
   308
        template< class I >
williamr@2
   309
        void constructor_impl( I first, I last, std::input_iterator_tag ) // basic
williamr@2
   310
        {
williamr@2
   311
            while( first != last )
williamr@2
   312
            {
williamr@2
   313
                insert( end(), null_cloner_type::allocate_clone_from_iterator(first) );
williamr@2
   314
                ++first;
williamr@2
   315
            }
williamr@2
   316
        }
williamr@2
   317
williamr@2
   318
        template< class I >
williamr@2
   319
        void constructor_impl( I first, I last, std::forward_iterator_tag ) // strong
williamr@2
   320
        {
williamr@2
   321
            if( first == last )
williamr@2
   322
                return;
williamr@2
   323
            clone_back_insert( first, last );
williamr@2
   324
        }
williamr@2
   325
williamr@2
   326
williamr@2
   327
    public:
williamr@2
   328
        // overhead: null-initilization of container pointer (very cheap compared to cloning)
williamr@2
   329
        // overhead: 1 heap allocation (very cheap compared to cloning)
williamr@2
   330
        template< class InputIterator >
williamr@2
   331
        reversible_ptr_container( InputIterator first, 
williamr@2
   332
                                  InputIterator last,
williamr@2
   333
                                  const allocator_type& a = allocator_type() ) // basic, strong
williamr@2
   334
        : c_( a )
williamr@2
   335
        { 
williamr@2
   336
            constructor_impl( first, last, 
williamr@2
   337
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
williamr@2
   338
#else
williamr@2
   339
                              BOOST_DEDUCED_TYPENAME
williamr@2
   340
#endif                              
williamr@2
   341
                              iterator_category<InputIterator>::type() );
williamr@2
   342
        }
williamr@2
   343
williamr@2
   344
        template< class Compare >
williamr@2
   345
        reversible_ptr_container( const Compare& comp,
williamr@2
   346
                                  const allocator_type& a )
williamr@2
   347
        : c_( comp, a ) {}
williamr@2
   348
williamr@2
   349
        template< class PtrContainer, class Compare >
williamr@2
   350
        reversible_ptr_container( std::auto_ptr<PtrContainer> clone, 
williamr@2
   351
                                  Compare comp )
williamr@2
   352
        : c_( comp, allocator_type() )                
williamr@2
   353
        { 
williamr@2
   354
            swap( *clone ); 
williamr@2
   355
        }
williamr@2
   356
williamr@2
   357
    public:        
williamr@2
   358
        ~reversible_ptr_container()
williamr@2
   359
        { 
williamr@2
   360
            remove_all();
williamr@2
   361
        }
williamr@2
   362
        
williamr@2
   363
        template< class PtrContainer >
williamr@2
   364
        void operator=( std::auto_ptr<PtrContainer> clone )     
williamr@2
   365
        {
williamr@2
   366
            swap( *clone );
williamr@2
   367
        }
williamr@2
   368
williamr@2
   369
    public:
williamr@2
   370
        
williamr@2
   371
        allocator_type get_allocator() const                   
williamr@2
   372
        {
williamr@2
   373
            return c_.get_allocator(); 
williamr@2
   374
        }
williamr@2
   375
 
williamr@2
   376
    public: // container requirements
williamr@2
   377
        iterator begin()            
williamr@2
   378
            { return iterator( c_.begin() ); }
williamr@2
   379
        const_iterator begin() const      
williamr@2
   380
            { return const_iterator( c_.begin() ); }
williamr@2
   381
        iterator end()              
williamr@2
   382
            { return iterator( c_.end() ); }
williamr@2
   383
        const_iterator end() const        
williamr@2
   384
            { return const_iterator( c_.end() ); }
williamr@2
   385
        
williamr@2
   386
        reverse_iterator rbegin()           
williamr@2
   387
            { return reverse_iterator( this->end() ); } 
williamr@2
   388
        const_reverse_iterator rbegin() const     
williamr@2
   389
            { return const_reverse_iterator( this->end() ); } 
williamr@2
   390
        reverse_iterator rend()             
williamr@2
   391
            { return reverse_iterator( this->begin() ); } 
williamr@2
   392
        const_reverse_iterator rend() const       
williamr@2
   393
            { return const_reverse_iterator( this->begin() ); } 
williamr@2
   394
 
williamr@2
   395
        void swap( reversible_ptr_container& r ) // nothrow
williamr@2
   396
        { 
williamr@2
   397
            c_.swap( r.c_ );
williamr@2
   398
        }
williamr@2
   399
          
williamr@2
   400
        size_type size() const // nothrow
williamr@2
   401
        {
williamr@2
   402
            return c_.size();
williamr@2
   403
        }
williamr@2
   404
williamr@2
   405
        size_type max_size() const // nothrow
williamr@2
   406
        {
williamr@2
   407
            return c_.max_size(); 
williamr@2
   408
        }
williamr@2
   409
        
williamr@2
   410
        bool empty() const // nothrow
williamr@2
   411
        {
williamr@2
   412
            return c_.empty();
williamr@2
   413
        }
williamr@2
   414
williamr@2
   415
    public: // optional container requirements
williamr@2
   416
williamr@2
   417
        bool operator==( const reversible_ptr_container& r ) const // nothrow
williamr@2
   418
        { 
williamr@2
   419
            if( size() != r.size() )
williamr@2
   420
                return false;
williamr@2
   421
            else
williamr@2
   422
                return std::equal( begin(), end(), r.begin() );
williamr@2
   423
        }
williamr@2
   424
williamr@2
   425
        bool operator!=( const reversible_ptr_container& r ) const // nothrow
williamr@2
   426
        {
williamr@2
   427
            return !(*this == r);
williamr@2
   428
        }
williamr@2
   429
        
williamr@2
   430
        bool operator<( const reversible_ptr_container& r ) const // nothrow 
williamr@2
   431
        {
williamr@2
   432
             return std::lexicographical_compare( begin(), end(), r.begin(), r.end() );
williamr@2
   433
        }
williamr@2
   434
williamr@2
   435
        bool operator<=( const reversible_ptr_container& r ) const // nothrow 
williamr@2
   436
        {
williamr@2
   437
            return !(r < *this);
williamr@2
   438
        }
williamr@2
   439
williamr@2
   440
        bool operator>( const reversible_ptr_container& r ) const // nothrow 
williamr@2
   441
        {
williamr@2
   442
            return r < *this;
williamr@2
   443
        }
williamr@2
   444
williamr@2
   445
        bool operator>=( const reversible_ptr_container& r ) const // nothrow 
williamr@2
   446
        {
williamr@2
   447
            return !(*this < r);
williamr@2
   448
        }
williamr@2
   449
williamr@2
   450
    public: // modifiers
williamr@2
   451
williamr@2
   452
        iterator insert( iterator before, Ty_* x )
williamr@2
   453
        {
williamr@2
   454
            enforce_null_policy( x, "Null pointer in 'insert()'" );
williamr@2
   455
williamr@2
   456
            auto_type ptr( x );                            // nothrow
williamr@2
   457
            iterator res( c_.insert( before.base(), x ) ); // strong, commit
williamr@2
   458
            ptr.release();                                 // nothrow
williamr@2
   459
            return res;
williamr@2
   460
        }
williamr@2
   461
williamr@2
   462
        template< class U >
williamr@2
   463
        iterator insert( iterator before, std::auto_ptr<U> x )
williamr@2
   464
        {
williamr@2
   465
            return insert( before, x.release() );
williamr@2
   466
        }
williamr@2
   467
williamr@2
   468
        iterator erase( iterator x ) // nothrow
williamr@2
   469
        {
williamr@2
   470
            BOOST_ASSERT( !empty() );
williamr@2
   471
            BOOST_ASSERT( x != end() );
williamr@2
   472
williamr@2
   473
            remove( x );
williamr@2
   474
            return iterator( c_.erase( x.base() ) );
williamr@2
   475
        }
williamr@2
   476
williamr@2
   477
        iterator erase( iterator first, iterator last ) // nothrow
williamr@2
   478
        {
williamr@2
   479
            //BOOST_ASSERT( !empty() );
williamr@2
   480
            remove( first, last );
williamr@2
   481
            return iterator( c_.erase( first.base(),
williamr@2
   482
                                       last.base() ) );
williamr@2
   483
        }
williamr@2
   484
williamr@2
   485
        template< class Range >
williamr@2
   486
        iterator erase( const Range& r )
williamr@2
   487
        {
williamr@2
   488
            return erase( boost::begin(r), boost::end(r) );
williamr@2
   489
        }
williamr@2
   490
williamr@2
   491
        void clear()
williamr@2
   492
        {
williamr@2
   493
            remove_all();
williamr@2
   494
            c_.clear();
williamr@2
   495
        }
williamr@2
   496
        
williamr@2
   497
    public: // access interface
williamr@2
   498
        
williamr@2
   499
        auto_type release( iterator where )
williamr@2
   500
        { 
williamr@2
   501
            BOOST_ASSERT( where != end() );
williamr@2
   502
            
williamr@2
   503
            BOOST_PTR_CONTAINER_THROW_EXCEPTION( empty(), bad_ptr_container_operation,
williamr@2
   504
                                                 "'release()' on empty container" ); 
williamr@2
   505
            
williamr@2
   506
            auto_type ptr( Config::get_pointer( where ) );  // nothrow
williamr@2
   507
            c_.erase( where.base() );                       // nothrow
williamr@2
   508
            return boost::ptr_container_detail::move( ptr ); 
williamr@2
   509
        }
williamr@2
   510
williamr@2
   511
        auto_type replace( iterator where, Ty_* x ) // strong  
williamr@2
   512
        { 
williamr@2
   513
            BOOST_ASSERT( where != end() );
williamr@2
   514
williamr@2
   515
            enforce_null_policy( x, "Null pointer in 'replace()'" );
williamr@2
   516
            
williamr@2
   517
            auto_type ptr( x );
williamr@2
   518
            
williamr@2
   519
            BOOST_PTR_CONTAINER_THROW_EXCEPTION( empty(), bad_ptr_container_operation,
williamr@2
   520
                                                 "'replace()' on empty container" );
williamr@2
   521
williamr@2
   522
            auto_type old( Config::get_pointer( where ) );  // nothrow
williamr@2
   523
            
williamr@2
   524
//#if defined( __GNUC__ ) || defined( __MWERKS__ ) || defined( __COMO__ )
williamr@2
   525
            const_cast<void*&>(*where.base()) = ptr.release();                
williamr@2
   526
//#else
williamr@2
   527
//            *where.base() = ptr.release(); // nothrow, commit
williamr@2
   528
//#endif            
williamr@2
   529
            return boost::ptr_container_detail::move( old );
williamr@2
   530
        }
williamr@2
   531
williamr@2
   532
        template< class U >
williamr@2
   533
        auto_type replace( iterator where, std::auto_ptr<U> x )
williamr@2
   534
        {
williamr@2
   535
            return replace( where, x.release() ); 
williamr@2
   536
        }
williamr@2
   537
williamr@2
   538
        auto_type replace( size_type idx, Ty_* x ) // strong
williamr@2
   539
        {
williamr@2
   540
            enforce_null_policy( x, "Null pointer in 'replace()'" );
williamr@2
   541
            
williamr@2
   542
            auto_type ptr( x ); 
williamr@2
   543
            
williamr@2
   544
            BOOST_PTR_CONTAINER_THROW_EXCEPTION( idx >= size(), bad_index, 
williamr@2
   545
                                                 "'replace()' out of bounds" );
williamr@2
   546
            
williamr@2
   547
            auto_type old( static_cast<Ty_*>( c_[idx] ) ); // nothrow
williamr@2
   548
            c_[idx] = ptr.release();                       // nothrow, commit
williamr@2
   549
            return boost::ptr_container_detail::move( old );
williamr@2
   550
        } 
williamr@2
   551
williamr@2
   552
        template< class U >
williamr@2
   553
        auto_type replace( size_type idx, std::auto_ptr<U> x )
williamr@2
   554
        {
williamr@2
   555
            return replace( idx, x.release() );
williamr@2
   556
        }
williamr@2
   557
williamr@2
   558
    //
williamr@2
   559
    // serialization
williamr@2
   560
    //
williamr@2
   561
    
williamr@2
   562
    protected:
williamr@2
   563
williamr@2
   564
        template< class Archive >
williamr@2
   565
        void save_helper( Archive& ar ) const
williamr@2
   566
        {
williamr@2
   567
            const_iterator i = this->begin(), e = this->end();
williamr@2
   568
            for( ; i != e; ++i )
williamr@2
   569
                ar & ptr_container_detail::serialize_as_const( 
williamr@2
   570
                                 static_cast<value_type>( *i.base() ) );
williamr@2
   571
        }
williamr@2
   572
williamr@2
   573
    public: 
williamr@2
   574
williamr@2
   575
        template< class Archive >
williamr@2
   576
        void save( Archive& ar, const unsigned ) const
williamr@2
   577
        {
williamr@2
   578
            ar & ptr_container_detail::serialize_as_const( this->size() );
williamr@2
   579
            this->save_helper( ar );
williamr@2
   580
        }
williamr@2
   581
williamr@2
   582
    protected:
williamr@2
   583
williamr@2
   584
        template< class Archive >
williamr@2
   585
        void load_helper( Archive& ar, size_type n )
williamr@2
   586
        {   
williamr@2
   587
            //
williamr@2
   588
            // Called after an appropriate reserve on c.
williamr@2
   589
            //
williamr@2
   590
williamr@2
   591
            this->clear();            
williamr@2
   592
            for( size_type i = 0u; i != n; ++i )
williamr@2
   593
            {
williamr@2
   594
                //
williamr@2
   595
                // Remark: pointers are not tracked,
williamr@2
   596
                // so we need not call ar.reset_object_address(v, u)
williamr@2
   597
                //
williamr@2
   598
                value_type ptr;
williamr@2
   599
                ar & ptr;
williamr@2
   600
                this->insert( this->end(), ptr );
williamr@2
   601
            }
williamr@2
   602
        }
williamr@2
   603
williamr@2
   604
    public:
williamr@2
   605
        
williamr@2
   606
        template< class Archive >
williamr@2
   607
        void load( Archive& ar, const unsigned ) 
williamr@2
   608
        {
williamr@2
   609
            size_type n;
williamr@2
   610
            ar & n;
williamr@2
   611
            this->load_helper( ar, n ); 
williamr@2
   612
        }
williamr@2
   613
        
williamr@2
   614
        BOOST_SERIALIZATION_SPLIT_MEMBER()
williamr@2
   615
        
williamr@2
   616
    }; // 'reversible_ptr_container'
williamr@2
   617
williamr@2
   618
williamr@2
   619
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))    
williamr@2
   620
#define BOOST_PTR_CONTAINER_DEFINE_RELEASE( base_type ) \
williamr@2
   621
    typename base_type::auto_type                   \
williamr@2
   622
    release( typename base_type::iterator i )       \
williamr@2
   623
    {                                               \
williamr@2
   624
        return boost::ptr_container_detail::move(base_type::release(i)); \
williamr@2
   625
    }                                               
williamr@2
   626
#else
williamr@2
   627
#define BOOST_PTR_CONTAINER_DEFINE_RELEASE( base_type ) \
williamr@2
   628
    using base_type::release;
williamr@2
   629
#endif
williamr@2
   630
    
williamr@2
   631
    //
williamr@2
   632
    // two-phase lookup of template functions 
williamr@2
   633
    // is buggy on most compilers, so we use a macro instead
williamr@2
   634
    //
williamr@2
   635
#define BOOST_PTR_CONTAINER_DEFINE_RELEASE_AND_CLONE( PC, base_type, this_type ) \
williamr@2
   636
                                                    \
williamr@2
   637
    PC( std::auto_ptr<this_type> r )                \
williamr@2
   638
    : base_type ( r ) { }                           \
williamr@2
   639
                                                    \
williamr@2
   640
    void operator=( std::auto_ptr<this_type> r )    \
williamr@2
   641
    {                                               \
williamr@2
   642
        base_type::operator=( r );                  \
williamr@2
   643
    }                                               \
williamr@2
   644
                                                    \
williamr@2
   645
    std::auto_ptr<this_type> release()              \
williamr@2
   646
    {                                               \
williamr@2
   647
      std::auto_ptr<this_type> ptr( new this_type );\
williamr@2
   648
      this->swap( *ptr );                           \
williamr@2
   649
      return ptr;                                   \
williamr@2
   650
    }                                               \
williamr@2
   651
    BOOST_PTR_CONTAINER_DEFINE_RELEASE( base_type ) \
williamr@2
   652
                                                    \
williamr@2
   653
    std::auto_ptr<this_type> clone() const          \
williamr@2
   654
    {                                               \
williamr@2
   655
       return std::auto_ptr<this_type>( new this_type( this->begin(), this->end() ) ); \
williamr@2
   656
    }
williamr@2
   657
williamr@2
   658
#define BOOST_PTR_CONTAINER_DEFINE_CONSTRUCTORS( PC, base_type )                       \
williamr@2
   659
    typedef BOOST_DEDUCED_TYPENAME base_type::iterator        iterator;                \
williamr@2
   660
    typedef BOOST_DEDUCED_TYPENAME base_type::size_type       size_type;               \
williamr@2
   661
    typedef BOOST_DEDUCED_TYPENAME base_type::const_reference const_reference;         \
williamr@2
   662
    typedef BOOST_DEDUCED_TYPENAME base_type::allocator_type  allocator_type;          \
williamr@2
   663
    PC( const allocator_type& a = allocator_type() ) : base_type(a) {}                 \
williamr@2
   664
    template< class InputIterator >                                                    \
williamr@2
   665
    PC( InputIterator first, InputIterator last,                                       \
williamr@2
   666
    const allocator_type& a = allocator_type() ) : base_type( first, last, a ) {}      
williamr@2
   667
    
williamr@2
   668
williamr@2
   669
                 
williamr@2
   670
#define BOOST_PTR_CONTAINER_DEFINE_NON_INHERITED_MEMBERS( PC, base_type, this_type )           \
williamr@2
   671
   BOOST_PTR_CONTAINER_DEFINE_CONSTRUCTORS( PC, base_type )                                    \
williamr@2
   672
   BOOST_PTR_CONTAINER_DEFINE_RELEASE_AND_CLONE( PC, base_type, this_type )
williamr@2
   673
    
williamr@2
   674
    } // namespace 'ptr_container_detail'
williamr@2
   675
williamr@2
   676
} // namespace 'boost'  
williamr@2
   677
williamr@2
   678
#endif