epoc32/include/stdapis/boost/ptr_container/ptr_sequence_adapter.hpp
author William Roberts <williamr@symbian.org>
Wed, 31 Mar 2010 12:33:34 +0100
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
#ifndef BOOST_ptr_container_PTR_SEQUENCE_ADAPTER_HPP
williamr@2
    15
#define BOOST_ptr_container_PTR_SEQUENCE_ADAPTER_HPP
williamr@2
    16
williamr@2
    17
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
williamr@2
    18
# pragma once
williamr@2
    19
#endif
williamr@2
    20
williamr@2
    21
williamr@2
    22
#include <boost/ptr_container/detail/reversible_ptr_container.hpp>
williamr@2
    23
#include <boost/ptr_container/indirect_fun.hpp>
williamr@2
    24
#include <boost/ptr_container/detail/void_ptr_iterator.hpp>
williamr@2
    25
#include <boost/type_traits/remove_pointer.hpp>
williamr@2
    26
#include <boost/type_traits/is_same.hpp>
williamr@2
    27
#include <boost/type_traits/is_pointer.hpp>
williamr@2
    28
#include <boost/type_traits/is_integral.hpp>
williamr@2
    29
#include <boost/iterator/iterator_categories.hpp>
williamr@2
    30
#ifdef __SYMBIAN32__
williamr@2
    31
#include <boost/range/begin.hpp>
williamr@2
    32
#include <boost/range/end.hpp>
williamr@2
    33
#endif
williamr@2
    34
williamr@2
    35
