Chris@16
|
1 // Implementation of the base circular buffer.
|
Chris@16
|
2
|
Chris@16
|
3 // Copyright (c) 2003-2008 Jan Gaspar
|
Chris@16
|
4 // Copyright (c) 2013 Paul A. Bristow // Doxygen comments changed.
|
Chris@16
|
5 // Copyright (c) 2013 Antony Polukhin // Move semantics implementation.
|
Chris@101
|
6 // Copyright (c) 2014 Glen Fernandes // C++11 allocator model support.
|
Chris@16
|
7
|
Chris@16
|
8 // Use, modification, and distribution is subject to the Boost Software
|
Chris@16
|
9 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
10 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
11
|
Chris@16
|
12 #if !defined(BOOST_CIRCULAR_BUFFER_BASE_HPP)
|
Chris@16
|
13 #define BOOST_CIRCULAR_BUFFER_BASE_HPP
|
Chris@16
|
14
|
Chris@101
|
15 #if defined(_MSC_VER)
|
Chris@16
|
16 #pragma once
|
Chris@16
|
17 #endif
|
Chris@16
|
18
|
Chris@16
|
19 #include <boost/config.hpp>
|
Chris@16
|
20 #include <boost/call_traits.hpp>
|
Chris@16
|
21 #include <boost/concept_check.hpp>
|
Chris@16
|
22 #include <boost/limits.hpp>
|
Chris@101
|
23 #include <boost/container/allocator_traits.hpp>
|
Chris@16
|
24 #include <boost/iterator/reverse_iterator.hpp>
|
Chris@16
|
25 #include <boost/iterator/iterator_traits.hpp>
|
Chris@16
|
26 #include <boost/type_traits/is_stateless.hpp>
|
Chris@16
|
27 #include <boost/type_traits/is_integral.hpp>
|
Chris@16
|
28 #include <boost/type_traits/is_scalar.hpp>
|
Chris@16
|
29 #include <boost/type_traits/is_nothrow_move_constructible.hpp>
|
Chris@16
|
30 #include <boost/type_traits/is_nothrow_move_assignable.hpp>
|
Chris@16
|
31 #include <boost/type_traits/is_copy_constructible.hpp>
|
Chris@16
|
32 #include <boost/type_traits/conditional.hpp>
|
Chris@16
|
33 #include <boost/move/move.hpp>
|
Chris@101
|
34 #include <boost/utility/addressof.hpp>
|
Chris@16
|
35 #include <algorithm>
|
Chris@16
|
36 #include <utility>
|
Chris@16
|
37 #include <deque>
|
Chris@16
|
38 #include <stdexcept>
|
Chris@101
|
39
|
Chris@16
|
40 #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205))
|
Chris@16
|
41 #include <stddef.h>
|
Chris@16
|
42 #endif
|
Chris@16
|
43
|
Chris@16
|
44 namespace boost {
|
Chris@16
|
45
|
Chris@16
|
46 /*!
|
Chris@16
|
47 \class circular_buffer
|
Chris@16
|
48 \brief Circular buffer - a STL compliant container.
|
Chris@16
|
49 \tparam T The type of the elements stored in the <code>circular_buffer</code>.
|
Chris@16
|
50 \par Type Requirements T
|
Chris@16
|
51 The <code>T</code> has to be <a href="http://www.sgi.com/tech/stl/Assignable.html">
|
Chris@16
|
52 SGIAssignable</a> (SGI STL defined combination of <a href="../../../utility/Assignable.html">
|
Chris@16
|
53 Assignable</a> and <a href="../../../utility/CopyConstructible.html">CopyConstructible</a>).
|
Chris@16
|
54 Moreover <code>T</code> has to be <a href="http://www.sgi.com/tech/stl/DefaultConstructible.html">
|
Chris@16
|
55 DefaultConstructible</a> if supplied as a default parameter when invoking some of the
|
Chris@16
|
56 <code>circular_buffer</code>'s methods e.g.
|
Chris@16
|
57 <code>insert(iterator pos, const value_type& item = %value_type())</code>. And
|
Chris@16
|
58 <a href="http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</a> and/or
|
Chris@16
|
59 <a href="../../../utility/LessThanComparable.html">LessThanComparable</a> if the <code>circular_buffer</code>
|
Chris@16
|
60 will be compared with another container.
|
Chris@16
|
61 \tparam Alloc The allocator type used for all internal memory management.
|
Chris@16
|
62 \par Type Requirements Alloc
|
Chris@16
|
63 The <code>Alloc</code> has to meet the allocator requirements imposed by STL.
|
Chris@16
|
64 \par Default Alloc
|
Chris@16
|
65 std::allocator<T>
|
Chris@16
|
66
|
Chris@16
|
67 For detailed documentation of the circular_buffer visit:
|
Chris@16
|
68 http://www.boost.org/libs/circular_buffer/doc/circular_buffer.html
|
Chris@16
|
69 */
|
Chris@16
|
70 template <class T, class Alloc>
|
Chris@16
|
71 class circular_buffer
|
Chris@16
|
72 /*! \cond */
|
Chris@16
|
73 #if BOOST_CB_ENABLE_DEBUG
|
Chris@16
|
74 : public cb_details::debug_iterator_registry
|
Chris@16
|
75 #endif
|
Chris@16
|
76 /*! \endcond */
|
Chris@16
|
77 {
|
Chris@16
|
78
|
Chris@16
|
79 // Requirements
|
Chris@16
|
80 //BOOST_CLASS_REQUIRE(T, boost, SGIAssignableConcept);
|
Chris@16
|
81
|
Chris@16
|
82
|
Chris@16
|
83 //BOOST_CONCEPT_ASSERT((Assignable<T>));
|
Chris@16
|
84 //BOOST_CONCEPT_ASSERT((CopyConstructible<T>));
|
Chris@16
|
85 //BOOST_CONCEPT_ASSERT((DefaultConstructible<T>));
|
Chris@16
|
86
|
Chris@16
|
87 // Required if the circular_buffer will be compared with anther container.
|
Chris@16
|
88 //BOOST_CONCEPT_ASSERT((EqualityComparable<T>));
|
Chris@16
|
89 //BOOST_CONCEPT_ASSERT((LessThanComparable<T>));
|
Chris@16
|
90
|
Chris@16
|
91 public:
|
Chris@16
|
92 // Basic types
|
Chris@16
|
93
|
Chris@16
|
94 //! The type of this <code>circular_buffer</code>.
|
Chris@16
|
95 typedef circular_buffer<T, Alloc> this_type;
|
Chris@16
|
96
|
Chris@16
|
97 //! The type of elements stored in the <code>circular_buffer</code>.
|
Chris@101
|
98 typedef typename boost::container::allocator_traits<Alloc>::value_type value_type;
|
Chris@16
|
99
|
Chris@16
|
100 //! A pointer to an element.
|
Chris@101
|
101 typedef typename boost::container::allocator_traits<Alloc>::pointer pointer;
|
Chris@16
|
102
|
Chris@16
|
103 //! A const pointer to the element.
|
Chris@101
|
104 typedef typename boost::container::allocator_traits<Alloc>::const_pointer const_pointer;
|
Chris@16
|
105
|
Chris@16
|
106 //! A reference to an element.
|
Chris@101
|
107 typedef typename boost::container::allocator_traits<Alloc>::reference reference;
|
Chris@16
|
108
|
Chris@16
|
109 //! A const reference to an element.
|
Chris@101
|
110 typedef typename boost::container::allocator_traits<Alloc>::const_reference const_reference;
|
Chris@16
|
111
|
Chris@16
|
112 //! The distance type.
|
Chris@16
|
113 /*!
|
Chris@16
|
114 (A signed integral type used to represent the distance between two iterators.)
|
Chris@16
|
115 */
|
Chris@101
|
116 typedef typename boost::container::allocator_traits<Alloc>::difference_type difference_type;
|
Chris@16
|
117
|
Chris@16
|
118 //! The size type.
|
Chris@16
|
119 /*!
|
Chris@16
|
120 (An unsigned integral type that can represent any non-negative value of the container's distance type.)
|
Chris@16
|
121 */
|
Chris@101
|
122 typedef typename boost::container::allocator_traits<Alloc>::size_type size_type;
|
Chris@16
|
123
|
Chris@16
|
124 //! The type of an allocator used in the <code>circular_buffer</code>.
|
Chris@16
|
125 typedef Alloc allocator_type;
|
Chris@16
|
126
|
Chris@16
|
127 // Iterators
|
Chris@16
|
128
|
Chris@16
|
129 //! A const (random access) iterator used to iterate through the <code>circular_buffer</code>.
|
Chris@101
|
130 typedef cb_details::iterator< circular_buffer<T, Alloc>, cb_details::const_traits<boost::container::allocator_traits<Alloc> > > const_iterator;
|
Chris@16
|
131
|
Chris@16
|
132 //! A (random access) iterator used to iterate through the <code>circular_buffer</code>.
|
Chris@101
|
133 typedef cb_details::iterator< circular_buffer<T, Alloc>, cb_details::nonconst_traits<boost::container::allocator_traits<Alloc> > > iterator;
|
Chris@16
|
134
|
Chris@16
|
135 //! A const iterator used to iterate backwards through a <code>circular_buffer</code>.
|
Chris@16
|
136 typedef boost::reverse_iterator<const_iterator> const_reverse_iterator;
|
Chris@16
|
137
|
Chris@16
|
138 //! An iterator used to iterate backwards through a <code>circular_buffer</code>.
|
Chris@16
|
139 typedef boost::reverse_iterator<iterator> reverse_iterator;
|
Chris@16
|
140
|
Chris@16
|
141 // Container specific types
|
Chris@16
|
142
|
Chris@16
|
143 //! An array range.
|
Chris@16
|
144 /*!
|
Chris@16
|
145 (A typedef for the <a href="http://www.sgi.com/tech/stl/pair.html"><code>std::pair</code></a> where
|
Chris@16
|
146 its first element is a pointer to a beginning of an array and its second element represents
|
Chris@16
|
147 a size of the array.)
|
Chris@16
|
148 */
|
Chris@16
|
149 typedef std::pair<pointer, size_type> array_range;
|
Chris@16
|
150
|
Chris@16
|
151 //! A range of a const array.
|
Chris@16
|
152 /*!
|
Chris@16
|
153 (A typedef for the <a href="http://www.sgi.com/tech/stl/pair.html"><code>std::pair</code></a> where
|
Chris@16
|
154 its first element is a pointer to a beginning of a const array and its second element represents
|
Chris@16
|
155 a size of the const array.)
|
Chris@16
|
156 */
|
Chris@16
|
157 typedef std::pair<const_pointer, size_type> const_array_range;
|
Chris@16
|
158
|
Chris@16
|
159 //! The capacity type.
|
Chris@16
|
160 /*!
|
Chris@16
|
161 (Same as <code>size_type</code> - defined for consistency with the __cbso class.
|
Chris@16
|
162
|
Chris@16
|
163 */
|
Chris@16
|
164 // <a href="space_optimized.html"><code>circular_buffer_space_optimized</code></a>.)
|
Chris@16
|
165
|
Chris@16
|
166 typedef size_type capacity_type;
|
Chris@16
|
167
|
Chris@16
|
168 // Helper types
|
Chris@16
|
169
|
Chris@16
|
170 //! A type representing the "best" way to pass the value_type to a method.
|
Chris@16
|
171 typedef const value_type& param_value_type;
|
Chris@16
|
172
|
Chris@16
|
173 //! A type representing rvalue from param type.
|
Chris@16
|
174 //! On compilers without rvalue references support this type is the Boost.Moves type used for emulation.
|
Chris@16
|
175 typedef BOOST_RV_REF(value_type) rvalue_type;
|
Chris@16
|
176
|
Chris@16
|
177 private:
|
Chris@16
|
178 // Member variables
|
Chris@16
|
179
|
Chris@16
|
180 //! The internal buffer used for storing elements in the circular buffer.
|
Chris@16
|
181 pointer m_buff;
|
Chris@16
|
182
|
Chris@16
|
183 //! The internal buffer's end (end of the storage space).
|
Chris@16
|
184 pointer m_end;
|
Chris@16
|
185
|
Chris@16
|
186 //! The virtual beginning of the circular buffer.
|
Chris@16
|
187 pointer m_first;
|
Chris@16
|
188
|
Chris@16
|
189 //! The virtual end of the circular buffer (one behind the last element).
|
Chris@16
|
190 pointer m_last;
|
Chris@16
|
191
|
Chris@16
|
192 //! The number of items currently stored in the circular buffer.
|
Chris@16
|
193 size_type m_size;
|
Chris@16
|
194
|
Chris@16
|
195 //! The allocator.
|
Chris@16
|
196 allocator_type m_alloc;
|
Chris@16
|
197
|
Chris@16
|
198 // Friends
|
Chris@16
|
199 #if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
|
Chris@16
|
200 friend iterator;
|
Chris@16
|
201 friend const_iterator;
|
Chris@16
|
202 #else
|
Chris@16
|
203 template <class Buff, class Traits> friend struct cb_details::iterator;
|
Chris@16
|
204 #endif
|
Chris@16
|
205
|
Chris@16
|
206 public:
|
Chris@16
|
207 // Allocator
|
Chris@16
|
208
|
Chris@16
|
209 //! Get the allocator.
|
Chris@16
|
210 /*!
|
Chris@16
|
211 \return The allocator.
|
Chris@16
|
212 \throws Nothing.
|
Chris@16
|
213 \par Exception Safety
|
Chris@16
|
214 No-throw.
|
Chris@16
|
215 \par Iterator Invalidation
|
Chris@16
|
216 Does not invalidate any iterators.
|
Chris@16
|
217 \par Complexity
|
Chris@16
|
218 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
219 \sa <code>get_allocator()</code> for obtaining an allocator %reference.
|
Chris@16
|
220 */
|
Chris@16
|
221 allocator_type get_allocator() const BOOST_NOEXCEPT { return m_alloc; }
|
Chris@16
|
222
|
Chris@16
|
223 //! Get the allocator reference.
|
Chris@16
|
224 /*!
|
Chris@16
|
225 \return A reference to the allocator.
|
Chris@16
|
226 \throws Nothing.
|
Chris@16
|
227 \par Exception Safety
|
Chris@16
|
228 No-throw.
|
Chris@16
|
229 \par Iterator Invalidation
|
Chris@16
|
230 Does not invalidate any iterators.
|
Chris@16
|
231 \par Complexity
|
Chris@16
|
232 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
233 \note This method was added in order to optimize obtaining of the allocator with a state,
|
Chris@16
|
234 although use of stateful allocators in STL is discouraged.
|
Chris@16
|
235 \sa <code>get_allocator() const</code>
|
Chris@16
|
236 */
|
Chris@16
|
237 allocator_type& get_allocator() BOOST_NOEXCEPT { return m_alloc; }
|
Chris@16
|
238
|
Chris@16
|
239 // Element access
|
Chris@16
|
240
|
Chris@16
|
241 //! Get the iterator pointing to the beginning of the <code>circular_buffer</code>.
|
Chris@16
|
242 /*!
|
Chris@16
|
243 \return A random access iterator pointing to the first element of the <code>circular_buffer</code>. If the
|
Chris@16
|
244 <code>circular_buffer</code> is empty it returns an iterator equal to the one returned by
|
Chris@16
|
245 <code>end()</code>.
|
Chris@16
|
246 \throws Nothing.
|
Chris@16
|
247 \par Exception Safety
|
Chris@16
|
248 No-throw.
|
Chris@16
|
249 \par Iterator Invalidation
|
Chris@16
|
250 Does not invalidate any iterators.
|
Chris@16
|
251 \par Complexity
|
Chris@16
|
252 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
253 \sa <code>end()</code>, <code>rbegin()</code>, <code>rend()</code>
|
Chris@16
|
254 */
|
Chris@16
|
255 iterator begin() BOOST_NOEXCEPT { return iterator(this, empty() ? 0 : m_first); }
|
Chris@16
|
256
|
Chris@16
|
257 //! Get the iterator pointing to the end of the <code>circular_buffer</code>.
|
Chris@16
|
258 /*!
|
Chris@16
|
259 \return A random access iterator pointing to the element "one behind" the last element of the <code>
|
Chris@16
|
260 circular_buffer</code>. If the <code>circular_buffer</code> is empty it returns an iterator equal to
|
Chris@16
|
261 the one returned by <code>begin()</code>.
|
Chris@16
|
262 \throws Nothing.
|
Chris@16
|
263 \par Exception Safety
|
Chris@16
|
264 No-throw.
|
Chris@16
|
265 \par Iterator Invalidation
|
Chris@16
|
266 Does not invalidate any iterators.
|
Chris@16
|
267 \par Complexity
|
Chris@16
|
268 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
269 \sa <code>begin()</code>, <code>rbegin()</code>, <code>rend()</code>
|
Chris@16
|
270 */
|
Chris@16
|
271 iterator end() BOOST_NOEXCEPT { return iterator(this, 0); }
|
Chris@16
|
272
|
Chris@16
|
273 //! Get the const iterator pointing to the beginning of the <code>circular_buffer</code>.
|
Chris@16
|
274 /*!
|
Chris@16
|
275 \return A const random access iterator pointing to the first element of the <code>circular_buffer</code>. If
|
Chris@16
|
276 the <code>circular_buffer</code> is empty it returns an iterator equal to the one returned by
|
Chris@16
|
277 <code>end() const</code>.
|
Chris@16
|
278 \throws Nothing.
|
Chris@16
|
279 \par Exception Safety
|
Chris@16
|
280 No-throw.
|
Chris@16
|
281 \par Iterator Invalidation
|
Chris@16
|
282 Does not invalidate any iterators.
|
Chris@16
|
283 \par Complexity
|
Chris@16
|
284 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
285 \sa <code>end() const</code>, <code>rbegin() const</code>, <code>rend() const</code>
|
Chris@16
|
286 */
|
Chris@16
|
287 const_iterator begin() const BOOST_NOEXCEPT { return const_iterator(this, empty() ? 0 : m_first); }
|
Chris@16
|
288
|
Chris@16
|
289 //! Get the const iterator pointing to the end of the <code>circular_buffer</code>.
|
Chris@16
|
290 /*!
|
Chris@16
|
291 \return A const random access iterator pointing to the element "one behind" the last element of the <code>
|
Chris@16
|
292 circular_buffer</code>. If the <code>circular_buffer</code> is empty it returns an iterator equal to
|
Chris@16
|
293 the one returned by <code>begin() const</code> const.
|
Chris@16
|
294 \throws Nothing.
|
Chris@16
|
295 \par Exception Safety
|
Chris@16
|
296 No-throw.
|
Chris@16
|
297 \par Iterator Invalidation
|
Chris@16
|
298 Does not invalidate any iterators.
|
Chris@16
|
299 \par Complexity
|
Chris@16
|
300 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
301 \sa <code>begin() const</code>, <code>rbegin() const</code>, <code>rend() const</code>
|
Chris@16
|
302 */
|
Chris@16
|
303 const_iterator end() const BOOST_NOEXCEPT { return const_iterator(this, 0); }
|
Chris@16
|
304
|
Chris@16
|
305 //! Get the iterator pointing to the beginning of the "reversed" <code>circular_buffer</code>.
|
Chris@16
|
306 /*!
|
Chris@16
|
307 \return A reverse random access iterator pointing to the last element of the <code>circular_buffer</code>.
|
Chris@16
|
308 If the <code>circular_buffer</code> is empty it returns an iterator equal to the one returned by
|
Chris@16
|
309 <code>rend()</code>.
|
Chris@16
|
310 \throws Nothing.
|
Chris@16
|
311 \par Exception Safety
|
Chris@16
|
312 No-throw.
|
Chris@16
|
313 \par Iterator Invalidation
|
Chris@16
|
314 Does not invalidate any iterators.
|
Chris@16
|
315 \par Complexity
|
Chris@16
|
316 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
317 \sa <code>rend()</code>, <code>begin()</code>, <code>end()</code>
|
Chris@16
|
318 */
|
Chris@16
|
319 reverse_iterator rbegin() BOOST_NOEXCEPT { return reverse_iterator(end()); }
|
Chris@16
|
320
|
Chris@16
|
321 //! Get the iterator pointing to the end of the "reversed" <code>circular_buffer</code>.
|
Chris@16
|
322 /*!
|
Chris@16
|
323 \return A reverse random access iterator pointing to the element "one before" the first element of the <code>
|
Chris@16
|
324 circular_buffer</code>. If the <code>circular_buffer</code> is empty it returns an iterator equal to
|
Chris@16
|
325 the one returned by <code>rbegin()</code>.
|
Chris@16
|
326 \throws Nothing.
|
Chris@16
|
327 \par Exception Safety
|
Chris@16
|
328 No-throw.
|
Chris@16
|
329 \par Iterator Invalidation
|
Chris@16
|
330 Does not invalidate any iterators.
|
Chris@16
|
331 \par Complexity
|
Chris@16
|
332 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
333 \sa <code>rbegin()</code>, <code>begin()</code>, <code>end()</code>
|
Chris@16
|
334 */
|
Chris@16
|
335 reverse_iterator rend() BOOST_NOEXCEPT { return reverse_iterator(begin()); }
|
Chris@16
|
336
|
Chris@16
|
337 //! Get the const iterator pointing to the beginning of the "reversed" <code>circular_buffer</code>.
|
Chris@16
|
338 /*!
|
Chris@16
|
339 \return A const reverse random access iterator pointing to the last element of the
|
Chris@16
|
340 <code>circular_buffer</code>. If the <code>circular_buffer</code> is empty it returns an iterator equal
|
Chris@16
|
341 to the one returned by <code>rend() const</code>.
|
Chris@16
|
342 \throws Nothing.
|
Chris@16
|
343 \par Exception Safety
|
Chris@16
|
344 No-throw.
|
Chris@16
|
345 \par Iterator Invalidation
|
Chris@16
|
346 Does not invalidate any iterators.
|
Chris@16
|
347 \par Complexity
|
Chris@16
|
348 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
349 \sa <code>rend() const</code>, <code>begin() const</code>, <code>end() const</code>
|
Chris@16
|
350 */
|
Chris@16
|
351 const_reverse_iterator rbegin() const BOOST_NOEXCEPT { return const_reverse_iterator(end()); }
|
Chris@16
|
352
|
Chris@16
|
353 //! Get the const iterator pointing to the end of the "reversed" <code>circular_buffer</code>.
|
Chris@16
|
354 /*!
|
Chris@16
|
355 \return A const reverse random access iterator pointing to the element "one before" the first element of the
|
Chris@16
|
356 <code>circular_buffer</code>. If the <code>circular_buffer</code> is empty it returns an iterator equal
|
Chris@16
|
357 to the one returned by <code>rbegin() const</code>.
|
Chris@16
|
358 \throws Nothing.
|
Chris@16
|
359 \par Exception Safety
|
Chris@16
|
360 No-throw.
|
Chris@16
|
361 \par Iterator Invalidation
|
Chris@16
|
362 Does not invalidate any iterators.
|
Chris@16
|
363 \par Complexity
|
Chris@16
|
364 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
365 \sa <code>rbegin() const</code>, <code>begin() const</code>, <code>end() const</code>
|
Chris@16
|
366 */
|
Chris@16
|
367 const_reverse_iterator rend() const BOOST_NOEXCEPT { return const_reverse_iterator(begin()); }
|
Chris@16
|
368
|
Chris@16
|
369 //! Get the element at the <code>index</code> position.
|
Chris@16
|
370 /*!
|
Chris@16
|
371 \pre <code>0 \<= index \&\& index \< size()</code>
|
Chris@16
|
372 \param index The position of the element.
|
Chris@16
|
373 \return A reference to the element at the <code>index</code> position.
|
Chris@16
|
374 \throws Nothing.
|
Chris@16
|
375 \par Exception Safety
|
Chris@16
|
376 No-throw.
|
Chris@16
|
377 \par Iterator Invalidation
|
Chris@16
|
378 Does not invalidate any iterators.
|
Chris@16
|
379 \par Complexity
|
Chris@16
|
380 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
381 \sa <code>at()</code>
|
Chris@16
|
382 */
|
Chris@16
|
383 reference operator [] (size_type index) {
|
Chris@16
|
384 BOOST_CB_ASSERT(index < size()); // check for invalid index
|
Chris@16
|
385 return *add(m_first, index);
|
Chris@16
|
386 }
|
Chris@16
|
387
|
Chris@16
|
388 //! Get the element at the <code>index</code> position.
|
Chris@16
|
389 /*!
|
Chris@16
|
390 \pre <code>0 \<= index \&\& index \< size()</code>
|
Chris@16
|
391 \param index The position of the element.
|
Chris@16
|
392 \return A const reference to the element at the <code>index</code> position.
|
Chris@16
|
393 \throws Nothing.
|
Chris@16
|
394 \par Exception Safety
|
Chris@16
|
395 No-throw.
|
Chris@16
|
396 \par Iterator Invalidation
|
Chris@16
|
397 Does not invalidate any iterators.
|
Chris@16
|
398 \par Complexity
|
Chris@16
|
399 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
400 \sa <code>\link at(size_type)const at() const \endlink</code>
|
Chris@16
|
401 */
|
Chris@16
|
402 const_reference operator [] (size_type index) const {
|
Chris@16
|
403 BOOST_CB_ASSERT(index < size()); // check for invalid index
|
Chris@16
|
404 return *add(m_first, index);
|
Chris@16
|
405 }
|
Chris@16
|
406
|
Chris@16
|
407 //! Get the element at the <code>index</code> position.
|
Chris@16
|
408 /*!
|
Chris@16
|
409 \param index The position of the element.
|
Chris@16
|
410 \return A reference to the element at the <code>index</code> position.
|
Chris@16
|
411 \throws <code>std::out_of_range</code> when the <code>index</code> is invalid (when
|
Chris@16
|
412 <code>index >= size()</code>).
|
Chris@16
|
413 \par Exception Safety
|
Chris@16
|
414 Strong.
|
Chris@16
|
415 \par Iterator Invalidation
|
Chris@16
|
416 Does not invalidate any iterators.
|
Chris@16
|
417 \par Complexity
|
Chris@16
|
418 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
419 \sa <code>\link operator[](size_type) operator[] \endlink</code>
|
Chris@16
|
420 */
|
Chris@16
|
421 reference at(size_type index) {
|
Chris@16
|
422 check_position(index);
|
Chris@16
|
423 return (*this)[index];
|
Chris@16
|
424 }
|
Chris@16
|
425
|
Chris@16
|
426 //! Get the element at the <code>index</code> position.
|
Chris@16
|
427 /*!
|
Chris@16
|
428 \param index The position of the element.
|
Chris@16
|
429 \return A const reference to the element at the <code>index</code> position.
|
Chris@16
|
430 \throws <code>std::out_of_range</code> when the <code>index</code> is invalid (when
|
Chris@16
|
431 <code>index >= size()</code>).
|
Chris@16
|
432 \par Exception Safety
|
Chris@16
|
433 Strong.
|
Chris@16
|
434 \par Iterator Invalidation
|
Chris@16
|
435 Does not invalidate any iterators.
|
Chris@16
|
436 \par Complexity
|
Chris@16
|
437 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
438 \sa <code>\link operator[](size_type)const operator[] const \endlink</code>
|
Chris@16
|
439 */
|
Chris@16
|
440 const_reference at(size_type index) const {
|
Chris@16
|
441 check_position(index);
|
Chris@16
|
442 return (*this)[index];
|
Chris@16
|
443 }
|
Chris@16
|
444
|
Chris@16
|
445 //! Get the first element.
|
Chris@16
|
446 /*!
|
Chris@16
|
447 \pre <code>!empty()</code>
|
Chris@16
|
448 \return A reference to the first element of the <code>circular_buffer</code>.
|
Chris@16
|
449 \throws Nothing.
|
Chris@16
|
450 \par Exception Safety
|
Chris@16
|
451 No-throw.
|
Chris@16
|
452 \par Iterator Invalidation
|
Chris@16
|
453 Does not invalidate any iterators.
|
Chris@16
|
454 \par Complexity
|
Chris@16
|
455 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
456 \sa <code>back()</code>
|
Chris@16
|
457 */
|
Chris@16
|
458 reference front() {
|
Chris@16
|
459 BOOST_CB_ASSERT(!empty()); // check for empty buffer (front element not available)
|
Chris@16
|
460 return *m_first;
|
Chris@16
|
461 }
|
Chris@16
|
462
|
Chris@16
|
463 //! Get the last element.
|
Chris@16
|
464 /*!
|
Chris@16
|
465 \pre <code>!empty()</code>
|
Chris@16
|
466 \return A reference to the last element of the <code>circular_buffer</code>.
|
Chris@16
|
467 \throws Nothing.
|
Chris@16
|
468 \par Exception Safety
|
Chris@16
|
469 No-throw.
|
Chris@16
|
470 \par Iterator Invalidation
|
Chris@16
|
471 Does not invalidate any iterators.
|
Chris@16
|
472 \par Complexity
|
Chris@16
|
473 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
474 \sa <code>front()</code>
|
Chris@16
|
475 */
|
Chris@16
|
476 reference back() {
|
Chris@16
|
477 BOOST_CB_ASSERT(!empty()); // check for empty buffer (back element not available)
|
Chris@16
|
478 return *((m_last == m_buff ? m_end : m_last) - 1);
|
Chris@16
|
479 }
|
Chris@16
|
480
|
Chris@16
|
481 //! Get the first element.
|
Chris@16
|
482 /*!
|
Chris@16
|
483 \pre <code>!empty()</code>
|
Chris@16
|
484 \return A const reference to the first element of the <code>circular_buffer</code>.
|
Chris@16
|
485 \throws Nothing.
|
Chris@16
|
486 \par Exception Safety
|
Chris@16
|
487 No-throw.
|
Chris@16
|
488 \par Iterator Invalidation
|
Chris@16
|
489 Does not invalidate any iterators.
|
Chris@16
|
490 \par Complexity
|
Chris@16
|
491 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
492 \sa <code>back() const</code>
|
Chris@16
|
493 */
|
Chris@16
|
494 const_reference front() const {
|
Chris@16
|
495 BOOST_CB_ASSERT(!empty()); // check for empty buffer (front element not available)
|
Chris@16
|
496 return *m_first;
|
Chris@16
|
497 }
|
Chris@16
|
498
|
Chris@16
|
499 //! Get the last element.
|
Chris@16
|
500 /*!
|
Chris@16
|
501 \pre <code>!empty()</code>
|
Chris@16
|
502 \return A const reference to the last element of the <code>circular_buffer</code>.
|
Chris@16
|
503 \throws Nothing.
|
Chris@16
|
504 \par Exception Safety
|
Chris@16
|
505 No-throw.
|
Chris@16
|
506 \par Iterator Invalidation
|
Chris@16
|
507 Does not invalidate any iterators.
|
Chris@16
|
508 \par Complexity
|
Chris@16
|
509 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
510 \sa <code>front() const</code>
|
Chris@16
|
511 */
|
Chris@16
|
512 const_reference back() const {
|
Chris@16
|
513 BOOST_CB_ASSERT(!empty()); // check for empty buffer (back element not available)
|
Chris@16
|
514 return *((m_last == m_buff ? m_end : m_last) - 1);
|
Chris@16
|
515 }
|
Chris@16
|
516
|
Chris@16
|
517 //! Get the first continuous array of the internal buffer.
|
Chris@16
|
518 /*!
|
Chris@16
|
519 This method in combination with <code>array_two()</code> can be useful when passing the stored data into
|
Chris@16
|
520 a legacy C API as an array. Suppose there is a <code>circular_buffer</code> of capacity 10, containing 7
|
Chris@16
|
521 characters <code>'a', 'b', ..., 'g'</code> where <code>buff[0] == 'a'</code>, <code>buff[1] == 'b'</code>,
|
Chris@16
|
522 ... and <code>buff[6] == 'g'</code>:<br><br>
|
Chris@16
|
523 <code>circular_buffer<char> buff(10);</code><br><br>
|
Chris@16
|
524 The internal representation is often not linear and the state of the internal buffer may look like this:<br>
|
Chris@16
|
525 <br><code>
|
Chris@16
|
526 |e|f|g| | | |a|b|c|d|<br>
|
Chris@16
|
527 end ___^<br>
|
Chris@16
|
528 begin _______^</code><br><br>
|
Chris@16
|
529
|
Chris@16
|
530 where <code>|a|b|c|d|</code> represents the "array one", <code>|e|f|g|</code> represents the "array two" and
|
Chris@16
|
531 <code>| | | |</code> is a free space.<br>
|
Chris@16
|
532 Now consider a typical C style function for writing data into a file:<br><br>
|
Chris@16
|
533 <code>int write(int file_desc, char* buff, int num_bytes);</code><br><br>
|
Chris@16
|
534 There are two ways how to write the content of the <code>circular_buffer</code> into a file. Either relying
|
Chris@16
|
535 on <code>array_one()</code> and <code>array_two()</code> methods and calling the write function twice:<br><br>
|
Chris@16
|
536 <code>array_range ar = buff.array_one();<br>
|
Chris@16
|
537 write(file_desc, ar.first, ar.second);<br>
|
Chris@16
|
538 ar = buff.array_two();<br>
|
Chris@16
|
539 write(file_desc, ar.first, ar.second);</code><br><br>
|
Chris@16
|
540 Or relying on the <code>linearize()</code> method:<br><br><code>
|
Chris@16
|
541 write(file_desc, buff.linearize(), buff.size());</code><br><br>
|
Chris@16
|
542 Since the complexity of <code>array_one()</code> and <code>array_two()</code> methods is constant the first
|
Chris@16
|
543 option is suitable when calling the write method is "cheap". On the other hand the second option is more
|
Chris@16
|
544 suitable when calling the write method is more "expensive" than calling the <code>linearize()</code> method
|
Chris@16
|
545 whose complexity is linear.
|
Chris@16
|
546 \return The array range of the first continuous array of the internal buffer. In the case the
|
Chris@16
|
547 <code>circular_buffer</code> is empty the size of the returned array is <code>0</code>.
|
Chris@16
|
548 \throws Nothing.
|
Chris@16
|
549 \par Exception Safety
|
Chris@16
|
550 No-throw.
|
Chris@16
|
551 \par Iterator Invalidation
|
Chris@16
|
552 Does not invalidate any iterators.
|
Chris@16
|
553 \par Complexity
|
Chris@16
|
554 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
555 \warning In general invoking any method which modifies the internal state of the circular_buffer may
|
Chris@16
|
556 delinearize the internal buffer and invalidate the array ranges returned by <code>array_one()</code>
|
Chris@16
|
557 and <code>array_two()</code> (and their const versions).
|
Chris@16
|
558 \note In the case the internal buffer is linear e.g. <code>|a|b|c|d|e|f|g| | | |</code> the "array one" is
|
Chris@16
|
559 represented by <code>|a|b|c|d|e|f|g|</code> and the "array two" does not exist (the
|
Chris@16
|
560 <code>array_two()</code> method returns an array with the size <code>0</code>).
|
Chris@16
|
561 \sa <code>array_two()</code>, <code>linearize()</code>
|
Chris@16
|
562 */
|
Chris@16
|
563 array_range array_one() {
|
Chris@16
|
564 return array_range(m_first, (m_last <= m_first && !empty() ? m_end : m_last) - m_first);
|
Chris@16
|
565 }
|
Chris@16
|
566
|
Chris@16
|
567 //! Get the second continuous array of the internal buffer.
|
Chris@16
|
568 /*!
|
Chris@16
|
569 This method in combination with <code>array_one()</code> can be useful when passing the stored data into
|
Chris@16
|
570 a legacy C API as an array.
|
Chris@16
|
571 \return The array range of the second continuous array of the internal buffer. In the case the internal buffer
|
Chris@16
|
572 is linear or the <code>circular_buffer</code> is empty the size of the returned array is
|
Chris@16
|
573 <code>0</code>.
|
Chris@16
|
574 \throws Nothing.
|
Chris@16
|
575 \par Exception Safety
|
Chris@16
|
576 No-throw.
|
Chris@16
|
577 \par Iterator Invalidation
|
Chris@16
|
578 Does not invalidate any iterators.
|
Chris@16
|
579 \par Complexity
|
Chris@16
|
580 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
581 \sa <code>array_one()</code>
|
Chris@16
|
582 */
|
Chris@16
|
583 array_range array_two() {
|
Chris@16
|
584 return array_range(m_buff, m_last <= m_first && !empty() ? m_last - m_buff : 0);
|
Chris@16
|
585 }
|
Chris@16
|
586
|
Chris@16
|
587 //! Get the first continuous array of the internal buffer.
|
Chris@16
|
588 /*!
|
Chris@16
|
589 This method in combination with <code>array_two() const</code> can be useful when passing the stored data into
|
Chris@16
|
590 a legacy C API as an array.
|
Chris@16
|
591 \return The array range of the first continuous array of the internal buffer. In the case the
|
Chris@16
|
592 <code>circular_buffer</code> is empty the size of the returned array is <code>0</code>.
|
Chris@16
|
593 \throws Nothing.
|
Chris@16
|
594 \par Exception Safety
|
Chris@16
|
595 No-throw.
|
Chris@16
|
596 \par Iterator Invalidation
|
Chris@16
|
597 Does not invalidate any iterators.
|
Chris@16
|
598 \par Complexity
|
Chris@16
|
599 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
600 \sa <code>array_two() const</code>; <code>array_one()</code> for more details how to pass data into a legacy C
|
Chris@16
|
601 API.
|
Chris@16
|
602 */
|
Chris@16
|
603 const_array_range array_one() const {
|
Chris@16
|
604 return const_array_range(m_first, (m_last <= m_first && !empty() ? m_end : m_last) - m_first);
|
Chris@16
|
605 }
|
Chris@16
|
606
|
Chris@16
|
607 //! Get the second continuous array of the internal buffer.
|
Chris@16
|
608 /*!
|
Chris@16
|
609 This method in combination with <code>array_one() const</code> can be useful when passing the stored data into
|
Chris@16
|
610 a legacy C API as an array.
|
Chris@16
|
611 \return The array range of the second continuous array of the internal buffer. In the case the internal buffer
|
Chris@16
|
612 is linear or the <code>circular_buffer</code> is empty the size of the returned array is
|
Chris@16
|
613 <code>0</code>.
|
Chris@16
|
614 \throws Nothing.
|
Chris@16
|
615 \par Exception Safety
|
Chris@16
|
616 No-throw.
|
Chris@16
|
617 \par Iterator Invalidation
|
Chris@16
|
618 Does not invalidate any iterators.
|
Chris@16
|
619 \par Complexity
|
Chris@16
|
620 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
621 \sa <code>array_one() const</code>
|
Chris@16
|
622 */
|
Chris@16
|
623 const_array_range array_two() const {
|
Chris@16
|
624 return const_array_range(m_buff, m_last <= m_first && !empty() ? m_last - m_buff : 0);
|
Chris@16
|
625 }
|
Chris@16
|
626
|
Chris@16
|
627 //! Linearize the internal buffer into a continuous array.
|
Chris@16
|
628 /*!
|
Chris@16
|
629 This method can be useful when passing the stored data into a legacy C API as an array.
|
Chris@16
|
630 \post <code>\&(*this)[0] \< \&(*this)[1] \< ... \< \&(*this)[size() - 1]</code>
|
Chris@16
|
631 \return A pointer to the beginning of the array or <code>0</code> if empty.
|
Chris@16
|
632 \throws <a href="circular_buffer/implementation.html#circular_buffer.implementation.exceptions_of_move_if_noexcept_t">Exceptions of move_if_noexcept(T&)</a>.
|
Chris@16
|
633 \par Exception Safety
|
Chris@16
|
634 Basic; no-throw if the operations in the <i>Throws</i> section do not throw anything.
|
Chris@16
|
635 \par Iterator Invalidation
|
Chris@16
|
636 Invalidates all iterators pointing to the <code>circular_buffer</code> (except iterators equal to
|
Chris@16
|
637 <code>end()</code>); does not invalidate any iterators if the postcondition (the <i>Effect</i>) is already
|
Chris@16
|
638 met prior calling this method.
|
Chris@16
|
639 \par Complexity
|
Chris@16
|
640 Linear (in the size of the <code>circular_buffer</code>); constant if the postcondition (the
|
Chris@16
|
641 <i>Effect</i>) is already met.
|
Chris@16
|
642 \warning In general invoking any method which modifies the internal state of the <code>circular_buffer</code>
|
Chris@16
|
643 may delinearize the internal buffer and invalidate the returned pointer.
|
Chris@16
|
644 \sa <code>array_one()</code> and <code>array_two()</code> for the other option how to pass data into a legacy
|
Chris@16
|
645 C API; <code>is_linearized()</code>, <code>rotate(const_iterator)</code>
|
Chris@16
|
646 */
|
Chris@16
|
647 pointer linearize() {
|
Chris@16
|
648 if (empty())
|
Chris@16
|
649 return 0;
|
Chris@16
|
650 if (m_first < m_last || m_last == m_buff)
|
Chris@16
|
651 return m_first;
|
Chris@16
|
652 pointer src = m_first;
|
Chris@16
|
653 pointer dest = m_buff;
|
Chris@16
|
654 size_type moved = 0;
|
Chris@16
|
655 size_type constructed = 0;
|
Chris@16
|
656 BOOST_TRY {
|
Chris@16
|
657 for (pointer first = m_first; dest < src; src = first) {
|
Chris@16
|
658 for (size_type ii = 0; src < m_end; ++src, ++dest, ++moved, ++ii) {
|
Chris@16
|
659 if (moved == size()) {
|
Chris@16
|
660 first = dest;
|
Chris@16
|
661 break;
|
Chris@16
|
662 }
|
Chris@16
|
663 if (dest == first) {
|
Chris@16
|
664 first += ii;
|
Chris@16
|
665 break;
|
Chris@16
|
666 }
|
Chris@16
|
667 if (is_uninitialized(dest)) {
|
Chris@101
|
668 boost::container::allocator_traits<Alloc>::construct(m_alloc, boost::addressof(*dest), boost::move_if_noexcept(*src));
|
Chris@16
|
669 ++constructed;
|
Chris@16
|
670 } else {
|
Chris@101
|
671 value_type tmp = boost::move_if_noexcept(*src);
|
Chris@101
|
672 replace(src, boost::move_if_noexcept(*dest));
|
Chris@16
|
673 replace(dest, boost::move(tmp));
|
Chris@16
|
674 }
|
Chris@16
|
675 }
|
Chris@16
|
676 }
|
Chris@16
|
677 } BOOST_CATCH(...) {
|
Chris@16
|
678 m_last += constructed;
|
Chris@16
|
679 m_size += constructed;
|
Chris@16
|
680 BOOST_RETHROW
|
Chris@16
|
681 }
|
Chris@16
|
682 BOOST_CATCH_END
|
Chris@16
|
683 for (src = m_end - constructed; src < m_end; ++src)
|
Chris@16
|
684 destroy_item(src);
|
Chris@16
|
685 m_first = m_buff;
|
Chris@16
|
686 m_last = add(m_buff, size());
|
Chris@16
|
687 #if BOOST_CB_ENABLE_DEBUG
|
Chris@16
|
688 invalidate_iterators_except(end());
|
Chris@16
|
689 #endif
|
Chris@16
|
690 return m_buff;
|
Chris@16
|
691 }
|
Chris@16
|
692
|
Chris@16
|
693 //! Is the <code>circular_buffer</code> linearized?
|
Chris@16
|
694 /*!
|
Chris@16
|
695 \return <code>true</code> if the internal buffer is linearized into a continuous array (i.e. the
|
Chris@16
|
696 <code>circular_buffer</code> meets a condition
|
Chris@16
|
697 <code>\&(*this)[0] \< \&(*this)[1] \< ... \< \&(*this)[size() - 1]</code>);
|
Chris@16
|
698 <code>false</code> otherwise.
|
Chris@16
|
699 \throws Nothing.
|
Chris@16
|
700 \par Exception Safety
|
Chris@16
|
701 No-throw.
|
Chris@16
|
702 \par Iterator Invalidation
|
Chris@16
|
703 Does not invalidate any iterators.
|
Chris@16
|
704 \par Complexity
|
Chris@16
|
705 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
706 \sa <code>linearize()</code>, <code>array_one()</code>, <code>array_two()</code>
|
Chris@16
|
707 */
|
Chris@16
|
708 bool is_linearized() const BOOST_NOEXCEPT { return m_first < m_last || m_last == m_buff; }
|
Chris@16
|
709
|
Chris@16
|
710 //! Rotate elements in the <code>circular_buffer</code>.
|
Chris@16
|
711 /*!
|
Chris@16
|
712 A more effective implementation of
|
Chris@16
|
713 <code><a href="http://www.sgi.com/tech/stl/rotate.html">std::rotate</a></code>.
|
Chris@16
|
714 \pre <code>new_begin</code> is a valid iterator pointing to the <code>circular_buffer</code> <b>except</b> its
|
Chris@16
|
715 end.
|
Chris@16
|
716 \post Before calling the method suppose:<br><br>
|
Chris@16
|
717 <code>m == std::distance(new_begin, end())</code><br><code>n == std::distance(begin(), new_begin)</code>
|
Chris@16
|
718 <br><code>val_0 == *new_begin, val_1 == *(new_begin + 1), ... val_m == *(new_begin + m)</code><br>
|
Chris@16
|
719 <code>val_r1 == *(new_begin - 1), val_r2 == *(new_begin - 2), ... val_rn == *(new_begin - n)</code><br>
|
Chris@16
|
720 <br>then after call to the method:<br><br>
|
Chris@16
|
721 <code>val_0 == (*this)[0] \&\& val_1 == (*this)[1] \&\& ... \&\& val_m == (*this)[m - 1] \&\& val_r1 ==
|
Chris@16
|
722 (*this)[m + n - 1] \&\& val_r2 == (*this)[m + n - 2] \&\& ... \&\& val_rn == (*this)[m]</code>
|
Chris@16
|
723 \param new_begin The new beginning.
|
Chris@16
|
724 \throws See <a href="circular_buffer/implementation.html#circular_buffer.implementation.exceptions_of_move_if_noexcept_t">Exceptions of move_if_noexcept(T&)</a>.
|
Chris@16
|
725 \par Exception Safety
|
Chris@16
|
726 Basic; no-throw if the <code>circular_buffer</code> is full or <code>new_begin</code> points to
|
Chris@16
|
727 <code>begin()</code> or if the operations in the <i>Throws</i> section do not throw anything.
|
Chris@16
|
728 \par Iterator Invalidation
|
Chris@16
|
729 If <code>m \< n</code> invalidates iterators pointing to the last <code>m</code> elements
|
Chris@16
|
730 (<b>including</b> <code>new_begin</code>, but not iterators equal to <code>end()</code>) else invalidates
|
Chris@16
|
731 iterators pointing to the first <code>n</code> elements; does not invalidate any iterators if the
|
Chris@16
|
732 <code>circular_buffer</code> is full.
|
Chris@16
|
733 \par Complexity
|
Chris@16
|
734 Linear (in <code>(std::min)(m, n)</code>); constant if the <code>circular_buffer</code> is full.
|
Chris@16
|
735 \sa <code><a href="http://www.sgi.com/tech/stl/rotate.html">std::rotate</a></code>
|
Chris@16
|
736 */
|
Chris@16
|
737 void rotate(const_iterator new_begin) {
|
Chris@16
|
738 BOOST_CB_ASSERT(new_begin.is_valid(this)); // check for uninitialized or invalidated iterator
|
Chris@16
|
739 BOOST_CB_ASSERT(new_begin.m_it != 0); // check for iterator pointing to end()
|
Chris@16
|
740 if (full()) {
|
Chris@16
|
741 m_first = m_last = const_cast<pointer>(new_begin.m_it);
|
Chris@16
|
742 } else {
|
Chris@16
|
743 difference_type m = end() - new_begin;
|
Chris@16
|
744 difference_type n = new_begin - begin();
|
Chris@16
|
745 if (m < n) {
|
Chris@16
|
746 for (; m > 0; --m) {
|
Chris@101
|
747 push_front(boost::move_if_noexcept(back()));
|
Chris@16
|
748 pop_back();
|
Chris@16
|
749 }
|
Chris@16
|
750 } else {
|
Chris@16
|
751 for (; n > 0; --n) {
|
Chris@101
|
752 push_back(boost::move_if_noexcept(front()));
|
Chris@16
|
753 pop_front();
|
Chris@16
|
754 }
|
Chris@16
|
755 }
|
Chris@16
|
756 }
|
Chris@16
|
757 }
|
Chris@16
|
758
|
Chris@16
|
759 // Size and capacity
|
Chris@16
|
760
|
Chris@16
|
761 //! Get the number of elements currently stored in the <code>circular_buffer</code>.
|
Chris@16
|
762 /*!
|
Chris@16
|
763 \return The number of elements stored in the <code>circular_buffer</code>.
|
Chris@16
|
764 \throws Nothing.
|
Chris@16
|
765 \par Exception Safety
|
Chris@16
|
766 No-throw.
|
Chris@16
|
767 \par Iterator Invalidation
|
Chris@16
|
768 Does not invalidate any iterators.
|
Chris@16
|
769 \par Complexity
|
Chris@16
|
770 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
771 \sa <code>capacity()</code>, <code>max_size()</code>, <code>reserve()</code>,
|
Chris@16
|
772 <code>\link resize() resize(size_type, const_reference)\endlink</code>
|
Chris@16
|
773 */
|
Chris@16
|
774 size_type size() const BOOST_NOEXCEPT { return m_size; }
|
Chris@16
|
775
|
Chris@16
|
776 /*! \brief Get the largest possible size or capacity of the <code>circular_buffer</code>. (It depends on
|
Chris@16
|
777 allocator's %max_size()).
|
Chris@16
|
778 \return The maximum size/capacity the <code>circular_buffer</code> can be set to.
|
Chris@16
|
779 \throws Nothing.
|
Chris@16
|
780 \par Exception Safety
|
Chris@16
|
781 No-throw.
|
Chris@16
|
782 \par Iterator Invalidation
|
Chris@16
|
783 Does not invalidate any iterators.
|
Chris@16
|
784 \par Complexity
|
Chris@16
|
785 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
786 \sa <code>size()</code>, <code>capacity()</code>, <code>reserve()</code>
|
Chris@16
|
787 */
|
Chris@16
|
788 size_type max_size() const BOOST_NOEXCEPT {
|
Chris@101
|
789 return (std::min<size_type>)(boost::container::allocator_traits<Alloc>::max_size(m_alloc), (std::numeric_limits<difference_type>::max)());
|
Chris@16
|
790 }
|
Chris@16
|
791
|
Chris@16
|
792 //! Is the <code>circular_buffer</code> empty?
|
Chris@16
|
793 /*!
|
Chris@16
|
794 \return <code>true</code> if there are no elements stored in the <code>circular_buffer</code>;
|
Chris@16
|
795 <code>false</code> otherwise.
|
Chris@16
|
796 \throws Nothing.
|
Chris@16
|
797 \par Exception Safety
|
Chris@16
|
798 No-throw.
|
Chris@16
|
799 \par Iterator Invalidation
|
Chris@16
|
800 Does not invalidate any iterators.
|
Chris@16
|
801 \par Complexity
|
Chris@16
|
802 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
803 \sa <code>full()</code>
|
Chris@16
|
804 */
|
Chris@16
|
805 bool empty() const BOOST_NOEXCEPT { return size() == 0; }
|
Chris@16
|
806
|
Chris@16
|
807 //! Is the <code>circular_buffer</code> full?
|
Chris@16
|
808 /*!
|
Chris@16
|
809 \return <code>true</code> if the number of elements stored in the <code>circular_buffer</code>
|
Chris@16
|
810 equals the capacity of the <code>circular_buffer</code>; <code>false</code> otherwise.
|
Chris@16
|
811 \throws Nothing.
|
Chris@16
|
812 \par Exception Safety
|
Chris@16
|
813 No-throw.
|
Chris@16
|
814 \par Iterator Invalidation
|
Chris@16
|
815 Does not invalidate any iterators.
|
Chris@16
|
816 \par Complexity
|
Chris@16
|
817 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
818 \sa <code>empty()</code>
|
Chris@16
|
819 */
|
Chris@16
|
820 bool full() const BOOST_NOEXCEPT { return capacity() == size(); }
|
Chris@16
|
821
|
Chris@16
|
822 /*! \brief Get the maximum number of elements which can be inserted into the <code>circular_buffer</code> without
|
Chris@16
|
823 overwriting any of already stored elements.
|
Chris@16
|
824 \return <code>capacity() - size()</code>
|
Chris@16
|
825 \throws Nothing.
|
Chris@16
|
826 \par Exception Safety
|
Chris@16
|
827 No-throw.
|
Chris@16
|
828 \par Iterator Invalidation
|
Chris@16
|
829 Does not invalidate any iterators.
|
Chris@16
|
830 \par Complexity
|
Chris@16
|
831 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
832 \sa <code>capacity()</code>, <code>size()</code>, <code>max_size()</code>
|
Chris@16
|
833 */
|
Chris@16
|
834 size_type reserve() const BOOST_NOEXCEPT { return capacity() - size(); }
|
Chris@16
|
835
|
Chris@16
|
836 //! Get the capacity of the <code>circular_buffer</code>.
|
Chris@16
|
837 /*!
|
Chris@16
|
838 \return The maximum number of elements which can be stored in the <code>circular_buffer</code>.
|
Chris@16
|
839 \throws Nothing.
|
Chris@16
|
840 \par Exception Safety
|
Chris@16
|
841 No-throw.
|
Chris@16
|
842 \par Iterator Invalidation
|
Chris@16
|
843 Does not invalidate any iterators.
|
Chris@16
|
844 \par Complexity
|
Chris@16
|
845 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
846 \sa <code>reserve()</code>, <code>size()</code>, <code>max_size()</code>,
|
Chris@16
|
847 <code>set_capacity(capacity_type)</code>
|
Chris@16
|
848 */
|
Chris@16
|
849 capacity_type capacity() const BOOST_NOEXCEPT { return m_end - m_buff; }
|
Chris@16
|
850
|
Chris@16
|
851 //! Change the capacity of the <code>circular_buffer</code>.
|
Chris@16
|
852 /*!
|
Chris@16
|
853 \pre If <code>T</code> is a move only type, then compiler shall support <code>noexcept</code> modifiers
|
Chris@16
|
854 and move constructor of <code>T</code> must be marked with it (must not throw exceptions).
|
Chris@16
|
855 \post <code>capacity() == new_capacity \&\& size() \<= new_capacity</code><br><br>
|
Chris@16
|
856 If the current number of elements stored in the <code>circular_buffer</code> is greater than the desired
|
Chris@16
|
857 new capacity then number of <code>[size() - new_capacity]</code> <b>last</b> elements will be removed and
|
Chris@16
|
858 the new size will be equal to <code>new_capacity</code>.
|
Chris@16
|
859 \param new_capacity The new capacity.
|
Chris@16
|
860 \throws "An allocation error" if memory is exhausted, (<code>std::bad_alloc</code> if the standard allocator is
|
Chris@16
|
861 used).
|
Chris@16
|
862 Whatever <code>T::T(const T&)</code> throws or nothing if <code>T::T(T&&)</code> is noexcept.
|
Chris@16
|
863 \par Exception Safety
|
Chris@16
|
864 Strong.
|
Chris@16
|
865 \par Iterator Invalidation
|
Chris@16
|
866 Invalidates all iterators pointing to the <code>circular_buffer</code> (except iterators equal to
|
Chris@16
|
867 <code>end()</code>) if the new capacity is different from the original.
|
Chris@16
|
868 \par Complexity
|
Chris@16
|
869 Linear (in <code>min[size(), new_capacity]</code>).
|
Chris@16
|
870 \sa <code>rset_capacity(capacity_type)</code>,
|
Chris@16
|
871 <code>\link resize() resize(size_type, const_reference)\endlink</code>
|
Chris@16
|
872 */
|
Chris@16
|
873 void set_capacity(capacity_type new_capacity) {
|
Chris@16
|
874 if (new_capacity == capacity())
|
Chris@16
|
875 return;
|
Chris@16
|
876 pointer buff = allocate(new_capacity);
|
Chris@16
|
877 iterator b = begin();
|
Chris@16
|
878 BOOST_TRY {
|
Chris@16
|
879 reset(buff,
|
Chris@101
|
880 cb_details::uninitialized_move_if_noexcept(b, b + (std::min)(new_capacity, size()), buff, m_alloc),
|
Chris@16
|
881 new_capacity);
|
Chris@16
|
882 } BOOST_CATCH(...) {
|
Chris@16
|
883 deallocate(buff, new_capacity);
|
Chris@16
|
884 BOOST_RETHROW
|
Chris@16
|
885 }
|
Chris@16
|
886 BOOST_CATCH_END
|
Chris@16
|
887 }
|
Chris@16
|
888
|
Chris@16
|
889 //! Change the size of the <code>circular_buffer</code>.
|
Chris@16
|
890 /*!
|
Chris@16
|
891 \post <code>size() == new_size \&\& capacity() >= new_size</code><br><br>
|
Chris@16
|
892 If the new size is greater than the current size, copies of <code>item</code> will be inserted at the
|
Chris@16
|
893 <b>back</b> of the of the <code>circular_buffer</code> in order to achieve the desired size. In the case
|
Chris@16
|
894 the resulting size exceeds the current capacity the capacity will be set to <code>new_size</code>.<br>
|
Chris@16
|
895 If the current number of elements stored in the <code>circular_buffer</code> is greater than the desired
|
Chris@16
|
896 new size then number of <code>[size() - new_size]</code> <b>last</b> elements will be removed. (The
|
Chris@16
|
897 capacity will remain unchanged.)
|
Chris@16
|
898 \param new_size The new size.
|
Chris@16
|
899 \param item The element the <code>circular_buffer</code> will be filled with in order to gain the requested
|
Chris@16
|
900 size. (See the <i>Effect</i>.)
|
Chris@16
|
901 \throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
|
Chris@16
|
902 used).
|
Chris@16
|
903 Whatever <code>T::T(const T&)</code> throws or nothing if <code>T::T(T&&)</code> is noexcept.
|
Chris@16
|
904 \par Exception Safety
|
Chris@16
|
905 Basic.
|
Chris@16
|
906 \par Iterator Invalidation
|
Chris@16
|
907 Invalidates all iterators pointing to the <code>circular_buffer</code> (except iterators equal to
|
Chris@16
|
908 <code>end()</code>) if the new size is greater than the current capacity. Invalidates iterators pointing
|
Chris@16
|
909 to the removed elements if the new size is lower that the original size. Otherwise it does not invalidate
|
Chris@16
|
910 any iterator.
|
Chris@16
|
911 \par Complexity
|
Chris@16
|
912 Linear (in the new size of the <code>circular_buffer</code>).
|
Chris@16
|
913 \sa <code>\link rresize() rresize(size_type, const_reference)\endlink</code>,
|
Chris@16
|
914 <code>set_capacity(capacity_type)</code>
|
Chris@16
|
915 */
|
Chris@16
|
916 void resize(size_type new_size, param_value_type item = value_type()) {
|
Chris@16
|
917 if (new_size > size()) {
|
Chris@16
|
918 if (new_size > capacity())
|
Chris@16
|
919 set_capacity(new_size);
|
Chris@16
|
920 insert(end(), new_size - size(), item);
|
Chris@16
|
921 } else {
|
Chris@16
|
922 iterator e = end();
|
Chris@16
|
923 erase(e - (size() - new_size), e);
|
Chris@16
|
924 }
|
Chris@16
|
925 }
|
Chris@16
|
926
|
Chris@16
|
927 //! Change the capacity of the <code>circular_buffer</code>.
|
Chris@16
|
928 /*!
|
Chris@16
|
929 \pre If <code>T</code> is a move only type, then compiler shall support <code>noexcept</code> modifiers
|
Chris@16
|
930 and move constructor of <code>T</code> must be marked with it (must not throw exceptions).
|
Chris@16
|
931 \post <code>capacity() == new_capacity \&\& size() \<= new_capacity</code><br><br>
|
Chris@16
|
932 If the current number of elements stored in the <code>circular_buffer</code> is greater than the desired
|
Chris@16
|
933 new capacity then number of <code>[size() - new_capacity]</code> <b>first</b> elements will be removed
|
Chris@16
|
934 and the new size will be equal to <code>new_capacity</code>.
|
Chris@16
|
935 \param new_capacity The new capacity.
|
Chris@16
|
936 \throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
|
Chris@16
|
937 used).
|
Chris@16
|
938 Whatever <code>T::T(const T&)</code> throws or nothing if <code>T::T(T&&)</code> is noexcept.
|
Chris@16
|
939 \par Exception Safety
|
Chris@16
|
940 Strong.
|
Chris@16
|
941 \par Iterator Invalidation
|
Chris@16
|
942 Invalidates all iterators pointing to the <code>circular_buffer</code> (except iterators equal to
|
Chris@16
|
943 <code>end()</code>) if the new capacity is different from the original.
|
Chris@16
|
944 \par Complexity
|
Chris@16
|
945 Linear (in <code>min[size(), new_capacity]</code>).
|
Chris@16
|
946 \sa <code>set_capacity(capacity_type)</code>,
|
Chris@16
|
947 <code>\link rresize() rresize(size_type, const_reference)\endlink</code>
|
Chris@16
|
948 */
|
Chris@16
|
949 void rset_capacity(capacity_type new_capacity) {
|
Chris@16
|
950 if (new_capacity == capacity())
|
Chris@16
|
951 return;
|
Chris@16
|
952 pointer buff = allocate(new_capacity);
|
Chris@16
|
953 iterator e = end();
|
Chris@16
|
954 BOOST_TRY {
|
Chris@101
|
955 reset(buff, cb_details::uninitialized_move_if_noexcept(e - (std::min)(new_capacity, size()),
|
Chris@101
|
956 e, buff, m_alloc), new_capacity);
|
Chris@16
|
957 } BOOST_CATCH(...) {
|
Chris@16
|
958 deallocate(buff, new_capacity);
|
Chris@16
|
959 BOOST_RETHROW
|
Chris@16
|
960 }
|
Chris@16
|
961 BOOST_CATCH_END
|
Chris@16
|
962 }
|
Chris@16
|
963
|
Chris@16
|
964 //! Change the size of the <code>circular_buffer</code>.
|
Chris@16
|
965 /*!
|
Chris@16
|
966 \post <code>size() == new_size \&\& capacity() >= new_size</code><br><br>
|
Chris@16
|
967 If the new size is greater than the current size, copies of <code>item</code> will be inserted at the
|
Chris@16
|
968 <b>front</b> of the of the <code>circular_buffer</code> in order to achieve the desired size. In the case
|
Chris@16
|
969 the resulting size exceeds the current capacity the capacity will be set to <code>new_size</code>.<br>
|
Chris@16
|
970 If the current number of elements stored in the <code>circular_buffer</code> is greater than the desired
|
Chris@16
|
971 new size then number of <code>[size() - new_size]</code> <b>first</b> elements will be removed. (The
|
Chris@16
|
972 capacity will remain unchanged.)
|
Chris@16
|
973 \param new_size The new size.
|
Chris@16
|
974 \param item The element the <code>circular_buffer</code> will be filled with in order to gain the requested
|
Chris@16
|
975 size. (See the <i>Effect</i>.)
|
Chris@16
|
976 \throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
|
Chris@16
|
977 used).
|
Chris@16
|
978 Whatever <code>T::T(const T&)</code> throws or nothing if <code>T::T(T&&)</code> is noexcept.
|
Chris@16
|
979 \par Exception Safety
|
Chris@16
|
980 Basic.
|
Chris@16
|
981 \par Iterator Invalidation
|
Chris@16
|
982 Invalidates all iterators pointing to the <code>circular_buffer</code> (except iterators equal to
|
Chris@16
|
983 <code>end()</code>) if the new size is greater than the current capacity. Invalidates iterators pointing
|
Chris@16
|
984 to the removed elements if the new size is lower that the original size. Otherwise it does not invalidate
|
Chris@16
|
985 any iterator.
|
Chris@16
|
986 \par Complexity
|
Chris@16
|
987 Linear (in the new size of the <code>circular_buffer</code>).
|
Chris@16
|
988 \sa <code>\link resize() resize(size_type, const_reference)\endlink</code>,
|
Chris@16
|
989 <code>rset_capacity(capacity_type)</code>
|
Chris@16
|
990 */
|
Chris@16
|
991 void rresize(size_type new_size, param_value_type item = value_type()) {
|
Chris@16
|
992 if (new_size > size()) {
|
Chris@16
|
993 if (new_size > capacity())
|
Chris@16
|
994 set_capacity(new_size);
|
Chris@16
|
995 rinsert(begin(), new_size - size(), item);
|
Chris@16
|
996 } else {
|
Chris@16
|
997 rerase(begin(), end() - new_size);
|
Chris@16
|
998 }
|
Chris@16
|
999 }
|
Chris@16
|
1000
|
Chris@16
|
1001 // Construction/Destruction
|
Chris@16
|
1002
|
Chris@16
|
1003 //! Create an empty <code>circular_buffer</code> with zero capacity.
|
Chris@16
|
1004 /*!
|
Chris@16
|
1005 \post <code>capacity() == 0 \&\& size() == 0</code>
|
Chris@16
|
1006 \param alloc The allocator.
|
Chris@16
|
1007 \throws Nothing.
|
Chris@16
|
1008 \par Complexity
|
Chris@16
|
1009 Constant.
|
Chris@16
|
1010 \warning Since Boost version 1.36 the behaviour of this constructor has changed. Now the constructor does not
|
Chris@16
|
1011 allocate any memory and both capacity and size are set to zero. Also note when inserting an element
|
Chris@16
|
1012 into a <code>circular_buffer</code> with zero capacity (e.g. by
|
Chris@16
|
1013 <code>\link push_back() push_back(const_reference)\endlink</code> or
|
Chris@16
|
1014 <code>\link insert(iterator, param_value_type) insert(iterator, value_type)\endlink</code>) nothing
|
Chris@16
|
1015 will be inserted and the size (as well as capacity) remains zero.
|
Chris@16
|
1016 \note You can explicitly set the capacity by calling the <code>set_capacity(capacity_type)</code> method or you
|
Chris@16
|
1017 can use the other constructor with the capacity specified.
|
Chris@16
|
1018 \sa <code>circular_buffer(capacity_type, const allocator_type& alloc)</code>,
|
Chris@16
|
1019 <code>set_capacity(capacity_type)</code>
|
Chris@16
|
1020 */
|
Chris@16
|
1021 explicit circular_buffer(const allocator_type& alloc = allocator_type()) BOOST_NOEXCEPT
|
Chris@16
|
1022 : m_buff(0), m_end(0), m_first(0), m_last(0), m_size(0), m_alloc(alloc) {}
|
Chris@16
|
1023
|
Chris@16
|
1024 //! Create an empty <code>circular_buffer</code> with the specified capacity.
|
Chris@16
|
1025 /*!
|
Chris@16
|
1026 \post <code>capacity() == buffer_capacity \&\& size() == 0</code>
|
Chris@16
|
1027 \param buffer_capacity The maximum number of elements which can be stored in the <code>circular_buffer</code>.
|
Chris@16
|
1028 \param alloc The allocator.
|
Chris@16
|
1029 \throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
|
Chris@16
|
1030 used).
|
Chris@16
|
1031 \par Complexity
|
Chris@16
|
1032 Constant.
|
Chris@16
|
1033 */
|
Chris@16
|
1034 explicit circular_buffer(capacity_type buffer_capacity, const allocator_type& alloc = allocator_type())
|
Chris@16
|
1035 : m_size(0), m_alloc(alloc) {
|
Chris@16
|
1036 initialize_buffer(buffer_capacity);
|
Chris@16
|
1037 m_first = m_last = m_buff;
|
Chris@16
|
1038 }
|
Chris@16
|
1039
|
Chris@16
|
1040 /*! \brief Create a full <code>circular_buffer</code> with the specified capacity and filled with <code>n</code>
|
Chris@16
|
1041 copies of <code>item</code>.
|
Chris@16
|
1042 \post <code>capacity() == n \&\& full() \&\& (*this)[0] == item \&\& (*this)[1] == item \&\& ... \&\&
|
Chris@16
|
1043 (*this)[n - 1] == item </code>
|
Chris@16
|
1044 \param n The number of elements the created <code>circular_buffer</code> will be filled with.
|
Chris@16
|
1045 \param item The element the created <code>circular_buffer</code> will be filled with.
|
Chris@16
|
1046 \param alloc The allocator.
|
Chris@16
|
1047 \throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
|
Chris@16
|
1048 used).
|
Chris@16
|
1049 Whatever <code>T::T(const T&)</code> throws.
|
Chris@16
|
1050 \par Complexity
|
Chris@16
|
1051 Linear (in the <code>n</code>).
|
Chris@16
|
1052 */
|
Chris@16
|
1053 circular_buffer(size_type n, param_value_type item, const allocator_type& alloc = allocator_type())
|
Chris@16
|
1054 : m_size(n), m_alloc(alloc) {
|
Chris@16
|
1055 initialize_buffer(n, item);
|
Chris@16
|
1056 m_first = m_last = m_buff;
|
Chris@16
|
1057 }
|
Chris@16
|
1058
|
Chris@16
|
1059 /*! \brief Create a <code>circular_buffer</code> with the specified capacity and filled with <code>n</code>
|
Chris@16
|
1060 copies of <code>item</code>.
|
Chris@16
|
1061 \pre <code>buffer_capacity >= n</code>
|
Chris@16
|
1062 \post <code>capacity() == buffer_capacity \&\& size() == n \&\& (*this)[0] == item \&\& (*this)[1] == item
|
Chris@16
|
1063 \&\& ... \&\& (*this)[n - 1] == item</code>
|
Chris@16
|
1064 \param buffer_capacity The capacity of the created <code>circular_buffer</code>.
|
Chris@16
|
1065 \param n The number of elements the created <code>circular_buffer</code> will be filled with.
|
Chris@16
|
1066 \param item The element the created <code>circular_buffer</code> will be filled with.
|
Chris@16
|
1067 \param alloc The allocator.
|
Chris@16
|
1068 \throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
|
Chris@16
|
1069 used).
|
Chris@16
|
1070 Whatever <code>T::T(const T&)</code> throws.
|
Chris@16
|
1071 \par Complexity
|
Chris@16
|
1072 Linear (in the <code>n</code>).
|
Chris@16
|
1073 */
|
Chris@16
|
1074 circular_buffer(capacity_type buffer_capacity, size_type n, param_value_type item,
|
Chris@16
|
1075 const allocator_type& alloc = allocator_type())
|
Chris@16
|
1076 : m_size(n), m_alloc(alloc) {
|
Chris@16
|
1077 BOOST_CB_ASSERT(buffer_capacity >= size()); // check for capacity lower than size
|
Chris@16
|
1078 initialize_buffer(buffer_capacity, item);
|
Chris@16
|
1079 m_first = m_buff;
|
Chris@16
|
1080 m_last = buffer_capacity == n ? m_buff : m_buff + n;
|
Chris@16
|
1081 }
|
Chris@16
|
1082
|
Chris@16
|
1083 //! The copy constructor.
|
Chris@16
|
1084 /*!
|
Chris@16
|
1085 Creates a copy of the specified <code>circular_buffer</code>.
|
Chris@16
|
1086 \post <code>*this == cb</code>
|
Chris@16
|
1087 \param cb The <code>circular_buffer</code> to be copied.
|
Chris@16
|
1088 \throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
|
Chris@16
|
1089 used).
|
Chris@16
|
1090 Whatever <code>T::T(const T&)</code> throws.
|
Chris@16
|
1091 \par Complexity
|
Chris@16
|
1092 Linear (in the size of <code>cb</code>).
|
Chris@16
|
1093 */
|
Chris@16
|
1094 circular_buffer(const circular_buffer<T, Alloc>& cb)
|
Chris@16
|
1095 :
|
Chris@16
|
1096 #if BOOST_CB_ENABLE_DEBUG
|
Chris@16
|
1097 debug_iterator_registry(),
|
Chris@16
|
1098 #endif
|
Chris@16
|
1099 m_size(cb.size()), m_alloc(cb.get_allocator()) {
|
Chris@16
|
1100 initialize_buffer(cb.capacity());
|
Chris@16
|
1101 m_first = m_buff;
|
Chris@16
|
1102 BOOST_TRY {
|
Chris@101
|
1103 m_last = cb_details::uninitialized_copy(cb.begin(), cb.end(), m_buff, m_alloc);
|
Chris@16
|
1104 } BOOST_CATCH(...) {
|
Chris@16
|
1105 deallocate(m_buff, cb.capacity());
|
Chris@16
|
1106 BOOST_RETHROW
|
Chris@16
|
1107 }
|
Chris@16
|
1108 BOOST_CATCH_END
|
Chris@16
|
1109 if (m_last == m_end)
|
Chris@16
|
1110 m_last = m_buff;
|
Chris@16
|
1111 }
|
Chris@16
|
1112
|
Chris@16
|
1113 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
1114 //! The move constructor.
|
Chris@16
|
1115 /*! \brief Move constructs a <code>circular_buffer</code> from <code>cb</code>, leaving <code>cb</code> empty.
|
Chris@16
|
1116 \pre C++ compiler with rvalue references support.
|
Chris@16
|
1117 \post <code>cb.empty()</code>
|
Chris@16
|
1118 \param cb <code>circular_buffer</code> to 'steal' value from.
|
Chris@16
|
1119 \throws Nothing.
|
Chris@16
|
1120 \par Constant.
|
Chris@16
|
1121 */
|
Chris@16
|
1122 circular_buffer(circular_buffer<T, Alloc>&& cb) BOOST_NOEXCEPT
|
Chris@16
|
1123 : m_buff(0), m_end(0), m_first(0), m_last(0), m_size(0), m_alloc(cb.get_allocator()) {
|
Chris@16
|
1124 cb.swap(*this);
|
Chris@16
|
1125 }
|
Chris@16
|
1126 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
1127
|
Chris@16
|
1128 //! Create a full <code>circular_buffer</code> filled with a copy of the range.
|
Chris@16
|
1129 /*!
|
Chris@16
|
1130 \pre Valid range <code>[first, last)</code>.<br>
|
Chris@16
|
1131 <code>first</code> and <code>last</code> have to meet the requirements of
|
Chris@16
|
1132 <a href="http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>.
|
Chris@16
|
1133 \post <code>capacity() == std::distance(first, last) \&\& full() \&\& (*this)[0]== *first \&\&
|
Chris@16
|
1134 (*this)[1] == *(first + 1) \&\& ... \&\& (*this)[std::distance(first, last) - 1] == *(last - 1)</code>
|
Chris@16
|
1135 \param first The beginning of the range to be copied.
|
Chris@16
|
1136 \param last The end of the range to be copied.
|
Chris@16
|
1137 \param alloc The allocator.
|
Chris@16
|
1138 \throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
|
Chris@16
|
1139 used).
|
Chris@16
|
1140 Whatever <code>T::T(const T&)</code> throws.
|
Chris@16
|
1141 \par Complexity
|
Chris@16
|
1142 Linear (in the <code>std::distance(first, last)</code>).
|
Chris@16
|
1143 */
|
Chris@16
|
1144 template <class InputIterator>
|
Chris@16
|
1145 circular_buffer(InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type())
|
Chris@16
|
1146 : m_alloc(alloc) {
|
Chris@16
|
1147 initialize(first, last, is_integral<InputIterator>());
|
Chris@16
|
1148 }
|
Chris@16
|
1149
|
Chris@16
|
1150 //! Create a <code>circular_buffer</code> with the specified capacity and filled with a copy of the range.
|
Chris@16
|
1151 /*!
|
Chris@16
|
1152 \pre Valid range <code>[first, last)</code>.<br>
|
Chris@16
|
1153 <code>first</code> and <code>last</code> have to meet the requirements of
|
Chris@16
|
1154 <a href="http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>.
|
Chris@16
|
1155 \post <code>capacity() == buffer_capacity \&\& size() \<= std::distance(first, last) \&\&
|
Chris@16
|
1156 (*this)[0]== *(last - buffer_capacity) \&\& (*this)[1] == *(last - buffer_capacity + 1) \&\& ... \&\&
|
Chris@16
|
1157 (*this)[buffer_capacity - 1] == *(last - 1)</code><br><br>
|
Chris@16
|
1158 If the number of items to be copied from the range <code>[first, last)</code> is greater than the
|
Chris@16
|
1159 specified <code>buffer_capacity</code> then only elements from the range
|
Chris@16
|
1160 <code>[last - buffer_capacity, last)</code> will be copied.
|
Chris@16
|
1161 \param buffer_capacity The capacity of the created <code>circular_buffer</code>.
|
Chris@16
|
1162 \param first The beginning of the range to be copied.
|
Chris@16
|
1163 \param last The end of the range to be copied.
|
Chris@16
|
1164 \param alloc The allocator.
|
Chris@16
|
1165 \throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
|
Chris@16
|
1166 used).
|
Chris@16
|
1167 Whatever <code>T::T(const T&)</code> throws.
|
Chris@16
|
1168 \par Complexity
|
Chris@16
|
1169 Linear (in <code>std::distance(first, last)</code>; in
|
Chris@16
|
1170 <code>min[capacity, std::distance(first, last)]</code> if the <code>InputIterator</code> is a
|
Chris@16
|
1171 <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a>).
|
Chris@16
|
1172 */
|
Chris@16
|
1173 template <class InputIterator>
|
Chris@16
|
1174 circular_buffer(capacity_type buffer_capacity, InputIterator first, InputIterator last,
|
Chris@16
|
1175 const allocator_type& alloc = allocator_type())
|
Chris@16
|
1176 : m_alloc(alloc) {
|
Chris@16
|
1177 initialize(buffer_capacity, first, last, is_integral<InputIterator>());
|
Chris@16
|
1178 }
|
Chris@16
|
1179
|
Chris@16
|
1180 //! The destructor.
|
Chris@16
|
1181 /*!
|
Chris@16
|
1182 Destroys the <code>circular_buffer</code>.
|
Chris@16
|
1183 \throws Nothing.
|
Chris@16
|
1184 \par Iterator Invalidation
|
Chris@16
|
1185 Invalidates all iterators pointing to the <code>circular_buffer</code> (including iterators equal to
|
Chris@16
|
1186 <code>end()</code>).
|
Chris@16
|
1187 \par Complexity
|
Chris@16
|
1188 Constant (in the size of the <code>circular_buffer</code>) for scalar types; linear for other types.
|
Chris@16
|
1189 \sa <code>clear()</code>
|
Chris@16
|
1190 */
|
Chris@16
|
1191 ~circular_buffer() BOOST_NOEXCEPT {
|
Chris@16
|
1192 destroy();
|
Chris@16
|
1193 #if BOOST_CB_ENABLE_DEBUG
|
Chris@16
|
1194 invalidate_all_iterators();
|
Chris@16
|
1195 #endif
|
Chris@16
|
1196 }
|
Chris@16
|
1197
|
Chris@16
|
1198 public:
|
Chris@16
|
1199 // Assign methods
|
Chris@16
|
1200
|
Chris@16
|
1201 //! The assign operator.
|
Chris@16
|
1202 /*!
|
Chris@16
|
1203 Makes this <code>circular_buffer</code> to become a copy of the specified <code>circular_buffer</code>.
|
Chris@16
|
1204 \post <code>*this == cb</code>
|
Chris@16
|
1205 \param cb The <code>circular_buffer</code> to be copied.
|
Chris@16
|
1206 \throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
|
Chris@16
|
1207 used).
|
Chris@16
|
1208 Whatever <code>T::T(const T&)</code> throws.
|
Chris@16
|
1209 \par Exception Safety
|
Chris@16
|
1210 Strong.
|
Chris@16
|
1211 \par Iterator Invalidation
|
Chris@16
|
1212 Invalidates all iterators pointing to this <code>circular_buffer</code> (except iterators equal to
|
Chris@16
|
1213 <code>end()</code>).
|
Chris@16
|
1214 \par Complexity
|
Chris@16
|
1215 Linear (in the size of <code>cb</code>).
|
Chris@16
|
1216 \sa <code>\link assign(size_type, param_value_type) assign(size_type, const_reference)\endlink</code>,
|
Chris@16
|
1217 <code>\link assign(capacity_type, size_type, param_value_type)
|
Chris@16
|
1218 assign(capacity_type, size_type, const_reference)\endlink</code>,
|
Chris@16
|
1219 <code>assign(InputIterator, InputIterator)</code>,
|
Chris@16
|
1220 <code>assign(capacity_type, InputIterator, InputIterator)</code>
|
Chris@16
|
1221 */
|
Chris@16
|
1222 circular_buffer<T, Alloc>& operator = (const circular_buffer<T, Alloc>& cb) {
|
Chris@16
|
1223 if (this == &cb)
|
Chris@16
|
1224 return *this;
|
Chris@16
|
1225 pointer buff = allocate(cb.capacity());
|
Chris@16
|
1226 BOOST_TRY {
|
Chris@101
|
1227 reset(buff, cb_details::uninitialized_copy(cb.begin(), cb.end(), buff, m_alloc), cb.capacity());
|
Chris@16
|
1228 } BOOST_CATCH(...) {
|
Chris@16
|
1229 deallocate(buff, cb.capacity());
|
Chris@16
|
1230 BOOST_RETHROW
|
Chris@16
|
1231 }
|
Chris@16
|
1232 BOOST_CATCH_END
|
Chris@16
|
1233 return *this;
|
Chris@16
|
1234 }
|
Chris@16
|
1235
|
Chris@16
|
1236 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
1237 /*! \brief Move assigns content of <code>cb</code> to <code>*this</code>, leaving <code>cb</code> empty.
|
Chris@16
|
1238 \pre C++ compiler with rvalue references support.
|
Chris@16
|
1239 \post <code>cb.empty()</code>
|
Chris@16
|
1240 \param cb <code>circular_buffer</code> to 'steal' value from.
|
Chris@16
|
1241 \throws Nothing.
|
Chris@16
|
1242 \par Complexity
|
Chris@16
|
1243 Constant.
|
Chris@16
|
1244 */
|
Chris@16
|
1245 circular_buffer<T, Alloc>& operator = (circular_buffer<T, Alloc>&& cb) BOOST_NOEXCEPT {
|
Chris@16
|
1246 cb.swap(*this); // now `this` holds `cb`
|
Chris@16
|
1247 circular_buffer<T, Alloc>(get_allocator()) // temprary that holds initial `cb` allocator
|
Chris@16
|
1248 .swap(cb); // makes `cb` empty
|
Chris@16
|
1249 return *this;
|
Chris@16
|
1250 }
|
Chris@16
|
1251 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
|
Chris@16
|
1252
|
Chris@16
|
1253 //! Assign <code>n</code> items into the <code>circular_buffer</code>.
|
Chris@16
|
1254 /*!
|
Chris@16
|
1255 The content of the <code>circular_buffer</code> will be removed and replaced with <code>n</code> copies of the
|
Chris@16
|
1256 <code>item</code>.
|
Chris@16
|
1257 \post <code>capacity() == n \&\& size() == n \&\& (*this)[0] == item \&\& (*this)[1] == item \&\& ... \&\&
|
Chris@16
|
1258 (*this) [n - 1] == item</code>
|
Chris@16
|
1259 \param n The number of elements the <code>circular_buffer</code> will be filled with.
|
Chris@16
|
1260 \param item The element the <code>circular_buffer</code> will be filled with.
|
Chris@16
|
1261 \throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
|
Chris@16
|
1262 used).
|
Chris@16
|
1263 Whatever <code>T::T(const T&)</code> throws.
|
Chris@16
|
1264 \par Exception Safety
|
Chris@16
|
1265 Basic.
|
Chris@16
|
1266 \par Iterator Invalidation
|
Chris@16
|
1267 Invalidates all iterators pointing to the <code>circular_buffer</code> (except iterators equal to
|
Chris@16
|
1268 <code>end()</code>).
|
Chris@16
|
1269 \par Complexity
|
Chris@16
|
1270 Linear (in the <code>n</code>).
|
Chris@16
|
1271 \sa <code>\link operator=(const circular_buffer&) operator=\endlink</code>,
|
Chris@16
|
1272 <code>\link assign(capacity_type, size_type, param_value_type)
|
Chris@16
|
1273 assign(capacity_type, size_type, const_reference)\endlink</code>,
|
Chris@16
|
1274 <code>assign(InputIterator, InputIterator)</code>,
|
Chris@16
|
1275 <code>assign(capacity_type, InputIterator, InputIterator)</code>
|
Chris@16
|
1276 */
|
Chris@16
|
1277 void assign(size_type n, param_value_type item) {
|
Chris@16
|
1278 assign_n(n, n, cb_details::assign_n<param_value_type, allocator_type>(n, item, m_alloc));
|
Chris@16
|
1279 }
|
Chris@16
|
1280
|
Chris@16
|
1281 //! Assign <code>n</code> items into the <code>circular_buffer</code> specifying the capacity.
|
Chris@16
|
1282 /*!
|
Chris@16
|
1283 The capacity of the <code>circular_buffer</code> will be set to the specified value and the content of the
|
Chris@16
|
1284 <code>circular_buffer</code> will be removed and replaced with <code>n</code> copies of the <code>item</code>.
|
Chris@16
|
1285 \pre <code>capacity >= n</code>
|
Chris@16
|
1286 \post <code>capacity() == buffer_capacity \&\& size() == n \&\& (*this)[0] == item \&\& (*this)[1] == item
|
Chris@16
|
1287 \&\& ... \&\& (*this) [n - 1] == item </code>
|
Chris@16
|
1288 \param buffer_capacity The new capacity.
|
Chris@16
|
1289 \param n The number of elements the <code>circular_buffer</code> will be filled with.
|
Chris@16
|
1290 \param item The element the <code>circular_buffer</code> will be filled with.
|
Chris@16
|
1291 \throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
|
Chris@16
|
1292 used).
|
Chris@16
|
1293 Whatever <code>T::T(const T&)</code> throws.
|
Chris@16
|
1294 \par Exception Safety
|
Chris@16
|
1295 Basic.
|
Chris@16
|
1296 \par Iterator Invalidation
|
Chris@16
|
1297 Invalidates all iterators pointing to the <code>circular_buffer</code> (except iterators equal to
|
Chris@16
|
1298 <code>end()</code>).
|
Chris@16
|
1299 \par Complexity
|
Chris@16
|
1300 Linear (in the <code>n</code>).
|
Chris@16
|
1301 \sa <code>\link operator=(const circular_buffer&) operator=\endlink</code>,
|
Chris@16
|
1302 <code>\link assign(size_type, param_value_type) assign(size_type, const_reference)\endlink</code>,
|
Chris@16
|
1303 <code>assign(InputIterator, InputIterator)</code>,
|
Chris@16
|
1304 <code>assign(capacity_type, InputIterator, InputIterator)</code>
|
Chris@16
|
1305 */
|
Chris@16
|
1306 void assign(capacity_type buffer_capacity, size_type n, param_value_type item) {
|
Chris@16
|
1307 BOOST_CB_ASSERT(buffer_capacity >= n); // check for new capacity lower than n
|
Chris@16
|
1308 assign_n(buffer_capacity, n, cb_details::assign_n<param_value_type, allocator_type>(n, item, m_alloc));
|
Chris@16
|
1309 }
|
Chris@16
|
1310
|
Chris@16
|
1311 //! Assign a copy of the range into the <code>circular_buffer</code>.
|
Chris@16
|
1312 /*!
|
Chris@16
|
1313 The content of the <code>circular_buffer</code> will be removed and replaced with copies of elements from the
|
Chris@16
|
1314 specified range.
|
Chris@16
|
1315 \pre Valid range <code>[first, last)</code>.<br>
|
Chris@16
|
1316 <code>first</code> and <code>last</code> have to meet the requirements of
|
Chris@16
|
1317 <a href="http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>.
|
Chris@16
|
1318 \post <code>capacity() == std::distance(first, last) \&\& size() == std::distance(first, last) \&\&
|
Chris@16
|
1319 (*this)[0]== *first \&\& (*this)[1] == *(first + 1) \&\& ... \&\& (*this)[std::distance(first, last) - 1]
|
Chris@16
|
1320 == *(last - 1)</code>
|
Chris@16
|
1321 \param first The beginning of the range to be copied.
|
Chris@16
|
1322 \param last The end of the range to be copied.
|
Chris@16
|
1323 \throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
|
Chris@16
|
1324 used).
|
Chris@16
|
1325 Whatever <code>T::T(const T&)</code> throws.
|
Chris@16
|
1326 \par Exception Safety
|
Chris@16
|
1327 Basic.
|
Chris@16
|
1328 \par Iterator Invalidation
|
Chris@16
|
1329 Invalidates all iterators pointing to the <code>circular_buffer</code> (except iterators equal to
|
Chris@16
|
1330 <code>end()</code>).
|
Chris@16
|
1331 \par Complexity
|
Chris@16
|
1332 Linear (in the <code>std::distance(first, last)</code>).
|
Chris@16
|
1333 \sa <code>\link operator=(const circular_buffer&) operator=\endlink</code>,
|
Chris@16
|
1334 <code>\link assign(size_type, param_value_type) assign(size_type, const_reference)\endlink</code>,
|
Chris@16
|
1335 <code>\link assign(capacity_type, size_type, param_value_type)
|
Chris@16
|
1336 assign(capacity_type, size_type, const_reference)\endlink</code>,
|
Chris@16
|
1337 <code>assign(capacity_type, InputIterator, InputIterator)</code>
|
Chris@16
|
1338 */
|
Chris@16
|
1339 template <class InputIterator>
|
Chris@16
|
1340 void assign(InputIterator first, InputIterator last) {
|
Chris@16
|
1341 assign(first, last, is_integral<InputIterator>());
|
Chris@16
|
1342 }
|
Chris@16
|
1343
|
Chris@16
|
1344 //! Assign a copy of the range into the <code>circular_buffer</code> specifying the capacity.
|
Chris@16
|
1345 /*!
|
Chris@16
|
1346 The capacity of the <code>circular_buffer</code> will be set to the specified value and the content of the
|
Chris@16
|
1347 <code>circular_buffer</code> will be removed and replaced with copies of elements from the specified range.
|
Chris@16
|
1348 \pre Valid range <code>[first, last)</code>.<br>
|
Chris@16
|
1349 <code>first</code> and <code>last</code> have to meet the requirements of
|
Chris@16
|
1350 <a href="http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>.
|
Chris@16
|
1351 \post <code>capacity() == buffer_capacity \&\& size() \<= std::distance(first, last) \&\&
|
Chris@16
|
1352 (*this)[0]== *(last - buffer_capacity) \&\& (*this)[1] == *(last - buffer_capacity + 1) \&\& ... \&\&
|
Chris@16
|
1353 (*this)[buffer_capacity - 1] == *(last - 1)</code><br><br>
|
Chris@16
|
1354 If the number of items to be copied from the range <code>[first, last)</code> is greater than the
|
Chris@16
|
1355 specified <code>buffer_capacity</code> then only elements from the range
|
Chris@16
|
1356 <code>[last - buffer_capacity, last)</code> will be copied.
|
Chris@16
|
1357 \param buffer_capacity The new capacity.
|
Chris@16
|
1358 \param first The beginning of the range to be copied.
|
Chris@16
|
1359 \param last The end of the range to be copied.
|
Chris@16
|
1360 \throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
|
Chris@16
|
1361 used).
|
Chris@16
|
1362 Whatever <code>T::T(const T&)</code> throws.
|
Chris@16
|
1363 \par Exception Safety
|
Chris@16
|
1364 Basic.
|
Chris@16
|
1365 \par Iterator Invalidation
|
Chris@16
|
1366 Invalidates all iterators pointing to the <code>circular_buffer</code> (except iterators equal to
|
Chris@16
|
1367 <code>end()</code>).
|
Chris@16
|
1368 \par Complexity
|
Chris@16
|
1369 Linear (in <code>std::distance(first, last)</code>; in
|
Chris@16
|
1370 <code>min[capacity, std::distance(first, last)]</code> if the <code>InputIterator</code> is a
|
Chris@16
|
1371 <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a>).
|
Chris@16
|
1372 \sa <code>\link operator=(const circular_buffer&) operator=\endlink</code>,
|
Chris@16
|
1373 <code>\link assign(size_type, param_value_type) assign(size_type, const_reference)\endlink</code>,
|
Chris@16
|
1374 <code>\link assign(capacity_type, size_type, param_value_type)
|
Chris@16
|
1375 assign(capacity_type, size_type, const_reference)\endlink</code>,
|
Chris@16
|
1376 <code>assign(InputIterator, InputIterator)</code>
|
Chris@16
|
1377 */
|
Chris@16
|
1378 template <class InputIterator>
|
Chris@16
|
1379 void assign(capacity_type buffer_capacity, InputIterator first, InputIterator last) {
|
Chris@16
|
1380 assign(buffer_capacity, first, last, is_integral<InputIterator>());
|
Chris@16
|
1381 }
|
Chris@16
|
1382
|
Chris@16
|
1383 //! Swap the contents of two <code>circular_buffer</code>s.
|
Chris@16
|
1384 /*!
|
Chris@16
|
1385 \post <code>this</code> contains elements of <code>cb</code> and vice versa; the capacity of <code>this</code>
|
Chris@16
|
1386 equals to the capacity of <code>cb</code> and vice versa.
|
Chris@16
|
1387 \param cb The <code>circular_buffer</code> whose content will be swapped.
|
Chris@16
|
1388 \throws Nothing.
|
Chris@16
|
1389 \par Exception Safety
|
Chris@16
|
1390 No-throw.
|
Chris@16
|
1391 \par Iterator Invalidation
|
Chris@16
|
1392 Invalidates all iterators of both <code>circular_buffer</code>s. (On the other hand the iterators still
|
Chris@16
|
1393 point to the same elements but within another container. If you want to rely on this feature you have to
|
Chris@16
|
1394 turn the <a href="#debug">Debug Support</a> off otherwise an assertion will report an error if such
|
Chris@16
|
1395 invalidated iterator is used.)
|
Chris@16
|
1396 \par Complexity
|
Chris@16
|
1397 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
1398 \sa <code>swap(circular_buffer<T, Alloc>&, circular_buffer<T, Alloc>&)</code>
|
Chris@16
|
1399 */
|
Chris@16
|
1400 void swap(circular_buffer<T, Alloc>& cb) BOOST_NOEXCEPT {
|
Chris@16
|
1401 swap_allocator(cb, is_stateless<allocator_type>());
|
Chris@16
|
1402 std::swap(m_buff, cb.m_buff);
|
Chris@16
|
1403 std::swap(m_end, cb.m_end);
|
Chris@16
|
1404 std::swap(m_first, cb.m_first);
|
Chris@16
|
1405 std::swap(m_last, cb.m_last);
|
Chris@16
|
1406 std::swap(m_size, cb.m_size);
|
Chris@16
|
1407 #if BOOST_CB_ENABLE_DEBUG
|
Chris@16
|
1408 invalidate_all_iterators();
|
Chris@16
|
1409 cb.invalidate_all_iterators();
|
Chris@16
|
1410 #endif
|
Chris@16
|
1411 }
|
Chris@16
|
1412
|
Chris@16
|
1413 // push and pop
|
Chris@16
|
1414 private:
|
Chris@16
|
1415 template <class ValT>
|
Chris@16
|
1416 void push_back_impl(ValT item) {
|
Chris@16
|
1417 if (full()) {
|
Chris@16
|
1418 if (empty())
|
Chris@16
|
1419 return;
|
Chris@16
|
1420 replace(m_last, static_cast<ValT>(item));
|
Chris@16
|
1421 increment(m_last);
|
Chris@16
|
1422 m_first = m_last;
|
Chris@16
|
1423 } else {
|
Chris@101
|
1424 boost::container::allocator_traits<Alloc>::construct(m_alloc, boost::addressof(*m_last), static_cast<ValT>(item));
|
Chris@16
|
1425 increment(m_last);
|
Chris@16
|
1426 ++m_size;
|
Chris@16
|
1427 }
|
Chris@16
|
1428 }
|
Chris@16
|
1429
|
Chris@16
|
1430 template <class ValT>
|
Chris@16
|
1431 void push_front_impl(ValT item) {
|
Chris@16
|
1432 BOOST_TRY {
|
Chris@16
|
1433 if (full()) {
|
Chris@16
|
1434 if (empty())
|
Chris@16
|
1435 return;
|
Chris@16
|
1436 decrement(m_first);
|
Chris@16
|
1437 replace(m_first, static_cast<ValT>(item));
|
Chris@16
|
1438 m_last = m_first;
|
Chris@16
|
1439 } else {
|
Chris@16
|
1440 decrement(m_first);
|
Chris@101
|
1441 boost::container::allocator_traits<Alloc>::construct(m_alloc, boost::addressof(*m_first), static_cast<ValT>(item));
|
Chris@16
|
1442 ++m_size;
|
Chris@16
|
1443 }
|
Chris@16
|
1444 } BOOST_CATCH(...) {
|
Chris@16
|
1445 increment(m_first);
|
Chris@16
|
1446 BOOST_RETHROW
|
Chris@16
|
1447 }
|
Chris@16
|
1448 BOOST_CATCH_END
|
Chris@16
|
1449 }
|
Chris@16
|
1450
|
Chris@16
|
1451 public:
|
Chris@16
|
1452 //! Insert a new element at the end of the <code>circular_buffer</code>.
|
Chris@16
|
1453 /*!
|
Chris@16
|
1454 \post if <code>capacity() > 0</code> then <code>back() == item</code><br>
|
Chris@16
|
1455 If the <code>circular_buffer</code> is full, the first element will be removed. If the capacity is
|
Chris@16
|
1456 <code>0</code>, nothing will be inserted.
|
Chris@16
|
1457 \param item The element to be inserted.
|
Chris@16
|
1458 \throws Whatever <code>T::T(const T&)</code> throws.
|
Chris@16
|
1459 Whatever <code>T::operator = (const T&)</code> throws.
|
Chris@16
|
1460 \par Exception Safety
|
Chris@16
|
1461 Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything.
|
Chris@16
|
1462 \par Iterator Invalidation
|
Chris@16
|
1463 Does not invalidate any iterators with the exception of iterators pointing to the overwritten element.
|
Chris@16
|
1464 \par Complexity
|
Chris@16
|
1465 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
1466 \sa <code>\link push_front() push_front(const_reference)\endlink</code>,
|
Chris@16
|
1467 <code>pop_back()</code>, <code>pop_front()</code>
|
Chris@16
|
1468 */
|
Chris@16
|
1469 void push_back(param_value_type item) {
|
Chris@16
|
1470 push_back_impl<param_value_type>(item);
|
Chris@16
|
1471 }
|
Chris@16
|
1472
|
Chris@16
|
1473 //! Insert a new element at the end of the <code>circular_buffer</code> using rvalue references or rvalues references emulation.
|
Chris@16
|
1474 /*!
|
Chris@16
|
1475 \post if <code>capacity() > 0</code> then <code>back() == item</code><br>
|
Chris@16
|
1476 If the <code>circular_buffer</code> is full, the first element will be removed. If the capacity is
|
Chris@16
|
1477 <code>0</code>, nothing will be inserted.
|
Chris@16
|
1478 \param item The element to be inserted.
|
Chris@16
|
1479 \throws Whatever <code>T::T(T&&)</code> throws.
|
Chris@16
|
1480 Whatever <code>T::operator = (T&&)</code> throws.
|
Chris@16
|
1481 \par Exception Safety
|
Chris@16
|
1482 Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything.
|
Chris@16
|
1483 \par Iterator Invalidation
|
Chris@16
|
1484 Does not invalidate any iterators with the exception of iterators pointing to the overwritten element.
|
Chris@16
|
1485 \par Complexity
|
Chris@16
|
1486 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
1487 \sa <code>\link push_front() push_front(const_reference)\endlink</code>,
|
Chris@16
|
1488 <code>pop_back()</code>, <code>pop_front()</code>
|
Chris@16
|
1489 */
|
Chris@16
|
1490 void push_back(rvalue_type item) {
|
Chris@16
|
1491 push_back_impl<rvalue_type>(boost::move(item));
|
Chris@16
|
1492 }
|
Chris@16
|
1493
|
Chris@16
|
1494 //! Insert a new default-constructed element at the end of the <code>circular_buffer</code>.
|
Chris@16
|
1495 /*!
|
Chris@16
|
1496 \post if <code>capacity() > 0</code> then <code>back() == item</code><br>
|
Chris@16
|
1497 If the <code>circular_buffer</code> is full, the first element will be removed. If the capacity is
|
Chris@16
|
1498 <code>0</code>, nothing will be inserted.
|
Chris@16
|
1499 \throws Whatever <code>T::T()</code> throws.
|
Chris@16
|
1500 Whatever <code>T::T(T&&)</code> throws.
|
Chris@16
|
1501 Whatever <code>T::operator = (T&&)</code> throws.
|
Chris@16
|
1502 \par Exception Safety
|
Chris@16
|
1503 Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything.
|
Chris@16
|
1504 \par Iterator Invalidation
|
Chris@16
|
1505 Does not invalidate any iterators with the exception of iterators pointing to the overwritten element.
|
Chris@16
|
1506 \par Complexity
|
Chris@16
|
1507 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
1508 \sa <code>\link push_front() push_front(const_reference)\endlink</code>,
|
Chris@16
|
1509 <code>pop_back()</code>, <code>pop_front()</code>
|
Chris@16
|
1510 */
|
Chris@16
|
1511 void push_back() {
|
Chris@16
|
1512 value_type temp;
|
Chris@16
|
1513 push_back(boost::move(temp));
|
Chris@16
|
1514 }
|
Chris@16
|
1515
|
Chris@16
|
1516 //! Insert a new element at the beginning of the <code>circular_buffer</code>.
|
Chris@16
|
1517 /*!
|
Chris@16
|
1518 \post if <code>capacity() > 0</code> then <code>front() == item</code><br>
|
Chris@16
|
1519 If the <code>circular_buffer</code> is full, the last element will be removed. If the capacity is
|
Chris@16
|
1520 <code>0</code>, nothing will be inserted.
|
Chris@16
|
1521 \param item The element to be inserted.
|
Chris@16
|
1522 \throws Whatever <code>T::T(const T&)</code> throws.
|
Chris@16
|
1523 Whatever <code>T::operator = (const T&)</code> throws.
|
Chris@16
|
1524 \par Exception Safety
|
Chris@16
|
1525 Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything.
|
Chris@16
|
1526 \par Iterator Invalidation
|
Chris@16
|
1527 Does not invalidate any iterators with the exception of iterators pointing to the overwritten element.
|
Chris@16
|
1528 \par Complexity
|
Chris@16
|
1529 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
1530 \sa <code>\link push_back() push_back(const_reference)\endlink</code>,
|
Chris@16
|
1531 <code>pop_back()</code>, <code>pop_front()</code>
|
Chris@16
|
1532 */
|
Chris@16
|
1533 void push_front(param_value_type item) {
|
Chris@16
|
1534 push_front_impl<param_value_type>(item);
|
Chris@16
|
1535 }
|
Chris@16
|
1536
|
Chris@16
|
1537 //! Insert a new element at the beginning of the <code>circular_buffer</code> using rvalue references or rvalues references emulation.
|
Chris@16
|
1538 /*!
|
Chris@16
|
1539 \post if <code>capacity() > 0</code> then <code>front() == item</code><br>
|
Chris@16
|
1540 If the <code>circular_buffer</code> is full, the last element will be removed. If the capacity is
|
Chris@16
|
1541 <code>0</code>, nothing will be inserted.
|
Chris@16
|
1542 \param item The element to be inserted.
|
Chris@16
|
1543 \throws Whatever <code>T::T(T&&)</code> throws.
|
Chris@16
|
1544 Whatever <code>T::operator = (T&&)</code> throws.
|
Chris@16
|
1545 \par Exception Safety
|
Chris@16
|
1546 Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything.
|
Chris@16
|
1547 \par Iterator Invalidation
|
Chris@16
|
1548 Does not invalidate any iterators with the exception of iterators pointing to the overwritten element.
|
Chris@16
|
1549 \par Complexity
|
Chris@16
|
1550 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
1551 \sa <code>\link push_back() push_back(const_reference)\endlink</code>,
|
Chris@16
|
1552 <code>pop_back()</code>, <code>pop_front()</code>
|
Chris@16
|
1553 */
|
Chris@16
|
1554 void push_front(rvalue_type item) {
|
Chris@16
|
1555 push_front_impl<rvalue_type>(boost::move(item));
|
Chris@16
|
1556 }
|
Chris@16
|
1557
|
Chris@16
|
1558 //! Insert a new default-constructed element at the beginning of the <code>circular_buffer</code>.
|
Chris@16
|
1559 /*!
|
Chris@16
|
1560 \post if <code>capacity() > 0</code> then <code>front() == item</code><br>
|
Chris@16
|
1561 If the <code>circular_buffer</code> is full, the last element will be removed. If the capacity is
|
Chris@16
|
1562 <code>0</code>, nothing will be inserted.
|
Chris@16
|
1563 \throws Whatever <code>T::T()</code> throws.
|
Chris@16
|
1564 Whatever <code>T::T(T&&)</code> throws.
|
Chris@16
|
1565 Whatever <code>T::operator = (T&&)</code> throws.
|
Chris@16
|
1566 \par Exception Safety
|
Chris@16
|
1567 Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything.
|
Chris@16
|
1568 \par Iterator Invalidation
|
Chris@16
|
1569 Does not invalidate any iterators with the exception of iterators pointing to the overwritten element.
|
Chris@16
|
1570 \par Complexity
|
Chris@16
|
1571 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
1572 \sa <code>\link push_back() push_back(const_reference)\endlink</code>,
|
Chris@16
|
1573 <code>pop_back()</code>, <code>pop_front()</code>
|
Chris@16
|
1574 */
|
Chris@16
|
1575 void push_front() {
|
Chris@16
|
1576 value_type temp;
|
Chris@16
|
1577 push_front(boost::move(temp));
|
Chris@16
|
1578 }
|
Chris@16
|
1579
|
Chris@16
|
1580 //! Remove the last element from the <code>circular_buffer</code>.
|
Chris@16
|
1581 /*!
|
Chris@16
|
1582 \pre <code>!empty()</code>
|
Chris@16
|
1583 \post The last element is removed from the <code>circular_buffer</code>.
|
Chris@16
|
1584 \throws Nothing.
|
Chris@16
|
1585 \par Exception Safety
|
Chris@16
|
1586 No-throw.
|
Chris@16
|
1587 \par Iterator Invalidation
|
Chris@16
|
1588 Invalidates only iterators pointing to the removed element.
|
Chris@16
|
1589 \par Complexity
|
Chris@16
|
1590 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
1591 \sa <code>pop_front()</code>, <code>\link push_back() push_back(const_reference)\endlink</code>,
|
Chris@16
|
1592 <code>\link push_front() push_front(const_reference)\endlink</code>
|
Chris@16
|
1593 */
|
Chris@16
|
1594 void pop_back() {
|
Chris@16
|
1595 BOOST_CB_ASSERT(!empty()); // check for empty buffer (back element not available)
|
Chris@16
|
1596 decrement(m_last);
|
Chris@16
|
1597 destroy_item(m_last);
|
Chris@16
|
1598 --m_size;
|
Chris@16
|
1599 }
|
Chris@16
|
1600
|
Chris@16
|
1601 //! Remove the first element from the <code>circular_buffer</code>.
|
Chris@16
|
1602 /*!
|
Chris@16
|
1603 \pre <code>!empty()</code>
|
Chris@16
|
1604 \post The first element is removed from the <code>circular_buffer</code>.
|
Chris@16
|
1605 \throws Nothing.
|
Chris@16
|
1606 \par Exception Safety
|
Chris@16
|
1607 No-throw.
|
Chris@16
|
1608 \par Iterator Invalidation
|
Chris@16
|
1609 Invalidates only iterators pointing to the removed element.
|
Chris@16
|
1610 \par Complexity
|
Chris@16
|
1611 Constant (in the size of the <code>circular_buffer</code>).
|
Chris@16
|
1612 \sa <code>pop_back()</code>, <code>\link push_back() push_back(const_reference)\endlink</code>,
|
Chris@16
|
1613 <code>\link push_front() push_front(const_reference)\endlink</code>
|
Chris@16
|
1614 */
|
Chris@16
|
1615 void pop_front() {
|
Chris@16
|
1616 BOOST_CB_ASSERT(!empty()); // check for empty buffer (front element not available)
|
Chris@16
|
1617 destroy_item(m_first);
|
Chris@16
|
1618 increment(m_first);
|
Chris@16
|
1619 --m_size;
|
Chris@16
|
1620 }
|
Chris@16
|
1621 private:
|
Chris@16
|
1622 template <class ValT>
|
Chris@16
|
1623 iterator insert_impl(iterator pos, ValT item) {
|
Chris@16
|
1624 BOOST_CB_ASSERT(pos.is_valid(this)); // check for uninitialized or invalidated iterator
|
Chris@16
|
1625 iterator b = begin();
|
Chris@16
|
1626 if (full() && pos == b)
|
Chris@16
|
1627 return b;
|
Chris@16
|
1628 return insert_item<ValT>(pos, static_cast<ValT>(item));
|
Chris@16
|
1629 }
|
Chris@16
|
1630
|
Chris@16
|
1631 public:
|
Chris@16
|
1632 // Insert
|
Chris@16
|
1633
|
Chris@16
|
1634 //! Insert an element at the specified position.
|
Chris@16
|
1635 /*!
|
Chris@16
|
1636 \pre <code>pos</code> is a valid iterator pointing to the <code>circular_buffer</code> or its end.
|
Chris@16
|
1637 \post The <code>item</code> will be inserted at the position <code>pos</code>.<br>
|
Chris@16
|
1638 If the <code>circular_buffer</code> is full, the first element will be overwritten. If the
|
Chris@16
|
1639 <code>circular_buffer</code> is full and the <code>pos</code> points to <code>begin()</code>, then the
|
Chris@16
|
1640 <code>item</code> will not be inserted. If the capacity is <code>0</code>, nothing will be inserted.
|
Chris@16
|
1641 \param pos An iterator specifying the position where the <code>item</code> will be inserted.
|
Chris@16
|
1642 \param item The element to be inserted.
|
Chris@16
|
1643 \return Iterator to the inserted element or <code>begin()</code> if the <code>item</code> is not inserted. (See
|
Chris@16
|
1644 the <i>Effect</i>.)
|
Chris@16
|
1645 \throws Whatever <code>T::T(const T&)</code> throws.
|
Chris@16
|
1646 Whatever <code>T::operator = (const T&)</code> throws.
|
Chris@16
|
1647 <a href="circular_buffer/implementation.html#circular_buffer.implementation.exceptions_of_move_if_noexcept_t">Exceptions of move_if_noexcept(T&)</a>.
|
Chris@16
|
1648
|
Chris@16
|
1649 \par Exception Safety
|
Chris@16
|
1650 Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything.
|
Chris@16
|
1651 \par Iterator Invalidation
|
Chris@16
|
1652 Invalidates iterators pointing to the elements at the insertion point (including <code>pos</code>) and
|
Chris@16
|
1653 iterators behind the insertion point (towards the end; except iterators equal to <code>end()</code>). It
|
Chris@16
|
1654 also invalidates iterators pointing to the overwritten element.
|
Chris@16
|
1655 \par Complexity
|
Chris@16
|
1656 Linear (in <code>std::distance(pos, end())</code>).
|
Chris@16
|
1657 \sa <code>\link insert(iterator, size_type, param_value_type)
|
Chris@16
|
1658 insert(iterator, size_type, value_type)\endlink</code>,
|
Chris@16
|
1659 <code>insert(iterator, InputIterator, InputIterator)</code>,
|
Chris@16
|
1660 <code>\link rinsert(iterator, param_value_type) rinsert(iterator, value_type)\endlink</code>,
|
Chris@16
|
1661 <code>\link rinsert(iterator, size_type, param_value_type)
|
Chris@16
|
1662 rinsert(iterator, size_type, value_type)\endlink</code>,
|
Chris@16
|
1663 <code>rinsert(iterator, InputIterator, InputIterator)</code>
|
Chris@16
|
1664 */
|
Chris@16
|
1665 iterator insert(iterator pos, param_value_type item) {
|
Chris@16
|
1666 return insert_impl<param_value_type>(pos, item);
|
Chris@16
|
1667 }
|
Chris@16
|
1668
|
Chris@16
|
1669 //! Insert an element at the specified position.
|
Chris@16
|
1670 /*!
|
Chris@16
|
1671 \pre <code>pos</code> is a valid iterator pointing to the <code>circular_buffer</code> or its end.
|
Chris@16
|
1672 \post The <code>item</code> will be inserted at the position <code>pos</code>.<br>
|
Chris@16
|
1673 If the <code>circular_buffer</code> is full, the first element will be overwritten. If the
|
Chris@16
|
1674 <code>circular_buffer</code> is full and the <code>pos</code> points to <code>begin()</code>, then the
|
Chris@16
|
1675 <code>item</code> will not be inserted. If the capacity is <code>0</code>, nothing will be inserted.
|
Chris@16
|
1676 \param pos An iterator specifying the position where the <code>item</code> will be inserted.
|
Chris@16
|
1677 \param item The element to be inserted.
|
Chris@16
|
1678 \return Iterator to the inserted element or <code>begin()</code> if the <code>item</code> is not inserted. (See
|
Chris@16
|
1679 the <i>Effect</i>.)
|
Chris@16
|
1680 \throws Whatever <code>T::T(T&&)</code> throws.
|
Chris@16
|
1681 Whatever <code>T::operator = (T&&)</code> throws.
|
Chris@16
|
1682 <a href="circular_buffer/implementation.html#circular_buffer.implementation.exceptions_of_move_if_noexcept_t">Exceptions of move_if_noexcept(T&)</a>.
|
Chris@16
|
1683 \par Exception Safety
|
Chris@16
|
1684 Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything.
|
Chris@16
|
1685 \par Iterator Invalidation
|
Chris@16
|
1686 Invalidates iterators pointing to the elements at the insertion point (including <code>pos</code>) and
|
Chris@16
|
1687 iterators behind the insertion point (towards the end; except iterators equal to <code>end()</code>). It
|
Chris@16
|
1688 also invalidates iterators pointing to the overwritten element.
|
Chris@16
|
1689 \par Complexity
|
Chris@16
|
1690 Linear (in <code>std::distance(pos, end())</code>).
|
Chris@16
|
1691 \sa <code>\link insert(iterator, size_type, param_value_type)
|
Chris@16
|
1692 insert(iterator, size_type, value_type)\endlink</code>,
|
Chris@16
|
1693 <code>insert(iterator, InputIterator, InputIterator)</code>,
|
Chris@16
|
1694 <code>\link rinsert(iterator, param_value_type) rinsert(iterator, value_type)\endlink</code>,
|
Chris@16
|
1695 <code>\link rinsert(iterator, size_type, param_value_type)
|
Chris@16
|
1696 rinsert(iterator, size_type, value_type)\endlink</code>,
|
Chris@16
|
1697 <code>rinsert(iterator, InputIterator, InputIterator)</code>
|
Chris@16
|
1698 */
|
Chris@16
|
1699 iterator insert(iterator pos, rvalue_type item) {
|
Chris@16
|
1700 return insert_impl<rvalue_type>(pos, boost::move(item));
|
Chris@16
|
1701 }
|
Chris@16
|
1702
|
Chris@16
|
1703 //! Insert a default-constructed element at the specified position.
|
Chris@16
|
1704 /*!
|
Chris@16
|
1705 \pre <code>pos</code> is a valid iterator pointing to the <code>circular_buffer</code> or its end.
|
Chris@16
|
1706 \post The <code>item</code> will be inserted at the position <code>pos</code>.<br>
|
Chris@16
|
1707 If the <code>circular_buffer</code> is full, the first element will be overwritten. If the
|
Chris@16
|
1708 <code>circular_buffer</code> is full and the <code>pos</code> points to <code>begin()</code>, then the
|
Chris@16
|
1709 <code>item</code> will not be inserted. If the capacity is <code>0</code>, nothing will be inserted.
|
Chris@16
|
1710 \param pos An iterator specifying the position where the <code>item</code> will be inserted.
|
Chris@16
|
1711 \return Iterator to the inserted element or <code>begin()</code> if the <code>item</code> is not inserted. (See
|
Chris@16
|
1712 the <i>Effect</i>.)
|
Chris@16
|
1713 \throws Whatever <code>T::T()</code> throws.
|
Chris@16
|
1714 Whatever <code>T::T(T&&)</code> throws.
|
Chris@16
|
1715 Whatever <code>T::operator = (T&&)</code> throws.
|
Chris@16
|
1716 <a href="circular_buffer/implementation.html#circular_buffer.implementation.exceptions_of_move_if_noexcept_t">Exceptions of move_if_noexcept(T&)</a>.
|
Chris@16
|
1717 \par Exception Safety
|
Chris@16
|
1718 Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything.
|
Chris@16
|
1719 \par Iterator Invalidation
|
Chris@16
|
1720 Invalidates iterators pointing to the elements at the insertion point (including <code>pos</code>) and
|
Chris@16
|
1721 iterators behind the insertion point (towards the end; except iterators equal to <code>end()</code>). It
|
Chris@16
|
1722 also invalidates iterators pointing to the overwritten element.
|
Chris@16
|
1723 \par Complexity
|
Chris@16
|
1724 Linear (in <code>std::distance(pos, end())</code>).
|
Chris@16
|
1725 \sa <code>\link insert(iterator, size_type, param_value_type)
|
Chris@16
|
1726 insert(iterator, size_type, value_type)\endlink</code>,
|
Chris@16
|
1727 <code>insert(iterator, InputIterator, InputIterator)</code>,
|
Chris@16
|
1728 <code>\link rinsert(iterator, param_value_type) rinsert(iterator, value_type)\endlink</code>,
|
Chris@16
|
1729 <code>\link rinsert(iterator, size_type, param_value_type)
|
Chris@16
|
1730 rinsert(iterator, size_type, value_type)\endlink</code>,
|
Chris@16
|
1731 <code>rinsert(iterator, InputIterator, InputIterator)</code>
|
Chris@16
|
1732 */
|
Chris@16
|
1733 iterator insert(iterator pos) {
|
Chris@16
|
1734 value_type temp;
|
Chris@16
|
1735 return insert(pos, boost::move(temp));
|
Chris@16
|
1736 }
|
Chris@16
|
1737
|
Chris@16
|
1738 //! Insert <code>n</code> copies of the <code>item</code> at the specified position.
|
Chris@16
|
1739 /*!
|
Chris@16
|
1740 \pre <code>pos</code> is a valid iterator pointing to the <code>circular_buffer</code> or its end.
|
Chris@16
|
1741 \post The number of <code>min[n, (pos - begin()) + reserve()]</code> elements will be inserted at the position
|
Chris@16
|
1742 <code>pos</code>.<br>The number of <code>min[pos - begin(), max[0, n - reserve()]]</code> elements will
|
Chris@16
|
1743 be overwritten at the beginning of the <code>circular_buffer</code>.<br>(See <i>Example</i> for the
|
Chris@16
|
1744 explanation.)
|
Chris@16
|
1745 \param pos An iterator specifying the position where the <code>item</code>s will be inserted.
|
Chris@16
|
1746 \param n The number of <code>item</code>s the to be inserted.
|
Chris@16
|
1747 \param item The element whose copies will be inserted.
|
Chris@16
|
1748 \throws Whatever <code>T::T(const T&)</code> throws.
|
Chris@16
|
1749 Whatever <code>T::operator = (const T&)</code> throws.
|
Chris@16
|
1750 <a href="circular_buffer/implementation.html#circular_buffer.implementation.exceptions_of_move_if_noexcept_t">Exceptions of move_if_noexcept(T&)</a>.
|
Chris@16
|
1751 \par Exception Safety
|
Chris@16
|
1752 Basic; no-throw if the operations in the <i>Throws</i> section do not throw anything.
|
Chris@16
|
1753 \par Iterator Invalidation
|
Chris@16
|
1754 Invalidates iterators pointing to the elements at the insertion point (including <code>pos</code>) and
|
Chris@16
|
1755 iterators behind the insertion point (towards the end; except iterators equal to <code>end()</code>). It
|
Chris@16
|
1756 also invalidates iterators pointing to the overwritten elements.
|
Chris@16
|
1757 \par Complexity
|
Chris@16
|
1758 Linear (in <code>min[capacity(), std::distance(pos, end()) + n]</code>).
|
Chris@16
|
1759 \par Example
|
Chris@16
|
1760 Consider a <code>circular_buffer</code> with the capacity of 6 and the size of 4. Its internal buffer may
|
Chris@16
|
1761 look like the one below.<br><br>
|
Chris@16
|
1762 <code>|1|2|3|4| | |</code><br>
|
Chris@16
|
1763 <code>p ___^</code><br><br>After inserting 5 elements at the position <code>p</code>:<br><br>
|
Chris@16
|
1764 <code>insert(p, (size_t)5, 0);</code><br><br>actually only 4 elements get inserted and elements
|
Chris@16
|
1765 <code>1</code> and <code>2</code> are overwritten. This is due to the fact the insert operation preserves
|
Chris@16
|
1766 the capacity. After insertion the internal buffer looks like this:<br><br><code>|0|0|0|0|3|4|</code><br>
|
Chris@16
|
1767 <br>For comparison if the capacity would not be preserved the internal buffer would then result in
|
Chris@16
|
1768 <code>|1|2|0|0|0|0|0|3|4|</code>.
|
Chris@16
|
1769 \sa <code>\link insert(iterator, param_value_type) insert(iterator, value_type)\endlink</code>,
|
Chris@16
|
1770 <code>insert(iterator, InputIterator, InputIterator)</code>,
|
Chris@16
|
1771 <code>\link rinsert(iterator, param_value_type) rinsert(iterator, value_type)\endlink</code>,
|
Chris@16
|
1772 <code>\link rinsert(iterator, size_type, param_value_type)
|
Chris@16
|
1773 rinsert(iterator, size_type, value_type)\endlink</code>,
|
Chris@16
|
1774 <code>rinsert(iterator, InputIterator, InputIterator)</code>
|
Chris@16
|
1775 */
|
Chris@16
|
1776 void insert(iterator pos, size_type n, param_value_type item) {
|
Chris@16
|
1777 BOOST_CB_ASSERT(pos.is_valid(this)); // check for uninitialized or invalidated iterator
|
Chris@16
|
1778 if (n == 0)
|
Chris@16
|
1779 return;
|
Chris@16
|
1780 size_type copy = capacity() - (end() - pos);
|
Chris@16
|
1781 if (copy == 0)
|
Chris@16
|
1782 return;
|
Chris@16
|
1783 if (n > copy)
|
Chris@16
|
1784 n = copy;
|
Chris@16
|
1785 insert_n(pos, n, cb_details::item_wrapper<const_pointer, param_value_type>(item));
|
Chris@16
|
1786 }
|
Chris@16
|
1787
|
Chris@16
|
1788 //! Insert the range <code>[first, last)</code> at the specified position.
|
Chris@16
|
1789 /*!
|
Chris@16
|
1790 \pre <code>pos</code> is a valid iterator pointing to the <code>circular_buffer</code> or its end.<br>
|
Chris@16
|
1791 Valid range <code>[first, last)</code> where <code>first</code> and <code>last</code> meet the
|
Chris@16
|
1792 requirements of an <a href="http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>.
|
Chris@16
|
1793 \post Elements from the range
|
Chris@16
|
1794 <code>[first + max[0, distance(first, last) - (pos - begin()) - reserve()], last)</code> will be
|
Chris@16
|
1795 inserted at the position <code>pos</code>.<br>The number of <code>min[pos - begin(), max[0,
|
Chris@16
|
1796 distance(first, last) - reserve()]]</code> elements will be overwritten at the beginning of the
|
Chris@16
|
1797 <code>circular_buffer</code>.<br>(See <i>Example</i> for the explanation.)
|
Chris@16
|
1798 \param pos An iterator specifying the position where the range will be inserted.
|
Chris@16
|
1799 \param first The beginning of the range to be inserted.
|
Chris@16
|
1800 \param last The end of the range to be inserted.
|
Chris@16
|
1801 \throws Whatever <code>T::T(const T&)</code> throws if the <code>InputIterator</code> is not a move iterator.
|
Chris@16
|
1802 Whatever <code>T::operator = (const T&)</code> throws if the <code>InputIterator</code> is not a move iterator.
|
Chris@16
|
1803 Whatever <code>T::T(T&&)</code> throws if the <code>InputIterator</code> is a move iterator.
|
Chris@16
|
1804 Whatever <code>T::operator = (T&&)</code> throws if the <code>InputIterator</code> is a move iterator.
|
Chris@16
|
1805 \par Exception Safety
|
Chris@16
|
1806 Basic; no-throw if the operations in the <i>Throws</i> section do not throw anything.
|
Chris@16
|
1807 \par Iterator Invalidation
|
Chris@16
|
1808 Invalidates iterators pointing to the elements at the insertion point (including <code>pos</code>) and
|
Chris@16
|
1809 iterators behind the insertion point (towards the end; except iterators equal to <code>end()</code>). It
|
Chris@16
|
1810 also invalidates iterators pointing to the overwritten elements.
|
Chris@16
|
1811 \par Complexity
|
Chris@16
|
1812 Linear (in <code>[std::distance(pos, end()) + std::distance(first, last)]</code>; in
|
Chris@16
|
1813 <code>min[capacity(), std::distance(pos, end()) + std::distance(first, last)]</code> if the
|
Chris@16
|
1814 <code>InputIterator</code> is a
|
Chris@16
|
1815 <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a>).
|
Chris@16
|
1816 \par Example
|
Chris@16
|
1817 Consider a <code>circular_buffer</code> with the capacity of 6 and the size of 4. Its internal buffer may
|
Chris@16
|
1818 look like the one below.<br><br>
|
Chris@16
|
1819 <code>|1|2|3|4| | |</code><br>
|
Chris@16
|
1820 <code>p ___^</code><br><br>After inserting a range of elements at the position <code>p</code>:<br><br>
|
Chris@16
|
1821 <code>int array[] = { 5, 6, 7, 8, 9 };</code><br><code>insert(p, array, array + 5);</code><br><br>
|
Chris@16
|
1822 actually only elements <code>6</code>, <code>7</code>, <code>8</code> and <code>9</code> from the
|
Chris@16
|
1823 specified range get inserted and elements <code>1</code> and <code>2</code> are overwritten. This is due
|
Chris@16
|
1824 to the fact the insert operation preserves the capacity. After insertion the internal buffer looks like
|
Chris@16
|
1825 this:<br><br><code>|6|7|8|9|3|4|</code><br><br>For comparison if the capacity would not be preserved the
|
Chris@16
|
1826 internal buffer would then result in <code>|1|2|5|6|7|8|9|3|4|</code>.
|
Chris@16
|
1827 \sa <code>\link insert(iterator, param_value_type) insert(iterator, value_type)\endlink</code>,
|
Chris@16
|
1828 <code>\link insert(iterator, size_type, param_value_type)
|
Chris@16
|
1829 insert(iterator, size_type, value_type)\endlink</code>, <code>\link rinsert(iterator, param_value_type)
|
Chris@16
|
1830 rinsert(iterator, value_type)\endlink</code>, <code>\link rinsert(iterator, size_type, param_value_type)
|
Chris@16
|
1831 rinsert(iterator, size_type, value_type)\endlink</code>,
|
Chris@16
|
1832 <code>rinsert(iterator, InputIterator, InputIterator)</code>
|
Chris@16
|
1833 */
|
Chris@16
|
1834 template <class InputIterator>
|
Chris@16
|
1835 void insert(iterator pos, InputIterator first, InputIterator last) {
|
Chris@16
|
1836 BOOST_CB_ASSERT(pos.is_valid(this)); // check for uninitialized or invalidated iterator
|
Chris@16
|
1837 insert(pos, first, last, is_integral<InputIterator>());
|
Chris@16
|
1838 }
|
Chris@16
|
1839
|
Chris@16
|
1840 private:
|
Chris@16
|
1841 template <class ValT>
|
Chris@16
|
1842 iterator rinsert_impl(iterator pos, ValT item) {
|
Chris@16
|
1843 BOOST_CB_ASSERT(pos.is_valid(this)); // check for uninitialized or invalidated iterator
|
Chris@16
|
1844 if (full() && pos.m_it == 0)
|
Chris@16
|
1845 return end();
|
Chris@16
|
1846 if (pos == begin()) {
|
Chris@16
|
1847 BOOST_TRY {
|
Chris@16
|
1848 decrement(m_first);
|
Chris@16
|
1849 construct_or_replace(!full(), m_first, static_cast<ValT>(item));
|
Chris@16
|
1850 } BOOST_CATCH(...) {
|
Chris@16
|
1851 increment(m_first);
|
Chris@16
|
1852 BOOST_RETHROW
|
Chris@16
|
1853 }
|
Chris@16
|
1854 BOOST_CATCH_END
|
Chris@16
|
1855 pos.m_it = m_first;
|
Chris@16
|
1856 } else {
|
Chris@16
|
1857 pointer src = m_first;
|
Chris@16
|
1858 pointer dest = m_first;
|
Chris@16
|
1859 decrement(dest);
|
Chris@16
|
1860 pos.m_it = map_pointer(pos.m_it);
|
Chris@16
|
1861 bool construct = !full();
|
Chris@16
|
1862 BOOST_TRY {
|
Chris@16
|
1863 while (src != pos.m_it) {
|
Chris@101
|
1864 construct_or_replace(construct, dest, boost::move_if_noexcept(*src));
|
Chris@16
|
1865 increment(src);
|
Chris@16
|
1866 increment(dest);
|
Chris@16
|
1867 construct = false;
|
Chris@16
|
1868 }
|
Chris@16
|
1869 decrement(pos.m_it);
|
Chris@16
|
1870 replace(pos.m_it, static_cast<ValT>(item));
|
Chris@16
|
1871 } BOOST_CATCH(...) {
|
Chris@16
|
1872 if (!construct && !full()) {
|
Chris@16
|
1873 decrement(m_first);
|
Chris@16
|
1874 ++m_size;
|
Chris@16
|
1875 }
|
Chris@16
|
1876 BOOST_RETHROW
|
Chris@16
|
1877 }
|
Chris@16
|
1878 BOOST_CATCH_END
|
Chris@16
|
1879 decrement(m_first);
|
Chris@16
|
1880 }
|
Chris@16
|
1881 if (full())
|
Chris@16
|
1882 m_last = m_first;
|
Chris@16
|
1883 else
|
Chris@16
|
1884 ++m_size;
|
Chris@16
|
1885 return iterator(this, pos.m_it);
|
Chris@16
|
1886 }
|
Chris@16
|
1887
|
Chris@16
|
1888 public:
|
Chris@16
|
1889
|
Chris@16
|
1890 //! Insert an element before the specified position.
|
Chris@16
|
1891 /*!
|
Chris@16
|
1892 \pre <code>pos</code> is a valid iterator pointing to the <code>circular_buffer</code> or its end.
|
Chris@16
|
1893 \post The <code>item</code> will be inserted before the position <code>pos</code>.<br>
|
Chris@16
|
1894 If the <code>circular_buffer</code> is full, the last element will be overwritten. If the
|
Chris@16
|
1895 <code>circular_buffer</code> is full and the <code>pos</code> points to <code>end()</code>, then the
|
Chris@16
|
1896 <code>item</code> will not be inserted. If the capacity is <code>0</code>, nothing will be inserted.
|
Chris@16
|
1897 \param pos An iterator specifying the position before which the <code>item</code> will be inserted.
|
Chris@16
|
1898 \param item The element to be inserted.
|
Chris@16
|
1899 \return Iterator to the inserted element or <code>end()</code> if the <code>item</code> is not inserted. (See
|
Chris@16
|
1900 the <i>Effect</i>.)
|
Chris@16
|
1901 \throws Whatever <code>T::T(const T&)</code> throws.
|
Chris@16
|
1902 Whatever <code>T::operator = (const T&)</code> throws.
|
Chris@16
|
1903 <a href="circular_buffer/implementation.html#circular_buffer.implementation.exceptions_of_move_if_noexcept_t">Exceptions of move_if_noexcept(T&)</a>.
|
Chris@16
|
1904 \par Exception Safety
|
Chris@16
|
1905 Basic; no-throw if the operations in the <i>Throws</i> section do not throw anything.
|
Chris@16
|
1906 \par Iterator Invalidation
|
Chris@16
|
1907 Invalidates iterators pointing to the elements before the insertion point (towards the beginning and
|
Chris@16
|
1908 excluding <code>pos</code>). It also invalidates iterators pointing to the overwritten element.
|
Chris@16
|
1909 \par Complexity
|
Chris@16
|
1910 Linear (in <code>std::distance(begin(), pos)</code>).
|
Chris@16
|
1911 \sa <code>\link rinsert(iterator, size_type, param_value_type)
|
Chris@16
|
1912 rinsert(iterator, size_type, value_type)\endlink</code>,
|
Chris@16
|
1913 <code>rinsert(iterator, InputIterator, InputIterator)</code>,
|
Chris@16
|
1914 <code>\link insert(iterator, param_value_type) insert(iterator, value_type)\endlink</code>,
|
Chris@16
|
1915 <code>\link insert(iterator, size_type, param_value_type)
|
Chris@16
|
1916 insert(iterator, size_type, value_type)\endlink</code>,
|
Chris@16
|
1917 <code>insert(iterator, InputIterator, InputIterator)</code>
|
Chris@16
|
1918 */
|
Chris@16
|
1919 iterator rinsert(iterator pos, param_value_type item) {
|
Chris@16
|
1920 return rinsert_impl<param_value_type>(pos, item);
|
Chris@16
|
1921 }
|
Chris@16
|
1922
|
Chris@16
|
1923 //! Insert an element before the specified position.
|
Chris@16
|
1924 /*!
|
Chris@16
|
1925 \pre <code>pos</code> is a valid iterator pointing to the <code>circular_buffer</code> or its end.
|
Chris@16
|
1926 \post The <code>item</code> will be inserted before the position <code>pos</code>.<br>
|
Chris@16
|
1927 If the <code>circular_buffer</code> is full, the last element will be overwritten. If the
|
Chris@16
|
1928 <code>circular_buffer</code> is full and the <code>pos</code> points to <code>end()</code>, then the
|
Chris@16
|
1929 <code>item</code> will not be inserted. If the capacity is <code>0</code>, nothing will be inserted.
|
Chris@16
|
1930 \param pos An iterator specifying the position before which the <code>item</code> will be inserted.
|
Chris@16
|
1931 \param item The element to be inserted.
|
Chris@16
|
1932 \return Iterator to the inserted element or <code>end()</code> if the <code>item</code> is not inserted. (See
|
Chris@16
|
1933 the <i>Effect</i>.)
|
Chris@16
|
1934 \throws Whatever <code>T::T(T&&)</code> throws.
|
Chris@16
|
1935 Whatever <code>T::operator = (T&&)</code> throws.
|
Chris@16
|
1936 <a href="circular_buffer/implementation.html#circular_buffer.implementation.exceptions_of_move_if_noexcept_t">Exceptions of move_if_noexcept(T&)</a>.
|
Chris@16
|
1937 \par Exception Safety
|
Chris@16
|
1938 Basic; no-throw if the operations in the <i>Throws</i> section do not throw anything.
|
Chris@16
|
1939 \par Iterator Invalidation
|
Chris@16
|
1940 Invalidates iterators pointing to the elements before the insertion point (towards the beginning and
|
Chris@16
|
1941 excluding <code>pos</code>). It also invalidates iterators pointing to the overwritten element.
|
Chris@16
|
1942 \par Complexity
|
Chris@16
|
1943 Linear (in <code>std::distance(begin(), pos)</code>).
|
Chris@16
|
1944 \sa <code>\link rinsert(iterator, size_type, param_value_type)
|
Chris@16
|
1945 rinsert(iterator, size_type, value_type)\endlink</code>,
|
Chris@16
|
1946 <code>rinsert(iterator, InputIterator, InputIterator)</code>,
|
Chris@16
|
1947 <code>\link insert(iterator, param_value_type) insert(iterator, value_type)\endlink</code>,
|
Chris@16
|
1948 <code>\link insert(iterator, size_type, param_value_type)
|
Chris@16
|
1949 insert(iterator, size_type, value_type)\endlink</code>,
|
Chris@16
|
1950 <code>insert(iterator, InputIterator, InputIterator)</code>
|
Chris@16
|
1951 */
|
Chris@16
|
1952 iterator rinsert(iterator pos, rvalue_type item) {
|
Chris@16
|
1953 return rinsert_impl<rvalue_type>(pos, boost::move(item));
|
Chris@16
|
1954 }
|
Chris@16
|
1955
|
Chris@16
|
1956 //! Insert an element before the specified position.
|
Chris@16
|
1957 /*!
|
Chris@16
|
1958 \pre <code>pos</code> is a valid iterator pointing to the <code>circular_buffer</code> or its end.
|
Chris@16
|
1959 \post The <code>item</code> will be inserted before the position <code>pos</code>.<br>
|
Chris@16
|
1960 If the <code>circular_buffer</code> is full, the last element will be overwritten. If the
|
Chris@16
|
1961 <code>circular_buffer</code> is full and the <code>pos</code> points to <code>end()</code>, then the
|
Chris@16
|
1962 <code>item</code> will not be inserted. If the capacity is <code>0</code>, nothing will be inserted.
|
Chris@16
|
1963 \param pos An iterator specifying the position before which the <code>item</code> will be inserted.
|
Chris@16
|
1964 \return Iterator to the inserted element or <code>end()</code> if the <code>item</code> is not inserted. (See
|
Chris@16
|
1965 the <i>Effect</i>.)
|
Chris@16
|
1966 \throws Whatever <code>T::T()</code> throws.
|
Chris@16
|
1967 Whatever <code>T::T(T&&)</code> throws.
|
Chris@16
|
1968 Whatever <code>T::operator = (T&&)</code> throws.
|
Chris@16
|
1969 <a href="circular_buffer/implementation.html#circular_buffer.implementation.exceptions_of_move_if_noexcept_t">Exceptions of move_if_noexcept(T&)</a>.
|
Chris@16
|
1970 \par Exception Safety
|
Chris@16
|
1971 Basic; no-throw if the operations in the <i>Throws</i> section do not throw anything.
|
Chris@16
|
1972 \par Iterator Invalidation
|
Chris@16
|
1973 Invalidates iterators pointing to the elements before the insertion point (towards the beginning and
|
Chris@16
|
1974 excluding <code>pos</code>). It also invalidates iterators pointing to the overwritten element.
|
Chris@16
|
1975 \par Complexity
|
Chris@16
|
1976 Linear (in <code>std::distance(begin(), pos)</code>).
|
Chris@16
|
1977 \sa <code>\link rinsert(iterator, size_type, param_value_type)
|
Chris@16
|
1978 rinsert(iterator, size_type, value_type)\endlink</code>,
|
Chris@16
|
1979 <code>rinsert(iterator, InputIterator, InputIterator)</code>,
|
Chris@16
|
1980 <code>\link insert(iterator, param_value_type) insert(iterator, value_type)\endlink</code>,
|
Chris@16
|
1981 <code>\link insert(iterator, size_type, param_value_type)
|
Chris@16
|
1982 insert(iterator, size_type, value_type)\endlink</code>,
|
Chris@16
|
1983 <code>insert(iterator, InputIterator, InputIterator)</code>
|
Chris@16
|
1984 */
|
Chris@16
|
1985 iterator rinsert(iterator pos) {
|
Chris@16
|
1986 value_type temp;
|
Chris@16
|
1987 return rinsert(pos, boost::move(temp));
|
Chris@16
|
1988 }
|
Chris@16
|
1989
|
Chris@16
|
1990 //! Insert <code>n</code> copies of the <code>item</code> before the specified position.
|
Chris@16
|
1991 /*!
|
Chris@16
|
1992 \pre <code>pos</code> is a valid iterator pointing to the <code>circular_buffer</code> or its end.
|
Chris@16
|
1993 \post The number of <code>min[n, (end() - pos) + reserve()]</code> elements will be inserted before the
|
Chris@16
|
1994 position <code>pos</code>.<br>The number of <code>min[end() - pos, max[0, n - reserve()]]</code> elements
|
Chris@16
|
1995 will be overwritten at the end of the <code>circular_buffer</code>.<br>(See <i>Example</i> for the
|
Chris@16
|
1996 explanation.)
|
Chris@16
|
1997 \param pos An iterator specifying the position where the <code>item</code>s will be inserted.
|
Chris@16
|
1998 \param n The number of <code>item</code>s the to be inserted.
|
Chris@16
|
1999 \param item The element whose copies will be inserted.
|
Chris@16
|
2000 \throws Whatever <code>T::T(const T&)</code> throws.
|
Chris@16
|
2001 Whatever <code>T::operator = (const T&)</code> throws.
|
Chris@16
|
2002 <a href="circular_buffer/implementation.html#circular_buffer.implementation.exceptions_of_move_if_noexcept_t">Exceptions of move_if_noexcept(T&)</a>.
|
Chris@16
|
2003 \par Exception Safety
|
Chris@16
|
2004 Basic; no-throw if the operations in the <i>Throws</i> section do not throw anything.
|
Chris@16
|
2005 \par Iterator Invalidation
|
Chris@16
|
2006 Invalidates iterators pointing to the elements before the insertion point (towards the beginning and
|
Chris@16
|
2007 excluding <code>pos</code>). It also invalidates iterators pointing to the overwritten elements.
|
Chris@16
|
2008 \par Complexity
|
Chris@16
|
2009 Linear (in <code>min[capacity(), std::distance(begin(), pos) + n]</code>).
|
Chris@16
|
2010 \par Example
|
Chris@16
|
2011 Consider a <code>circular_buffer</code> with the capacity of 6 and the size of 4. Its internal buffer may
|
Chris@16
|
2012 look like the one below.<br><br>
|
Chris@16
|
2013 <code>|1|2|3|4| | |</code><br>
|
Chris@16
|
2014 <code>p ___^</code><br><br>After inserting 5 elements before the position <code>p</code>:<br><br>
|
Chris@16
|
2015 <code>rinsert(p, (size_t)5, 0);</code><br><br>actually only 4 elements get inserted and elements
|
Chris@16
|
2016 <code>3</code> and <code>4</code> are overwritten. This is due to the fact the rinsert operation preserves
|
Chris@16
|
2017 the capacity. After insertion the internal buffer looks like this:<br><br><code>|1|2|0|0|0|0|</code><br>
|
Chris@16
|
2018 <br>For comparison if the capacity would not be preserved the internal buffer would then result in
|
Chris@16
|
2019 <code>|1|2|0|0|0|0|0|3|4|</code>.
|
Chris@16
|
2020 \sa <code>\link rinsert(iterator, param_value_type) rinsert(iterator, value_type)\endlink</code>,
|
Chris@16
|
2021 <code>rinsert(iterator, InputIterator, InputIterator)</code>,
|
Chris@16
|
2022 <code>\link insert(iterator, param_value_type) insert(iterator, value_type)\endlink</code>,
|
Chris@16
|
2023 <code>\link insert(iterator, size_type, param_value_type)
|
Chris@16
|
2024 insert(iterator, size_type, value_type)\endlink</code>,
|
Chris@16
|
2025 <code>insert(iterator, InputIterator, InputIterator)</code>
|
Chris@16
|
2026 */
|
Chris@16
|
2027 void rinsert(iterator pos, size_type n, param_value_type item) {
|
Chris@16
|
2028 BOOST_CB_ASSERT(pos.is_valid(this)); // check for uninitialized or invalidated iterator
|
Chris@16
|
2029 rinsert_n(pos, n, cb_details::item_wrapper<const_pointer, param_value_type>(item));
|
Chris@16
|
2030 }
|
Chris@16
|
2031
|
Chris@16
|
2032 //! Insert the range <code>[first, last)</code> before the specified position.
|
Chris@16
|
2033 /*!
|
Chris@16
|
2034 \pre <code>pos</code> is a valid iterator pointing to the <code>circular_buffer</code> or its end.<br>
|
Chris@16
|
2035 Valid range <code>[first, last)</code> where <code>first</code> and <code>last</code> meet the
|
Chris@16
|
2036 requirements of an <a href="http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>.
|
Chris@16
|
2037 \post Elements from the range
|
Chris@16
|
2038 <code>[first, last - max[0, distance(first, last) - (end() - pos) - reserve()])</code> will be inserted
|
Chris@16
|
2039 before the position <code>pos</code>.<br>The number of <code>min[end() - pos, max[0,
|
Chris@16
|
2040 distance(first, last) - reserve()]]</code> elements will be overwritten at the end of the
|
Chris@16
|
2041 <code>circular_buffer</code>.<br>(See <i>Example</i> for the explanation.)
|
Chris@16
|
2042 \param pos An iterator specifying the position where the range will be inserted.
|
Chris@16
|
2043 \param first The beginning of the range to be inserted.
|
Chris@16
|
2044 \param last The end of the range to be inserted.
|
Chris@16
|
2045 \throws Whatever <code>T::T(const T&)</code> throws if the <code>InputIterator</code> is not a move iterator.
|
Chris@16
|
2046 Whatever <code>T::operator = (const T&)</code> throws if the <code>InputIterator</code> is not a move iterator.
|
Chris@16
|
2047 Whatever <code>T::T(T&&)</code> throws if the <code>InputIterator</code> is a move iterator.
|
Chris@16
|
2048 Whatever <code>T::operator = (T&&)</code> throws if the <code>InputIterator</code> is a move iterator.
|
Chris@16
|
2049 \par Exception Safety
|
Chris@16
|
2050 Basic; no-throw if the operations in the <i>Throws</i> section do not throw anything.
|
Chris@16
|
2051 \par Iterator Invalidation
|
Chris@16
|
2052 Invalidates iterators pointing to the elements before the insertion point (towards the beginning and
|
Chris@16
|
2053 excluding <code>pos</code>). It also invalidates iterators pointing to the overwritten elements.
|
Chris@16
|
2054 \par Complexity
|
Chris@16
|
2055 Linear (in <code>[std::distance(begin(), pos) + std::distance(first, last)]</code>; in
|
Chris@16
|
2056 <code>min[capacity(), std::distance(begin(), pos) + std::distance(first, last)]</code> if the
|
Chris@16
|
2057 <code>InputIterator</code> is a
|
Chris@16
|
2058 <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a>).
|
Chris@16
|
2059 \par Example
|
Chris@16
|
2060 Consider a <code>circular_buffer</code> with the capacity of 6 and the size of 4. Its internal buffer may
|
Chris@16
|
2061 look like the one below.<br><br>
|
Chris@16
|
2062 <code>|1|2|3|4| | |</code><br>
|
Chris@16
|
2063 <code>p ___^</code><br><br>After inserting a range of elements before the position <code>p</code>:<br><br>
|
Chris@16
|
2064 <code>int array[] = { 5, 6, 7, 8, 9 };</code><br><code>insert(p, array, array + 5);</code><br><br>
|
Chris@16
|
2065 actually only elements <code>5</code>, <code>6</code>, <code>7</code> and <code>8</code> from the
|
Chris@16
|
2066 specified range get inserted and elements <code>3</code> and <code>4</code> are overwritten. This is due
|
Chris@16
|
2067 to the fact the rinsert operation preserves the capacity. After insertion the internal buffer looks like
|
Chris@16
|
2068 this:<br><br><code>|1|2|5|6|7|8|</code><br><br>For comparison if the capacity would not be preserved the
|
Chris@16
|
2069 internal buffer would then result in <code>|1|2|5|6|7|8|9|3|4|</code>.
|
Chris@16
|
2070 \sa <code>\link rinsert(iterator, param_value_type) rinsert(iterator, value_type)\endlink</code>,
|
Chris@16
|
2071 <code>\link rinsert(iterator, size_type, param_value_type)
|
Chris@16
|
2072 rinsert(iterator, size_type, value_type)\endlink</code>, <code>\link insert(iterator, param_value_type)
|
Chris@16
|
2073 insert(iterator, value_type)\endlink</code>, <code>\link insert(iterator, size_type, param_value_type)
|
Chris@16
|
2074 insert(iterator, size_type, value_type)\endlink</code>,
|
Chris@16
|
2075 <code>insert(iterator, InputIterator, InputIterator)</code>
|
Chris@16
|
2076 */
|
Chris@16
|
2077 template <class InputIterator>
|
Chris@16
|
2078 void rinsert(iterator pos, InputIterator first, InputIterator last) {
|
Chris@16
|
2079 BOOST_CB_ASSERT(pos.is_valid(this)); // check for uninitialized or invalidated iterator
|
Chris@16
|
2080 rinsert(pos, first, last, is_integral<InputIterator>());
|
Chris@16
|
2081 }
|
Chris@16
|
2082
|
Chris@16
|
2083 // Erase
|
Chris@16
|
2084
|
Chris@16
|
2085 //! Remove an element at the specified position.
|
Chris@16
|
2086 /*!
|
Chris@16
|
2087 \pre <code>pos</code> is a valid iterator pointing to the <code>circular_buffer</code> (but not an
|
Chris@16
|
2088 <code>end()</code>).
|
Chris@16
|
2089 \post The element at the position <code>pos</code> is removed.
|
Chris@16
|
2090 \param pos An iterator pointing at the element to be removed.
|
Chris@16
|
2091 \return Iterator to the first element remaining beyond the removed element or <code>end()</code> if no such
|
Chris@16
|
2092 element exists.
|
Chris@16
|
2093 \throws <a href="circular_buffer/implementation.html#circular_buffer.implementation.exceptions_of_move_if_noexcept_t">Exceptions of move_if_noexcept(T&)</a>.
|
Chris@16
|
2094 \par Exception Safety
|
Chris@16
|
2095 Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything.
|
Chris@16
|
2096 \par Iterator Invalidation
|
Chris@16
|
2097 Invalidates iterators pointing to the erased element and iterators pointing to the elements behind
|
Chris@16
|
2098 the erased element (towards the end; except iterators equal to <code>end()</code>).
|
Chris@16
|
2099 \par Complexity
|
Chris@16
|
2100 Linear (in <code>std::distance(pos, end())</code>).
|
Chris@16
|
2101 \sa <code>erase(iterator, iterator)</code>, <code>rerase(iterator)</code>,
|
Chris@16
|
2102 <code>rerase(iterator, iterator)</code>, <code>erase_begin(size_type)</code>,
|
Chris@16
|
2103 <code>erase_end(size_type)</code>, <code>clear()</code>
|
Chris@16
|
2104 */
|
Chris@16
|
2105 iterator erase(iterator pos) {
|
Chris@16
|
2106 BOOST_CB_ASSERT(pos.is_valid(this)); // check for uninitialized or invalidated iterator
|
Chris@16
|
2107 BOOST_CB_ASSERT(pos.m_it != 0); // check for iterator pointing to end()
|
Chris@16
|
2108 pointer next = pos.m_it;
|
Chris@16
|
2109 increment(next);
|
Chris@16
|
2110 for (pointer p = pos.m_it; next != m_last; p = next, increment(next))
|
Chris@101
|
2111 replace(p, boost::move_if_noexcept(*next));
|
Chris@16
|
2112 decrement(m_last);
|
Chris@16
|
2113 destroy_item(m_last);
|
Chris@16
|
2114 --m_size;
|
Chris@16
|
2115 #if BOOST_CB_ENABLE_DEBUG
|
Chris@16
|
2116 return m_last == pos.m_it ? end() : iterator(this, pos.m_it);
|
Chris@16
|
2117 #else
|
Chris@16
|
2118 return m_last == pos.m_it ? end() : pos;
|
Chris@16
|
2119 #endif
|
Chris@16
|
2120 }
|
Chris@16
|
2121
|
Chris@16
|
2122 //! Erase the range <code>[first, last)</code>.
|
Chris@16
|
2123 /*!
|
Chris@16
|
2124 \pre Valid range <code>[first, last)</code>.
|
Chris@16
|
2125 \post The elements from the range <code>[first, last)</code> are removed. (If <code>first == last</code>
|
Chris@16
|
2126 nothing is removed.)
|
Chris@16
|
2127 \param first The beginning of the range to be removed.
|
Chris@16
|
2128 \param last The end of the range to be removed.
|
Chris@16
|
2129 \return Iterator to the first element remaining beyond the removed elements or <code>end()</code> if no such
|
Chris@16
|
2130 element exists.
|
Chris@16
|
2131 \throws <a href="circular_buffer/implementation.html#circular_buffer.implementation.exceptions_of_move_if_noexcept_t">Exceptions of move_if_noexcept(T&)</a>.
|
Chris@16
|
2132 \par Exception Safety
|
Chris@16
|
2133 Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything.
|
Chris@16
|
2134 \par Iterator Invalidation
|
Chris@16
|
2135 Invalidates iterators pointing to the erased elements and iterators pointing to the elements behind
|
Chris@16
|
2136 the erased range (towards the end; except iterators equal to <code>end()</code>).
|
Chris@16
|
2137 \par Complexity
|
Chris@16
|
2138 Linear (in <code>std::distance(first, end())</code>).
|
Chris@16
|
2139 \sa <code>erase(iterator)</code>, <code>rerase(iterator)</code>, <code>rerase(iterator, iterator)</code>,
|
Chris@16
|
2140 <code>erase_begin(size_type)</code>, <code>erase_end(size_type)</code>, <code>clear()</code>
|
Chris@16
|
2141 */
|
Chris@16
|
2142 iterator erase(iterator first, iterator last) {
|
Chris@16
|
2143 BOOST_CB_ASSERT(first.is_valid(this)); // check for uninitialized or invalidated iterator
|
Chris@16
|
2144 BOOST_CB_ASSERT(last.is_valid(this)); // check for uninitialized or invalidated iterator
|
Chris@16
|
2145 BOOST_CB_ASSERT(first <= last); // check for wrong range
|
Chris@16
|
2146 if (first == last)
|
Chris@16
|
2147 return first;
|
Chris@16
|
2148 pointer p = first.m_it;
|
Chris@16
|
2149 while (last.m_it != 0)
|
Chris@101
|
2150 replace((first++).m_it, boost::move_if_noexcept(*last++));
|
Chris@16
|
2151 do {
|
Chris@16
|
2152 decrement(m_last);
|
Chris@16
|
2153 destroy_item(m_last);
|
Chris@16
|
2154 --m_size;
|
Chris@16
|
2155 } while(m_last != first.m_it);
|
Chris@16
|
2156 return m_last == p ? end() : iterator(this, p);
|
Chris@16
|
2157 }
|
Chris@16
|
2158
|
Chris@16
|
2159 //! Remove an element at the specified position.
|
Chris@16
|
2160 /*!
|
Chris@16
|
2161 \pre <code>pos</code> is a valid iterator pointing to the <code>circular_buffer</code> (but not an
|
Chris@16
|
2162 <code>end()</code>).
|
Chris@16
|
2163 \post The element at the position <code>pos</code> is removed.
|
Chris@16
|
2164 \param pos An iterator pointing at the element to be removed.
|
Chris@16
|
2165 \return Iterator to the first element remaining in front of the removed element or <code>begin()</code> if no
|
Chris@16
|
2166 such element exists.
|
Chris@16
|
2167 \throws <a href="circular_buffer/implementation.html#circular_buffer.implementation.exceptions_of_move_if_noexcept_t">Exceptions of move_if_noexcept(T&)</a>.
|
Chris@16
|
2168 \par Exception Safety
|
Chris@16
|
2169 Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything.
|
Chris@16
|
2170 \par Iterator Invalidation
|
Chris@16
|
2171 Invalidates iterators pointing to the erased element and iterators pointing to the elements in front of
|
Chris@16
|
2172 the erased element (towards the beginning).
|
Chris@16
|
2173 \par Complexity
|
Chris@16
|
2174 Linear (in <code>std::distance(begin(), pos)</code>).
|
Chris@16
|
2175 \note This method is symetric to the <code>erase(iterator)</code> method and is more effective than
|
Chris@16
|
2176 <code>erase(iterator)</code> if the iterator <code>pos</code> is close to the beginning of the
|
Chris@16
|
2177 <code>circular_buffer</code>. (See the <i>Complexity</i>.)
|
Chris@16
|
2178 \sa <code>erase(iterator)</code>, <code>erase(iterator, iterator)</code>,
|
Chris@16
|
2179 <code>rerase(iterator, iterator)</code>, <code>erase_begin(size_type)</code>,
|
Chris@16
|
2180 <code>erase_end(size_type)</code>, <code>clear()</code>
|
Chris@16
|
2181 */
|
Chris@16
|
2182 iterator rerase(iterator pos) {
|
Chris@16
|
2183 BOOST_CB_ASSERT(pos.is_valid(this)); // check for uninitialized or invalidated iterator
|
Chris@16
|
2184 BOOST_CB_ASSERT(pos.m_it != 0); // check for iterator pointing to end()
|
Chris@16
|
2185 pointer prev = pos.m_it;
|
Chris@16
|
2186 pointer p = prev;
|
Chris@16
|
2187 for (decrement(prev); p != m_first; p = prev, decrement(prev))
|
Chris@101
|
2188 replace(p, boost::move_if_noexcept(*prev));
|
Chris@16
|
2189 destroy_item(m_first);
|
Chris@16
|
2190 increment(m_first);
|
Chris@16
|
2191 --m_size;
|
Chris@16
|
2192 #if BOOST_CB_ENABLE_DEBUG
|
Chris@16
|
2193 return p == pos.m_it ? begin() : iterator(this, pos.m_it);
|
Chris@16
|
2194 #else
|
Chris@16
|
2195 return p == pos.m_it ? begin() : pos;
|
Chris@16
|
2196 #endif
|
Chris@16
|
2197 }
|
Chris@16
|
2198
|
Chris@16
|
2199 //! Erase the range <code>[first, last)</code>.
|
Chris@16
|
2200 /*!
|
Chris@16
|
2201 \pre Valid range <code>[first, last)</code>.
|
Chris@16
|
2202 \post The elements from the range <code>[first, last)</code> are removed. (If <code>first == last</code>
|
Chris@16
|
2203 nothing is removed.)
|
Chris@16
|
2204 \param first The beginning of the range to be removed.
|
Chris@16
|
2205 \param last The end of the range to be removed.
|
Chris@16
|
2206 \return Iterator to the first element remaining in front of the removed elements or <code>begin()</code> if no
|
Chris@16
|
2207 such element exists.
|
Chris@16
|
2208 \throws <a href="circular_buffer/implementation.html#circular_buffer.implementation.exceptions_of_move_if_noexcept_t">Exceptions of move_if_noexcept(T&)</a>.
|
Chris@16
|
2209 \par Exception Safety
|
Chris@16
|
2210 Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything.
|
Chris@16
|
2211 \par Iterator Invalidation
|
Chris@16
|
2212 Invalidates iterators pointing to the erased elements and iterators pointing to the elements in front of
|
Chris@16
|
2213 the erased range (towards the beginning).
|
Chris@16
|
2214 \par Complexity
|
Chris@16
|
2215 Linear (in <code>std::distance(begin(), last)</code>).
|
Chris@16
|
2216 \note This method is symetric to the <code>erase(iterator, iterator)</code> method and is more effective than
|
Chris@16
|
2217 <code>erase(iterator, iterator)</code> if <code>std::distance(begin(), first)</code> is lower that
|
Chris@16
|
2218 <code>std::distance(last, end())</code>.
|
Chris@16
|
2219 \sa <code>erase(iterator)</code>, <code>erase(iterator, iterator)</code>, <code>rerase(iterator)</code>,
|
Chris@16
|
2220 <code>erase_begin(size_type)</code>, <code>erase_end(size_type)</code>, <code>clear()</code>
|
Chris@16
|
2221 */
|
Chris@16
|
2222 iterator rerase(iterator first, iterator last) {
|
Chris@16
|
2223 BOOST_CB_ASSERT(first.is_valid(this)); // check for uninitialized or invalidated iterator
|
Chris@16
|
2224 BOOST_CB_ASSERT(last.is_valid(this)); // check for uninitialized or invalidated iterator
|
Chris@16
|
2225 BOOST_CB_ASSERT(first <= last); // check for wrong range
|
Chris@16
|
2226 if (first == last)
|
Chris@16
|
2227 return first;
|
Chris@16
|
2228 pointer p = map_pointer(last.m_it);
|
Chris@16
|
2229 last.m_it = p;
|
Chris@16
|
2230 while (first.m_it != m_first) {
|
Chris@16
|
2231 decrement(first.m_it);
|
Chris@16
|
2232 decrement(p);
|
Chris@101
|
2233 replace(p, boost::move_if_noexcept(*first.m_it));
|
Chris@16
|
2234 }
|
Chris@16
|
2235 do {
|
Chris@16
|
2236 destroy_item(m_first);
|
Chris@16
|
2237 increment(m_first);
|
Chris@16
|
2238 --m_size;
|
Chris@16
|
2239 } while(m_first != p);
|
Chris@16
|
2240 if (m_first == last.m_it)
|
Chris@16
|
2241 return begin();
|
Chris@16
|
2242 decrement(last.m_it);
|
Chris@16
|
2243 return iterator(this, last.m_it);
|
Chris@16
|
2244 }
|
Chris@16
|
2245
|
Chris@16
|
2246 //! Remove first <code>n</code> elements (with constant complexity for scalar types).
|
Chris@16
|
2247 /*!
|
Chris@16
|
2248 \pre <code>n \<= size()</code>
|
Chris@16
|
2249 \post The <code>n</code> elements at the beginning of the <code>circular_buffer</code> will be removed.
|
Chris@16
|
2250 \param n The number of elements to be removed.
|
Chris@16
|
2251 \throws <a href="circular_buffer/implementation.html#circular_buffer.implementation.exceptions_of_move_if_noexcept_t">Exceptions of move_if_noexcept(T&)</a>.
|
Chris@16
|
2252 \par Exception Safety
|
Chris@16
|
2253 Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything. (I.e. no throw in
|
Chris@16
|
2254 case of scalars.)
|
Chris@16
|
2255 \par Iterator Invalidation
|
Chris@16
|
2256 Invalidates iterators pointing to the first <code>n</code> erased elements.
|
Chris@16
|
2257 \par Complexity
|
Chris@16
|
2258 Constant (in <code>n</code>) for scalar types; linear for other types.
|
Chris@16
|
2259 \note This method has been specially designed for types which do not require an explicit destructruction (e.g.
|
Chris@16
|
2260 integer, float or a pointer). For these scalar types a call to a destructor is not required which makes
|
Chris@16
|
2261 it possible to implement the "erase from beginning" operation with a constant complexity. For non-sacalar
|
Chris@16
|
2262 types the complexity is linear (hence the explicit destruction is needed) and the implementation is
|
Chris@16
|
2263 actually equivalent to
|
Chris@16
|
2264 <code>\link circular_buffer::rerase(iterator, iterator) rerase(begin(), begin() + n)\endlink</code>.
|
Chris@16
|
2265 \sa <code>erase(iterator)</code>, <code>erase(iterator, iterator)</code>,
|
Chris@16
|
2266 <code>rerase(iterator)</code>, <code>rerase(iterator, iterator)</code>,
|
Chris@16
|
2267 <code>erase_end(size_type)</code>, <code>clear()</code>
|
Chris@16
|
2268 */
|
Chris@16
|
2269 void erase_begin(size_type n) {
|
Chris@16
|
2270 BOOST_CB_ASSERT(n <= size()); // check for n greater than size
|
Chris@16
|
2271 #if BOOST_CB_ENABLE_DEBUG
|
Chris@16
|
2272 erase_begin(n, false_type());
|
Chris@16
|
2273 #else
|
Chris@16
|
2274 erase_begin(n, is_scalar<value_type>());
|
Chris@16
|
2275 #endif
|
Chris@16
|
2276 }
|
Chris@16
|
2277
|
Chris@16
|
2278 //! Remove last <code>n</code> elements (with constant complexity for scalar types).
|
Chris@16
|
2279 /*!
|
Chris@16
|
2280 \pre <code>n \<= size()</code>
|
Chris@16
|
2281 \post The <code>n</code> elements at the end of the <code>circular_buffer</code> will be removed.
|
Chris@16
|
2282 \param n The number of elements to be removed.
|
Chris@16
|
2283 \throws <a href="circular_buffer/implementation.html#circular_buffer.implementation.exceptions_of_move_if_noexcept_t">Exceptions of move_if_noexcept(T&)</a>.
|
Chris@16
|
2284 \par Exception Safety
|
Chris@16
|
2285 Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything. (I.e. no throw in
|
Chris@16
|
2286 case of scalars.)
|
Chris@16
|
2287 \par Iterator Invalidation
|
Chris@16
|
2288 Invalidates iterators pointing to the last <code>n</code> erased elements.
|
Chris@16
|
2289 \par Complexity
|
Chris@16
|
2290 Constant (in <code>n</code>) for scalar types; linear for other types.
|
Chris@16
|
2291 \note This method has been specially designed for types which do not require an explicit destructruction (e.g.
|
Chris@16
|
2292 integer, float or a pointer). For these scalar types a call to a destructor is not required which makes
|
Chris@16
|
2293 it possible to implement the "erase from end" operation with a constant complexity. For non-sacalar
|
Chris@16
|
2294 types the complexity is linear (hence the explicit destruction is needed) and the implementation is
|
Chris@16
|
2295 actually equivalent to
|
Chris@16
|
2296 <code>\link circular_buffer::erase(iterator, iterator) erase(end() - n, end())\endlink</code>.
|
Chris@16
|
2297 \sa <code>erase(iterator)</code>, <code>erase(iterator, iterator)</code>,
|
Chris@16
|
2298 <code>rerase(iterator)</code>, <code>rerase(iterator, iterator)</code>,
|
Chris@16
|
2299 <code>erase_begin(size_type)</code>, <code>clear()</code>
|
Chris@16
|
2300 */
|
Chris@16
|
2301 void erase_end(size_type n) {
|
Chris@16
|
2302 BOOST_CB_ASSERT(n <= size()); // check for n greater than size
|
Chris@16
|
2303 #if BOOST_CB_ENABLE_DEBUG
|
Chris@16
|
2304 erase_end(n, false_type());
|
Chris@16
|
2305 #else
|
Chris@16
|
2306 erase_end(n, is_scalar<value_type>());
|
Chris@16
|
2307 #endif
|
Chris@16
|
2308 }
|
Chris@16
|
2309
|
Chris@16
|
2310 //! Remove all stored elements from the <code>circular_buffer</code>.
|
Chris@16
|
2311 /*!
|
Chris@16
|
2312 \post <code>size() == 0</code>
|
Chris@16
|
2313 \throws Nothing.
|
Chris@16
|
2314 \par Exception Safety
|
Chris@16
|
2315 No-throw.
|
Chris@16
|
2316 \par Iterator Invalidation
|
Chris@16
|
2317 Invalidates all iterators pointing to the <code>circular_buffer</code> (except iterators equal to
|
Chris@16
|
2318 <code>end()</code>).
|
Chris@16
|
2319 \par Complexity
|
Chris@16
|
2320 Constant (in the size of the <code>circular_buffer</code>) for scalar types; linear for other types.
|
Chris@16
|
2321 \sa <code>~circular_buffer()</code>, <code>erase(iterator)</code>, <code>erase(iterator, iterator)</code>,
|
Chris@16
|
2322 <code>rerase(iterator)</code>, <code>rerase(iterator, iterator)</code>,
|
Chris@16
|
2323 <code>erase_begin(size_type)</code>, <code>erase_end(size_type)</code>
|
Chris@16
|
2324 */
|
Chris@16
|
2325 void clear() BOOST_NOEXCEPT {
|
Chris@16
|
2326 destroy_content();
|
Chris@16
|
2327 m_size = 0;
|
Chris@16
|
2328 }
|
Chris@16
|
2329
|
Chris@16
|
2330 private:
|
Chris@16
|
2331 // Helper methods
|
Chris@16
|
2332
|
Chris@16
|
2333 //! Check if the <code>index</code> is valid.
|
Chris@16
|
2334 void check_position(size_type index) const {
|
Chris@16
|
2335 if (index >= size())
|
Chris@16
|
2336 throw_exception(std::out_of_range("circular_buffer"));
|
Chris@16
|
2337 }
|
Chris@16
|
2338
|
Chris@16
|
2339 //! Increment the pointer.
|
Chris@16
|
2340 template <class Pointer>
|
Chris@16
|
2341 void increment(Pointer& p) const {
|
Chris@16
|
2342 if (++p == m_end)
|
Chris@16
|
2343 p = m_buff;
|
Chris@16
|
2344 }
|
Chris@16
|
2345
|
Chris@16
|
2346 //! Decrement the pointer.
|
Chris@16
|
2347 template <class Pointer>
|
Chris@16
|
2348 void decrement(Pointer& p) const {
|
Chris@16
|
2349 if (p == m_buff)
|
Chris@16
|
2350 p = m_end;
|
Chris@16
|
2351 --p;
|
Chris@16
|
2352 }
|
Chris@16
|
2353
|
Chris@16
|
2354 //! Add <code>n</code> to the pointer.
|
Chris@16
|
2355 template <class Pointer>
|
Chris@16
|
2356 Pointer add(Pointer p, difference_type n) const {
|
Chris@16
|
2357 return p + (n < (m_end - p) ? n : n - capacity());
|
Chris@16
|
2358 }
|
Chris@16
|
2359
|
Chris@16
|
2360 //! Subtract <code>n</code> from the pointer.
|
Chris@16
|
2361 template <class Pointer>
|
Chris@16
|
2362 Pointer sub(Pointer p, difference_type n) const {
|
Chris@16
|
2363 return p - (n > (p - m_buff) ? n - capacity() : n);
|
Chris@16
|
2364 }
|
Chris@16
|
2365
|
Chris@16
|
2366 //! Map the null pointer to virtual end of circular buffer.
|
Chris@16
|
2367 pointer map_pointer(pointer p) const { return p == 0 ? m_last : p; }
|
Chris@16
|
2368
|
Chris@16
|
2369 //! Allocate memory.
|
Chris@16
|
2370 pointer allocate(size_type n) {
|
Chris@16
|
2371 if (n > max_size())
|
Chris@16
|
2372 throw_exception(std::length_error("circular_buffer"));
|
Chris@16
|
2373 #if BOOST_CB_ENABLE_DEBUG
|
Chris@101
|
2374 pointer p = (n == 0) ? 0 : m_alloc.allocate(n);
|
Chris@101
|
2375 cb_details::do_fill_uninitialized_memory(p, sizeof(value_type) * n);
|
Chris@16
|
2376 return p;
|
Chris@16
|
2377 #else
|
Chris@101
|
2378 return (n == 0) ? 0 : m_alloc.allocate(n);
|
Chris@16
|
2379 #endif
|
Chris@16
|
2380 }
|
Chris@16
|
2381
|
Chris@16
|
2382 //! Deallocate memory.
|
Chris@16
|
2383 void deallocate(pointer p, size_type n) {
|
Chris@16
|
2384 if (p != 0)
|
Chris@16
|
2385 m_alloc.deallocate(p, n);
|
Chris@16
|
2386 }
|
Chris@16
|
2387
|
Chris@16
|
2388 //! Does the pointer point to the uninitialized memory?
|
Chris@16
|
2389 bool is_uninitialized(const_pointer p) const BOOST_NOEXCEPT {
|
Chris@16
|
2390 return p >= m_last && (m_first < m_last || p < m_first);
|
Chris@16
|
2391 }
|
Chris@16
|
2392
|
Chris@16
|
2393 //! Replace an element.
|
Chris@16
|
2394 void replace(pointer pos, param_value_type item) {
|
Chris@16
|
2395 *pos = item;
|
Chris@16
|
2396 #if BOOST_CB_ENABLE_DEBUG
|
Chris@16
|
2397 invalidate_iterators(iterator(this, pos));
|
Chris@16
|
2398 #endif
|
Chris@16
|
2399 }
|
Chris@16
|
2400
|
Chris@16
|
2401 //! Replace an element.
|
Chris@16
|
2402 void replace(pointer pos, rvalue_type item) {
|
Chris@16
|
2403 *pos = boost::move(item);
|
Chris@16
|
2404 #if BOOST_CB_ENABLE_DEBUG
|
Chris@16
|
2405 invalidate_iterators(iterator(this, pos));
|
Chris@16
|
2406 #endif
|
Chris@16
|
2407 }
|
Chris@16
|
2408
|
Chris@16
|
2409 //! Construct or replace an element.
|
Chris@16
|
2410 /*!
|
Chris@16
|
2411 <code>construct</code> has to be set to <code>true</code> if and only if
|
Chris@16
|
2412 <code>pos</code> points to an uninitialized memory.
|
Chris@16
|
2413 */
|
Chris@16
|
2414 void construct_or_replace(bool construct, pointer pos, param_value_type item) {
|
Chris@16
|
2415 if (construct)
|
Chris@101
|
2416 boost::container::allocator_traits<Alloc>::construct(m_alloc, boost::addressof(*pos), item);
|
Chris@16
|
2417 else
|
Chris@16
|
2418 replace(pos, item);
|
Chris@16
|
2419 }
|
Chris@16
|
2420
|
Chris@16
|
2421 //! Construct or replace an element.
|
Chris@16
|
2422 /*!
|
Chris@16
|
2423 <code>construct</code> has to be set to <code>true</code> if and only if
|
Chris@16
|
2424 <code>pos</code> points to an uninitialized memory.
|
Chris@16
|
2425 */
|
Chris@16
|
2426 void construct_or_replace(bool construct, pointer pos, rvalue_type item) {
|
Chris@16
|
2427 if (construct)
|
Chris@101
|
2428 boost::container::allocator_traits<Alloc>::construct(m_alloc, boost::addressof(*pos), boost::move(item));
|
Chris@16
|
2429 else
|
Chris@16
|
2430 replace(pos, boost::move(item));
|
Chris@16
|
2431 }
|
Chris@16
|
2432
|
Chris@16
|
2433 //! Destroy an item.
|
Chris@16
|
2434 void destroy_item(pointer p) {
|
Chris@101
|
2435 boost::container::allocator_traits<Alloc>::destroy(m_alloc, boost::addressof(*p));
|
Chris@16
|
2436 #if BOOST_CB_ENABLE_DEBUG
|
Chris@16
|
2437 invalidate_iterators(iterator(this, p));
|
Chris@101
|
2438 cb_details::do_fill_uninitialized_memory(p, sizeof(value_type));
|
Chris@16
|
2439 #endif
|
Chris@16
|
2440 }
|
Chris@16
|
2441
|
Chris@16
|
2442 //! Destroy an item only if it has been constructed.
|
Chris@16
|
2443 void destroy_if_constructed(pointer pos) {
|
Chris@16
|
2444 if (is_uninitialized(pos))
|
Chris@16
|
2445 destroy_item(pos);
|
Chris@16
|
2446 }
|
Chris@16
|
2447
|
Chris@16
|
2448 //! Destroy the whole content of the circular buffer.
|
Chris@16
|
2449 void destroy_content() {
|
Chris@16
|
2450 #if BOOST_CB_ENABLE_DEBUG
|
Chris@16
|
2451 destroy_content(false_type());
|
Chris@16
|
2452 #else
|
Chris@16
|
2453 destroy_content(is_scalar<value_type>());
|
Chris@16
|
2454 #endif
|
Chris@16
|
2455 }
|
Chris@16
|
2456
|
Chris@16
|
2457 //! Specialized destroy_content method.
|
Chris@16
|
2458 void destroy_content(const true_type&) {
|
Chris@16
|
2459 m_first = add(m_first, size());
|
Chris@16
|
2460 }
|
Chris@16
|
2461
|
Chris@16
|
2462 //! Specialized destroy_content method.
|
Chris@16
|
2463 void destroy_content(const false_type&) {
|
Chris@16
|
2464 for (size_type ii = 0; ii < size(); ++ii, increment(m_first))
|
Chris@16
|
2465 destroy_item(m_first);
|
Chris@16
|
2466 }
|
Chris@16
|
2467
|
Chris@16
|
2468 //! Destroy content and free allocated memory.
|
Chris@16
|
2469 void destroy() BOOST_NOEXCEPT {
|
Chris@16
|
2470 destroy_content();
|
Chris@16
|
2471 deallocate(m_buff, capacity());
|
Chris@16
|
2472 #if BOOST_CB_ENABLE_DEBUG
|
Chris@16
|
2473 m_buff = 0;
|
Chris@16
|
2474 m_first = 0;
|
Chris@16
|
2475 m_last = 0;
|
Chris@16
|
2476 m_end = 0;
|
Chris@16
|
2477 #endif
|
Chris@16
|
2478 }
|
Chris@16
|
2479
|
Chris@16
|
2480 //! Initialize the internal buffer.
|
Chris@16
|
2481 void initialize_buffer(capacity_type buffer_capacity) {
|
Chris@16
|
2482 m_buff = allocate(buffer_capacity);
|
Chris@16
|
2483 m_end = m_buff + buffer_capacity;
|
Chris@16
|
2484 }
|
Chris@16
|
2485
|
Chris@16
|
2486 //! Initialize the internal buffer.
|
Chris@16
|
2487 void initialize_buffer(capacity_type buffer_capacity, param_value_type item) {
|
Chris@16
|
2488 initialize_buffer(buffer_capacity);
|
Chris@16
|
2489 BOOST_TRY {
|
Chris@16
|
2490 cb_details::uninitialized_fill_n_with_alloc(m_buff, size(), item, m_alloc);
|
Chris@16
|
2491 } BOOST_CATCH(...) {
|
Chris@16
|
2492 deallocate(m_buff, size());
|
Chris@16
|
2493 BOOST_RETHROW
|
Chris@16
|
2494 }
|
Chris@16
|
2495 BOOST_CATCH_END
|
Chris@16
|
2496 }
|
Chris@16
|
2497
|
Chris@16
|
2498 //! Specialized initialize method.
|
Chris@16
|
2499 template <class IntegralType>
|
Chris@16
|
2500 void initialize(IntegralType n, IntegralType item, const true_type&) {
|
Chris@16
|
2501 m_size = static_cast<size_type>(n);
|
Chris@16
|
2502 initialize_buffer(size(), item);
|
Chris@16
|
2503 m_first = m_last = m_buff;
|
Chris@16
|
2504 }
|
Chris@16
|
2505
|
Chris@16
|
2506 //! Specialized initialize method.
|
Chris@16
|
2507 template <class Iterator>
|
Chris@16
|
2508 void initialize(Iterator first, Iterator last, const false_type&) {
|
Chris@16
|
2509 BOOST_CB_IS_CONVERTIBLE(Iterator, value_type); // check for invalid iterator type
|
Chris@16
|
2510 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581))
|
Chris@101
|
2511 initialize(first, last, iterator_category<Iterator>::type());
|
Chris@16
|
2512 #else
|
Chris@101
|
2513 initialize(first, last, BOOST_DEDUCED_TYPENAME iterator_category<Iterator>::type());
|
Chris@16
|
2514 #endif
|
Chris@16
|
2515 }
|
Chris@16
|
2516
|
Chris@16
|
2517 //! Specialized initialize method.
|
Chris@16
|
2518 template <class InputIterator>
|
Chris@16
|
2519 void initialize(InputIterator first, InputIterator last, const std::input_iterator_tag&) {
|
Chris@16
|
2520 BOOST_CB_ASSERT_TEMPLATED_ITERATOR_CONSTRUCTORS // check if the STL provides templated iterator constructors
|
Chris@16
|
2521 // for containers
|
Chris@16
|
2522 std::deque<value_type, allocator_type> tmp(first, last, m_alloc);
|
Chris@16
|
2523 size_type distance = tmp.size();
|
Chris@16
|
2524 initialize(distance, boost::make_move_iterator(tmp.begin()), boost::make_move_iterator(tmp.end()), distance);
|
Chris@16
|
2525 }
|
Chris@16
|
2526
|
Chris@16
|
2527 //! Specialized initialize method.
|
Chris@16
|
2528 template <class ForwardIterator>
|
Chris@16
|
2529 void initialize(ForwardIterator first, ForwardIterator last, const std::forward_iterator_tag&) {
|
Chris@16
|
2530 BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range
|
Chris@16
|
2531 size_type distance = std::distance(first, last);
|
Chris@16
|
2532 initialize(distance, first, last, distance);
|
Chris@16
|
2533 }
|
Chris@16
|
2534
|
Chris@16
|
2535 //! Specialized initialize method.
|
Chris@16
|
2536 template <class IntegralType>
|
Chris@16
|
2537 void initialize(capacity_type buffer_capacity, IntegralType n, IntegralType item, const true_type&) {
|
Chris@16
|
2538 BOOST_CB_ASSERT(buffer_capacity >= static_cast<size_type>(n)); // check for capacity lower than n
|
Chris@16
|
2539 m_size = static_cast<size_type>(n);
|
Chris@16
|
2540 initialize_buffer(buffer_capacity, item);
|
Chris@16
|
2541 m_first = m_buff;
|
Chris@16
|
2542 m_last = buffer_capacity == size() ? m_buff : m_buff + size();
|
Chris@16
|
2543 }
|
Chris@16
|
2544
|
Chris@16
|
2545 //! Specialized initialize method.
|
Chris@16
|
2546 template <class Iterator>
|
Chris@16
|
2547 void initialize(capacity_type buffer_capacity, Iterator first, Iterator last, const false_type&) {
|
Chris@16
|
2548 BOOST_CB_IS_CONVERTIBLE(Iterator, value_type); // check for invalid iterator type
|
Chris@16
|
2549 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581))
|
Chris@101
|
2550 initialize(buffer_capacity, first, last, iterator_category<Iterator>::type());
|
Chris@16
|
2551 #else
|
Chris@101
|
2552 initialize(buffer_capacity, first, last, BOOST_DEDUCED_TYPENAME iterator_category<Iterator>::type());
|
Chris@16
|
2553 #endif
|
Chris@16
|
2554 }
|
Chris@16
|
2555
|
Chris@16
|
2556 //! Specialized initialize method.
|
Chris@16
|
2557 template <class InputIterator>
|
Chris@16
|
2558 void initialize(capacity_type buffer_capacity,
|
Chris@16
|
2559 InputIterator first,
|
Chris@16
|
2560 InputIterator last,
|
Chris@16
|
2561 const std::input_iterator_tag&) {
|
Chris@16
|
2562 initialize_buffer(buffer_capacity);
|
Chris@16
|
2563 m_first = m_last = m_buff;
|
Chris@16
|
2564 m_size = 0;
|
Chris@16
|
2565 if (buffer_capacity == 0)
|
Chris@16
|
2566 return;
|
Chris@16
|
2567 while (first != last && !full()) {
|
Chris@101
|
2568 boost::container::allocator_traits<Alloc>::construct(m_alloc, boost::addressof(*m_last), *first++);
|
Chris@16
|
2569 increment(m_last);
|
Chris@16
|
2570 ++m_size;
|
Chris@16
|
2571 }
|
Chris@16
|
2572 while (first != last) {
|
Chris@16
|
2573 replace(m_last, *first++);
|
Chris@16
|
2574 increment(m_last);
|
Chris@16
|
2575 m_first = m_last;
|
Chris@16
|
2576 }
|
Chris@16
|
2577 }
|
Chris@16
|
2578
|
Chris@16
|
2579 //! Specialized initialize method.
|
Chris@16
|
2580 template <class ForwardIterator>
|
Chris@16
|
2581 void initialize(capacity_type buffer_capacity,
|
Chris@16
|
2582 ForwardIterator first,
|
Chris@16
|
2583 ForwardIterator last,
|
Chris@16
|
2584 const std::forward_iterator_tag&) {
|
Chris@16
|
2585 BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range
|
Chris@16
|
2586 initialize(buffer_capacity, first, last, std::distance(first, last));
|
Chris@16
|
2587 }
|
Chris@16
|
2588
|
Chris@16
|
2589 //! Initialize the circular buffer.
|
Chris@16
|
2590 template <class ForwardIterator>
|
Chris@16
|
2591 void initialize(capacity_type buffer_capacity,
|
Chris@16
|
2592 ForwardIterator first,
|
Chris@16
|
2593 ForwardIterator last,
|
Chris@16
|
2594 size_type distance) {
|
Chris@16
|
2595 initialize_buffer(buffer_capacity);
|
Chris@16
|
2596 m_first = m_buff;
|
Chris@16
|
2597 if (distance > buffer_capacity) {
|
Chris@16
|
2598 std::advance(first, distance - buffer_capacity);
|
Chris@16
|
2599 m_size = buffer_capacity;
|
Chris@16
|
2600 } else {
|
Chris@16
|
2601 m_size = distance;
|
Chris@16
|
2602 }
|
Chris@16
|
2603 BOOST_TRY {
|
Chris@101
|
2604 m_last = cb_details::uninitialized_copy(first, last, m_buff, m_alloc);
|
Chris@16
|
2605 } BOOST_CATCH(...) {
|
Chris@16
|
2606 deallocate(m_buff, buffer_capacity);
|
Chris@16
|
2607 BOOST_RETHROW
|
Chris@16
|
2608 }
|
Chris@16
|
2609 BOOST_CATCH_END
|
Chris@16
|
2610 if (m_last == m_end)
|
Chris@16
|
2611 m_last = m_buff;
|
Chris@16
|
2612 }
|
Chris@16
|
2613
|
Chris@16
|
2614 //! Reset the circular buffer.
|
Chris@16
|
2615 void reset(pointer buff, pointer last, capacity_type new_capacity) {
|
Chris@16
|
2616 destroy();
|
Chris@16
|
2617 m_size = last - buff;
|
Chris@16
|
2618 m_first = m_buff = buff;
|
Chris@16
|
2619 m_end = m_buff + new_capacity;
|
Chris@16
|
2620 m_last = last == m_end ? m_buff : last;
|
Chris@16
|
2621 }
|
Chris@16
|
2622
|
Chris@16
|
2623 //! Specialized method for swapping the allocator.
|
Chris@16
|
2624 void swap_allocator(circular_buffer<T, Alloc>&, const true_type&) {
|
Chris@16
|
2625 // Swap is not needed because allocators have no state.
|
Chris@16
|
2626 }
|
Chris@16
|
2627
|
Chris@16
|
2628 //! Specialized method for swapping the allocator.
|
Chris@16
|
2629 void swap_allocator(circular_buffer<T, Alloc>& cb, const false_type&) {
|
Chris@16
|
2630 std::swap(m_alloc, cb.m_alloc);
|
Chris@16
|
2631 }
|
Chris@16
|
2632
|
Chris@16
|
2633 //! Specialized assign method.
|
Chris@16
|
2634 template <class IntegralType>
|
Chris@16
|
2635 void assign(IntegralType n, IntegralType item, const true_type&) {
|
Chris@16
|
2636 assign(static_cast<size_type>(n), static_cast<value_type>(item));
|
Chris@16
|
2637 }
|
Chris@16
|
2638
|
Chris@16
|
2639 //! Specialized assign method.
|
Chris@16
|
2640 template <class Iterator>
|
Chris@16
|
2641 void assign(Iterator first, Iterator last, const false_type&) {
|
Chris@16
|
2642 BOOST_CB_IS_CONVERTIBLE(Iterator, value_type); // check for invalid iterator type
|
Chris@16
|
2643 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581))
|
Chris@101
|
2644 assign(first, last, iterator_category<Iterator>::type());
|
Chris@16
|
2645 #else
|
Chris@101
|
2646 assign(first, last, BOOST_DEDUCED_TYPENAME iterator_category<Iterator>::type());
|
Chris@16
|
2647 #endif
|
Chris@16
|
2648 }
|
Chris@16
|
2649
|
Chris@16
|
2650 //! Specialized assign method.
|
Chris@16
|
2651 template <class InputIterator>
|
Chris@16
|
2652 void assign(InputIterator first, InputIterator last, const std::input_iterator_tag&) {
|
Chris@16
|
2653 BOOST_CB_ASSERT_TEMPLATED_ITERATOR_CONSTRUCTORS // check if the STL provides templated iterator constructors
|
Chris@16
|
2654 // for containers
|
Chris@16
|
2655 std::deque<value_type, allocator_type> tmp(first, last, m_alloc);
|
Chris@16
|
2656 size_type distance = tmp.size();
|
Chris@16
|
2657 assign_n(distance, distance,
|
Chris@101
|
2658 cb_details::make_assign_range
|
Chris@101
|
2659 (boost::make_move_iterator(tmp.begin()), boost::make_move_iterator(tmp.end()), m_alloc));
|
Chris@16
|
2660 }
|
Chris@16
|
2661
|
Chris@16
|
2662 //! Specialized assign method.
|
Chris@16
|
2663 template <class ForwardIterator>
|
Chris@16
|
2664 void assign(ForwardIterator first, ForwardIterator last, const std::forward_iterator_tag&) {
|
Chris@16
|
2665 BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range
|
Chris@16
|
2666 size_type distance = std::distance(first, last);
|
Chris@101
|
2667 assign_n(distance, distance, cb_details::make_assign_range(first, last, m_alloc));
|
Chris@16
|
2668 }
|
Chris@16
|
2669
|
Chris@16
|
2670 //! Specialized assign method.
|
Chris@16
|
2671 template <class IntegralType>
|
Chris@16
|
2672 void assign(capacity_type new_capacity, IntegralType n, IntegralType item, const true_type&) {
|
Chris@16
|
2673 assign(new_capacity, static_cast<size_type>(n), static_cast<value_type>(item));
|
Chris@16
|
2674 }
|
Chris@16
|
2675
|
Chris@16
|
2676 //! Specialized assign method.
|
Chris@16
|
2677 template <class Iterator>
|
Chris@16
|
2678 void assign(capacity_type new_capacity, Iterator first, Iterator last, const false_type&) {
|
Chris@16
|
2679 BOOST_CB_IS_CONVERTIBLE(Iterator, value_type); // check for invalid iterator type
|
Chris@16
|
2680 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581))
|
Chris@101
|
2681 assign(new_capacity, first, last, iterator_category<Iterator>::type());
|
Chris@16
|
2682 #else
|
Chris@101
|
2683 assign(new_capacity, first, last, BOOST_DEDUCED_TYPENAME iterator_category<Iterator>::type());
|
Chris@16
|
2684 #endif
|
Chris@16
|
2685 }
|
Chris@16
|
2686
|
Chris@16
|
2687 //! Specialized assign method.
|
Chris@16
|
2688 template <class InputIterator>
|
Chris@16
|
2689 void assign(capacity_type new_capacity, InputIterator first, InputIterator last, const std::input_iterator_tag&) {
|
Chris@16
|
2690 if (new_capacity == capacity()) {
|
Chris@16
|
2691 clear();
|
Chris@16
|
2692 insert(begin(), first, last);
|
Chris@16
|
2693 } else {
|
Chris@16
|
2694 circular_buffer<value_type, allocator_type> tmp(new_capacity, first, last, m_alloc);
|
Chris@16
|
2695 tmp.swap(*this);
|
Chris@16
|
2696 }
|
Chris@16
|
2697 }
|
Chris@16
|
2698
|
Chris@16
|
2699 //! Specialized assign method.
|
Chris@16
|
2700 template <class ForwardIterator>
|
Chris@16
|
2701 void assign(capacity_type new_capacity, ForwardIterator first, ForwardIterator last,
|
Chris@16
|
2702 const std::forward_iterator_tag&) {
|
Chris@16
|
2703 BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range
|
Chris@16
|
2704 size_type distance = std::distance(first, last);
|
Chris@16
|
2705 if (distance > new_capacity) {
|
Chris@16
|
2706 std::advance(first, distance - new_capacity);
|
Chris@16
|
2707 distance = new_capacity;
|
Chris@16
|
2708 }
|
Chris@16
|
2709 assign_n(new_capacity, distance,
|
Chris@101
|
2710 cb_details::make_assign_range(first, last, m_alloc));
|
Chris@16
|
2711 }
|
Chris@16
|
2712
|
Chris@16
|
2713 //! Helper assign method.
|
Chris@16
|
2714 template <class Functor>
|
Chris@16
|
2715 void assign_n(capacity_type new_capacity, size_type n, const Functor& fnc) {
|
Chris@16
|
2716 if (new_capacity == capacity()) {
|
Chris@16
|
2717 destroy_content();
|
Chris@16
|
2718 BOOST_TRY {
|
Chris@16
|
2719 fnc(m_buff);
|
Chris@16
|
2720 } BOOST_CATCH(...) {
|
Chris@16
|
2721 m_size = 0;
|
Chris@16
|
2722 BOOST_RETHROW
|
Chris@16
|
2723 }
|
Chris@16
|
2724 BOOST_CATCH_END
|
Chris@16
|
2725 } else {
|
Chris@16
|
2726 pointer buff = allocate(new_capacity);
|
Chris@16
|
2727 BOOST_TRY {
|
Chris@16
|
2728 fnc(buff);
|
Chris@16
|
2729 } BOOST_CATCH(...) {
|
Chris@16
|
2730 deallocate(buff, new_capacity);
|
Chris@16
|
2731 BOOST_RETHROW
|
Chris@16
|
2732 }
|
Chris@16
|
2733 BOOST_CATCH_END
|
Chris@16
|
2734 destroy();
|
Chris@16
|
2735 m_buff = buff;
|
Chris@16
|
2736 m_end = m_buff + new_capacity;
|
Chris@16
|
2737 }
|
Chris@16
|
2738 m_size = n;
|
Chris@16
|
2739 m_first = m_buff;
|
Chris@16
|
2740 m_last = add(m_buff, size());
|
Chris@16
|
2741 }
|
Chris@16
|
2742
|
Chris@16
|
2743 //! Helper insert method.
|
Chris@16
|
2744 template <class ValT>
|
Chris@16
|
2745 iterator insert_item(const iterator& pos, ValT item) {
|
Chris@16
|
2746 pointer p = pos.m_it;
|
Chris@16
|
2747 if (p == 0) {
|
Chris@16
|
2748 construct_or_replace(!full(), m_last, static_cast<ValT>(item));
|
Chris@16
|
2749 p = m_last;
|
Chris@16
|
2750 } else {
|
Chris@16
|
2751 pointer src = m_last;
|
Chris@16
|
2752 pointer dest = m_last;
|
Chris@16
|
2753 bool construct = !full();
|
Chris@16
|
2754 BOOST_TRY {
|
Chris@16
|
2755 while (src != p) {
|
Chris@16
|
2756 decrement(src);
|
Chris@101
|
2757 construct_or_replace(construct, dest, boost::move_if_noexcept(*src));
|
Chris@16
|
2758 decrement(dest);
|
Chris@16
|
2759 construct = false;
|
Chris@16
|
2760 }
|
Chris@16
|
2761 replace(p, static_cast<ValT>(item));
|
Chris@16
|
2762 } BOOST_CATCH(...) {
|
Chris@16
|
2763 if (!construct && !full()) {
|
Chris@16
|
2764 increment(m_last);
|
Chris@16
|
2765 ++m_size;
|
Chris@16
|
2766 }
|
Chris@16
|
2767 BOOST_RETHROW
|
Chris@16
|
2768 }
|
Chris@16
|
2769 BOOST_CATCH_END
|
Chris@16
|
2770 }
|
Chris@16
|
2771 increment(m_last);
|
Chris@16
|
2772 if (full())
|
Chris@16
|
2773 m_first = m_last;
|
Chris@16
|
2774 else
|
Chris@16
|
2775 ++m_size;
|
Chris@16
|
2776 return iterator(this, p);
|
Chris@16
|
2777 }
|
Chris@16
|
2778
|
Chris@16
|
2779 //! Specialized insert method.
|
Chris@16
|
2780 template <class IntegralType>
|
Chris@16
|
2781 void insert(const iterator& pos, IntegralType n, IntegralType item, const true_type&) {
|
Chris@16
|
2782 insert(pos, static_cast<size_type>(n), static_cast<value_type>(item));
|
Chris@16
|
2783 }
|
Chris@16
|
2784
|
Chris@16
|
2785 //! Specialized insert method.
|
Chris@16
|
2786 template <class Iterator>
|
Chris@16
|
2787 void insert(const iterator& pos, Iterator first, Iterator last, const false_type&) {
|
Chris@16
|
2788 BOOST_CB_IS_CONVERTIBLE(Iterator, value_type); // check for invalid iterator type
|
Chris@16
|
2789 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581))
|
Chris@101
|
2790 insert(pos, first, last, iterator_category<Iterator>::type());
|
Chris@16
|
2791 #else
|
Chris@101
|
2792 insert(pos, first, last, BOOST_DEDUCED_TYPENAME iterator_category<Iterator>::type());
|
Chris@16
|
2793 #endif
|
Chris@16
|
2794 }
|
Chris@16
|
2795
|
Chris@16
|
2796 //! Specialized insert method.
|
Chris@16
|
2797 template <class InputIterator>
|
Chris@16
|
2798 void insert(iterator pos, InputIterator first, InputIterator last, const std::input_iterator_tag&) {
|
Chris@16
|
2799 if (!full() || pos != begin()) {
|
Chris@16
|
2800 for (;first != last; ++pos)
|
Chris@16
|
2801 pos = insert(pos, *first++);
|
Chris@16
|
2802 }
|
Chris@16
|
2803 }
|
Chris@16
|
2804
|
Chris@16
|
2805 //! Specialized insert method.
|
Chris@16
|
2806 template <class ForwardIterator>
|
Chris@16
|
2807 void insert(const iterator& pos, ForwardIterator first, ForwardIterator last, const std::forward_iterator_tag&) {
|
Chris@16
|
2808 BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range
|
Chris@16
|
2809 size_type n = std::distance(first, last);
|
Chris@16
|
2810 if (n == 0)
|
Chris@16
|
2811 return;
|
Chris@16
|
2812 size_type copy = capacity() - (end() - pos);
|
Chris@16
|
2813 if (copy == 0)
|
Chris@16
|
2814 return;
|
Chris@16
|
2815 if (n > copy) {
|
Chris@16
|
2816 std::advance(first, n - copy);
|
Chris@16
|
2817 n = copy;
|
Chris@16
|
2818 }
|
Chris@16
|
2819 insert_n(pos, n, cb_details::iterator_wrapper<ForwardIterator>(first));
|
Chris@16
|
2820 }
|
Chris@16
|
2821
|
Chris@16
|
2822 //! Helper insert method.
|
Chris@16
|
2823 template <class Wrapper>
|
Chris@16
|
2824 void insert_n(const iterator& pos, size_type n, const Wrapper& wrapper) {
|
Chris@16
|
2825 size_type construct = reserve();
|
Chris@16
|
2826 if (construct > n)
|
Chris@16
|
2827 construct = n;
|
Chris@16
|
2828 if (pos.m_it == 0) {
|
Chris@16
|
2829 size_type ii = 0;
|
Chris@16
|
2830 pointer p = m_last;
|
Chris@16
|
2831 BOOST_TRY {
|
Chris@16
|
2832 for (; ii < construct; ++ii, increment(p))
|
Chris@101
|
2833 boost::container::allocator_traits<Alloc>::construct(m_alloc, boost::addressof(*p), *wrapper());
|
Chris@16
|
2834 for (;ii < n; ++ii, increment(p))
|
Chris@16
|
2835 replace(p, *wrapper());
|
Chris@16
|
2836 } BOOST_CATCH(...) {
|
Chris@16
|
2837 size_type constructed = (std::min)(ii, construct);
|
Chris@16
|
2838 m_last = add(m_last, constructed);
|
Chris@16
|
2839 m_size += constructed;
|
Chris@16
|
2840 BOOST_RETHROW
|
Chris@16
|
2841 }
|
Chris@16
|
2842 BOOST_CATCH_END
|
Chris@16
|
2843 } else {
|
Chris@16
|
2844 pointer src = m_last;
|
Chris@16
|
2845 pointer dest = add(m_last, n - 1);
|
Chris@16
|
2846 pointer p = pos.m_it;
|
Chris@16
|
2847 size_type ii = 0;
|
Chris@16
|
2848 BOOST_TRY {
|
Chris@16
|
2849 while (src != pos.m_it) {
|
Chris@16
|
2850 decrement(src);
|
Chris@16
|
2851 construct_or_replace(is_uninitialized(dest), dest, *src);
|
Chris@16
|
2852 decrement(dest);
|
Chris@16
|
2853 }
|
Chris@16
|
2854 for (; ii < n; ++ii, increment(p))
|
Chris@16
|
2855 construct_or_replace(is_uninitialized(p), p, *wrapper());
|
Chris@16
|
2856 } BOOST_CATCH(...) {
|
Chris@16
|
2857 for (p = add(m_last, n - 1); p != dest; decrement(p))
|
Chris@16
|
2858 destroy_if_constructed(p);
|
Chris@16
|
2859 for (n = 0, p = pos.m_it; n < ii; ++n, increment(p))
|
Chris@16
|
2860 destroy_if_constructed(p);
|
Chris@16
|
2861 BOOST_RETHROW
|
Chris@16
|
2862 }
|
Chris@16
|
2863 BOOST_CATCH_END
|
Chris@16
|
2864 }
|
Chris@16
|
2865 m_last = add(m_last, n);
|
Chris@16
|
2866 m_first = add(m_first, n - construct);
|
Chris@16
|
2867 m_size += construct;
|
Chris@16
|
2868 }
|
Chris@16
|
2869
|
Chris@16
|
2870 //! Specialized rinsert method.
|
Chris@16
|
2871 template <class IntegralType>
|
Chris@16
|
2872 void rinsert(const iterator& pos, IntegralType n, IntegralType item, const true_type&) {
|
Chris@16
|
2873 rinsert(pos, static_cast<size_type>(n), static_cast<value_type>(item));
|
Chris@16
|
2874 }
|
Chris@16
|
2875
|
Chris@16
|
2876 //! Specialized rinsert method.
|
Chris@16
|
2877 template <class Iterator>
|
Chris@16
|
2878 void rinsert(const iterator& pos, Iterator first, Iterator last, const false_type&) {
|
Chris@16
|
2879 BOOST_CB_IS_CONVERTIBLE(Iterator, value_type); // check for invalid iterator type
|
Chris@16
|
2880 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581))
|
Chris@101
|
2881 rinsert(pos, first, last, iterator_category<Iterator>::type());
|
Chris@16
|
2882 #else
|
Chris@101
|
2883 rinsert(pos, first, last, BOOST_DEDUCED_TYPENAME iterator_category<Iterator>::type());
|
Chris@16
|
2884 #endif
|
Chris@16
|
2885 }
|
Chris@16
|
2886
|
Chris@16
|
2887 //! Specialized insert method.
|
Chris@16
|
2888 template <class InputIterator>
|
Chris@16
|
2889 void rinsert(iterator pos, InputIterator first, InputIterator last, const std::input_iterator_tag&) {
|
Chris@16
|
2890 if (!full() || pos.m_it != 0) {
|
Chris@16
|
2891 for (;first != last; ++pos) {
|
Chris@16
|
2892 pos = rinsert(pos, *first++);
|
Chris@16
|
2893 if (pos.m_it == 0)
|
Chris@16
|
2894 break;
|
Chris@16
|
2895 }
|
Chris@16
|
2896 }
|
Chris@16
|
2897 }
|
Chris@16
|
2898
|
Chris@16
|
2899 //! Specialized rinsert method.
|
Chris@16
|
2900 template <class ForwardIterator>
|
Chris@16
|
2901 void rinsert(const iterator& pos, ForwardIterator first, ForwardIterator last, const std::forward_iterator_tag&) {
|
Chris@16
|
2902 BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range
|
Chris@16
|
2903 rinsert_n(pos, std::distance(first, last), cb_details::iterator_wrapper<ForwardIterator>(first));
|
Chris@16
|
2904 }
|
Chris@16
|
2905
|
Chris@16
|
2906 //! Helper rinsert method.
|
Chris@16
|
2907 template <class Wrapper>
|
Chris@16
|
2908 void rinsert_n(const iterator& pos, size_type n, const Wrapper& wrapper) {
|
Chris@16
|
2909 if (n == 0)
|
Chris@16
|
2910 return;
|
Chris@16
|
2911 iterator b = begin();
|
Chris@16
|
2912 size_type copy = capacity() - (pos - b);
|
Chris@16
|
2913 if (copy == 0)
|
Chris@16
|
2914 return;
|
Chris@16
|
2915 if (n > copy)
|
Chris@16
|
2916 n = copy;
|
Chris@16
|
2917 size_type construct = reserve();
|
Chris@16
|
2918 if (construct > n)
|
Chris@16
|
2919 construct = n;
|
Chris@16
|
2920 if (pos == b) {
|
Chris@16
|
2921 pointer p = sub(m_first, n);
|
Chris@16
|
2922 size_type ii = n;
|
Chris@16
|
2923 BOOST_TRY {
|
Chris@16
|
2924 for (;ii > construct; --ii, increment(p))
|
Chris@16
|
2925 replace(p, *wrapper());
|
Chris@16
|
2926 for (; ii > 0; --ii, increment(p))
|
Chris@101
|
2927 boost::container::allocator_traits<Alloc>::construct(m_alloc, boost::addressof(*p), *wrapper());
|
Chris@16
|
2928 } BOOST_CATCH(...) {
|
Chris@16
|
2929 size_type constructed = ii < construct ? construct - ii : 0;
|
Chris@16
|
2930 m_last = add(m_last, constructed);
|
Chris@16
|
2931 m_size += constructed;
|
Chris@16
|
2932 BOOST_RETHROW
|
Chris@16
|
2933 }
|
Chris@16
|
2934 BOOST_CATCH_END
|
Chris@16
|
2935 } else {
|
Chris@16
|
2936 pointer src = m_first;
|
Chris@16
|
2937 pointer dest = sub(m_first, n);
|
Chris@16
|
2938 pointer p = map_pointer(pos.m_it);
|
Chris@16
|
2939 BOOST_TRY {
|
Chris@16
|
2940 while (src != p) {
|
Chris@16
|
2941 construct_or_replace(is_uninitialized(dest), dest, *src);
|
Chris@16
|
2942 increment(src);
|
Chris@16
|
2943 increment(dest);
|
Chris@16
|
2944 }
|
Chris@16
|
2945 for (size_type ii = 0; ii < n; ++ii, increment(dest))
|
Chris@16
|
2946 construct_or_replace(is_uninitialized(dest), dest, *wrapper());
|
Chris@16
|
2947 } BOOST_CATCH(...) {
|
Chris@16
|
2948 for (src = sub(m_first, n); src != dest; increment(src))
|
Chris@16
|
2949 destroy_if_constructed(src);
|
Chris@16
|
2950 BOOST_RETHROW
|
Chris@16
|
2951 }
|
Chris@16
|
2952 BOOST_CATCH_END
|
Chris@16
|
2953 }
|
Chris@16
|
2954 m_first = sub(m_first, n);
|
Chris@16
|
2955 m_last = sub(m_last, n - construct);
|
Chris@16
|
2956 m_size += construct;
|
Chris@16
|
2957 }
|
Chris@16
|
2958
|
Chris@16
|
2959 //! Specialized erase_begin method.
|
Chris@16
|
2960 void erase_begin(size_type n, const true_type&) {
|
Chris@16
|
2961 m_first = add(m_first, n);
|
Chris@16
|
2962 m_size -= n;
|
Chris@16
|
2963 }
|
Chris@16
|
2964
|
Chris@16
|
2965 //! Specialized erase_begin method.
|
Chris@16
|
2966 void erase_begin(size_type n, const false_type&) {
|
Chris@16
|
2967 iterator b = begin();
|
Chris@16
|
2968 rerase(b, b + n);
|
Chris@16
|
2969 }
|
Chris@16
|
2970
|
Chris@16
|
2971 //! Specialized erase_end method.
|
Chris@16
|
2972 void erase_end(size_type n, const true_type&) {
|
Chris@16
|
2973 m_last = sub(m_last, n);
|
Chris@16
|
2974 m_size -= n;
|
Chris@16
|
2975 }
|
Chris@16
|
2976
|
Chris@16
|
2977 //! Specialized erase_end method.
|
Chris@16
|
2978 void erase_end(size_type n, const false_type&) {
|
Chris@16
|
2979 iterator e = end();
|
Chris@16
|
2980 erase(e - n, e);
|
Chris@16
|
2981 }
|
Chris@16
|
2982 };
|
Chris@16
|
2983
|
Chris@16
|
2984 // Non-member functions
|
Chris@16
|
2985
|
Chris@16
|
2986 //! Compare two <code>circular_buffer</code>s element-by-element to determine if they are equal.
|
Chris@16
|
2987 /*!
|
Chris@16
|
2988 \param lhs The <code>circular_buffer</code> to compare.
|
Chris@16
|
2989 \param rhs The <code>circular_buffer</code> to compare.
|
Chris@16
|
2990 \return <code>lhs.\link circular_buffer::size() size()\endlink == rhs.\link circular_buffer::size() size()\endlink
|
Chris@16
|
2991 && <a href="http://www.sgi.com/tech/stl/equal.html">std::equal</a>(lhs.\link circular_buffer::begin()
|
Chris@16
|
2992 begin()\endlink, lhs.\link circular_buffer::end() end()\endlink,
|
Chris@16
|
2993 rhs.\link circular_buffer::begin() begin()\endlink)</code>
|
Chris@16
|
2994 \throws Nothing.
|
Chris@16
|
2995 \par Complexity
|
Chris@16
|
2996 Linear (in the size of the <code>circular_buffer</code>s).
|
Chris@16
|
2997 \par Iterator Invalidation
|
Chris@16
|
2998 Does not invalidate any iterators.
|
Chris@16
|
2999 */
|
Chris@16
|
3000 template <class T, class Alloc>
|
Chris@16
|
3001 inline bool operator == (const circular_buffer<T, Alloc>& lhs, const circular_buffer<T, Alloc>& rhs) {
|
Chris@16
|
3002 return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
|
Chris@16
|
3003 }
|
Chris@16
|
3004
|
Chris@16
|
3005 /*!
|
Chris@16
|
3006 \brief Compare two <code>circular_buffer</code>s element-by-element to determine if the left one is lesser than the
|
Chris@16
|
3007 right one.
|
Chris@16
|
3008 \param lhs The <code>circular_buffer</code> to compare.
|
Chris@16
|
3009 \param rhs The <code>circular_buffer</code> to compare.
|
Chris@16
|
3010 \return <code><a href="http://www.sgi.com/tech/stl/lexicographical_compare.html">
|
Chris@16
|
3011 std::lexicographical_compare</a>(lhs.\link circular_buffer::begin() begin()\endlink,
|
Chris@16
|
3012 lhs.\link circular_buffer::end() end()\endlink, rhs.\link circular_buffer::begin() begin()\endlink,
|
Chris@16
|
3013 rhs.\link circular_buffer::end() end()\endlink)</code>
|
Chris@16
|
3014 \throws Nothing.
|
Chris@16
|
3015 \par Complexity
|
Chris@16
|
3016 Linear (in the size of the <code>circular_buffer</code>s).
|
Chris@16
|
3017 \par Iterator Invalidation
|
Chris@16
|
3018 Does not invalidate any iterators.
|
Chris@16
|
3019 */
|
Chris@16
|
3020 template <class T, class Alloc>
|
Chris@16
|
3021 inline bool operator < (const circular_buffer<T, Alloc>& lhs, const circular_buffer<T, Alloc>& rhs) {
|
Chris@16
|
3022 return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
|
Chris@16
|
3023 }
|
Chris@16
|
3024
|
Chris@16
|
3025 #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) || defined(BOOST_MSVC)
|
Chris@16
|
3026
|
Chris@16
|
3027 //! Compare two <code>circular_buffer</code>s element-by-element to determine if they are non-equal.
|
Chris@16
|
3028 /*!
|
Chris@16
|
3029 \param lhs The <code>circular_buffer</code> to compare.
|
Chris@16
|
3030 \param rhs The <code>circular_buffer</code> to compare.
|
Chris@16
|
3031 \return <code>!(lhs == rhs)</code>
|
Chris@16
|
3032 \throws Nothing.
|
Chris@16
|
3033 \par Complexity
|
Chris@16
|
3034 Linear (in the size of the <code>circular_buffer</code>s).
|
Chris@16
|
3035 \par Iterator Invalidation
|
Chris@16
|
3036 Does not invalidate any iterators.
|
Chris@16
|
3037 \sa <code>operator==(const circular_buffer<T,Alloc>&, const circular_buffer<T,Alloc>&)</code>
|
Chris@16
|
3038 */
|
Chris@16
|
3039 template <class T, class Alloc>
|
Chris@16
|
3040 inline bool operator != (const circular_buffer<T, Alloc>& lhs, const circular_buffer<T, Alloc>& rhs) {
|
Chris@16
|
3041 return !(lhs == rhs);
|
Chris@16
|
3042 }
|
Chris@16
|
3043
|
Chris@16
|
3044 /*!
|
Chris@16
|
3045 \brief Compare two <code>circular_buffer</code>s element-by-element to determine if the left one is greater than
|
Chris@16
|
3046 the right one.
|
Chris@16
|
3047 \param lhs The <code>circular_buffer</code> to compare.
|
Chris@16
|
3048 \param rhs The <code>circular_buffer</code> to compare.
|
Chris@16
|
3049 \return <code>rhs \< lhs</code>
|
Chris@16
|
3050 \throws Nothing.
|
Chris@16
|
3051 \par Complexity
|
Chris@16
|
3052 Linear (in the size of the <code>circular_buffer</code>s).
|
Chris@16
|
3053 \par Iterator Invalidation
|
Chris@16
|
3054 Does not invalidate any iterators.
|
Chris@16
|
3055 \sa <code>operator<(const circular_buffer<T,Alloc>&, const circular_buffer<T,Alloc>&)</code>
|
Chris@16
|
3056 */
|
Chris@16
|
3057 template <class T, class Alloc>
|
Chris@16
|
3058 inline bool operator > (const circular_buffer<T, Alloc>& lhs, const circular_buffer<T, Alloc>& rhs) {
|
Chris@16
|
3059 return rhs < lhs;
|
Chris@16
|
3060 }
|
Chris@16
|
3061
|
Chris@16
|
3062 /*!
|
Chris@16
|
3063 \brief Compare two <code>circular_buffer</code>s element-by-element to determine if the left one is lesser or equal
|
Chris@16
|
3064 to the right one.
|
Chris@16
|
3065 \param lhs The <code>circular_buffer</code> to compare.
|
Chris@16
|
3066 \param rhs The <code>circular_buffer</code> to compare.
|
Chris@16
|
3067 \return <code>!(rhs \< lhs)</code>
|
Chris@16
|
3068 \throws Nothing.
|
Chris@16
|
3069 \par Complexity
|
Chris@16
|
3070 Linear (in the size of the <code>circular_buffer</code>s).
|
Chris@16
|
3071 \par Iterator Invalidation
|
Chris@16
|
3072 Does not invalidate any iterators.
|
Chris@16
|
3073 \sa <code>operator<(const circular_buffer<T,Alloc>&, const circular_buffer<T,Alloc>&)</code>
|
Chris@16
|
3074 */
|
Chris@16
|
3075 template <class T, class Alloc>
|
Chris@16
|
3076 inline bool operator <= (const circular_buffer<T, Alloc>& lhs, const circular_buffer<T, Alloc>& rhs) {
|
Chris@16
|
3077 return !(rhs < lhs);
|
Chris@16
|
3078 }
|
Chris@16
|
3079
|
Chris@16
|
3080 /*!
|
Chris@16
|
3081 \brief Compare two <code>circular_buffer</code>s element-by-element to determine if the left one is greater or
|
Chris@16
|
3082 equal to the right one.
|
Chris@16
|
3083 \param lhs The <code>circular_buffer</code> to compare.
|
Chris@16
|
3084 \param rhs The <code>circular_buffer</code> to compare.
|
Chris@16
|
3085 \return <code>!(lhs < rhs)</code>
|
Chris@16
|
3086 \throws Nothing.
|
Chris@16
|
3087 \par Complexity
|
Chris@16
|
3088 Linear (in the size of the <code>circular_buffer</code>s).
|
Chris@16
|
3089 \par Iterator Invalidation
|
Chris@16
|
3090 Does not invalidate any iterators.
|
Chris@16
|
3091 \sa <code>operator<(const circular_buffer<T,Alloc>&, const circular_buffer<T,Alloc>&)</code>
|
Chris@16
|
3092 */
|
Chris@16
|
3093 template <class T, class Alloc>
|
Chris@16
|
3094 inline bool operator >= (const circular_buffer<T, Alloc>& lhs, const circular_buffer<T, Alloc>& rhs) {
|
Chris@16
|
3095 return !(lhs < rhs);
|
Chris@16
|
3096 }
|
Chris@16
|
3097
|
Chris@16
|
3098 //! Swap the contents of two <code>circular_buffer</code>s.
|
Chris@16
|
3099 /*!
|
Chris@16
|
3100 \post <code>lhs</code> contains elements of <code>rhs</code> and vice versa.
|
Chris@16
|
3101 \param lhs The <code>circular_buffer</code> whose content will be swapped with <code>rhs</code>.
|
Chris@16
|
3102 \param rhs The <code>circular_buffer</code> whose content will be swapped with <code>lhs</code>.
|
Chris@16
|
3103 \throws Nothing.
|
Chris@16
|
3104 \par Complexity
|
Chris@16
|
3105 Constant (in the size of the <code>circular_buffer</code>s).
|
Chris@16
|
3106 \par Iterator Invalidation
|
Chris@16
|
3107 Invalidates all iterators of both <code>circular_buffer</code>s. (On the other hand the iterators still
|
Chris@16
|
3108 point to the same elements but within another container. If you want to rely on this feature you have to
|
Chris@16
|
3109 turn the <a href="#debug">Debug Support</a> off otherwise an assertion will report an error if such
|
Chris@16
|
3110 invalidated iterator is used.)
|
Chris@16
|
3111 \sa <code>\link circular_buffer::swap(circular_buffer<T, Alloc>&) swap(circular_buffer<T, Alloc>&)\endlink</code>
|
Chris@16
|
3112 */
|
Chris@16
|
3113 template <class T, class Alloc>
|
Chris@16
|
3114 inline void swap(circular_buffer<T, Alloc>& lhs, circular_buffer<T, Alloc>& rhs) BOOST_NOEXCEPT {
|
Chris@16
|
3115 lhs.swap(rhs);
|
Chris@16
|
3116 }
|
Chris@16
|
3117
|
Chris@16
|
3118 #endif // #if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) || defined(BOOST_MSVC)
|
Chris@16
|
3119
|
Chris@16
|
3120 } // namespace boost
|
Chris@16
|
3121
|
Chris@16
|
3122 #endif // #if !defined(BOOST_CIRCULAR_BUFFER_BASE_HPP)
|