• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef BOOST_PTR_CONTAINER_PTR_SEQUENCE_ADAPTER_HPP
13 #define BOOST_PTR_CONTAINER_PTR_SEQUENCE_ADAPTER_HPP
14 
15 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
16 # pragma once
17 #endif
18 
19 
20 #include <boost/ptr_container/detail/reversible_ptr_container.hpp>
21 #include <boost/ptr_container/indirect_fun.hpp>
22 #include <boost/ptr_container/detail/void_ptr_iterator.hpp>
23 #include <boost/ptr_container/detail/ptr_container_disable_deprecated.hpp>
24 #include <boost/type_traits/remove_pointer.hpp>
25 #include <boost/type_traits/is_same.hpp>
26 #include <boost/next_prior.hpp>
27 
28 #if defined(BOOST_PTR_CONTAINER_DISABLE_DEPRECATED)
29 #pragma GCC diagnostic push
30 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
31 #endif
32 
33 namespace boost
34 {
35 namespace ptr_container_detail
36 {
37     template
38     <
39         class T,
40         class VoidPtrSeq
41     >
42     struct sequence_config
43     {
44         typedef BOOST_DEDUCED_TYPENAME remove_nullable<T>::type
45                     U;
46         typedef VoidPtrSeq
47                     void_container_type;
48 
49         typedef BOOST_DEDUCED_TYPENAME VoidPtrSeq::allocator_type
50                     allocator_type;
51 
52         typedef U   value_type;
53 
54         typedef void_ptr_iterator<
55                         BOOST_DEDUCED_TYPENAME VoidPtrSeq::iterator, U >
56                     iterator;
57 
58         typedef void_ptr_iterator<
59                         BOOST_DEDUCED_TYPENAME VoidPtrSeq::const_iterator, const U >
60                     const_iterator;
61 
62 #if defined(BOOST_NO_SFINAE) || defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
63 
64         template< class Iter >
get_pointerboost::ptr_container_detail::sequence_config65         static U* get_pointer( Iter i )
66         {
67             return static_cast<U*>( *i.base() );
68         }
69 
70 #else
71         template< class Iter >
get_pointerboost::ptr_container_detail::sequence_config72         static U* get_pointer( void_ptr_iterator<Iter,U> i )
73         {
74             return static_cast<U*>( *i.base() );
75         }
76 
77         template< class Iter >
get_pointerboost::ptr_container_detail::sequence_config78         static U* get_pointer( Iter i )
79         {
80             return &*i;
81         }
82 #endif
83 
84 #if defined(BOOST_NO_SFINAE) && !BOOST_WORKAROUND(__MWERKS__, <= 0x3003)
85 
86         template< class Iter >
get_const_pointerboost::ptr_container_detail::sequence_config87         static const U* get_const_pointer( Iter i )
88         {
89             return static_cast<const U*>( *i.base() );
90         }
91 
92 #else // BOOST_NO_SFINAE
93 
94 #if BOOST_WORKAROUND(__MWERKS__, <= 0x3003)
95         template< class Iter >
get_const_pointerboost::ptr_container_detail::sequence_config96         static const U* get_const_pointer( void_ptr_iterator<Iter,U> i )
97         {
98             return static_cast<const U*>( *i.base() );
99         }
100 #else // BOOST_WORKAROUND
101         template< class Iter >
get_const_pointerboost::ptr_container_detail::sequence_config102         static const U* get_const_pointer( void_ptr_iterator<Iter,const U> i )
103         {
104             return static_cast<const U*>( *i.base() );
105         }
106 #endif // BOOST_WORKAROUND
107 
108         template< class Iter >
get_const_pointerboost::ptr_container_detail::sequence_config109         static const U* get_const_pointer( Iter i )
110         {
111             return &*i;
112         }
113 #endif // BOOST_NO_SFINAE
114 
115         BOOST_STATIC_CONSTANT(bool, allow_null = boost::is_nullable<T>::value );
116     };
117 
118 } // ptr_container_detail
119 
120 
121     template< class Iterator, class T >
is_null(void_ptr_iterator<Iterator,T> i)122     inline bool is_null( void_ptr_iterator<Iterator,T> i )
123     {
124         return *i.base() == 0;
125     }
126 
127 
128 
129     template
130     <
131         class T,
132         class VoidPtrSeq,
133         class CloneAllocator = heap_clone_allocator
134     >
135     class ptr_sequence_adapter : public
136         ptr_container_detail::reversible_ptr_container< ptr_container_detail::sequence_config<T,VoidPtrSeq>,
137                                             CloneAllocator >
138     {
139         typedef ptr_container_detail::reversible_ptr_container< ptr_container_detail::sequence_config<T,VoidPtrSeq>,
140                                                     CloneAllocator >
141              base_type;
142 
143         typedef ptr_sequence_adapter<T,VoidPtrSeq,CloneAllocator>
144             this_type;
145 
146     protected:
147         typedef BOOST_DEDUCED_TYPENAME base_type::scoped_deleter scoped_deleter;
148 
149     public:
150         typedef BOOST_DEDUCED_TYPENAME base_type::value_type  value_type;
151         typedef BOOST_DEDUCED_TYPENAME base_type::reference   reference;
152         typedef BOOST_DEDUCED_TYPENAME base_type::const_reference
153                                                               const_reference;
154         typedef BOOST_DEDUCED_TYPENAME base_type::auto_type   auto_type;
155         typedef BOOST_DEDUCED_TYPENAME base_type::clone_allocator_type
156                                                               clone_allocator_type;
157         typedef BOOST_DEDUCED_TYPENAME base_type::iterator    iterator;
158         typedef BOOST_DEDUCED_TYPENAME base_type::size_type   size_type;
159         typedef BOOST_DEDUCED_TYPENAME base_type::allocator_type
160                                                               allocator_type;
161 
ptr_sequence_adapter()162         ptr_sequence_adapter()
163         { }
164 
165         template< class Allocator >
ptr_sequence_adapter(const Allocator & a)166         explicit ptr_sequence_adapter( const Allocator& a )
167           : base_type( a )
168         { }
169 
170         template< class SizeType >
ptr_sequence_adapter(SizeType n,ptr_container_detail::fixed_length_sequence_tag tag)171         ptr_sequence_adapter( SizeType n,
172                               ptr_container_detail::fixed_length_sequence_tag tag )
173           : base_type( n, tag )
174         { }
175 
176         template< class SizeType, class Allocator >
ptr_sequence_adapter(SizeType n,const Allocator & a,ptr_container_detail::fixed_length_sequence_tag tag)177         ptr_sequence_adapter( SizeType n, const Allocator& a,
178                               ptr_container_detail::fixed_length_sequence_tag tag )
179           : base_type( n, a, tag )
180         { }
181 
182         template< class InputIterator >
ptr_sequence_adapter(InputIterator first,InputIterator last)183         ptr_sequence_adapter( InputIterator first, InputIterator last )
184           : base_type( first, last )
185         { }
186 
187         template< class InputIterator, class Allocator >
ptr_sequence_adapter(InputIterator first,InputIterator last,const Allocator & a)188         ptr_sequence_adapter( InputIterator first, InputIterator last,
189                               const Allocator& a )
190           : base_type( first, last, a )
191         { }
192 
193         template< class ForwardIterator >
ptr_sequence_adapter(ForwardIterator first,ForwardIterator last,ptr_container_detail::fixed_length_sequence_tag tag)194         ptr_sequence_adapter( ForwardIterator first,
195                               ForwardIterator last,
196                               ptr_container_detail::fixed_length_sequence_tag tag )
197           : base_type( first, last,  tag )
198         { }
199 
200         template< class SizeType, class ForwardIterator >
ptr_sequence_adapter(SizeType n,ForwardIterator first,ForwardIterator last,ptr_container_detail::fixed_length_sequence_tag tag)201         ptr_sequence_adapter( SizeType n,
202                               ForwardIterator first,
203                               ForwardIterator last,
204                               ptr_container_detail::fixed_length_sequence_tag tag )
205           : base_type( n, first, last,  tag )
206         { }
207 
ptr_sequence_adapter(const ptr_sequence_adapter & r)208         ptr_sequence_adapter( const ptr_sequence_adapter& r )
209           : base_type( r )
210         { }
211 
212         template< class U >
ptr_sequence_adapter(const ptr_sequence_adapter<U,VoidPtrSeq,CloneAllocator> & r)213         ptr_sequence_adapter( const ptr_sequence_adapter<U,VoidPtrSeq,CloneAllocator>& r )
214           : base_type( r )
215         { }
216 
ptr_sequence_adapter(const ptr_sequence_adapter & r,ptr_container_detail::fixed_length_sequence_tag tag)217         ptr_sequence_adapter( const ptr_sequence_adapter& r,
218                               ptr_container_detail::fixed_length_sequence_tag tag )
219           : base_type( r, tag )
220         { }
221 
222         template< class U >
ptr_sequence_adapter(const ptr_sequence_adapter<U,VoidPtrSeq,CloneAllocator> & r,ptr_container_detail::fixed_length_sequence_tag tag)223         ptr_sequence_adapter( const ptr_sequence_adapter<U,VoidPtrSeq,CloneAllocator>& r,
224                               ptr_container_detail::fixed_length_sequence_tag tag )
225           : base_type( r, tag )
226         { }
227 
228 #ifndef BOOST_NO_AUTO_PTR
229         template< class PtrContainer >
ptr_sequence_adapter(std::auto_ptr<PtrContainer> clone)230         explicit ptr_sequence_adapter( std::auto_ptr<PtrContainer> clone )
231           : base_type( clone )
232         { }
233 #endif
234 #ifndef BOOST_NO_CXX11_SMART_PTR
235         template< class PtrContainer >
ptr_sequence_adapter(std::unique_ptr<PtrContainer> clone)236         explicit ptr_sequence_adapter( std::unique_ptr<PtrContainer> clone )
237           : base_type( std::move( clone ) )
238         { }
239 #endif
240 
operator =(const ptr_sequence_adapter r)241         ptr_sequence_adapter& operator=( const ptr_sequence_adapter r )
242         {
243             this->swap( r );
244             return *this;
245         }
246 
247 #ifndef BOOST_NO_AUTO_PTR
248         template< class PtrContainer >
operator =(std::auto_ptr<PtrContainer> clone)249         ptr_sequence_adapter& operator=( std::auto_ptr<PtrContainer> clone )
250         {
251             base_type::operator=( clone );
252             return *this;
253         }
254 #endif
255 #ifndef BOOST_NO_CXX11_SMART_PTR
256         template< class PtrContainer >
operator =(std::unique_ptr<PtrContainer> clone)257         ptr_sequence_adapter& operator=( std::unique_ptr<PtrContainer> clone )
258         {
259             base_type::operator=( std::move( clone ) );
260             return *this;
261         }
262 #endif
263 
264         /////////////////////////////////////////////////////////////
265         // modifiers
266         /////////////////////////////////////////////////////////////
267 
push_back(value_type x)268         void push_back( value_type x )  // strong
269         {
270             this->enforce_null_policy( x, "Null pointer in 'push_back()'" );
271             auto_type ptr( x, *this );    // notrow
272             this->base().push_back( x );  // strong, commit
273             ptr.release();                // nothrow
274         }
275 
276 #ifndef BOOST_NO_AUTO_PTR
277         template< class U >
push_back(std::auto_ptr<U> x)278         void push_back( std::auto_ptr<U> x )
279         {
280             push_back( x.release() );
281         }
282 #endif
283 #ifndef BOOST_NO_CXX11_SMART_PTR
284         template< class U >
push_back(std::unique_ptr<U> x)285         void push_back( std::unique_ptr<U> x )
286         {
287             push_back( x.release() );
288         }
289 #endif
290 
push_front(value_type x)291         void push_front( value_type x )
292         {
293             this->enforce_null_policy( x, "Null pointer in 'push_front()'" );
294             auto_type ptr( x, *this );    // nothrow
295             this->base().push_front( x ); // strong, commit
296             ptr.release();                // nothrow
297         }
298 
299 #ifndef BOOST_NO_AUTO_PTR
300         template< class U >
push_front(std::auto_ptr<U> x)301         void push_front( std::auto_ptr<U> x )
302         {
303             push_front( x.release() );
304         }
305 #endif
306 #ifndef BOOST_NO_CXX11_SMART_PTR
307         template< class U >
push_front(std::unique_ptr<U> x)308         void push_front( std::unique_ptr<U> x )
309         {
310             push_front( x.release() );
311         }
312 #endif
313 
pop_back()314         auto_type pop_back()
315         {
316             BOOST_ASSERT( !this->empty() &&
317                           "'pop_back()' on empty container" );
318             auto_type ptr( static_cast<value_type>(this->base().back()), *this );
319                                                        // nothrow
320             this->base().pop_back();                   // nothrow
321             return ptr_container_detail::move( ptr );  // nothrow
322         }
323 
pop_front()324         auto_type pop_front()
325         {
326             BOOST_ASSERT( !this->empty() &&
327                           "'pop_front()' on empty container" );
328             auto_type ptr( static_cast<value_type>(this->base().front()), *this );
329                                          // nothrow
330             this->base().pop_front();    // nothrow
331             return ptr_container_detail::move( ptr );
332         }
333 
front()334         reference front()
335         {
336             BOOST_ASSERT( !this->empty() &&
337                           "accessing 'front()' on empty container" );
338 
339             BOOST_ASSERT( !::boost::is_null( this->begin() ) );
340             return *this->begin();
341         }
342 
front() const343         const_reference front() const
344         {
345             return const_cast<ptr_sequence_adapter*>(this)->front();
346         }
347 
back()348         reference back()
349         {
350             BOOST_ASSERT( !this->empty() &&
351                           "accessing 'back()' on empty container" );
352             BOOST_ASSERT( !::boost::is_null( --this->end() ) );
353             return *--this->end();
354         }
355 
back() const356         const_reference back() const
357         {
358             return const_cast<ptr_sequence_adapter*>(this)->back();
359         }
360 
361     public: // deque/vector inerface
362 
operator [](size_type n)363         reference operator[]( size_type n ) // nothrow
364         {
365             BOOST_ASSERT( n < this->size() );
366             BOOST_ASSERT( !this->is_null( n ) );
367             return *static_cast<value_type>( this->base()[n] );
368         }
369 
operator [](size_type n) const370         const_reference operator[]( size_type n ) const // nothrow
371         {
372             BOOST_ASSERT( n < this->size() );
373             BOOST_ASSERT( !this->is_null( n ) );
374             return *static_cast<value_type>( this->base()[n] );
375         }
376 
at(size_type n)377         reference at( size_type n )
378         {
379             BOOST_PTR_CONTAINER_THROW_EXCEPTION( n >= this->size(), bad_index,
380                                                  "'at()' out of bounds" );
381             BOOST_ASSERT( !this->is_null( n ) );
382             return (*this)[n];
383         }
384 
at(size_type n) const385         const_reference at( size_type n ) const
386         {
387             BOOST_PTR_CONTAINER_THROW_EXCEPTION( n >= this->size(), bad_index,
388                                                  "'at()' out of bounds" );
389             BOOST_ASSERT( !this->is_null( n ) );
390             return (*this)[n];
391         }
392 
393     public: // vector interface
394 
capacity() const395         size_type capacity() const
396         {
397             return this->base().capacity();
398         }
399 
reserve(size_type n)400         void reserve( size_type n )
401         {
402             this->base().reserve( n );
403         }
404 
reverse()405         void reverse()
406         {
407             this->base().reverse();
408         }
409 
410     public: // assign, insert, transfer
411 
412         // overhead: 1 heap allocation (very cheap compared to cloning)
413         template< class InputIterator >
assign(InputIterator first,InputIterator last)414         void assign( InputIterator first, InputIterator last ) // strong
415         {
416             base_type temp( first, last );
417             this->swap( temp );
418         }
419 
420         template< class Range >
assign(const Range & r)421         void assign( const Range& r ) // strong
422         {
423             assign( boost::begin(r), boost::end(r ) );
424         }
425 
426     private:
427         template< class I >
insert_impl(iterator before,I first,I last,std::input_iterator_tag)428         void insert_impl( iterator before, I first, I last, std::input_iterator_tag ) // strong
429         {
430             ptr_sequence_adapter temp(first,last);  // strong
431             transfer( before, temp );               // strong, commit
432         }
433 
434         template< class I >
insert_impl(iterator before,I first,I last,std::forward_iterator_tag)435         void insert_impl( iterator before, I first, I last, std::forward_iterator_tag ) // strong
436         {
437             if( first == last )
438                 return;
439             scoped_deleter sd( *this, first, last );         // strong
440             this->insert_clones_and_release( sd, before );   // strong, commit
441         }
442 
443     public:
444 
445         using base_type::insert;
446 
447         template< class InputIterator >
insert(iterator before,InputIterator first,InputIterator last)448         void insert( iterator before, InputIterator first, InputIterator last ) // strong
449         {
450             insert_impl( before, first, last, BOOST_DEDUCED_TYPENAME
451                          iterator_category<InputIterator>::type() );
452         }
453 
454 #if defined(BOOST_NO_SFINAE) || defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
455 #else
456         template< class Range >
457         BOOST_DEDUCED_TYPENAME
458         boost::disable_if< ptr_container_detail::is_pointer_or_integral<Range> >::type
insert(iterator before,const Range & r)459         insert( iterator before, const Range& r )
460         {
461             insert( before, boost::begin(r), boost::end(r) );
462         }
463 
464 #endif
465 
466         template< class PtrSeqAdapter >
transfer(iterator before,BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator first,BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator last,PtrSeqAdapter & from)467         void transfer( iterator before,
468                        BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator first,
469                        BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator last,
470                        PtrSeqAdapter& from ) // strong
471         {
472             BOOST_ASSERT( (void*)&from != (void*)this );
473             if( from.empty() )
474                 return;
475             this->base().
476                 insert( before.base(), first.base(), last.base() ); // strong
477             from.base().erase( first.base(), last.base() );         // nothrow
478         }
479 
480         template< class PtrSeqAdapter >
transfer(iterator before,BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator object,PtrSeqAdapter & from)481         void transfer( iterator before,
482                        BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator object,
483                        PtrSeqAdapter& from ) // strong
484         {
485             BOOST_ASSERT( (void*)&from != (void*)this );
486             if( from.empty() )
487                 return;
488             this->base().insert( before.base(), *object.base() ); // strong
489             from.base().erase( object.base() );                  // nothrow
490         }
491 
492 #if defined(BOOST_NO_SFINAE) || defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
493 #else
494 
495         template< class PtrSeqAdapter, class Range >
496         BOOST_DEDUCED_TYPENAME boost::disable_if< boost::is_same< Range,
497                       BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator > >::type
transfer(iterator before,const Range & r,PtrSeqAdapter & from)498         transfer( iterator before, const Range& r, PtrSeqAdapter& from ) // strong
499         {
500             transfer( before, boost::begin(r), boost::end(r), from );
501         }
502 
503 #endif
504         template< class PtrSeqAdapter >
transfer(iterator before,PtrSeqAdapter & from)505         void transfer( iterator before, PtrSeqAdapter& from ) // strong
506         {
507             BOOST_ASSERT( (void*)&from != (void*)this );
508             if( from.empty() )
509                 return;
510             this->base().
511                 insert( before.base(),
512                         from.begin().base(), from.end().base() ); // strong
513             from.base().clear();                                  // nothrow
514         }
515 
516     public: // C-array support
517 
transfer(iterator before,value_type * from,size_type size,bool delete_from=true)518         void transfer( iterator before, value_type* from,
519                        size_type size, bool delete_from = true ) // strong
520         {
521             BOOST_ASSERT( from != 0 );
522             if( delete_from )
523             {
524                 BOOST_DEDUCED_TYPENAME base_type::scoped_deleter
525                     deleter( *this, from, size );                         // nothrow
526                 this->base().insert( before.base(), from, from + size );  // strong
527                 deleter.release();                                        // nothrow
528             }
529             else
530             {
531                 this->base().insert( before.base(), from, from + size ); // strong
532             }
533         }
534 
c_array()535         value_type* c_array() // nothrow
536         {
537             if( this->empty() )
538                 return 0;
539             T** res = reinterpret_cast<T**>( &this->begin().base()[0] );
540             return res;
541         }
542 
543     public: // null functions
544 
is_null(size_type idx) const545         bool is_null( size_type idx ) const
546         {
547             BOOST_ASSERT( idx < this->size() );
548             return this->base()[idx] == 0;
549         }
550 
551     public: // resize
552 
resize(size_type size)553         void resize( size_type size ) // basic
554         {
555             size_type old_size = this->size();
556             if( old_size > size )
557             {
558                 this->erase( boost::next( this->begin(), size ), this->end() );
559             }
560             else if( size > old_size )
561             {
562                 for( ; old_size != size; ++old_size )
563                     this->push_back( new BOOST_DEDUCED_TYPENAME
564                                      boost::remove_pointer<value_type>::type() );
565             }
566 
567             BOOST_ASSERT( this->size() == size );
568         }
569 
resize(size_type size,value_type to_clone)570         void resize( size_type size, value_type to_clone ) // basic
571         {
572             size_type old_size = this->size();
573             if( old_size > size )
574             {
575                 this->erase( boost::next( this->begin(), size ), this->end() );
576             }
577             else if( size > old_size )
578             {
579                 for( ; old_size != size; ++old_size )
580                     this->push_back( this->null_policy_allocate_clone( to_clone ) );
581             }
582 
583             BOOST_ASSERT( this->size() == size );
584         }
585 
rresize(size_type size)586         void rresize( size_type size ) // basic
587         {
588             size_type old_size = this->size();
589             if( old_size > size )
590             {
591                 this->erase( this->begin(),
592                              boost::next( this->begin(), old_size - size ) );
593             }
594             else if( size > old_size )
595             {
596                 for( ; old_size != size; ++old_size )
597                     this->push_front( new BOOST_DEDUCED_TYPENAME
598                                       boost::remove_pointer<value_type>::type() );
599             }
600 
601             BOOST_ASSERT( this->size() == size );
602         }
603 
rresize(size_type size,value_type to_clone)604         void rresize( size_type size, value_type to_clone ) // basic
605         {
606             size_type old_size = this->size();
607             if( old_size > size )
608             {
609                 this->erase( this->begin(),
610                              boost::next( this->begin(), old_size - size ) );
611             }
612             else if( size > old_size )
613             {
614                 for( ; old_size != size; ++old_size )
615                     this->push_front( this->null_policy_allocate_clone( to_clone ) );
616             }
617 
618             BOOST_ASSERT( this->size() == size );
619         }
620 
621     public: // algorithms
622 
sort(iterator first,iterator last)623         void sort( iterator first, iterator last )
624         {
625             sort( first, last, std::less<T>() );
626         }
627 
sort()628         void sort()
629         {
630             sort( this->begin(), this->end() );
631         }
632 
633         template< class Compare >
sort(iterator first,iterator last,Compare comp)634         void sort( iterator first, iterator last, Compare comp )
635         {
636             BOOST_ASSERT( first <= last && "out of range sort()" );
637             BOOST_ASSERT( this->begin() <= first && "out of range sort()" );
638             BOOST_ASSERT( last <= this->end() && "out of range sort()" );
639             // some static assert on the arguments of the comparison
640             std::sort( first.base(), last.base(),
641                        void_ptr_indirect_fun<Compare,T>(comp) );
642         }
643 
644         template< class Compare >
sort(Compare comp)645         void sort( Compare comp )
646         {
647             sort( this->begin(), this->end(), comp );
648         }
649 
unique(iterator first,iterator last)650         void unique( iterator first, iterator last )
651         {
652             unique( first, last, std::equal_to<T>() );
653         }
654 
unique()655         void unique()
656         {
657             unique( this->begin(), this->end() );
658         }
659 
660     private:
661         struct is_not_zero_ptr
662         {
663             template< class U >
operator ()boost::ptr_sequence_adapter::is_not_zero_ptr664             bool operator()( const U* r ) const
665             {
666                 return r != 0;
667             }
668         };
669 
670     protected:
671         template< class Fun, class Arg1 >
672         class void_ptr_delete_if
673         {
674             Fun fun;
675         public:
676 
void_ptr_delete_if()677             void_ptr_delete_if() : fun(Fun())
678             { }
679 
void_ptr_delete_if(Fun f)680             void_ptr_delete_if( Fun f ) : fun(f)
681             { }
682 
operator ()(void * r) const683             bool operator()( void* r ) const
684             {
685                BOOST_ASSERT( r != 0 );
686                Arg1 arg1 = static_cast<Arg1>(r);
687                if( fun( *arg1 ) )
688                {
689                    clone_allocator_type::deallocate_clone( arg1 );
690                    return true;
691                }
692                return false;
693             }
694         };
695 
696     private:
compact_and_erase_nulls(iterator first,iterator last)697         void compact_and_erase_nulls( iterator first, iterator last ) // nothrow
698         {
699             typename base_type::ptr_iterator p = std::stable_partition(
700                                                     first.base(),
701                                                     last.base(),
702                                                     is_not_zero_ptr() );
703             this->base().erase( p, this->end().base() );
704 
705         }
706 
range_check_impl(iterator,iterator,std::bidirectional_iterator_tag)707         void range_check_impl( iterator, iterator,
708                                std::bidirectional_iterator_tag )
709         { /* do nothing */ }
710 
range_check_impl(iterator first,iterator last,std::random_access_iterator_tag)711         void range_check_impl( iterator first, iterator last,
712                                std::random_access_iterator_tag )
713         {
714             BOOST_ASSERT( first <= last && "out of range unique()/erase_if()" );
715             BOOST_ASSERT( this->begin() <= first && "out of range unique()/erase_if()" );
716             BOOST_ASSERT( last <= this->end() && "out of range unique()/erase_if)(" );
717         }
718 
range_check(iterator first,iterator last)719         void range_check( iterator first, iterator last )
720         {
721             range_check_impl( first, last,
722                               BOOST_DEDUCED_TYPENAME iterator_category<iterator>::type() );
723         }
724 
725     public:
726 
727         template< class Compare >
unique(iterator first,iterator last,Compare comp)728         void unique( iterator first, iterator last, Compare comp )
729         {
730             range_check(first,last);
731 
732             iterator prev = first;
733             iterator next = first;
734             ++next;
735             for( ; next != last; ++next )
736             {
737                 BOOST_ASSERT( !::boost::is_null(prev) );
738                 BOOST_ASSERT( !::boost::is_null(next) );
739                 if( comp( *prev, *next ) )
740                 {
741                     this->remove( next ); // delete object
742                     *next.base() = 0;     // mark pointer as deleted
743                 }
744                 else
745                 {
746                     prev = next;
747                 }
748                 // ++next
749             }
750 
751             compact_and_erase_nulls( first, last );
752         }
753 
754         template< class Compare >
unique(Compare comp)755         void unique( Compare comp )
756         {
757             unique( this->begin(), this->end(), comp );
758         }
759 
760         template< class Pred >
erase_if(iterator first,iterator last,Pred pred)761         void erase_if( iterator first, iterator last, Pred pred )
762         {
763             range_check(first,last);
764             this->base().erase( std::remove_if( first.base(), last.base(),
765                                                 void_ptr_delete_if<Pred,value_type>(pred) ),
766                                 last.base() );
767         }
768 
769         template< class Pred >
erase_if(Pred pred)770         void erase_if( Pred pred )
771         {
772             erase_if( this->begin(), this->end(), pred );
773         }
774 
775 
merge(iterator first,iterator last,ptr_sequence_adapter & from)776         void merge( iterator first, iterator last,
777                     ptr_sequence_adapter& from )
778         {
779              merge( first, last, from, std::less<T>() );
780         }
781 
782         template< class BinPred >
merge(iterator first,iterator last,ptr_sequence_adapter & from,BinPred pred)783         void merge( iterator first, iterator last,
784                     ptr_sequence_adapter& from, BinPred pred )
785         {
786             void_ptr_indirect_fun<BinPred,T>  bin_pred(pred);
787             size_type                         current_size = this->size();
788             this->transfer( this->end(), first, last, from );
789             typename base_type::ptr_iterator middle = this->begin().base();
790             std::advance(middle,current_size);
791             std::inplace_merge( this->begin().base(),
792                                 middle,
793                                 this->end().base(),
794                                 bin_pred );
795         }
796 
merge(ptr_sequence_adapter & r)797         void merge( ptr_sequence_adapter& r )
798         {
799             merge( r, std::less<T>() );
800             BOOST_ASSERT( r.empty() );
801         }
802 
803         template< class BinPred >
merge(ptr_sequence_adapter & r,BinPred pred)804         void merge( ptr_sequence_adapter& r, BinPred pred )
805         {
806             merge( r.begin(), r.end(), r, pred );
807             BOOST_ASSERT( r.empty() );
808         }
809 
810     };
811 
812 
813 } // namespace 'boost'
814 
815 #if defined(BOOST_PTR_CONTAINER_DISABLE_DEPRECATED)
816 #pragma GCC diagnostic pop
817 #endif
818 
819 #endif
820