2 // Boost.Pointer Container
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)
9 // For more information, see http://www.boost.org/libs/ptr_container/
12 #ifndef BOOST_PTR_CONTAINER_PTR_SEQUENCE_ADAPTER_HPP
13 #define BOOST_PTR_CONTAINER_PTR_SEQUENCE_ADAPTER_HPP
15 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
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/type_traits/remove_pointer.hpp>
24 #include <boost/type_traits/is_same.hpp>
29 namespace ptr_container_detail
36 struct sequence_config
38 typedef BOOST_DEDUCED_TYPENAME remove_nullable
<T
>::type
43 typedef BOOST_DEDUCED_TYPENAME
VoidPtrSeq::allocator_type
48 typedef void_ptr_iterator
<
49 BOOST_DEDUCED_TYPENAME
VoidPtrSeq::iterator
, U
>
52 typedef void_ptr_iterator
<
53 BOOST_DEDUCED_TYPENAME
VoidPtrSeq::const_iterator
, const U
>
56 #if defined(BOOST_NO_SFINAE) || defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
58 template< class Iter
>
59 static U
* get_pointer( Iter i
)
61 return static_cast<U
*>( *i
.base() );
65 template< class Iter
>
66 static U
* get_pointer( void_ptr_iterator
<Iter
,U
> i
)
68 return static_cast<U
*>( *i
.base() );
71 template< class Iter
>
72 static U
* get_pointer( Iter i
)
78 #if defined(BOOST_NO_SFINAE) && !BOOST_WORKAROUND(__MWERKS__, <= 0x3003)
80 template< class Iter
>
81 static const U
* get_const_pointer( Iter i
)
83 return static_cast<const U
*>( *i
.base() );
86 #else // BOOST_NO_SFINAE
88 #if BOOST_WORKAROUND(__MWERKS__, <= 0x3003)
89 template< class Iter
>
90 static const U
* get_const_pointer( void_ptr_iterator
<Iter
,U
> i
)
92 return static_cast<const U
*>( *i
.base() );
94 #else // BOOST_WORKAROUND
95 template< class Iter
>
96 static const U
* get_const_pointer( void_ptr_iterator
<Iter
,const U
> i
)
98 return static_cast<const U
*>( *i
.base() );
100 #endif // BOOST_WORKAROUND
102 template< class Iter
>
103 static const U
* get_const_pointer( Iter i
)
107 #endif // BOOST_NO_SFINAE
109 BOOST_STATIC_CONSTANT(bool, allow_null
= boost::is_nullable
<T
>::value
);
112 } // ptr_container_detail
115 template< class Iterator
, class T
>
116 inline bool is_null( void_ptr_iterator
<Iterator
,T
> i
)
118 return *i
.base() == 0;
127 class CloneAllocator
= heap_clone_allocator
129 class ptr_sequence_adapter
: public
130 ptr_container_detail::reversible_ptr_container
< ptr_container_detail::sequence_config
<T
,VoidPtrSeq
>,
133 typedef ptr_container_detail::reversible_ptr_container
< ptr_container_detail::sequence_config
<T
,VoidPtrSeq
>,
137 typedef ptr_sequence_adapter
<T
,VoidPtrSeq
,CloneAllocator
>
141 typedef BOOST_DEDUCED_TYPENAME
base_type::scoped_deleter scoped_deleter
;
144 typedef BOOST_DEDUCED_TYPENAME
base_type::value_type value_type
;
145 typedef BOOST_DEDUCED_TYPENAME
base_type::reference reference
;
146 typedef BOOST_DEDUCED_TYPENAME
base_type::const_reference
148 typedef BOOST_DEDUCED_TYPENAME
base_type::auto_type auto_type
;
149 typedef BOOST_DEDUCED_TYPENAME
base_type::clone_allocator_type
150 clone_allocator_type
;
151 typedef BOOST_DEDUCED_TYPENAME
base_type::iterator iterator
;
152 typedef BOOST_DEDUCED_TYPENAME
base_type::size_type size_type
;
153 typedef BOOST_DEDUCED_TYPENAME
base_type::allocator_type
156 ptr_sequence_adapter()
159 template< class Allocator
>
160 explicit ptr_sequence_adapter( const Allocator
& a
)
164 template< class SizeType
>
165 ptr_sequence_adapter( SizeType n
,
166 ptr_container_detail::fixed_length_sequence_tag tag
)
167 : base_type( n
, tag
)
170 template< class SizeType
, class Allocator
>
171 ptr_sequence_adapter( SizeType n
, const Allocator
& a
,
172 ptr_container_detail::fixed_length_sequence_tag tag
)
173 : base_type( n
, a
, tag
)
176 template< class InputIterator
>
177 ptr_sequence_adapter( InputIterator first
, InputIterator last
)
178 : base_type( first
, last
)
181 template< class InputIterator
, class Allocator
>
182 ptr_sequence_adapter( InputIterator first
, InputIterator last
,
184 : base_type( first
, last
, a
)
187 template< class ForwardIterator
>
188 ptr_sequence_adapter( ForwardIterator first
,
189 ForwardIterator last
,
190 ptr_container_detail::fixed_length_sequence_tag tag
)
191 : base_type( first
, last
, tag
)
194 template< class SizeType
, class ForwardIterator
>
195 ptr_sequence_adapter( SizeType n
,
196 ForwardIterator first
,
197 ForwardIterator last
,
198 ptr_container_detail::fixed_length_sequence_tag tag
)
199 : base_type( n
, first
, last
, tag
)
202 ptr_sequence_adapter( const ptr_sequence_adapter
& r
)
207 ptr_sequence_adapter( const ptr_sequence_adapter
<U
,VoidPtrSeq
,CloneAllocator
>& r
)
211 ptr_sequence_adapter( const ptr_sequence_adapter
& r
,
212 ptr_container_detail::fixed_length_sequence_tag tag
)
213 : base_type( r
, tag
)
217 ptr_sequence_adapter( const ptr_sequence_adapter
<U
,VoidPtrSeq
,CloneAllocator
>& r
,
218 ptr_container_detail::fixed_length_sequence_tag tag
)
219 : base_type( r
, tag
)
222 template< class PtrContainer
>
223 explicit ptr_sequence_adapter( std::auto_ptr
<PtrContainer
> clone
)
227 ptr_sequence_adapter
& operator=( const ptr_sequence_adapter r
)
233 template< class PtrContainer
>
234 ptr_sequence_adapter
& operator=( std::auto_ptr
<PtrContainer
> clone
)
236 base_type::operator=( clone
);
240 /////////////////////////////////////////////////////////////
242 /////////////////////////////////////////////////////////////
244 void push_back( value_type x
) // strong
246 this->enforce_null_policy( x
, "Null pointer in 'push_back()'" );
248 auto_type
ptr( x
); // notrow
249 this->base().push_back( x
); // strong, commit
250 ptr
.release(); // nothrow
254 void push_back( std::auto_ptr
<U
> x
)
256 push_back( x
.release() );
259 void push_front( value_type x
)
261 this->enforce_null_policy( x
, "Null pointer in 'push_front()'" );
263 auto_type
ptr( x
); // nothrow
264 this->base().push_front( x
); // strong, commit
265 ptr
.release(); // nothrow
269 void push_front( std::auto_ptr
<U
> x
)
271 push_front( x
.release() );
276 BOOST_ASSERT( !this->empty() &&
277 "'pop_back()' on empty container" );
278 auto_type
ptr( static_cast<value_type
>( this->base().back() ) );
280 this->base().pop_back(); // nothrow
281 return ptr_container_detail::move( ptr
); // nothrow
284 auto_type
pop_front()
286 BOOST_ASSERT( !this->empty() &&
287 "'pop_front()' on empty container" );
288 auto_type
ptr( static_cast<value_type
>( this->base().front() ) );
290 this->base().pop_front(); // nothrow
291 return ptr_container_detail::move( ptr
);
296 BOOST_ASSERT( !this->empty() &&
297 "accessing 'front()' on empty container" );
299 BOOST_ASSERT( !::boost::is_null( this->begin() ) );
300 return *this->begin();
303 const_reference
front() const
305 return const_cast<ptr_sequence_adapter
*>(this)->front();
310 BOOST_ASSERT( !this->empty() &&
311 "accessing 'back()' on empty container" );
312 BOOST_ASSERT( !::boost::is_null( --this->end() ) );
313 return *--this->end();
316 const_reference
back() const
318 return const_cast<ptr_sequence_adapter
*>(this)->back();
321 public: // deque/vector inerface
323 reference
operator[]( size_type n
) // nothrow
325 BOOST_ASSERT( n
< this->size() );
326 BOOST_ASSERT( !this->is_null( n
) );
327 return *static_cast<value_type
>( this->base()[n
] );
330 const_reference
operator[]( size_type n
) const // nothrow
332 BOOST_ASSERT( n
< this->size() );
333 BOOST_ASSERT( !this->is_null( n
) );
334 return *static_cast<value_type
>( this->base()[n
] );
337 reference
at( size_type n
)
339 BOOST_PTR_CONTAINER_THROW_EXCEPTION( n
>= this->size(), bad_index
,
340 "'at()' out of bounds" );
341 BOOST_ASSERT( !this->is_null( n
) );
345 const_reference
at( size_type n
) const
347 BOOST_PTR_CONTAINER_THROW_EXCEPTION( n
>= this->size(), bad_index
,
348 "'at()' out of bounds" );
349 BOOST_ASSERT( !this->is_null( n
) );
353 public: // vector interface
355 size_type
capacity() const
357 return this->base().capacity();
360 void reserve( size_type n
)
362 this->base().reserve( n
);
367 this->base().reverse();
370 public: // assign, insert, transfer
372 // overhead: 1 heap allocation (very cheap compared to cloning)
373 template< class InputIterator
>
374 void assign( InputIterator first
, InputIterator last
) // strong
376 base_type
temp( first
, last
);
380 template< class Range
>
381 void assign( const Range
& r
) // strong
383 assign( boost::begin(r
), boost::end(r
) );
388 void insert_impl( iterator before
, I first
, I last
, std::input_iterator_tag
) // strong
390 ptr_sequence_adapter
temp(first
,last
); // strong
391 transfer( before
, temp
); // strong, commit
395 void insert_impl( iterator before
, I first
, I last
, std::forward_iterator_tag
) // strong
399 scoped_deleter
sd( first
, last
); // strong
400 this->insert_clones_and_release( sd
, before
); // strong, commit
405 using base_type::insert
;
407 template< class InputIterator
>
408 void insert( iterator before
, InputIterator first
, InputIterator last
) // strong
410 insert_impl( before
, first
, last
, BOOST_DEDUCED_TYPENAME
411 iterator_category
<InputIterator
>::type() );
414 #if defined(BOOST_NO_SFINAE) || defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
416 template< class Range
>
417 BOOST_DEDUCED_TYPENAME
418 boost::disable_if
< ptr_container_detail::is_pointer_or_integral
<Range
> >::type
419 insert( iterator before
, const Range
& r
)
421 insert( before
, boost::begin(r
), boost::end(r
) );
426 template< class PtrSeqAdapter
>
427 void transfer( iterator before
,
428 BOOST_DEDUCED_TYPENAME
PtrSeqAdapter::iterator first
,
429 BOOST_DEDUCED_TYPENAME
PtrSeqAdapter::iterator last
,
430 PtrSeqAdapter
& from
) // strong
432 BOOST_ASSERT( (void*)&from
!= (void*)this );
436 insert( before
.base(), first
.base(), last
.base() ); // strong
437 from
.base().erase( first
.base(), last
.base() ); // nothrow
440 template< class PtrSeqAdapter
>
441 void transfer( iterator before
,
442 BOOST_DEDUCED_TYPENAME
PtrSeqAdapter::iterator object
,
443 PtrSeqAdapter
& from
) // strong
445 BOOST_ASSERT( (void*)&from
!= (void*)this );
448 this->base().insert( before
.base(), *object
.base() ); // strong
449 from
.base().erase( object
.base() ); // nothrow
452 #if defined(BOOST_NO_SFINAE) || defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
455 template< class PtrSeqAdapter
, class Range
>
456 BOOST_DEDUCED_TYPENAME
boost::disable_if
< boost::is_same
< Range
,
457 BOOST_DEDUCED_TYPENAME
PtrSeqAdapter::iterator
> >::type
458 transfer( iterator before
, const Range
& r
, PtrSeqAdapter
& from
) // strong
460 transfer( before
, boost::begin(r
), boost::end(r
), from
);
464 template< class PtrSeqAdapter
>
465 void transfer( iterator before
, PtrSeqAdapter
& from
) // strong
467 BOOST_ASSERT( (void*)&from
!= (void*)this );
471 insert( before
.base(),
472 from
.begin().base(), from
.end().base() ); // strong
473 from
.base().clear(); // nothrow
476 public: // C-array support
478 void transfer( iterator before
, value_type
* from
,
479 size_type size
, bool delete_from
= true ) // strong
481 BOOST_ASSERT( from
!= 0 );
484 BOOST_DEDUCED_TYPENAME
base_type::scoped_deleter
485 deleter( from
, size
); // nothrow
486 this->base().insert( before
.base(), from
, from
+ size
); // strong
487 deleter
.release(); // nothrow
491 this->base().insert( before
.base(), from
, from
+ size
); // strong
495 value_type
* c_array() // nothrow
499 T
** res
= reinterpret_cast<T
**>( &this->begin().base()[0] );
503 public: // null functions
505 bool is_null( size_type idx
) const
507 BOOST_ASSERT( idx
< this->size() );
508 return this->base()[idx
] == 0;
513 void resize( size_type size
) // basic
515 size_type old_size
= this->size();
516 if( old_size
> size
)
518 this->erase( boost::next( this->begin(), size
), this->end() );
520 else if( size
> old_size
)
522 for( ; old_size
!= size
; ++old_size
)
523 this->push_back( new BOOST_DEDUCED_TYPENAME
524 boost::remove_pointer
<value_type
>::type
);
527 BOOST_ASSERT( this->size() == size
);
530 void resize( size_type size
, value_type to_clone
) // basic
532 size_type old_size
= this->size();
533 if( old_size
> size
)
535 this->erase( boost::next( this->begin(), size
), this->end() );
537 else if( size
> old_size
)
539 for( ; old_size
!= size
; ++old_size
)
540 this->push_back( this->null_policy_allocate_clone( to_clone
) );
543 BOOST_ASSERT( this->size() == size
);
546 void rresize( size_type size
) // basic
548 size_type old_size
= this->size();
549 if( old_size
> size
)
551 this->erase( this->begin(),
552 boost::next( this->begin(), old_size
- size
) );
554 else if( size
> old_size
)
556 for( ; old_size
!= size
; ++old_size
)
557 this->push_front( new BOOST_DEDUCED_TYPENAME
558 boost::remove_pointer
<value_type
>::type
);
561 BOOST_ASSERT( this->size() == size
);
564 void rresize( size_type size
, value_type to_clone
) // basic
566 size_type old_size
= this->size();
567 if( old_size
> size
)
569 this->erase( this->begin(),
570 boost::next( this->begin(), old_size
- size
) );
572 else if( size
> old_size
)
574 for( ; old_size
!= size
; ++old_size
)
575 this->push_front( this->null_policy_allocate_clone( to_clone
) );
578 BOOST_ASSERT( this->size() == size
);
581 public: // algorithms
583 void sort( iterator first
, iterator last
)
585 sort( first
, last
, std::less
<T
>() );
590 sort( this->begin(), this->end() );
593 template< class Compare
>
594 void sort( iterator first
, iterator last
, Compare comp
)
596 BOOST_ASSERT( first
<= last
&& "out of range sort()" );
597 BOOST_ASSERT( this->begin() <= first
&& "out of range sort()" );
598 BOOST_ASSERT( last
<= this->end() && "out of range sort()" );
599 // some static assert on the arguments of the comparison
600 std::sort( first
.base(), last
.base(),
601 void_ptr_indirect_fun
<Compare
,T
>(comp
) );
604 template< class Compare
>
605 void sort( Compare comp
)
607 sort( this->begin(), this->end(), comp
);
610 void unique( iterator first
, iterator last
)
612 unique( first
, last
, std::equal_to
<T
>() );
617 unique( this->begin(), this->end() );
621 struct is_not_zero_ptr
624 bool operator()( const U
* r
) const
631 template< class Fun
, class Arg1
>
632 class void_ptr_delete_if
637 void_ptr_delete_if() : fun(Fun())
640 void_ptr_delete_if( Fun f
) : fun(f
)
643 bool operator()( void* r
) const
645 BOOST_ASSERT( r
!= 0 );
646 Arg1 arg1
= static_cast<Arg1
>(r
);
649 clone_allocator_type::deallocate_clone( arg1
);
657 void compact_and_erase_nulls( iterator first
, iterator last
) // nothrow
659 typename
base_type::ptr_iterator p
= std::stable_partition(
663 this->base().erase( p
, this->end().base() );
667 void range_check_impl( iterator first
, iterator last
,
668 std::bidirectional_iterator_tag
)
671 void range_check_impl( iterator first
, iterator last
,
672 std::random_access_iterator_tag
)
674 BOOST_ASSERT( first
<= last
&& "out of range unique()/erase_if()" );
675 BOOST_ASSERT( this->begin() <= first
&& "out of range unique()/erase_if()" );
676 BOOST_ASSERT( last
<= this->end() && "out of range unique()/erase_if)(" );
679 void range_check( iterator first
, iterator last
)
681 range_check_impl( first
, last
,
682 BOOST_DEDUCED_TYPENAME iterator_category
<iterator
>::type() );
687 template< class Compare
>
688 void unique( iterator first
, iterator last
, Compare comp
)
690 range_check(first
,last
);
692 iterator prev
= first
;
693 iterator next
= first
;
695 for( ; next
!= last
; ++next
)
697 BOOST_ASSERT( !::boost::is_null(prev
) );
698 BOOST_ASSERT( !::boost::is_null(next
) );
699 if( comp( *prev
, *next
) )
701 this->remove( next
); // delete object
702 *next
.base() = 0; // mark pointer as deleted
711 compact_and_erase_nulls( first
, last
);
714 template< class Compare
>
715 void unique( Compare comp
)
717 unique( this->begin(), this->end(), comp
);
720 template< class Pred
>
721 void erase_if( iterator first
, iterator last
, Pred pred
)
723 range_check(first
,last
);
724 this->base().erase( std::remove_if( first
.base(), last
.base(),
725 void_ptr_delete_if
<Pred
,value_type
>(pred
) ),
729 template< class Pred
>
730 void erase_if( Pred pred
)
732 erase_if( this->begin(), this->end(), pred
);
736 void merge( iterator first
, iterator last
,
737 ptr_sequence_adapter
& from
)
739 merge( first
, last
, from
, std::less
<T
>() );
742 template< class BinPred
>
743 void merge( iterator first
, iterator last
,
744 ptr_sequence_adapter
& from
, BinPred pred
)
746 void_ptr_indirect_fun
<BinPred
,T
> bin_pred(pred
);
747 size_type current_size
= this->size();
748 this->transfer( this->end(), first
, last
, from
);
749 typename
base_type::ptr_iterator middle
= this->begin().base();
750 std::advance(middle
,current_size
);
751 std::inplace_merge( this->begin().base(),
757 void merge( ptr_sequence_adapter
& r
)
759 merge( r
, std::less
<T
>() );
760 BOOST_ASSERT( r
.empty() );
763 template< class BinPred
>
764 void merge( ptr_sequence_adapter
& r
, BinPred pred
)
766 merge( r
.begin(), r
.end(), r
, pred
);
767 BOOST_ASSERT( r
.empty() );
773 } // namespace 'boost'