annotate DEPENDENCIES/generic/include/boost/circular_buffer/base.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents c530137014c0
children
rev   line source
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)