2 // Boost.Pointer Container
4 // Copyright Thorsten Ottosen 2008. 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_CIRCULAR_BUFFER_HPP
13 #define BOOST_PTR_CONTAINER_PTR_CIRCULAR_BUFFER_HPP
15 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
19 #include <boost/circular_buffer.hpp>
20 #include <boost/ptr_container/ptr_sequence_adapter.hpp>
28 class CloneAllocator
= heap_clone_allocator
,
29 class Allocator
= std::allocator
<void*>
31 class ptr_circular_buffer
: public
32 ptr_sequence_adapter
< T
,
33 boost::circular_buffer
<void*,Allocator
>,
36 typedef ptr_sequence_adapter
< T
,
37 boost::circular_buffer
<void*,Allocator
>,
41 typedef boost::circular_buffer
<void*,Allocator
> circular_buffer_type
;
42 typedef ptr_circular_buffer
<T
,CloneAllocator
,Allocator
> this_type
;
45 typedef typename
base_type::value_type value_type
;
46 typedef value_type
* pointer
;
47 typedef const value_type
* const_pointer
;
48 typedef typename
base_type::size_type size_type
;
49 typedef typename
base_type::allocator_type allocator_type
;
50 typedef typename
base_type::iterator iterator
;
51 typedef typename
base_type::const_iterator const_iterator
;
52 typedef typename
base_type::auto_type auto_type
;
54 typedef std::pair
<pointer
,size_type
> array_range
;
55 typedef std::pair
<const_pointer
,size_type
> const_array_range
;
56 typedef typename
circular_buffer_type::capacity_type capacity_type
;
58 public: // constructors
62 explicit ptr_circular_buffer( capacity_type n
)
63 : base_type( n
, ptr_container_detail::fixed_length_sequence_tag() )
66 ptr_circular_buffer( capacity_type n
,
67 const allocator_type
& alloc
)
68 : base_type( n
, alloc
, ptr_container_detail::fixed_length_sequence_tag() )
71 template< class ForwardIterator
>
72 ptr_circular_buffer( ForwardIterator first
, ForwardIterator last
)
73 : base_type( first
, last
, ptr_container_detail::fixed_length_sequence_tag() )
76 template< class InputIterator
>
77 ptr_circular_buffer( capacity_type n
, InputIterator first
, InputIterator last
)
78 : base_type( n
, first
, last
, ptr_container_detail::fixed_length_sequence_tag() )
81 ptr_circular_buffer( const ptr_circular_buffer
& r
)
82 : base_type( r
.size(), r
.begin(), r
.end(),
83 ptr_container_detail::fixed_length_sequence_tag() )
87 ptr_circular_buffer( const ptr_circular_buffer
<U
>& r
)
88 : base_type( r
.size(), r
.begin(), r
.end(),
89 ptr_container_detail::fixed_length_sequence_tag() )
92 ptr_circular_buffer
& operator=( ptr_circular_buffer r
)
98 BOOST_PTR_CONTAINER_DEFINE_RELEASE_AND_CLONE( ptr_circular_buffer
,
99 base_type
, this_type
)
101 public: // allocators
102 allocator_type
& get_allocator()
104 return this->base().get_allocator();
107 allocator_type
get_allocator() const
109 return this->base().get_allocator();
112 public: // circular buffer functions
113 array_range
array_one() // nothrow
115 typename
circular_buffer_type::array_range r
= this->base().array_one();
116 return array_range( reinterpret_cast<pointer
>(r
.first
), r
.second
);
119 const_array_range
array_one() const // nothrow
121 typename
circular_buffer_type::const_array_range r
= this->base().array_one();
122 return const_array_range( reinterpret_cast<const_pointer
>(r
.first
), r
.second
);
125 array_range
array_two() // nothrow
127 typename
circular_buffer_type::array_range r
= this->base().array_two();
128 return array_range( reinterpret_cast<pointer
>(r
.first
), r
.second
);
131 const_array_range
array_two() const // nothrow
133 typename
circular_buffer_type::const_array_range r
= this->base().array_two();
134 return const_array_range( reinterpret_cast<const_pointer
>(r
.first
), r
.second
);
137 pointer
linearize() // nothrow
139 return reinterpret_cast<pointer
>(this->base().linearize());
142 bool full() const // nothrow
144 return this->base().full();
147 size_type
reserve() const // nothrow
149 return this->base().reserve();
152 void reserve( size_type n
) // strong
158 capacity_type
capacity() const // nothrow
160 return this->base().capacity();
163 void set_capacity( capacity_type new_capacity
) // strong
165 if( this->size() > new_capacity
)
167 this->erase( this->begin() + new_capacity
, this->end() );
169 this->base().set_capacity( new_capacity
);
172 void rset_capacity( capacity_type new_capacity
) // strong
174 if( this->size() > new_capacity
)
176 this->erase( this->begin(),
177 this->begin() + (this->size()-new_capacity
) );
179 this->base().rset_capacity( new_capacity
);
182 void resize( size_type size
) // basic
184 size_type old_size
= this->size();
185 if( old_size
> size
)
187 this->erase( boost::next( this->begin(), size
), this->end() );
189 else if( size
> old_size
)
191 for( ; old_size
!= size
; ++old_size
)
192 this->push_back( new BOOST_DEDUCED_TYPENAME
193 boost::remove_pointer
<value_type
>::type
);
196 BOOST_ASSERT( this->size() == size
);
199 void resize( size_type size
, value_type to_clone
) // basic
201 size_type old_size
= this->size();
202 if( old_size
> size
)
204 this->erase( boost::next( this->begin(), size
), this->end() );
206 else if( size
> old_size
)
208 for( ; old_size
!= size
; ++old_size
)
209 this->push_back( this->null_policy_allocate_clone( to_clone
) );
212 BOOST_ASSERT( this->size() == size
);
215 void rresize( size_type size
) // basic
217 size_type old_size
= this->size();
218 if( old_size
> size
)
220 this->erase( this->begin(),
221 boost::next( this->begin(), old_size
- size
) );
223 else if( size
> old_size
)
225 for( ; old_size
!= size
; ++old_size
)
226 this->push_front( new BOOST_DEDUCED_TYPENAME
227 boost::remove_pointer
<value_type
>::type
);
230 BOOST_ASSERT( this->size() == size
);
233 void rresize( size_type size
, value_type to_clone
) // basic
235 size_type old_size
= this->size();
236 if( old_size
> size
)
238 this->erase( this->begin(),
239 boost::next( this->begin(), old_size
- size
) );
241 else if( size
> old_size
)
243 for( ; old_size
!= size
; ++old_size
)
244 this->push_front( this->null_policy_allocate_clone( to_clone
) );
247 BOOST_ASSERT( this->size() == size
);
250 template< class InputIterator
>
251 void assign( InputIterator first
, InputIterator last
) // strong
253 ptr_circular_buffer
temp( first
, last
);
257 template< class Range
>
258 void assign( const Range
& r
) // strong
260 assign( boost::begin(r
), boost::end(r
) );
263 void assign( size_type n
, value_type to_clone
) // strong
265 ptr_circular_buffer
temp( n
);
266 for( size_type i
= 0u; i
!= n
; ++i
)
267 temp
.push_back( this->null_policy_allocate_clone( to_clone
) );
271 void assign( capacity_type capacity
, size_type n
,
272 value_type to_clone
) // basic
274 this->assign( (std::min
)(n
,capacity
), to_clone
);
277 template< class InputIterator
>
278 void assign( capacity_type capacity
,
279 InputIterator first
, InputIterator last
) // basic
281 this->assign( first
, last
);
282 this->set_capacity( capacity
);
285 void push_back( value_type ptr
) // nothrow
287 BOOST_ASSERT( capacity() > 0 );
288 this->enforce_null_policy( ptr
, "Null pointer in 'push_back()'" );
292 old_ptr
.reset( &*this->begin() );
293 this->base().push_back( ptr
);
297 void push_back( std::auto_ptr
<U
> ptr
) // nothrow
299 push_back( ptr
.release() );
302 void push_front( value_type ptr
) // nothrow
304 BOOST_ASSERT( capacity() > 0 );
305 this->enforce_null_policy( ptr
, "Null pointer in 'push_front()'" );
309 old_ptr
.reset( &*(--this->end()) );
310 this->base().push_front( ptr
);
314 void push_front( std::auto_ptr
<U
> ptr
) // nothrow
316 push_front( ptr
.release() );
319 iterator
insert( iterator pos
, value_type ptr
) // nothrow
321 BOOST_ASSERT( capacity() > 0 );
322 this->enforce_null_policy( ptr
, "Null pointer in 'insert()'" );
324 auto_type
new_ptr( ptr
);
325 iterator b
= this->begin();
326 if( full() && pos
== b
)
331 old_ptr
.reset( &*this->begin() );
334 return this->base().insert( pos
.base(), ptr
);
338 iterator
insert( iterator pos
, std::auto_ptr
<U
> ptr
) // nothrow
340 return insert( pos
, ptr
.release() );
343 template< class InputIterator
>
344 void insert( iterator pos
, InputIterator first
, InputIterator last
) // basic
346 for( ; first
!= last
; ++first
, ++pos
)
347 pos
= insert( pos
, this->null_policy_allocate_clone( &*first
) );
350 #if defined(BOOST_NO_SFINAE) || defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
352 template< class Range
>
353 BOOST_DEDUCED_TYPENAME
354 boost::disable_if
< ptr_container_detail::is_pointer_or_integral
<Range
> >::type
355 insert( iterator before
, const Range
& r
)
357 insert( before
, boost::begin(r
), boost::end(r
) );
362 iterator
rinsert( iterator pos
, value_type ptr
) // nothrow
364 BOOST_ASSERT( capacity() > 0 );
365 this->enforce_null_policy( ptr
, "Null pointer in 'rinsert()'" );
367 auto_type
new_ptr( ptr
);
368 iterator b
= this->end();
369 if (full() && pos
== b
)
374 old_ptr
.reset( &this->back() );
377 return this->base().rinsert( pos
.base(), ptr
);
381 iterator
rinsert( iterator pos
, std::auto_ptr
<U
> ptr
) // nothrow
383 return rinsert( pos
, ptr
.release() );
387 template< class InputIterator
>
388 void rinsert( iterator pos
, InputIterator first
, InputIterator last
) // basic
390 for( ; first
!= last
; ++first
, ++pos
)
391 pos
= rinsert( pos
, this->null_policy_allocate_clone( &*first
) );
394 #if defined(BOOST_NO_SFINAE) || defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
396 template< class Range
>
397 BOOST_DEDUCED_TYPENAME
398 boost::disable_if
< ptr_container_detail::is_pointer_or_integral
<Range
> >::type
399 rinsert( iterator before
, const Range
& r
)
401 rinsert( before
, boost::begin(r
), boost::end(r
) );
406 iterator
rerase( iterator pos
) // nothrow
408 BOOST_ASSERT( !this->empty() );
409 BOOST_ASSERT( pos
!= this->end() );
412 return iterator( this->base().rerase( pos
.base() ) );
415 iterator
rerase( iterator first
, iterator last
) // nothrow
417 this->remove( first
, last
);
418 return iterator( this->base().rerase( first
.base(),
422 template< class Range
>
423 iterator
rerase( const Range
& r
) // nothrow
425 return rerase( boost::begin(r
), boost::end(r
) );
428 void rotate( const_iterator new_begin
) // nothrow
430 this->base().rotate( new_begin
.base() );
434 template< class PtrSeqAdapter
>
435 void transfer( iterator before
,
436 BOOST_DEDUCED_TYPENAME
PtrSeqAdapter::iterator first
,
437 BOOST_DEDUCED_TYPENAME
PtrSeqAdapter::iterator last
,
438 PtrSeqAdapter
& from
) // nothrow
440 BOOST_ASSERT( (void*)&from
!= (void*)this );
443 for( BOOST_DEDUCED_TYPENAME
PtrSeqAdapter::iterator begin
= first
;
444 begin
!= last
; ++begin
, ++before
)
445 before
= insert( before
, &*begin
); // nothrow
446 from
.base().erase( first
.base(), last
.base() ); // nothrow
449 template< class PtrSeqAdapter
>
450 void transfer( iterator before
,
451 BOOST_DEDUCED_TYPENAME
PtrSeqAdapter::iterator object
,
452 PtrSeqAdapter
& from
) // nothrow
454 BOOST_ASSERT( (void*)&from
!= (void*)this );
457 insert( before
, &*object
); // nothrow
458 from
.base().erase( object
.base() ); // nothrow
461 #if defined(BOOST_NO_SFINAE) || defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
464 template< class PtrSeqAdapter
, class Range
>
465 BOOST_DEDUCED_TYPENAME
boost::disable_if
< boost::is_same
< Range
,
466 BOOST_DEDUCED_TYPENAME
PtrSeqAdapter::iterator
> >::type
467 transfer( iterator before
, const Range
& r
, PtrSeqAdapter
& from
) // nothrow
469 transfer( before
, boost::begin(r
), boost::end(r
), from
);
473 template< class PtrSeqAdapter
>
474 void transfer( iterator before
, PtrSeqAdapter
& from
) // nothrow
476 transfer( before
, from
.begin(), from
.end(), from
);
479 public: // C-array support
481 void transfer( iterator before
, value_type
* from
,
482 size_type size
, bool delete_from
= true ) // nothrow
484 BOOST_ASSERT( from
!= 0 );
487 BOOST_DEDUCED_TYPENAME
base_type::scoped_deleter
488 deleter( from
, size
); // nothrow
489 for( size_type i
= 0u; i
!= size
; ++i
, ++before
)
490 before
= insert( before
, *(from
+i
) ); // nothrow
491 deleter
.release(); // nothrow
495 for( size_type i
= 0u; i
!= size
; ++i
, ++before
)
496 before
= insert( before
, *(from
+i
) ); // nothrow
500 value_type
* c_array() // nothrow
505 T
** res
= reinterpret_cast<T
**>( &this->begin().base()[0] );
511 //////////////////////////////////////////////////////////////////////////////
514 template< typename T
, typename CA
, typename A
>
515 inline ptr_circular_buffer
<T
,CA
,A
>* new_clone( const ptr_circular_buffer
<T
,CA
,A
>& r
)
517 return r
.clone().release();
520 /////////////////////////////////////////////////////////////////////////
523 template< typename T
, typename CA
, typename A
>
524 inline void swap( ptr_circular_buffer
<T
,CA
,A
>& l
, ptr_circular_buffer
<T
,CA
,A
>& r
)