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 * © Portions copyright (c) 2006-2007 Nokia Corporation. All rights reserved.
14 #ifndef BOOST_ptr_container_PTR_SEQUENCE_ADAPTER_HPP
15 #define BOOST_ptr_container_PTR_SEQUENCE_ADAPTER_HPP
17 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
22 #include <boost/ptr_container/detail/reversible_ptr_container.hpp>
23 #include <boost/ptr_container/indirect_fun.hpp>
24 #include <boost/ptr_container/detail/void_ptr_iterator.hpp>
25 #include <boost/type_traits/remove_pointer.hpp>
26 #include <boost/type_traits/is_same.hpp>
27 #include <boost/type_traits/is_pointer.hpp>
28 #include <boost/type_traits/is_integral.hpp>
29 #include <boost/iterator/iterator_categories.hpp>
31 #include <boost/range/begin.hpp>
32 #include <boost/range/end.hpp>
37 namespace ptr_container_detail
48 struct sequence_config
50 typedef BOOST_DEDUCED_TYPENAME remove_nullable<T>::type
55 typedef BOOST_DEDUCED_TYPENAME VoidPtrSeq::allocator_type
60 typedef void_ptr_iterator<
61 BOOST_DEDUCED_TYPENAME VoidPtrSeq::iterator, U >
64 typedef void_ptr_iterator<
65 BOOST_DEDUCED_TYPENAME VoidPtrSeq::const_iterator, const U >
68 #ifdef BOOST_NO_SFINAE
70 template< class Iter >
71 static U* get_pointer( Iter i )
73 return static_cast<U*>( *i.base() );
77 template< class Iter >
78 static U* get_pointer( void_ptr_iterator<Iter,U> i )
80 return static_cast<U*>( *i.base() );
83 template< class Iter >
84 static U* get_pointer( Iter i )
90 #if defined(BOOST_NO_SFINAE) && !BOOST_WORKAROUND(__MWERKS__, <= 0x3003)
92 template< class Iter >
93 static const U* get_const_pointer( Iter i )
95 return static_cast<const U*>( *i.base() );
98 #else // BOOST_NO_SFINAE
100 #if BOOST_WORKAROUND(__MWERKS__, <= 0x3003)
101 template< class Iter >
102 static const U* get_const_pointer( void_ptr_iterator<Iter,U> i )
104 return static_cast<const U*>( *i.base() );
106 #else // BOOST_WORKAROUND
107 template< class Iter >
108 static const U* get_const_pointer( void_ptr_iterator<Iter,const U> i )
110 return static_cast<const U*>( *i.base() );
112 #endif // BOOST_WORKAROUND
114 template< class Iter >
115 static const U* get_const_pointer( Iter i )
119 #endif // BOOST_NO_SFINAE
121 BOOST_STATIC_CONSTANT(bool, allow_null = boost::is_nullable<T>::value );
124 } // ptr_container_detail
127 template< class Iterator, class T >
128 inline bool is_null( void_ptr_iterator<Iterator,T> i )
130 return *i.base() == 0;
139 class CloneAllocator = heap_clone_allocator
141 class ptr_sequence_adapter : public
142 ptr_container_detail::reversible_ptr_container< ptr_container_detail::sequence_config<T,VoidPtrSeq>,
145 typedef ptr_container_detail::reversible_ptr_container< ptr_container_detail::sequence_config<T,VoidPtrSeq>,
149 typedef BOOST_DEDUCED_TYPENAME base_type::scoped_deleter scoped_deleter;
151 typedef ptr_sequence_adapter<T,VoidPtrSeq,CloneAllocator>
155 typedef BOOST_DEDUCED_TYPENAME base_type::value_type value_type;
156 typedef BOOST_DEDUCED_TYPENAME base_type::reference reference;
157 typedef BOOST_DEDUCED_TYPENAME base_type::auto_type auto_type;
159 BOOST_PTR_CONTAINER_DEFINE_CONSTRUCTORS( ptr_sequence_adapter,
162 template< class PtrContainer >
163 ptr_sequence_adapter( std::auto_ptr<PtrContainer> clone )
167 template< class PtrContainer >
168 void operator=( std::auto_ptr<PtrContainer> clone )
170 base_type::operator=( clone );
173 /////////////////////////////////////////////////////////////
175 /////////////////////////////////////////////////////////////
177 void push_back( value_type x ) // strong
179 this->enforce_null_policy( x, "Null pointer in 'push_back()'" );
181 auto_type ptr( x ); // notrow
182 this->c_private().push_back( x ); // strong, commit
183 ptr.release(); // nothrow
187 void push_back( std::auto_ptr<U> x )
189 push_back( x.release() );
192 void push_front( value_type x )
194 this->enforce_null_policy( x, "Null pointer in 'push_front()'" );
196 auto_type ptr( x ); // nothrow
197 this->c_private().push_front( x ); // strong, commit
198 ptr.release(); // nothrow
202 void push_front( std::auto_ptr<U> x )
204 push_front( x.release() );
209 BOOST_PTR_CONTAINER_THROW_EXCEPTION( this->empty(),
210 bad_ptr_container_operation,
211 "'pop_back()' on empty container" );
212 auto_type ptr( static_cast<value_type>(
213 this->c_private().back() ) ); // nothrow
214 this->c_private().pop_back(); // nothrow
215 return ptr_container_detail::move( ptr ); // nothrow
218 auto_type pop_front()
220 BOOST_PTR_CONTAINER_THROW_EXCEPTION( this->empty(),
221 bad_ptr_container_operation,
222 "'pop_front()' on empty container" );
223 auto_type ptr( static_cast<value_type>(
224 this->c_private().front() ) ); // nothrow
225 this->c_private().pop_front(); // nothrow
226 return ptr_container_detail::move( ptr );
231 BOOST_PTR_CONTAINER_THROW_EXCEPTION( this->empty(),
232 bad_ptr_container_operation,
233 "accessing 'front()' on empty container" );
234 BOOST_ASSERT( !::boost::is_null( this->begin() ) );
235 return *this->begin();
238 const_reference front() const
240 BOOST_PTR_CONTAINER_THROW_EXCEPTION( this->empty(),
241 bad_ptr_container_operation,
242 "accessing 'front()' on empty container" );
243 BOOST_ASSERT( !::boost::is_null( this->begin() ) );
244 return *this->begin();
249 BOOST_PTR_CONTAINER_THROW_EXCEPTION( this->empty(),
250 bad_ptr_container_operation,
251 "accessing 'back()' on empty container" );
252 BOOST_ASSERT( !::boost::is_null( --this->end() ) );
253 return *--this->end();
256 const_reference back() const
258 BOOST_PTR_CONTAINER_THROW_EXCEPTION( this->empty(),
259 bad_ptr_container_operation,
260 "accessing 'back()' on empty container" );
261 BOOST_ASSERT( !::boost::is_null( --this->end() ) );
262 return *--this->end();
265 public: // deque/vector inerface
267 reference operator[]( size_type n ) // nothrow
269 BOOST_ASSERT( n < this->size() );
270 BOOST_ASSERT( !this->is_null( n ) );
271 return *static_cast<value_type>( this->c_private()[n] );
274 const_reference operator[]( size_type n ) const // nothrow
276 BOOST_ASSERT( n < this->size() );
277 BOOST_ASSERT( !this->is_null( n ) );
278 return *static_cast<value_type>( this->c_private()[n] );
281 reference at( size_type n )
283 BOOST_PTR_CONTAINER_THROW_EXCEPTION( n >= this->size(), bad_index,
284 "'at()' out of bounds" );
285 BOOST_ASSERT( !this->is_null( n ) );
289 const_reference at( size_type n ) const
291 BOOST_PTR_CONTAINER_THROW_EXCEPTION( n >= this->size(), bad_index,
292 "'at()' out of bounds" );
293 BOOST_ASSERT( !this->is_null( n ) );
297 public: // vector interface
299 size_type capacity() const
301 return this->c_private().capacity();
304 void reserve( size_type n )
306 this->c_private().reserve( n );
311 this->c_private().reverse();
314 public: // assign, insert, transfer
316 // overhead: 1 heap allocation (very cheap compared to cloning)
317 template< class InputIterator >
318 void assign( InputIterator first, InputIterator last ) // strong
320 base_type temp( first, last );
324 template< class Range >
325 void assign( const Range& r )
327 assign( boost::begin(r), boost::end(r ) );
332 void insert_impl( iterator before, I first, I last, std::input_iterator_tag ) // strong
334 ptr_sequence_adapter temp(first,last); // strong
335 transfer( before, temp ); // strong, commit
339 void insert_impl( iterator before, I first, I last, std::forward_iterator_tag ) // strong
343 scoped_deleter sd( first, last ); // strong
344 this->insert_clones_and_release( sd, before ); // strong, commit
349 using base_type::insert;
351 template< class InputIterator >
352 void insert( iterator before, InputIterator first, InputIterator last ) // strong
354 insert_impl( before, first, last, BOOST_DEDUCED_TYPENAME
355 iterator_category<InputIterator>::type() );
358 #if defined(BOOST_NO_SFINAE) || BOOST_WORKAROUND(__SUNPRO_CC, <= 0x580)
360 template< class Range >
361 BOOST_DEDUCED_TYPENAME
362 boost::disable_if< ptr_container_detail::is_pointer_or_integral<Range> >::type
363 insert( iterator before, const Range& r )
365 insert( before, boost::begin(r), boost::end(r) );
370 template< class PtrSeqAdapter >
371 void transfer( iterator before,
372 BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator first,
373 BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator last,
374 PtrSeqAdapter& from ) // strong
376 BOOST_ASSERT( (void*)&from != (void*)this );
380 insert( before.base(),
381 first.base(), last.base() ); // strong
382 from.c_private().erase( first.base(),
383 last.base() ); // nothrow
386 template< class PtrSeqAdapter >
387 void transfer( iterator before,
388 BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator object,
389 PtrSeqAdapter& from ) // strong
391 BOOST_ASSERT( (void*)&from != (void*)this );
395 insert( before.base(),
396 *object.base() ); // strong
397 from.c_private().erase( object.base() ); // nothrow
400 #if defined(BOOST_NO_SFINAE) || BOOST_WORKAROUND(__SUNPRO_CC, <= 0x580)
403 template< class PtrSeqAdapter, class Range >
404 BOOST_DEDUCED_TYPENAME boost::disable_if< boost::is_same< Range,
405 BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator > >::type
406 transfer( iterator before, const Range& r, PtrSeqAdapter& from ) // strong
408 transfer( before, boost::begin(r), boost::end(r), from );
412 template< class PtrSeqAdapter >
413 void transfer( iterator before, PtrSeqAdapter& from ) // strong
415 BOOST_ASSERT( (void*)&from != (void*)this );
419 insert( before.base(),
420 from.begin().base(), from.end().base() ); // strong
421 from.c_private().clear(); // nothrow
424 public: // null functions
426 bool is_null( size_type idx ) const
428 BOOST_ASSERT( idx < this->size() );
429 return this->c_private()[idx] == 0;
432 public: // algorithms
434 void sort( iterator first, iterator last )
436 sort( first, last, std::less<T>() );
441 sort( this->begin(), this->end() );
444 template< class Compare >
445 void sort( iterator first, iterator last, Compare comp )
447 BOOST_ASSERT( first <= last && "out of range sort()" );
448 BOOST_ASSERT( this->begin() <= first && "out of range sort()" );
449 BOOST_ASSERT( last <= this->end() && "out of range sort()" );
450 // some static assert on the arguments of the comparison
451 std::sort( first.base(), last.base(),
452 void_ptr_indirect_fun<Compare,T>(comp) );
455 template< class Compare >
456 void sort( Compare comp )
458 sort( this->begin(), this->end(), comp );
461 void unique( iterator first, iterator last )
463 unique( first, last, std::equal_to<T>() );
468 unique( this->begin(), this->end() );
472 struct is_not_zero_ptr
475 bool operator()( const U* r ) const
481 void compact_and_erase_nulls( iterator first, iterator last ) // nothrow
484 typename base_type::ptr_iterator p = std::stable_partition(
488 this->c_private().erase( p, this->end().base() );
492 void range_check_impl( iterator first, iterator last,
493 std::bidirectional_iterator_tag )
496 void range_check_impl( iterator first, iterator last,
497 std::random_access_iterator_tag )
499 BOOST_ASSERT( first <= last && "out of range unique()/erase_if()" );
500 BOOST_ASSERT( this->begin() <= first && "out of range unique()/erase_if()" );
501 BOOST_ASSERT( last <= this->end() && "out of range unique()/erase_if)(" );
504 void range_check( iterator first, iterator last )
506 range_check_impl( first, last,
507 BOOST_DEDUCED_TYPENAME iterator_category<iterator>::type() );
512 template< class Compare >
513 void unique( iterator first, iterator last, Compare comp )
515 range_check(first,last);
517 iterator prev = first;
518 iterator next = first;
520 for( ; next != last; ++next )
522 BOOST_ASSERT( !::boost::is_null(prev) );
523 BOOST_ASSERT( !::boost::is_null(next) );
524 if( comp( *prev, *next ) )
526 this->remove( next ); // delete object
527 *next.base() = 0; // mark pointer as deleted
536 compact_and_erase_nulls( first, last );
539 template< class Compare >
540 void unique( Compare comp )
542 unique( this->begin(), this->end(), comp );
545 template< class Pred >
546 void erase_if( iterator first, iterator last, Pred pred )
548 range_check(first,last);
550 iterator next = first;
551 for( ; next != last; ++next )
553 BOOST_ASSERT( !::boost::is_null(next) );
556 this->remove( next ); // delete object
557 *next.base() = 0; // mark pointer as deleted
561 compact_and_erase_nulls( first, last );
564 template< class Pred >
565 void erase_if( Pred pred )
567 erase_if( this->begin(), this->end(), pred );
571 void merge( iterator first, iterator last,
572 ptr_sequence_adapter& from )
574 merge( first, last, from, std::less<T>() );
577 template< class BinPred >
578 void merge( iterator first, iterator last,
579 ptr_sequence_adapter& from, BinPred pred )
581 void_ptr_indirect_fun<BinPred,T> bin_pred(pred);
582 size_type current_size = this->size();
583 this->transfer( this->end(), first, last, from );
584 typename base_type::ptr_iterator middle = this->begin().base();
585 std::advance(middle,current_size);
586 std::inplace_merge( this->begin().base(),
592 void merge( ptr_sequence_adapter& r )
594 merge( r, std::less<T>() );
595 BOOST_ASSERT( r.empty() );
598 template< class BinPred >
599 void merge( ptr_sequence_adapter& r, BinPred pred )
601 merge( r.begin(), r.end(), r, pred );
602 BOOST_ASSERT( r.empty() );
608 } // namespace 'boost'