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