namespace boost
williamr@2
    36
{   
williamr@2
    37
namespace ptr_container_detail
williamr@2
    38
{
williamr@2
    39
williamr@2
    40
williamr@2
    41
    
williamr@2
    42
    
williamr@2
    43
    template
williamr@2
    44
    < 
williamr@2
    45
        class T, 
williamr@2
    46
        class VoidPtrSeq
williamr@2
    47
    >
williamr@2
    48
    struct sequence_config
williamr@2
    49
    {
williamr@2
    50
        typedef BOOST_DEDUCED_TYPENAME remove_nullable<T>::type
williamr@2
    51
                    U;
williamr@2
    52
        typedef VoidPtrSeq
williamr@2
    53
                    void_container_type;
williamr@2
    54
williamr@2
    55
        typedef BOOST_DEDUCED_TYPENAME VoidPtrSeq::allocator_type
williamr@2
    56
                    allocator_type;
williamr@2
    57
        
williamr@2
    58
        typedef U   value_type;
williamr@2
    59
williamr@2
    60
        typedef void_ptr_iterator<
williamr@2
    61
                        BOOST_DEDUCED_TYPENAME VoidPtrSeq::iterator, U > 
williamr@2
    62
                    iterator;
williamr@2
    63
       
williamr@2
    64
        typedef void_ptr_iterator<
williamr@2
    65
                        BOOST_DEDUCED_TYPENAME VoidPtrSeq::const_iterator, const U >
williamr@2
    66
                    const_iterator;
williamr@2
    67
williamr@2
    68
#ifdef BOOST_NO_SFINAE
williamr@2
    69
williamr@2
    70
        template< class Iter >
williamr@2
    71
        static U* get_pointer( Iter i )
williamr@2
    72
        {
williamr@2
    73
            return static_cast<U*>( *i.base() );
williamr@2
    74
        }
williamr@2
    75
        
williamr@2
    76
#else
williamr@2
    77
        template< class Iter >
williamr@2
    78
        static U* get_pointer( void_ptr_iterator<Iter,U> i )
williamr@2
    79
        {
williamr@2
    80
            return static_cast<U*>( *i.base() );
williamr@2
    81
        }
williamr@2
    82
williamr@2
    83
        template< class Iter >
williamr@2
    84
        static U* get_pointer( Iter i )
williamr@2
    85
        {
williamr@2
    86
            return &*i;
williamr@2
    87
        }
williamr@2
    88
#endif        
williamr@2
    89
williamr@2
    90
#if defined(BOOST_NO_SFINAE) && !BOOST_WORKAROUND(__MWERKS__, <= 0x3003)
williamr@2
    91
williamr@2
    92
        template< class Iter >
williamr@2
    93
        static const U* get_const_pointer( Iter i )
williamr@2
    94
        {
williamr@2
    95
            return static_cast<const U*>( *i.base() );
williamr@2
    96
        }
williamr@2
    97
        
williamr@2
    98
#else // BOOST_NO_SFINAE
williamr@2
    99
williamr@2
   100
#if BOOST_WORKAROUND(__MWERKS__, <= 0x3003)
williamr@2
   101
        template< class Iter >
williamr@2
   102
        static const U* get_const_pointer( void_ptr_iterator<Iter,U> i )
williamr@2
   103
        {
williamr@2
   104
            return static_cast<const U*>( *i.base() );
williamr@2
   105
        }
williamr@2
   106
#else // BOOST_WORKAROUND
williamr@2
   107
        template< class Iter >
williamr@2
   108
        static const U* get_const_pointer( void_ptr_iterator<Iter,const U> i )
williamr@2
   109
        {
williamr@2
   110
            return static_cast<const U*>( *i.base() );
williamr@2
   111
        }
williamr@2
   112
#endif // BOOST_WORKAROUND
williamr@2
   113
williamr@2
   114
        template< class Iter >
williamr@2
   115
        static const U* get_const_pointer( Iter i )
williamr@2
   116
        {
williamr@2
   117
            return &*i;
williamr@2
   118
        }
williamr@2
   119
#endif // BOOST_NO_SFINAE
williamr@2
   120
williamr@2
   121
        BOOST_STATIC_CONSTANT(bool, allow_null = boost::is_nullable<T>::value );
williamr@2
   122
    };
williamr@2
   123
    
williamr@2
   124
} // ptr_container_detail
williamr@2
   125
williamr@2
   126
williamr@2
   127
    template< class Iterator, class T >
williamr@2
   128
    inline bool is_null( void_ptr_iterator<Iterator,T> i )
williamr@2
   129
    {
williamr@2
   130
        return *i.base() == 0;
williamr@2
   131
    }
williamr@2
   132
williamr@2
   133
williamr@2
   134
    
williamr@2
   135
    template
williamr@2
   136
    < 
williamr@2
   137
        class T,
williamr@2
   138
        class VoidPtrSeq, 
williamr@2
   139
        class CloneAllocator = heap_clone_allocator
williamr@2
   140
    >
williamr@2
   141
    class ptr_sequence_adapter : public 
williamr@2
   142
        ptr_container_detail::reversible_ptr_container< ptr_container_detail::sequence_config<T,VoidPtrSeq>, 
williamr@2
   143
                                            CloneAllocator >
williamr@2
   144
    {
williamr@2
   145
        typedef ptr_container_detail::reversible_ptr_container< ptr_container_detail::sequence_config<T,VoidPtrSeq>,
williamr@2
   146
                                                    CloneAllocator >
williamr@2
   147
             base_type;
williamr@2
   148
        
williamr@2
   149
        typedef BOOST_DEDUCED_TYPENAME base_type::scoped_deleter scoped_deleter;
williamr@2
   150
williamr@2
   151
        typedef ptr_sequence_adapter<T,VoidPtrSeq,CloneAllocator>                         
williamr@2
   152
            this_type;
williamr@2
   153
         
williamr@2
   154
    public:
williamr@2
   155
        typedef BOOST_DEDUCED_TYPENAME base_type::value_type  value_type; 
williamr@2
   156
        typedef BOOST_DEDUCED_TYPENAME base_type::reference   reference; 
williamr@2
   157
        typedef BOOST_DEDUCED_TYPENAME base_type::auto_type   auto_type;
williamr@2
   158
         
williamr@2
   159
        BOOST_PTR_CONTAINER_DEFINE_CONSTRUCTORS( ptr_sequence_adapter, 
williamr@2
   160
                                                 base_type )
williamr@2
   161
    
williamr@2
   162
        template< class PtrContainer >
williamr@2
   163
        ptr_sequence_adapter( std::auto_ptr<PtrContainer> clone )
williamr@2
   164
          : base_type( clone )
williamr@2
   165
        { }
williamr@2
   166
williamr@2
   167
        template< class PtrContainer >
williamr@2
   168
        void operator=( std::auto_ptr<PtrContainer> clone )    
williamr@2
   169
        {
williamr@2
   170
            base_type::operator=( clone );
williamr@2
   171
        }
williamr@2
   172
williamr@2
   173
        /////////////////////////////////////////////////////////////
williamr@2
   174
        // modifiers
williamr@2
   175
        /////////////////////////////////////////////////////////////
williamr@2
   176
williamr@2
   177
        void push_back( value_type x )  // strong               
williamr@2
   178
        {
williamr@2
   179
            this->enforce_null_policy( x, "Null pointer in 'push_back()'" );
williamr@2
   180
williamr@2
   181
            auto_type ptr( x );                // notrow
williamr@2
   182
            this->c_private().push_back( x );  // strong, commit
williamr@2
   183
            ptr.release();                     // nothrow
williamr@2
   184
        }
williamr@2
   185
williamr@2
   186
        template< class U >
williamr@2
   187
        void push_back( std::auto_ptr<U> x )
williamr@2
   188
        {
williamr@2
   189
            push_back( x.release() );
williamr@2
   190
        }
williamr@2
   191
        
williamr@2
   192
        void push_front( value_type x )                
williamr@2
   193
        {
williamr@2
   194
            this->enforce_null_policy( x, "Null pointer in 'push_front()'" );
williamr@2
   195
williamr@2
   196
            auto_type ptr( x );                // nothrow
williamr@2
   197
            this->c_private().push_front( x ); // strong, commit
williamr@2
   198
            ptr.release();                     // nothrow
williamr@2
   199
        }
williamr@2
   200
williamr@2
   201
        template< class U >
williamr@2
   202
        void push_front( std::auto_ptr<U> x )
williamr@2
   203
        {
williamr@2
   204
            push_front( x.release() );
williamr@2
   205
        }
williamr@2
   206
williamr@2
   207
        auto_type pop_back()
williamr@2
   208
        {
williamr@2
   209
            BOOST_PTR_CONTAINER_THROW_EXCEPTION( this->empty(), 
williamr@2
   210
                                                 bad_ptr_container_operation,
williamr@2
   211
                                          "'pop_back()' on empty container" );
williamr@2
   212
            auto_type ptr( static_cast<value_type>( 
williamr@2
   213
                         this->c_private().back() ) ); // nothrow
williamr@2
   214
            this->c_private().pop_back();              // nothrow
williamr@2
   215
            return ptr_container_detail::move( ptr );  // nothrow
williamr@2
   216
        }
williamr@2
   217
williamr@2
   218
        auto_type pop_front()
williamr@2
   219
        {
williamr@2
   220
            BOOST_PTR_CONTAINER_THROW_EXCEPTION( this->empty(),
williamr@2
   221
                                                 bad_ptr_container_operation,
williamr@2
   222
                                         "'pop_front()' on empty container" ); 
williamr@2
   223
            auto_type ptr( static_cast<value_type>(
williamr@2
   224
                        this->c_private().front() ) ); // nothrow 
williamr@2
   225
            this->c_private().pop_front();             // nothrow
williamr@2
   226
            return ptr_container_detail::move( ptr ); 
williamr@2
   227
        }
williamr@2
   228
        
williamr@2
   229
        reference front()        
williamr@2
   230
        { 
williamr@2
   231
            BOOST_PTR_CONTAINER_THROW_EXCEPTION( this->empty(), 
williamr@2
   232
                                                 bad_ptr_container_operation,
williamr@2
   233
                                    "accessing 'front()' on empty container" );
williamr@2
   234
            BOOST_ASSERT( !::boost::is_null( this->begin() ) );
williamr@2
   235
            return *this->begin(); 
williamr@2
   236
        }
williamr@2
   237
williamr@2
   238
        const_reference front() const  
williamr@2
   239
        {
williamr@2
   240
            BOOST_PTR_CONTAINER_THROW_EXCEPTION( this->empty(), 
williamr@2
   241
                                                 bad_ptr_container_operation, 
williamr@2
   242
                                   "accessing 'front()' on empty container" );
williamr@2
   243
            BOOST_ASSERT( !::boost::is_null( this->begin() ) );
williamr@2
   244
            return *this->begin(); 
williamr@2
   245
        }
williamr@2
   246
williamr@2
   247
        reference back()
williamr@2
   248
        {
williamr@2
   249
            BOOST_PTR_CONTAINER_THROW_EXCEPTION( this->empty(),
williamr@2
   250
                                                 bad_ptr_container_operation,
williamr@2
   251
                                    "accessing 'back()' on empty container" );
williamr@2
   252
            BOOST_ASSERT( !::boost::is_null( --this->end() ) );
williamr@2
   253
            return *--this->end(); 
williamr@2
   254
        }
williamr@2
   255
williamr@2
   256
        const_reference back() const
williamr@2
   257
        {
williamr@2
   258
            BOOST_PTR_CONTAINER_THROW_EXCEPTION( this->empty(),
williamr@2
   259
                                                 bad_ptr_container_operation,
williamr@2
   260
                                    "accessing 'back()' on empty container" );
williamr@2
   261
            BOOST_ASSERT( !::boost::is_null( --this->end() ) );
williamr@2
   262
            return *--this->end(); 
williamr@2
   263
        }
williamr@2
   264
williamr@2
   265
    public: // deque/vector inerface
williamr@2
   266
        
williamr@2
   267
        reference operator[]( size_type n ) // nothrow 
williamr@2
   268
        {
williamr@2
   269
            BOOST_ASSERT( n < this->size() );
williamr@2
   270
            BOOST_ASSERT( !this->is_null( n ) );
williamr@2
   271
            return *static_cast<value_type>( this->c_private()[n] ); 
williamr@2
   272
        }
williamr@2
   273
        
williamr@2
   274
        const_reference operator[]( size_type n ) const // nothrow  
williamr@2
   275
        { 
williamr@2
   276
            BOOST_ASSERT( n < this->size() ); 
williamr@2
   277
            BOOST_ASSERT( !this->is_null( n ) );
williamr@2
   278
            return *static_cast<value_type>( this->c_private()[n] );
williamr@2
   279
        }
williamr@2
   280
        
williamr@2
   281
        reference at( size_type n )
williamr@2
   282
        {
williamr@2
   283
            BOOST_PTR_CONTAINER_THROW_EXCEPTION( n >= this->size(), bad_index, 
williamr@2
   284
                                                 "'at()' out of bounds" );
williamr@2
   285
            BOOST_ASSERT( !this->is_null( n ) );
williamr@2
   286
            return (*this)[n];
williamr@2
   287
        }
williamr@2
   288
        
williamr@2
   289
        const_reference at( size_type n ) const
williamr@2
   290
        {
williamr@2
   291
            BOOST_PTR_CONTAINER_THROW_EXCEPTION( n >= this->size(), bad_index, 
williamr@2
   292
                                                 "'at()' out of bounds" );
williamr@2
   293
            BOOST_ASSERT( !this->is_null( n ) );
williamr@2
   294
            return (*this)[n]; 
williamr@2
   295
        }
williamr@2
   296
        
williamr@2
   297
    public: // vector interface
williamr@2
   298
        
williamr@2
   299
        size_type capacity() const
williamr@2
   300
        {
williamr@2
   301
            return this->c_private().capacity();
williamr@2
   302
        }
williamr@2
   303
        
williamr@2
   304
        void reserve( size_type n )
williamr@2
   305
        {
williamr@2
   306
            this->c_private().reserve( n ); 
williamr@2
   307
        }
williamr@2
   308
williamr@2
   309
        void reverse()
williamr@2
   310
        {
williamr@2
   311
            this->c_private().reverse(); 
williamr@2
   312
        }
williamr@2
   313
williamr@2
   314
    public: // assign, insert, transfer
williamr@2
   315
williamr@2
   316
        // overhead: 1 heap allocation (very cheap compared to cloning)
williamr@2
   317
        template< class InputIterator >
williamr@2
   318
        void assign( InputIterator first, InputIterator last ) // strong
williamr@2
   319
        { 
williamr@2
   320
            base_type temp( first, last );
williamr@2
   321
            this->swap( temp );
williamr@2
   322
        }
williamr@2
   323
williamr@2
   324
        template< class Range >
williamr@2
   325
        void assign( const Range& r )
williamr@2
   326
        {
williamr@2
   327
            assign( boost::begin(r), boost::end(r ) );
williamr@2
   328
        }
williamr@2
   329
williamr@2
   330
    private:
williamr@2
   331
        template< class I >
williamr@2
   332
        void insert_impl( iterator before, I first, I last, std::input_iterator_tag ) // strong
williamr@2
   333
        {
williamr@2
   334
            ptr_sequence_adapter temp(first,last);  // strong
williamr@2
   335
            transfer( before, temp );               // strong, commit
williamr@2
   336
        }
williamr@2
   337
williamr@2
   338
        template< class I >
williamr@2
   339
        void insert_impl( iterator before, I first, I last, std::forward_iterator_tag ) // strong
williamr@2
   340
        {
williamr@2
   341
            if( first == last ) 
williamr@2
   342
                return;
williamr@2
   343
            scoped_deleter sd( first, last );                // strong
williamr@2
   344
            this->insert_clones_and_release( sd, before );   // strong, commit 
williamr@2
   345
        }
williamr@2
   346
williamr@2
   347
    public:
williamr@2
   348
williamr@2
   349
        using base_type::insert;
williamr@2
   350
        
williamr@2
   351
        template< class InputIterator >
williamr@2
   352
        void insert( iterator before, InputIterator first, InputIterator last ) // strong
williamr@2
   353
        {
williamr@2
   354
            insert_impl( before, first, last, BOOST_DEDUCED_TYPENAME
williamr@2
   355
                         iterator_category<InputIterator>::type() );
williamr@2
   356
        } 
williamr@2
   357
williamr@2
   358
#if defined(BOOST_NO_SFINAE) || BOOST_WORKAROUND(__SUNPRO_CC, <= 0x580)
williamr@2
   359
#else
williamr@2
   360
        template< class Range >
williamr@2
   361
        BOOST_DEDUCED_TYPENAME
williamr@2
   362
        boost::disable_if< ptr_container_detail::is_pointer_or_integral<Range> >::type
williamr@2
   363
        insert( iterator before, const Range& r )
williamr@2
   364
        {
williamr@2
   365
            insert( before, boost::begin(r), boost::end(r) );
williamr@2
   366
        }
williamr@2
   367
williamr@2
   368
#endif
williamr@2
   369
williamr@2
   370
        template< class PtrSeqAdapter >
williamr@2
   371
        void transfer( iterator before, 
williamr@2
   372
                       BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator first, 
williamr@2
   373
                       BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator last, 
williamr@2
   374
                       PtrSeqAdapter& from ) // strong
williamr@2
   375
        {
williamr@2
   376
            BOOST_ASSERT( (void*)&from != (void*)this );
williamr@2
   377
            if( from.empty() )
williamr@2
   378
                return;
williamr@2
   379
            this->c_private().
williamr@2
   380
                insert( before.base(), 
williamr@2
   381
                        first.base(), last.base() ); // strong
williamr@2
   382
            from.c_private().erase( first.base(),
williamr@2
   383
                                    last.base() );   // nothrow
williamr@2
   384
        }
williamr@2
   385
williamr@2
   386
        template< class PtrSeqAdapter >
williamr@2
   387
        void transfer( iterator before, 
williamr@2
   388
                       BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator object, 
williamr@2
   389
                       PtrSeqAdapter& from ) // strong
williamr@2
   390
        {
williamr@2
   391
            BOOST_ASSERT( (void*)&from != (void*)this );
williamr@2
   392
            if( from.empty() )
williamr@2
   393
                return;
williamr@2
   394
            this->c_private().
williamr@2
   395
                insert( before.base(),
williamr@2
   396
                        *object.base() );                 // strong
williamr@2
   397
            from.c_private().erase( object.base() );      // nothrow
williamr@2
   398
        }
williamr@2
   399
williamr@2
   400
#if defined(BOOST_NO_SFINAE) || BOOST_WORKAROUND(__SUNPRO_CC, <= 0x580)
williamr@2
   401
#else
williamr@2
   402
        
williamr@2
   403
        template< class PtrSeqAdapter, class Range >
williamr@2
   404
        BOOST_DEDUCED_TYPENAME boost::disable_if< boost::is_same< Range,
williamr@2
   405
                      BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator > >::type
williamr@2
   406
        transfer( iterator before, const Range& r, PtrSeqAdapter& from ) // strong
williamr@2
   407
        {
williamr@2
   408
            transfer( before, boost::begin(r), boost::end(r), from );
williamr@2
   409
        }
williamr@2
   410
williamr@2
   411
#endif
williamr@2
   412
        template< class PtrSeqAdapter >
williamr@2
   413
        void transfer( iterator before, PtrSeqAdapter& from ) // strong
williamr@2
   414
        {
williamr@2
   415
            BOOST_ASSERT( (void*)&from != (void*)this );
williamr@2
   416
            if( from.empty() )
williamr@2
   417
                return;
williamr@2
   418
            this->c_private().
williamr@2
   419
                insert( before.base(),
williamr@2
   420
                        from.begin().base(), from.end().base() ); // strong
williamr@2
   421
            from.c_private().clear();                             // nothrow
williamr@2
   422
        }
williamr@2
   423
williamr@2
   424
    public: // null functions
williamr@2
   425
         
williamr@2
   426
        bool is_null( size_type idx ) const
williamr@2
   427
        {
williamr@2
   428
            BOOST_ASSERT( idx < this->size() );
williamr@2
   429
            return this->c_private()[idx] == 0;
williamr@2
   430
        }
williamr@2
   431
williamr@2
   432
    public: // algorithms
williamr@2
   433
williamr@2
   434
        void sort( iterator first, iterator last )
williamr@2
   435
        {
williamr@2
   436
            sort( first, last, std::less<T>() );
williamr@2
   437
        }
williamr@2
   438
        
williamr@2
   439
        void sort()
williamr@2
   440
        {
williamr@2
   441
            sort( this->begin(), this->end() );
williamr@2
   442
        }
williamr@2
   443
williamr@2
   444
        template< class Compare >
williamr@2
   445
        void sort( iterator first, iterator last, Compare comp )
williamr@2
   446
        {
williamr@2
   447
            BOOST_ASSERT( first <= last && "out of range sort()" );
williamr@2
   448
            BOOST_ASSERT( this->begin() <= first && "out of range sort()" );
williamr@2
   449
            BOOST_ASSERT( last <= this->end() && "out of range sort()" ); 
williamr@2
   450
            // some static assert on the arguments of the comparison
williamr@2
   451
            std::sort( first.base(), last.base(), 
williamr@2
   452
                       void_ptr_indirect_fun<Compare,T>(comp) );
williamr@2
   453
        }
williamr@2
   454
        
williamr@2
   455
        template< class Compare >
williamr@2
   456
        void sort( Compare comp )
williamr@2
   457
        {
williamr@2
   458
            sort( this->begin(), this->end(), comp );
williamr@2
   459
        }
williamr@2
   460
        
williamr@2
   461
        void unique( iterator first, iterator last )
williamr@2
   462
        {
williamr@2
   463
            unique( first, last, std::equal_to<T>() );
williamr@2
   464
        }
williamr@2
   465
        
williamr@2
   466
        void unique()
williamr@2
   467
        {
williamr@2
   468
            unique( this->begin(), this->end() );
williamr@2
   469
        }
williamr@2
   470
williamr@2
   471
    private:
williamr@2
   472
        struct is_not_zero_ptr
williamr@2
   473
        {
williamr@2
   474
            template< class U >
williamr@2
   475
            bool operator()( const U* r ) const
williamr@2
   476
            {
williamr@2
   477
                return r != 0;
williamr@2
   478
            }
williamr@2
   479
        };
williamr@2
   480
williamr@2
   481
        void compact_and_erase_nulls( iterator first, iterator last ) // nothrow
williamr@2
   482
        {
williamr@2
   483
            
williamr@2
   484
            typename base_type::ptr_iterator p = std::stable_partition( 
williamr@2
   485
                                                    first.base(), 
williamr@2
   486
                                                    last.base(), 
williamr@2
   487
                                                    is_not_zero_ptr() );
williamr@2
   488
            this->c_private().erase( p, this->end().base() );
williamr@2
   489
            
williamr@2
   490
        }
williamr@2
   491
williamr@2
   492
        void range_check_impl( iterator first, iterator last, 
williamr@2
   493
                               std::bidirectional_iterator_tag )
williamr@2
   494
        { /* do nothing */ }
williamr@2
   495
williamr@2
   496
        void range_check_impl( iterator first, iterator last,
williamr@2
   497
                               std::random_access_iterator_tag )
williamr@2
   498
        {
williamr@2
   499
            BOOST_ASSERT( first <= last && "out of range unique()/erase_if()" );
williamr@2
   500
            BOOST_ASSERT( this->begin() <= first && "out of range unique()/erase_if()" );
williamr@2
   501
            BOOST_ASSERT( last <= this->end() && "out of range unique()/erase_if)(" );             
williamr@2
   502
        }
williamr@2
   503
        
williamr@2
   504
        void range_check( iterator first, iterator last )
williamr@2
   505
        {
williamr@2
   506
            range_check_impl( first, last, 
williamr@2
   507
                              BOOST_DEDUCED_TYPENAME iterator_category<iterator>::type() );
williamr@2
   508
        }
williamr@2
   509
        
williamr@2
   510
    public:
williamr@2
   511
        
williamr@2
   512
        template< class Compare >
williamr@2
   513
        void unique( iterator first, iterator last, Compare comp )
williamr@2
   514
        {
williamr@2
   515
            range_check(first,last);
williamr@2
   516
            
williamr@2
   517
            iterator prev = first;
williamr@2
   518
            iterator next = first;
williamr@2
   519
            ++next;
williamr@2
   520
            for( ; next != last; ++next )
williamr@2
   521
            {
williamr@2
   522
                BOOST_ASSERT( !::boost::is_null(prev) );
williamr@2
   523
                BOOST_ASSERT( !::boost::is_null(next) );
williamr@2
   524
                if( comp( *prev, *next ) )
williamr@2
   525
                {
williamr@2
   526
                    this->remove( next ); // delete object
williamr@2
   527
                    *next.base() = 0;     // mark pointer as deleted
williamr@2
   528
                }
williamr@2
   529
                else
williamr@2
   530
                {
williamr@2
   531
                    prev = next;
williamr@2
   532
                }
williamr@2
   533
                // ++next
williamr@2
   534
            }
williamr@2
   535
williamr@2
   536
            compact_and_erase_nulls( first, last );
williamr@2
   537
        }
williamr@2
   538
        
williamr@2
   539
        template< class Compare >
williamr@2
   540
        void unique( Compare comp )
williamr@2
   541
        {
williamr@2
   542
            unique( this->begin(), this->end(), comp );
williamr@2
   543
        }
williamr@2
   544
williamr@2
   545
        template< class Pred >
williamr@2
   546
        void erase_if( iterator first, iterator last, Pred pred )
williamr@2
   547
        {
williamr@2
   548
            range_check(first,last);
williamr@2
   549
williamr@2
   550
            iterator next = first; 
williamr@2
   551
            for( ; next != last; ++next )
williamr@2
   552
            {
williamr@2
   553
                BOOST_ASSERT( !::boost::is_null(next) );
williamr@2
   554
                if( pred( *next ) )
williamr@2
   555
                {
williamr@2
   556
                    this->remove( next ); // delete object
williamr@2
   557
                    *next.base() = 0;     // mark pointer as deleted
williamr@2
   558
                }
williamr@2
   559
            }
williamr@2
   560
williamr@2
   561
            compact_and_erase_nulls( first, last );
williamr@2
   562
        }
williamr@2
   563
        
williamr@2
   564
        template< class Pred >
williamr@2
   565
        void erase_if( Pred pred )
williamr@2
   566
        {
williamr@2
   567
            erase_if( this->begin(), this->end(), pred );
williamr@2
   568
        }
williamr@2
   569
williamr@2
   570
williamr@2
   571
        void merge( iterator first, iterator last, 
williamr@2
   572
                    ptr_sequence_adapter& from )
williamr@2
   573
        {
williamr@2
   574
             merge( first, last, from, std::less<T>() );
williamr@2
   575
        }
williamr@2
   576
        
williamr@2
   577
        template< class BinPred >
williamr@2
   578
        void merge( iterator first, iterator last, 
williamr@2
   579
                    ptr_sequence_adapter& from, BinPred pred )
williamr@2
   580
        {
williamr@2
   581
            void_ptr_indirect_fun<BinPred,T>  bin_pred(pred);
williamr@2
   582
            size_type                         current_size = this->size(); 
williamr@2
   583
            this->transfer( this->end(), first, last, from );
williamr@2
   584
            typename base_type::ptr_iterator middle = this->begin().base();
williamr@2
   585
            std::advance(middle,current_size); 
williamr@2
   586
            std::inplace_merge( this->begin().base(),
williamr@2
   587
                                middle,
williamr@2
   588
                                this->end().base(),
williamr@2
   589
                                bin_pred );
williamr@2
   590
        }
williamr@2
   591
        
williamr@2
   592
        void merge( ptr_sequence_adapter& r )
williamr@2
   593
        {
williamr@2
   594
            merge( r, std::less<T>() );
williamr@2
   595
            BOOST_ASSERT( r.empty() );
williamr@2
   596
        }
williamr@2
   597
        
williamr@2
   598
        template< class BinPred >
williamr@2
   599
        void merge( ptr_sequence_adapter& r, BinPred pred )
williamr@2
   600
        {
williamr@2
   601
            merge( r.begin(), r.end(), r, pred );
williamr@2
   602
            BOOST_ASSERT( r.empty() );    
williamr@2
   603
        }
williamr@2
   604
        
williamr@2
   605
    };
williamr@2
   606
williamr@2
   607
williamr@2
   608
} // namespace 'boost'  
williamr@2
   609
williamr@2
   610
#endif