summaryrefslogtreecommitdiff
path: root/boost/circular_buffer/base.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/circular_buffer/base.hpp')
-rw-r--r--boost/circular_buffer/base.hpp795
1 files changed, 548 insertions, 247 deletions
diff --git a/boost/circular_buffer/base.hpp b/boost/circular_buffer/base.hpp
index 3b9886a3d3..3efa8de145 100644
--- a/boost/circular_buffer/base.hpp
+++ b/boost/circular_buffer/base.hpp
@@ -1,6 +1,9 @@
// Implementation of the base circular buffer.
// Copyright (c) 2003-2008 Jan Gaspar
+// Copyright (c) 2013 Paul A. Bristow // Doxygen comments changed.
+// Copyright (c) 2013 Antony Polukhin // Move semantics implementation.
+// Copyright (c) 2014 Glen Fernandes // C++11 allocator model support.
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -9,55 +12,53 @@
#if !defined(BOOST_CIRCULAR_BUFFER_BASE_HPP)
#define BOOST_CIRCULAR_BUFFER_BASE_HPP
-#if defined(_MSC_VER) && _MSC_VER >= 1200
+#if defined(_MSC_VER)
#pragma once
#endif
+#include <boost/config.hpp>
#include <boost/call_traits.hpp>
#include <boost/concept_check.hpp>
#include <boost/limits.hpp>
+#include <boost/container/allocator_traits.hpp>
#include <boost/iterator/reverse_iterator.hpp>
#include <boost/iterator/iterator_traits.hpp>
#include <boost/type_traits/is_stateless.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/is_scalar.hpp>
+#include <boost/type_traits/is_nothrow_move_constructible.hpp>
+#include <boost/type_traits/is_nothrow_move_assignable.hpp>
+#include <boost/type_traits/is_copy_constructible.hpp>
+#include <boost/type_traits/conditional.hpp>
+#include <boost/move/move.hpp>
+#include <boost/utility/addressof.hpp>
#include <algorithm>
#include <utility>
#include <deque>
-#if !defined(BOOST_NO_EXCEPTIONS)
- #include <stdexcept>
-#endif
-#if BOOST_CB_ENABLE_DEBUG
- #include <cstring>
-#endif
+#include <stdexcept>
+
#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205))
#include <stddef.h>
#endif
-#if defined(BOOST_NO_STDC_NAMESPACE)
-namespace std {
- using ::memset;
-}
-#endif
-
namespace boost {
/*!
\class circular_buffer
\brief Circular buffer - a STL compliant container.
- \param T The type of the elements stored in the <code>circular_buffer</code>.
+ \tparam T The type of the elements stored in the <code>circular_buffer</code>.
\par Type Requirements T
The <code>T</code> has to be <a href="http://www.sgi.com/tech/stl/Assignable.html">
- SGIAssignable</a> (SGI STL defined combination of <a href="../../utility/Assignable.html">
- Assignable</a> and <a href="../../utility/CopyConstructible.html">CopyConstructible</a>).
+ SGIAssignable</a> (SGI STL defined combination of <a href="../../../utility/Assignable.html">
+ Assignable</a> and <a href="../../../utility/CopyConstructible.html">CopyConstructible</a>).
Moreover <code>T</code> has to be <a href="http://www.sgi.com/tech/stl/DefaultConstructible.html">
DefaultConstructible</a> if supplied as a default parameter when invoking some of the
<code>circular_buffer</code>'s methods e.g.
<code>insert(iterator pos, const value_type& item = %value_type())</code>. And
<a href="http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</a> and/or
- <a href="../../utility/LessThanComparable.html">LessThanComparable</a> if the <code>circular_buffer</code>
+ <a href="../../../utility/LessThanComparable.html">LessThanComparable</a> if the <code>circular_buffer</code>
will be compared with another container.
- \param Alloc The allocator type used for all internal memory management.
+ \tparam Alloc The allocator type used for all internal memory management.
\par Type Requirements Alloc
The <code>Alloc</code> has to meet the allocator requirements imposed by STL.
\par Default Alloc
@@ -75,38 +76,50 @@ class circular_buffer
/*! \endcond */
{
-// Requirements
- BOOST_CLASS_REQUIRE(T, boost, SGIAssignableConcept);
+ // Requirements
+ //BOOST_CLASS_REQUIRE(T, boost, SGIAssignableConcept);
+
+
+ //BOOST_CONCEPT_ASSERT((Assignable<T>));
+ //BOOST_CONCEPT_ASSERT((CopyConstructible<T>));
+ //BOOST_CONCEPT_ASSERT((DefaultConstructible<T>));
+
+ // Required if the circular_buffer will be compared with anther container.
+ //BOOST_CONCEPT_ASSERT((EqualityComparable<T>));
+ //BOOST_CONCEPT_ASSERT((LessThanComparable<T>));
public:
// Basic types
+
+ //! The type of this <code>circular_buffer</code>.
+ typedef circular_buffer<T, Alloc> this_type;
//! The type of elements stored in the <code>circular_buffer</code>.
- typedef typename Alloc::value_type value_type;
+ typedef typename boost::container::allocator_traits<Alloc>::value_type value_type;
//! A pointer to an element.
- typedef typename Alloc::pointer pointer;
+ typedef typename boost::container::allocator_traits<Alloc>::pointer pointer;
//! A const pointer to the element.
- typedef typename Alloc::const_pointer const_pointer;
+ typedef typename boost::container::allocator_traits<Alloc>::const_pointer const_pointer;
//! A reference to an element.
- typedef typename Alloc::reference reference;
+ typedef typename boost::container::allocator_traits<Alloc>::reference reference;
//! A const reference to an element.
- typedef typename Alloc::const_reference const_reference;
+ typedef typename boost::container::allocator_traits<Alloc>::const_reference const_reference;
//! The distance type.
/*!
(A signed integral type used to represent the distance between two iterators.)
*/
- typedef typename Alloc::difference_type difference_type;
+ typedef typename boost::container::allocator_traits<Alloc>::difference_type difference_type;
//! The size type.
/*!
(An unsigned integral type that can represent any non-negative value of the container's distance type.)
*/
- typedef typename Alloc::size_type size_type;
+ typedef typename boost::container::allocator_traits<Alloc>::size_type size_type;
//! The type of an allocator used in the <code>circular_buffer</code>.
typedef Alloc allocator_type;
@@ -114,10 +127,10 @@ public:
// Iterators
//! A const (random access) iterator used to iterate through the <code>circular_buffer</code>.
- typedef cb_details::iterator< circular_buffer<T, Alloc>, cb_details::const_traits<Alloc> > const_iterator;
+ typedef cb_details::iterator< circular_buffer<T, Alloc>, cb_details::const_traits<boost::container::allocator_traits<Alloc> > > const_iterator;
//! A (random access) iterator used to iterate through the <code>circular_buffer</code>.
- typedef cb_details::iterator< circular_buffer<T, Alloc>, cb_details::nonconst_traits<Alloc> > iterator;
+ typedef cb_details::iterator< circular_buffer<T, Alloc>, cb_details::nonconst_traits<boost::container::allocator_traits<Alloc> > > iterator;
//! A const iterator used to iterate backwards through a <code>circular_buffer</code>.
typedef boost::reverse_iterator<const_iterator> const_reverse_iterator;
@@ -145,18 +158,21 @@ public:
//! The capacity type.
/*!
- (Same as <code>size_type</code> - defined for consistency with the
- <a href="space_optimized.html"><code>circular_buffer_space_optimized</code></a>.)
+ (Same as <code>size_type</code> - defined for consistency with the __cbso class.
+
*/
+ // <a href="space_optimized.html"><code>circular_buffer_space_optimized</code></a>.)
+
typedef size_type capacity_type;
// Helper types
- // A type representing the "best" way to pass the value_type to a method.
- typedef typename call_traits<value_type>::param_type param_value_type;
+ //! A type representing the "best" way to pass the value_type to a method.
+ typedef const value_type& param_value_type;
- // A type representing the "best" way to return the value_type from a const method.
- typedef typename call_traits<value_type>::param_type return_value_type;
+ //! A type representing rvalue from param type.
+ //! On compilers without rvalue references support this type is the Boost.Moves type used for emulation.
+ typedef BOOST_RV_REF(value_type) rvalue_type;
private:
// Member variables
@@ -202,7 +218,7 @@ public:
Constant (in the size of the <code>circular_buffer</code>).
\sa <code>get_allocator()</code> for obtaining an allocator %reference.
*/
- allocator_type get_allocator() const { return m_alloc; }
+ allocator_type get_allocator() const BOOST_NOEXCEPT { return m_alloc; }
//! Get the allocator reference.
/*!
@@ -218,7 +234,7 @@ public:
although use of stateful allocators in STL is discouraged.
\sa <code>get_allocator() const</code>
*/
- allocator_type& get_allocator() { return m_alloc; }
+ allocator_type& get_allocator() BOOST_NOEXCEPT { return m_alloc; }
// Element access
@@ -236,7 +252,7 @@ public:
Constant (in the size of the <code>circular_buffer</code>).
\sa <code>end()</code>, <code>rbegin()</code>, <code>rend()</code>
*/
- iterator begin() { return iterator(this, empty() ? 0 : m_first); }
+ iterator begin() BOOST_NOEXCEPT { return iterator(this, empty() ? 0 : m_first); }
//! Get the iterator pointing to the end of the <code>circular_buffer</code>.
/*!
@@ -252,7 +268,7 @@ public:
Constant (in the size of the <code>circular_buffer</code>).
\sa <code>begin()</code>, <code>rbegin()</code>, <code>rend()</code>
*/
- iterator end() { return iterator(this, 0); }
+ iterator end() BOOST_NOEXCEPT { return iterator(this, 0); }
//! Get the const iterator pointing to the beginning of the <code>circular_buffer</code>.
/*!
@@ -268,7 +284,7 @@ public:
Constant (in the size of the <code>circular_buffer</code>).
\sa <code>end() const</code>, <code>rbegin() const</code>, <code>rend() const</code>
*/
- const_iterator begin() const { return const_iterator(this, empty() ? 0 : m_first); }
+ const_iterator begin() const BOOST_NOEXCEPT { return const_iterator(this, empty() ? 0 : m_first); }
//! Get the const iterator pointing to the end of the <code>circular_buffer</code>.
/*!
@@ -284,7 +300,7 @@ public:
Constant (in the size of the <code>circular_buffer</code>).
\sa <code>begin() const</code>, <code>rbegin() const</code>, <code>rend() const</code>
*/
- const_iterator end() const { return const_iterator(this, 0); }
+ const_iterator end() const BOOST_NOEXCEPT { return const_iterator(this, 0); }
//! Get the iterator pointing to the beginning of the "reversed" <code>circular_buffer</code>.
/*!
@@ -300,7 +316,7 @@ public:
Constant (in the size of the <code>circular_buffer</code>).
\sa <code>rend()</code>, <code>begin()</code>, <code>end()</code>
*/
- reverse_iterator rbegin() { return reverse_iterator(end()); }
+ reverse_iterator rbegin() BOOST_NOEXCEPT { return reverse_iterator(end()); }
//! Get the iterator pointing to the end of the "reversed" <code>circular_buffer</code>.
/*!
@@ -316,7 +332,7 @@ public:
Constant (in the size of the <code>circular_buffer</code>).
\sa <code>rbegin()</code>, <code>begin()</code>, <code>end()</code>
*/
- reverse_iterator rend() { return reverse_iterator(begin()); }
+ reverse_iterator rend() BOOST_NOEXCEPT { return reverse_iterator(begin()); }
//! Get the const iterator pointing to the beginning of the "reversed" <code>circular_buffer</code>.
/*!
@@ -332,7 +348,7 @@ public:
Constant (in the size of the <code>circular_buffer</code>).
\sa <code>rend() const</code>, <code>begin() const</code>, <code>end() const</code>
*/
- const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
+ const_reverse_iterator rbegin() const BOOST_NOEXCEPT { return const_reverse_iterator(end()); }
//! Get the const iterator pointing to the end of the "reversed" <code>circular_buffer</code>.
/*!
@@ -348,7 +364,7 @@ public:
Constant (in the size of the <code>circular_buffer</code>).
\sa <code>rbegin() const</code>, <code>begin() const</code>, <code>end() const</code>
*/
- const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
+ const_reverse_iterator rend() const BOOST_NOEXCEPT { return const_reverse_iterator(begin()); }
//! Get the element at the <code>index</code> position.
/*!
@@ -383,7 +399,7 @@ public:
Constant (in the size of the <code>circular_buffer</code>).
\sa <code>\link at(size_type)const at() const \endlink</code>
*/
- return_value_type operator [] (size_type index) const {
+ const_reference operator [] (size_type index) const {
BOOST_CB_ASSERT(index < size()); // check for invalid index
return *add(m_first, index);
}
@@ -421,7 +437,7 @@ public:
Constant (in the size of the <code>circular_buffer</code>).
\sa <code>\link operator[](size_type)const operator[] const \endlink</code>
*/
- return_value_type at(size_type index) const {
+ const_reference at(size_type index) const {
check_position(index);
return (*this)[index];
}
@@ -475,7 +491,7 @@ public:
Constant (in the size of the <code>circular_buffer</code>).
\sa <code>back() const</code>
*/
- return_value_type front() const {
+ const_reference front() const {
BOOST_CB_ASSERT(!empty()); // check for empty buffer (front element not available)
return *m_first;
}
@@ -493,7 +509,7 @@ public:
Constant (in the size of the <code>circular_buffer</code>).
\sa <code>front() const</code>
*/
- return_value_type back() const {
+ const_reference back() const {
BOOST_CB_ASSERT(!empty()); // check for empty buffer (back element not available)
return *((m_last == m_buff ? m_end : m_last) - 1);
}
@@ -508,8 +524,9 @@ public:
The internal representation is often not linear and the state of the internal buffer may look like this:<br>
<br><code>
|e|f|g| | | |a|b|c|d|<br>
- end ---^<br>
- begin -------^</code><br><br>
+ end ___^<br>
+ begin _______^</code><br><br>
+
where <code>|a|b|c|d|</code> represents the "array one", <code>|e|f|g|</code> represents the "array two" and
<code>| | | |</code> is a free space.<br>
Now consider a typical C style function for writing data into a file:<br><br>
@@ -612,8 +629,7 @@ public:
This method can be useful when passing the stored data into a legacy C API as an array.
\post <code>\&(*this)[0] \< \&(*this)[1] \< ... \< \&(*this)[size() - 1]</code>
\return A pointer to the beginning of the array or <code>0</code> if empty.
- \throws Whatever <code>T::T(const T&)</code> throws.
- \throws Whatever <code>T::operator = (const T&)</code> throws.
+ \throws <a href="circular_buffer/implementation.html#circular_buffer.implementation.exceptions_of_move_if_noexcept_t">Exceptions of move_if_noexcept(T&)</a>.
\par Exception Safety
Basic; no-throw if the operations in the <i>Throws</i> section do not throw anything.
\par Iterator Invalidation
@@ -649,12 +665,12 @@ public:
break;
}
if (is_uninitialized(dest)) {
- m_alloc.construct(dest, *src);
+ boost::container::allocator_traits<Alloc>::construct(m_alloc, boost::addressof(*dest), boost::move_if_noexcept(*src));
++constructed;
} else {
- value_type tmp = *src;
- replace(src, *dest);
- replace(dest, tmp);
+ value_type tmp = boost::move_if_noexcept(*src);
+ replace(src, boost::move_if_noexcept(*dest));
+ replace(dest, boost::move(tmp));
}
}
}
@@ -689,7 +705,7 @@ public:
Constant (in the size of the <code>circular_buffer</code>).
\sa <code>linearize()</code>, <code>array_one()</code>, <code>array_two()</code>
*/
- bool is_linearized() const { return m_first < m_last || m_last == m_buff; }
+ bool is_linearized() const BOOST_NOEXCEPT { return m_first < m_last || m_last == m_buff; }
//! Rotate elements in the <code>circular_buffer</code>.
/*!
@@ -705,8 +721,7 @@ public:
<code>val_0 == (*this)[0] \&\& val_1 == (*this)[1] \&\& ... \&\& val_m == (*this)[m - 1] \&\& val_r1 ==
(*this)[m + n - 1] \&\& val_r2 == (*this)[m + n - 2] \&\& ... \&\& val_rn == (*this)[m]</code>
\param new_begin The new beginning.
- \throws Whatever <code>T::T(const T&)</code> throws.
- \throws Whatever <code>T::operator = (const T&)</code> throws.
+ \throws See <a href="circular_buffer/implementation.html#circular_buffer.implementation.exceptions_of_move_if_noexcept_t">Exceptions of move_if_noexcept(T&)</a>.
\par Exception Safety
Basic; no-throw if the <code>circular_buffer</code> is full or <code>new_begin</code> points to
<code>begin()</code> or if the operations in the <i>Throws</i> section do not throw anything.
@@ -729,12 +744,12 @@ public:
difference_type n = new_begin - begin();
if (m < n) {
for (; m > 0; --m) {
- push_front(back());
+ push_front(boost::move_if_noexcept(back()));
pop_back();
}
} else {
for (; n > 0; --n) {
- push_back(front());
+ push_back(boost::move_if_noexcept(front()));
pop_front();
}
}
@@ -756,7 +771,7 @@ public:
\sa <code>capacity()</code>, <code>max_size()</code>, <code>reserve()</code>,
<code>\link resize() resize(size_type, const_reference)\endlink</code>
*/
- size_type size() const { return m_size; }
+ size_type size() const BOOST_NOEXCEPT { return m_size; }
/*! \brief Get the largest possible size or capacity of the <code>circular_buffer</code>. (It depends on
allocator's %max_size()).
@@ -770,8 +785,8 @@ public:
Constant (in the size of the <code>circular_buffer</code>).
\sa <code>size()</code>, <code>capacity()</code>, <code>reserve()</code>
*/
- size_type max_size() const {
- return (std::min<size_type>)(m_alloc.max_size(), (std::numeric_limits<difference_type>::max)());
+ size_type max_size() const BOOST_NOEXCEPT {
+ return (std::min<size_type>)(boost::container::allocator_traits<Alloc>::max_size(m_alloc), (std::numeric_limits<difference_type>::max)());
}
//! Is the <code>circular_buffer</code> empty?
@@ -787,7 +802,7 @@ public:
Constant (in the size of the <code>circular_buffer</code>).
\sa <code>full()</code>
*/
- bool empty() const { return size() == 0; }
+ bool empty() const BOOST_NOEXCEPT { return size() == 0; }
//! Is the <code>circular_buffer</code> full?
/*!
@@ -802,7 +817,7 @@ public:
Constant (in the size of the <code>circular_buffer</code>).
\sa <code>empty()</code>
*/
- bool full() const { return capacity() == size(); }
+ bool full() const BOOST_NOEXCEPT { return capacity() == size(); }
/*! \brief Get the maximum number of elements which can be inserted into the <code>circular_buffer</code> without
overwriting any of already stored elements.
@@ -816,7 +831,7 @@ public:
Constant (in the size of the <code>circular_buffer</code>).
\sa <code>capacity()</code>, <code>size()</code>, <code>max_size()</code>
*/
- size_type reserve() const { return capacity() - size(); }
+ size_type reserve() const BOOST_NOEXCEPT { return capacity() - size(); }
//! Get the capacity of the <code>circular_buffer</code>.
/*!
@@ -831,18 +846,20 @@ public:
\sa <code>reserve()</code>, <code>size()</code>, <code>max_size()</code>,
<code>set_capacity(capacity_type)</code>
*/
- capacity_type capacity() const { return m_end - m_buff; }
+ capacity_type capacity() const BOOST_NOEXCEPT { return m_end - m_buff; }
//! Change the capacity of the <code>circular_buffer</code>.
- /*!
+ /*!
+ \pre If <code>T</code> is a move only type, then compiler shall support <code>noexcept</code> modifiers
+ and move constructor of <code>T</code> must be marked with it (must not throw exceptions).
\post <code>capacity() == new_capacity \&\& size() \<= new_capacity</code><br><br>
If the current number of elements stored in the <code>circular_buffer</code> is greater than the desired
new capacity then number of <code>[size() - new_capacity]</code> <b>last</b> elements will be removed and
the new size will be equal to <code>new_capacity</code>.
\param new_capacity The new capacity.
- \throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
+ \throws "An allocation error" if memory is exhausted, (<code>std::bad_alloc</code> if the standard allocator is
used).
- \throws Whatever <code>T::T(const T&)</code> throws.
+ Whatever <code>T::T(const T&)</code> throws or nothing if <code>T::T(T&&)</code> is noexcept.
\par Exception Safety
Strong.
\par Iterator Invalidation
@@ -860,7 +877,7 @@ public:
iterator b = begin();
BOOST_TRY {
reset(buff,
- cb_details::uninitialized_copy_with_alloc(b, b + (std::min)(new_capacity, size()), buff, m_alloc),
+ cb_details::uninitialized_move_if_noexcept(b, b + (std::min)(new_capacity, size()), buff, m_alloc),
new_capacity);
} BOOST_CATCH(...) {
deallocate(buff, new_capacity);
@@ -883,7 +900,7 @@ public:
size. (See the <i>Effect</i>.)
\throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
used).
- \throws Whatever <code>T::T(const T&)</code> throws.
+ Whatever <code>T::T(const T&)</code> throws or nothing if <code>T::T(T&&)</code> is noexcept.
\par Exception Safety
Basic.
\par Iterator Invalidation
@@ -908,7 +925,9 @@ public:
}
//! Change the capacity of the <code>circular_buffer</code>.
- /*!
+ /*!
+ \pre If <code>T</code> is a move only type, then compiler shall support <code>noexcept</code> modifiers
+ and move constructor of <code>T</code> must be marked with it (must not throw exceptions).
\post <code>capacity() == new_capacity \&\& size() \<= new_capacity</code><br><br>
If the current number of elements stored in the <code>circular_buffer</code> is greater than the desired
new capacity then number of <code>[size() - new_capacity]</code> <b>first</b> elements will be removed
@@ -916,7 +935,7 @@ public:
\param new_capacity The new capacity.
\throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
used).
- \throws Whatever <code>T::T(const T&)</code> throws.
+ Whatever <code>T::T(const T&)</code> throws or nothing if <code>T::T(T&&)</code> is noexcept.
\par Exception Safety
Strong.
\par Iterator Invalidation
@@ -933,7 +952,7 @@ public:
pointer buff = allocate(new_capacity);
iterator e = end();
BOOST_TRY {
- reset(buff, cb_details::uninitialized_copy_with_alloc(e - (std::min)(new_capacity, size()),
+ reset(buff, cb_details::uninitialized_move_if_noexcept(e - (std::min)(new_capacity, size()),
e, buff, m_alloc), new_capacity);
} BOOST_CATCH(...) {
deallocate(buff, new_capacity);
@@ -956,7 +975,7 @@ public:
size. (See the <i>Effect</i>.)
\throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
used).
- \throws Whatever <code>T::T(const T&)</code> throws.
+ Whatever <code>T::T(const T&)</code> throws or nothing if <code>T::T(T&&)</code> is noexcept.
\par Exception Safety
Basic.
\par Iterator Invalidation
@@ -985,8 +1004,7 @@ public:
/*!
\post <code>capacity() == 0 \&\& size() == 0</code>
\param alloc The allocator.
- \throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
- used).
+ \throws Nothing.
\par Complexity
Constant.
\warning Since Boost version 1.36 the behaviour of this constructor has changed. Now the constructor does not
@@ -1000,7 +1018,7 @@ public:
\sa <code>circular_buffer(capacity_type, const allocator_type& alloc)</code>,
<code>set_capacity(capacity_type)</code>
*/
- explicit circular_buffer(const allocator_type& alloc = allocator_type())
+ explicit circular_buffer(const allocator_type& alloc = allocator_type()) BOOST_NOEXCEPT
: m_buff(0), m_end(0), m_first(0), m_last(0), m_size(0), m_alloc(alloc) {}
//! Create an empty <code>circular_buffer</code> with the specified capacity.
@@ -1028,7 +1046,7 @@ public:
\param alloc The allocator.
\throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
used).
- \throws Whatever <code>T::T(const T&)</code> throws.
+ Whatever <code>T::T(const T&)</code> throws.
\par Complexity
Linear (in the <code>n</code>).
*/
@@ -1049,7 +1067,7 @@ public:
\param alloc The allocator.
\throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
used).
- \throws Whatever <code>T::T(const T&)</code> throws.
+ Whatever <code>T::T(const T&)</code> throws.
\par Complexity
Linear (in the <code>n</code>).
*/
@@ -1069,7 +1087,7 @@ public:
\param cb The <code>circular_buffer</code> to be copied.
\throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
used).
- \throws Whatever <code>T::T(const T&)</code> throws.
+ Whatever <code>T::T(const T&)</code> throws.
\par Complexity
Linear (in the size of <code>cb</code>).
*/
@@ -1082,7 +1100,7 @@ public:
initialize_buffer(cb.capacity());
m_first = m_buff;
BOOST_TRY {
- m_last = cb_details::uninitialized_copy_with_alloc(cb.begin(), cb.end(), m_buff, m_alloc);
+ m_last = cb_details::uninitialized_copy(cb.begin(), cb.end(), m_buff, m_alloc);
} BOOST_CATCH(...) {
deallocate(m_buff, cb.capacity());
BOOST_RETHROW
@@ -1091,24 +1109,21 @@ public:
if (m_last == m_end)
m_last = m_buff;
}
-
-#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
-
- /*! \cond */
- template <class InputIterator>
- circular_buffer(InputIterator first, InputIterator last)
- : m_alloc(allocator_type()) {
- initialize(first, last, is_integral<InputIterator>());
- }
-
- template <class InputIterator>
- circular_buffer(capacity_type capacity, InputIterator first, InputIterator last)
- : m_alloc(allocator_type()) {
- initialize(capacity, first, last, is_integral<InputIterator>());
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ //! The move constructor.
+ /*! \brief Move constructs a <code>circular_buffer</code> from <code>cb</code>, leaving <code>cb</code> empty.
+ \pre C++ compiler with rvalue references support.
+ \post <code>cb.empty()</code>
+ \param cb <code>circular_buffer</code> to 'steal' value from.
+ \throws Nothing.
+ \par Constant.
+ */
+ circular_buffer(circular_buffer<T, Alloc>&& cb) BOOST_NOEXCEPT
+ : m_buff(0), m_end(0), m_first(0), m_last(0), m_size(0), m_alloc(cb.get_allocator()) {
+ cb.swap(*this);
}
- /*! \endcond */
-
-#else
+#endif // BOOST_NO_CXX11_RVALUE_REFERENCES
//! Create a full <code>circular_buffer</code> filled with a copy of the range.
/*!
@@ -1122,7 +1137,7 @@ public:
\param alloc The allocator.
\throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
used).
- \throws Whatever <code>T::T(const T&)</code> throws.
+ Whatever <code>T::T(const T&)</code> throws.
\par Complexity
Linear (in the <code>std::distance(first, last)</code>).
*/
@@ -1149,7 +1164,7 @@ public:
\param alloc The allocator.
\throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
used).
- \throws Whatever <code>T::T(const T&)</code> throws.
+ Whatever <code>T::T(const T&)</code> throws.
\par Complexity
Linear (in <code>std::distance(first, last)</code>; in
<code>min[capacity, std::distance(first, last)]</code> if the <code>InputIterator</code> is a
@@ -1162,8 +1177,6 @@ public:
initialize(buffer_capacity, first, last, is_integral<InputIterator>());
}
-#endif // #if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
-
//! The destructor.
/*!
Destroys the <code>circular_buffer</code>.
@@ -1175,7 +1188,7 @@ public:
Constant (in the size of the <code>circular_buffer</code>) for scalar types; linear for other types.
\sa <code>clear()</code>
*/
- ~circular_buffer() {
+ ~circular_buffer() BOOST_NOEXCEPT {
destroy();
#if BOOST_CB_ENABLE_DEBUG
invalidate_all_iterators();
@@ -1192,7 +1205,7 @@ public:
\param cb The <code>circular_buffer</code> to be copied.
\throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
used).
- \throws Whatever <code>T::T(const T&)</code> throws.
+ Whatever <code>T::T(const T&)</code> throws.
\par Exception Safety
Strong.
\par Iterator Invalidation
@@ -1211,7 +1224,7 @@ public:
return *this;
pointer buff = allocate(cb.capacity());
BOOST_TRY {
- reset(buff, cb_details::uninitialized_copy_with_alloc(cb.begin(), cb.end(), buff, m_alloc), cb.capacity());
+ reset(buff, cb_details::uninitialized_copy(cb.begin(), cb.end(), buff, m_alloc), cb.capacity());
} BOOST_CATCH(...) {
deallocate(buff, cb.capacity());
BOOST_RETHROW
@@ -1220,6 +1233,23 @@ public:
return *this;
}
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ /*! \brief Move assigns content of <code>cb</code> to <code>*this</code>, leaving <code>cb</code> empty.
+ \pre C++ compiler with rvalue references support.
+ \post <code>cb.empty()</code>
+ \param cb <code>circular_buffer</code> to 'steal' value from.
+ \throws Nothing.
+ \par Complexity
+ Constant.
+ */
+ circular_buffer<T, Alloc>& operator = (circular_buffer<T, Alloc>&& cb) BOOST_NOEXCEPT {
+ cb.swap(*this); // now `this` holds `cb`
+ circular_buffer<T, Alloc>(get_allocator()) // temprary that holds initial `cb` allocator
+ .swap(cb); // makes `cb` empty
+ return *this;
+ }
+#endif // BOOST_NO_CXX11_RVALUE_REFERENCES
+
//! Assign <code>n</code> items into the <code>circular_buffer</code>.
/*!
The content of the <code>circular_buffer</code> will be removed and replaced with <code>n</code> copies of the
@@ -1230,7 +1260,7 @@ public:
\param item The element the <code>circular_buffer</code> will be filled with.
\throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
used).
- \throws Whatever <code>T::T(const T&)</code> throws.
+ Whatever <code>T::T(const T&)</code> throws.
\par Exception Safety
Basic.
\par Iterator Invalidation
@@ -1260,7 +1290,7 @@ public:
\param item The element the <code>circular_buffer</code> will be filled with.
\throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
used).
- \throws Whatever <code>T::T(const T&)</code> throws.
+ Whatever <code>T::T(const T&)</code> throws.
\par Exception Safety
Basic.
\par Iterator Invalidation
@@ -1292,7 +1322,7 @@ public:
\param last The end of the range to be copied.
\throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
used).
- \throws Whatever <code>T::T(const T&)</code> throws.
+ Whatever <code>T::T(const T&)</code> throws.
\par Exception Safety
Basic.
\par Iterator Invalidation
@@ -1329,7 +1359,7 @@ public:
\param last The end of the range to be copied.
\throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
used).
- \throws Whatever <code>T::T(const T&)</code> throws.
+ Whatever <code>T::T(const T&)</code> throws.
\par Exception Safety
Basic.
\par Iterator Invalidation
@@ -1367,7 +1397,7 @@ public:
Constant (in the size of the <code>circular_buffer</code>).
\sa <code>swap(circular_buffer<T, Alloc>&, circular_buffer<T, Alloc>&)</code>
*/
- void swap(circular_buffer<T, Alloc>& cb) {
+ void swap(circular_buffer<T, Alloc>& cb) BOOST_NOEXCEPT {
swap_allocator(cb, is_stateless<allocator_type>());
std::swap(m_buff, cb.m_buff);
std::swap(m_end, cb.m_end);
@@ -1381,7 +1411,44 @@ public:
}
// push and pop
+private:
+ template <class ValT>
+ void push_back_impl(ValT item) {
+ if (full()) {
+ if (empty())
+ return;
+ replace(m_last, static_cast<ValT>(item));
+ increment(m_last);
+ m_first = m_last;
+ } else {
+ boost::container::allocator_traits<Alloc>::construct(m_alloc, boost::addressof(*m_last), static_cast<ValT>(item));
+ increment(m_last);
+ ++m_size;
+ }
+ }
+
+ template <class ValT>
+ void push_front_impl(ValT item) {
+ BOOST_TRY {
+ if (full()) {
+ if (empty())
+ return;
+ decrement(m_first);
+ replace(m_first, static_cast<ValT>(item));
+ m_last = m_first;
+ } else {
+ decrement(m_first);
+ boost::container::allocator_traits<Alloc>::construct(m_alloc, boost::addressof(*m_first), static_cast<ValT>(item));
+ ++m_size;
+ }
+ } BOOST_CATCH(...) {
+ increment(m_first);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ }
+public:
//! Insert a new element at the end of the <code>circular_buffer</code>.
/*!
\post if <code>capacity() > 0</code> then <code>back() == item</code><br>
@@ -1389,7 +1456,7 @@ public:
<code>0</code>, nothing will be inserted.
\param item The element to be inserted.
\throws Whatever <code>T::T(const T&)</code> throws.
- \throws Whatever <code>T::operator = (const T&)</code> throws.
+ Whatever <code>T::operator = (const T&)</code> throws.
\par Exception Safety
Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything.
\par Iterator Invalidation
@@ -1399,18 +1466,51 @@ public:
\sa <code>\link push_front() push_front(const_reference)\endlink</code>,
<code>pop_back()</code>, <code>pop_front()</code>
*/
- void push_back(param_value_type item = value_type()) {
- if (full()) {
- if (empty())
- return;
- replace(m_last, item);
- increment(m_last);
- m_first = m_last;
- } else {
- m_alloc.construct(m_last, item);
- increment(m_last);
- ++m_size;
- }
+ void push_back(param_value_type item) {
+ push_back_impl<param_value_type>(item);
+ }
+
+ //! Insert a new element at the end of the <code>circular_buffer</code> using rvalue references or rvalues references emulation.
+ /*!
+ \post if <code>capacity() > 0</code> then <code>back() == item</code><br>
+ If the <code>circular_buffer</code> is full, the first element will be removed. If the capacity is
+ <code>0</code>, nothing will be inserted.
+ \param item The element to be inserted.
+ \throws Whatever <code>T::T(T&&)</code> throws.
+ Whatever <code>T::operator = (T&&)</code> throws.
+ \par Exception Safety
+ Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything.
+ \par Iterator Invalidation
+ Does not invalidate any iterators with the exception of iterators pointing to the overwritten element.
+ \par Complexity
+ Constant (in the size of the <code>circular_buffer</code>).
+ \sa <code>\link push_front() push_front(const_reference)\endlink</code>,
+ <code>pop_back()</code>, <code>pop_front()</code>
+ */
+ void push_back(rvalue_type item) {
+ push_back_impl<rvalue_type>(boost::move(item));
+ }
+
+ //! Insert a new default-constructed element at the end of the <code>circular_buffer</code>.
+ /*!
+ \post if <code>capacity() > 0</code> then <code>back() == item</code><br>
+ If the <code>circular_buffer</code> is full, the first element will be removed. If the capacity is
+ <code>0</code>, nothing will be inserted.
+ \throws Whatever <code>T::T()</code> throws.
+ Whatever <code>T::T(T&&)</code> throws.
+ Whatever <code>T::operator = (T&&)</code> throws.
+ \par Exception Safety
+ Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything.
+ \par Iterator Invalidation
+ Does not invalidate any iterators with the exception of iterators pointing to the overwritten element.
+ \par Complexity
+ Constant (in the size of the <code>circular_buffer</code>).
+ \sa <code>\link push_front() push_front(const_reference)\endlink</code>,
+ <code>pop_back()</code>, <code>pop_front()</code>
+ */
+ void push_back() {
+ value_type temp;
+ push_back(boost::move(temp));
}
//! Insert a new element at the beginning of the <code>circular_buffer</code>.
@@ -1420,7 +1520,7 @@ public:
<code>0</code>, nothing will be inserted.
\param item The element to be inserted.
\throws Whatever <code>T::T(const T&)</code> throws.
- \throws Whatever <code>T::operator = (const T&)</code> throws.
+ Whatever <code>T::operator = (const T&)</code> throws.
\par Exception Safety
Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything.
\par Iterator Invalidation
@@ -1430,24 +1530,51 @@ public:
\sa <code>\link push_back() push_back(const_reference)\endlink</code>,
<code>pop_back()</code>, <code>pop_front()</code>
*/
- void push_front(param_value_type item = value_type()) {
- BOOST_TRY {
- if (full()) {
- if (empty())
- return;
- decrement(m_first);
- replace(m_first, item);
- m_last = m_first;
- } else {
- decrement(m_first);
- m_alloc.construct(m_first, item);
- ++m_size;
- }
- } BOOST_CATCH(...) {
- increment(m_first);
- BOOST_RETHROW
- }
- BOOST_CATCH_END
+ void push_front(param_value_type item) {
+ push_front_impl<param_value_type>(item);
+ }
+
+ //! Insert a new element at the beginning of the <code>circular_buffer</code> using rvalue references or rvalues references emulation.
+ /*!
+ \post if <code>capacity() > 0</code> then <code>front() == item</code><br>
+ If the <code>circular_buffer</code> is full, the last element will be removed. If the capacity is
+ <code>0</code>, nothing will be inserted.
+ \param item The element to be inserted.
+ \throws Whatever <code>T::T(T&&)</code> throws.
+ Whatever <code>T::operator = (T&&)</code> throws.
+ \par Exception Safety
+ Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything.
+ \par Iterator Invalidation
+ Does not invalidate any iterators with the exception of iterators pointing to the overwritten element.
+ \par Complexity
+ Constant (in the size of the <code>circular_buffer</code>).
+ \sa <code>\link push_back() push_back(const_reference)\endlink</code>,
+ <code>pop_back()</code>, <code>pop_front()</code>
+ */
+ void push_front(rvalue_type item) {
+ push_front_impl<rvalue_type>(boost::move(item));
+ }
+
+ //! Insert a new default-constructed element at the beginning of the <code>circular_buffer</code>.
+ /*!
+ \post if <code>capacity() > 0</code> then <code>front() == item</code><br>
+ If the <code>circular_buffer</code> is full, the last element will be removed. If the capacity is
+ <code>0</code>, nothing will be inserted.
+ \throws Whatever <code>T::T()</code> throws.
+ Whatever <code>T::T(T&&)</code> throws.
+ Whatever <code>T::operator = (T&&)</code> throws.
+ \par Exception Safety
+ Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything.
+ \par Iterator Invalidation
+ Does not invalidate any iterators with the exception of iterators pointing to the overwritten element.
+ \par Complexity
+ Constant (in the size of the <code>circular_buffer</code>).
+ \sa <code>\link push_back() push_back(const_reference)\endlink</code>,
+ <code>pop_back()</code>, <code>pop_front()</code>
+ */
+ void push_front() {
+ value_type temp;
+ push_front(boost::move(temp));
}
//! Remove the last element from the <code>circular_buffer</code>.
@@ -1491,6 +1618,15 @@ public:
increment(m_first);
--m_size;
}
+private:
+ template <class ValT>
+ iterator insert_impl(iterator pos, ValT item) {
+ BOOST_CB_ASSERT(pos.is_valid(this)); // check for uninitialized or invalidated iterator
+ iterator b = begin();
+ if (full() && pos == b)
+ return b;
+ return insert_item<ValT>(pos, static_cast<ValT>(item));
+ }
public:
// Insert
@@ -1507,7 +1643,9 @@ public:
\return Iterator to the inserted element or <code>begin()</code> if the <code>item</code> is not inserted. (See
the <i>Effect</i>.)
\throws Whatever <code>T::T(const T&)</code> throws.
- \throws Whatever <code>T::operator = (const T&)</code> throws.
+ Whatever <code>T::operator = (const T&)</code> throws.
+ <a href="circular_buffer/implementation.html#circular_buffer.implementation.exceptions_of_move_if_noexcept_t">Exceptions of move_if_noexcept(T&)</a>.
+
\par Exception Safety
Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything.
\par Iterator Invalidation
@@ -1524,12 +1662,77 @@ public:
rinsert(iterator, size_type, value_type)\endlink</code>,
<code>rinsert(iterator, InputIterator, InputIterator)</code>
*/
- iterator insert(iterator pos, param_value_type item = value_type()) {
- BOOST_CB_ASSERT(pos.is_valid(this)); // check for uninitialized or invalidated iterator
- iterator b = begin();
- if (full() && pos == b)
- return b;
- return insert_item(pos, item);
+ iterator insert(iterator pos, param_value_type item) {
+ return insert_impl<param_value_type>(pos, item);
+ }
+
+ //! Insert an element at the specified position.
+ /*!
+ \pre <code>pos</code> is a valid iterator pointing to the <code>circular_buffer</code> or its end.
+ \post The <code>item</code> will be inserted at the position <code>pos</code>.<br>
+ If the <code>circular_buffer</code> is full, the first element will be overwritten. If the
+ <code>circular_buffer</code> is full and the <code>pos</code> points to <code>begin()</code>, then the
+ <code>item</code> will not be inserted. If the capacity is <code>0</code>, nothing will be inserted.
+ \param pos An iterator specifying the position where the <code>item</code> will be inserted.
+ \param item The element to be inserted.
+ \return Iterator to the inserted element or <code>begin()</code> if the <code>item</code> is not inserted. (See
+ the <i>Effect</i>.)
+ \throws Whatever <code>T::T(T&&)</code> throws.
+ Whatever <code>T::operator = (T&&)</code> throws.
+ <a href="circular_buffer/implementation.html#circular_buffer.implementation.exceptions_of_move_if_noexcept_t">Exceptions of move_if_noexcept(T&)</a>.
+ \par Exception Safety
+ Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything.
+ \par Iterator Invalidation
+ Invalidates iterators pointing to the elements at the insertion point (including <code>pos</code>) and
+ iterators behind the insertion point (towards the end; except iterators equal to <code>end()</code>). It
+ also invalidates iterators pointing to the overwritten element.
+ \par Complexity
+ Linear (in <code>std::distance(pos, end())</code>).
+ \sa <code>\link insert(iterator, size_type, param_value_type)
+ insert(iterator, size_type, value_type)\endlink</code>,
+ <code>insert(iterator, InputIterator, InputIterator)</code>,
+ <code>\link rinsert(iterator, param_value_type) rinsert(iterator, value_type)\endlink</code>,
+ <code>\link rinsert(iterator, size_type, param_value_type)
+ rinsert(iterator, size_type, value_type)\endlink</code>,
+ <code>rinsert(iterator, InputIterator, InputIterator)</code>
+ */
+ iterator insert(iterator pos, rvalue_type item) {
+ return insert_impl<rvalue_type>(pos, boost::move(item));
+ }
+
+ //! Insert a default-constructed element at the specified position.
+ /*!
+ \pre <code>pos</code> is a valid iterator pointing to the <code>circular_buffer</code> or its end.
+ \post The <code>item</code> will be inserted at the position <code>pos</code>.<br>
+ If the <code>circular_buffer</code> is full, the first element will be overwritten. If the
+ <code>circular_buffer</code> is full and the <code>pos</code> points to <code>begin()</code>, then the
+ <code>item</code> will not be inserted. If the capacity is <code>0</code>, nothing will be inserted.
+ \param pos An iterator specifying the position where the <code>item</code> will be inserted.
+ \return Iterator to the inserted element or <code>begin()</code> if the <code>item</code> is not inserted. (See
+ the <i>Effect</i>.)
+ \throws Whatever <code>T::T()</code> throws.
+ Whatever <code>T::T(T&&)</code> throws.
+ Whatever <code>T::operator = (T&&)</code> throws.
+ <a href="circular_buffer/implementation.html#circular_buffer.implementation.exceptions_of_move_if_noexcept_t">Exceptions of move_if_noexcept(T&)</a>.
+ \par Exception Safety
+ Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything.
+ \par Iterator Invalidation
+ Invalidates iterators pointing to the elements at the insertion point (including <code>pos</code>) and
+ iterators behind the insertion point (towards the end; except iterators equal to <code>end()</code>). It
+ also invalidates iterators pointing to the overwritten element.
+ \par Complexity
+ Linear (in <code>std::distance(pos, end())</code>).
+ \sa <code>\link insert(iterator, size_type, param_value_type)
+ insert(iterator, size_type, value_type)\endlink</code>,
+ <code>insert(iterator, InputIterator, InputIterator)</code>,
+ <code>\link rinsert(iterator, param_value_type) rinsert(iterator, value_type)\endlink</code>,
+ <code>\link rinsert(iterator, size_type, param_value_type)
+ rinsert(iterator, size_type, value_type)\endlink</code>,
+ <code>rinsert(iterator, InputIterator, InputIterator)</code>
+ */
+ iterator insert(iterator pos) {
+ value_type temp;
+ return insert(pos, boost::move(temp));
}
//! Insert <code>n</code> copies of the <code>item</code> at the specified position.
@@ -1543,7 +1746,8 @@ public:
\param n The number of <code>item</code>s the to be inserted.
\param item The element whose copies will be inserted.
\throws Whatever <code>T::T(const T&)</code> throws.
- \throws Whatever <code>T::operator = (const T&)</code> throws.
+ Whatever <code>T::operator = (const T&)</code> throws.
+ <a href="circular_buffer/implementation.html#circular_buffer.implementation.exceptions_of_move_if_noexcept_t">Exceptions of move_if_noexcept(T&)</a>.
\par Exception Safety
Basic; no-throw if the operations in the <i>Throws</i> section do not throw anything.
\par Iterator Invalidation
@@ -1556,7 +1760,7 @@ public:
Consider a <code>circular_buffer</code> with the capacity of 6 and the size of 4. Its internal buffer may
look like the one below.<br><br>
<code>|1|2|3|4| | |</code><br>
- <code>p ---^</code><br><br>After inserting 5 elements at the position <code>p</code>:<br><br>
+ <code>p ___^</code><br><br>After inserting 5 elements at the position <code>p</code>:<br><br>
<code>insert(p, (size_t)5, 0);</code><br><br>actually only 4 elements get inserted and elements
<code>1</code> and <code>2</code> are overwritten. This is due to the fact the insert operation preserves
the capacity. After insertion the internal buffer looks like this:<br><br><code>|0|0|0|0|3|4|</code><br>
@@ -1594,8 +1798,10 @@ public:
\param pos An iterator specifying the position where the range will be inserted.
\param first The beginning of the range to be inserted.
\param last The end of the range to be inserted.
- \throws Whatever <code>T::T(const T&)</code> throws.
- \throws Whatever <code>T::operator = (const T&)</code> throws.
+ \throws Whatever <code>T::T(const T&)</code> throws if the <code>InputIterator</code> is not a move iterator.
+ Whatever <code>T::operator = (const T&)</code> throws if the <code>InputIterator</code> is not a move iterator.
+ Whatever <code>T::T(T&&)</code> throws if the <code>InputIterator</code> is a move iterator.
+ Whatever <code>T::operator = (T&&)</code> throws if the <code>InputIterator</code> is a move iterator.
\par Exception Safety
Basic; no-throw if the operations in the <i>Throws</i> section do not throw anything.
\par Iterator Invalidation
@@ -1611,7 +1817,7 @@ public:
Consider a <code>circular_buffer</code> with the capacity of 6 and the size of 4. Its internal buffer may
look like the one below.<br><br>
<code>|1|2|3|4| | |</code><br>
- <code>p ---^</code><br><br>After inserting a range of elements at the position <code>p</code>:<br><br>
+ <code>p ___^</code><br><br>After inserting a range of elements at the position <code>p</code>:<br><br>
<code>int array[] = { 5, 6, 7, 8, 9 };</code><br><code>insert(p, array, array + 5);</code><br><br>
actually only elements <code>6</code>, <code>7</code>, <code>8</code> and <code>9</code> from the
specified range get inserted and elements <code>1</code> and <code>2</code> are overwritten. This is due
@@ -1631,42 +1837,16 @@ public:
insert(pos, first, last, is_integral<InputIterator>());
}
- //! Insert an element before the specified position.
- /*!
- \pre <code>pos</code> is a valid iterator pointing to the <code>circular_buffer</code> or its end.
- \post The <code>item</code> will be inserted before the position <code>pos</code>.<br>
- If the <code>circular_buffer</code> is full, the last element will be overwritten. If the
- <code>circular_buffer</code> is full and the <code>pos</code> points to <code>end()</code>, then the
- <code>item</code> will not be inserted. If the capacity is <code>0</code>, nothing will be inserted.
- \param pos An iterator specifying the position before which the <code>item</code> will be inserted.
- \param item The element to be inserted.
- \return Iterator to the inserted element or <code>end()</code> if the <code>item</code> is not inserted. (See
- the <i>Effect</i>.)
- \throws Whatever <code>T::T(const T&)</code> throws.
- \throws Whatever <code>T::operator = (const T&)</code> throws.
- \par Exception Safety
- Basic; no-throw if the operations in the <i>Throws</i> section do not throw anything.
- \par Iterator Invalidation
- Invalidates iterators pointing to the elements before the insertion point (towards the beginning and
- excluding <code>pos</code>). It also invalidates iterators pointing to the overwritten element.
- \par Complexity
- Linear (in <code>std::distance(begin(), pos)</code>).
- \sa <code>\link rinsert(iterator, size_type, param_value_type)
- rinsert(iterator, size_type, value_type)\endlink</code>,
- <code>rinsert(iterator, InputIterator, InputIterator)</code>,
- <code>\link insert(iterator, param_value_type) insert(iterator, value_type)\endlink</code>,
- <code>\link insert(iterator, size_type, param_value_type)
- insert(iterator, size_type, value_type)\endlink</code>,
- <code>insert(iterator, InputIterator, InputIterator)</code>
- */
- iterator rinsert(iterator pos, param_value_type item = value_type()) {
+private:
+ template <class ValT>
+ iterator rinsert_impl(iterator pos, ValT item) {
BOOST_CB_ASSERT(pos.is_valid(this)); // check for uninitialized or invalidated iterator
if (full() && pos.m_it == 0)
return end();
if (pos == begin()) {
BOOST_TRY {
decrement(m_first);
- construct_or_replace(!full(), m_first, item);
+ construct_or_replace(!full(), m_first, static_cast<ValT>(item));
} BOOST_CATCH(...) {
increment(m_first);
BOOST_RETHROW
@@ -1681,13 +1861,13 @@ public:
bool construct = !full();
BOOST_TRY {
while (src != pos.m_it) {
- construct_or_replace(construct, dest, *src);
+ construct_or_replace(construct, dest, boost::move_if_noexcept(*src));
increment(src);
increment(dest);
construct = false;
}
decrement(pos.m_it);
- replace(pos.m_it, item);
+ replace(pos.m_it, static_cast<ValT>(item));
} BOOST_CATCH(...) {
if (!construct && !full()) {
decrement(m_first);
@@ -1705,6 +1885,108 @@ public:
return iterator(this, pos.m_it);
}
+public:
+
+ //! Insert an element before the specified position.
+ /*!
+ \pre <code>pos</code> is a valid iterator pointing to the <code>circular_buffer</code> or its end.
+ \post The <code>item</code> will be inserted before the position <code>pos</code>.<br>
+ If the <code>circular_buffer</code> is full, the last element will be overwritten. If the
+ <code>circular_buffer</code> is full and the <code>pos</code> points to <code>end()</code>, then the
+ <code>item</code> will not be inserted. If the capacity is <code>0</code>, nothing will be inserted.
+ \param pos An iterator specifying the position before which the <code>item</code> will be inserted.
+ \param item The element to be inserted.
+ \return Iterator to the inserted element or <code>end()</code> if the <code>item</code> is not inserted. (See
+ the <i>Effect</i>.)
+ \throws Whatever <code>T::T(const T&)</code> throws.
+ Whatever <code>T::operator = (const T&)</code> throws.
+ <a href="circular_buffer/implementation.html#circular_buffer.implementation.exceptions_of_move_if_noexcept_t">Exceptions of move_if_noexcept(T&)</a>.
+ \par Exception Safety
+ Basic; no-throw if the operations in the <i>Throws</i> section do not throw anything.
+ \par Iterator Invalidation
+ Invalidates iterators pointing to the elements before the insertion point (towards the beginning and
+ excluding <code>pos</code>). It also invalidates iterators pointing to the overwritten element.
+ \par Complexity
+ Linear (in <code>std::distance(begin(), pos)</code>).
+ \sa <code>\link rinsert(iterator, size_type, param_value_type)
+ rinsert(iterator, size_type, value_type)\endlink</code>,
+ <code>rinsert(iterator, InputIterator, InputIterator)</code>,
+ <code>\link insert(iterator, param_value_type) insert(iterator, value_type)\endlink</code>,
+ <code>\link insert(iterator, size_type, param_value_type)
+ insert(iterator, size_type, value_type)\endlink</code>,
+ <code>insert(iterator, InputIterator, InputIterator)</code>
+ */
+ iterator rinsert(iterator pos, param_value_type item) {
+ return rinsert_impl<param_value_type>(pos, item);
+ }
+
+ //! Insert an element before the specified position.
+ /*!
+ \pre <code>pos</code> is a valid iterator pointing to the <code>circular_buffer</code> or its end.
+ \post The <code>item</code> will be inserted before the position <code>pos</code>.<br>
+ If the <code>circular_buffer</code> is full, the last element will be overwritten. If the
+ <code>circular_buffer</code> is full and the <code>pos</code> points to <code>end()</code>, then the
+ <code>item</code> will not be inserted. If the capacity is <code>0</code>, nothing will be inserted.
+ \param pos An iterator specifying the position before which the <code>item</code> will be inserted.
+ \param item The element to be inserted.
+ \return Iterator to the inserted element or <code>end()</code> if the <code>item</code> is not inserted. (See
+ the <i>Effect</i>.)
+ \throws Whatever <code>T::T(T&&)</code> throws.
+ Whatever <code>T::operator = (T&&)</code> throws.
+ <a href="circular_buffer/implementation.html#circular_buffer.implementation.exceptions_of_move_if_noexcept_t">Exceptions of move_if_noexcept(T&)</a>.
+ \par Exception Safety
+ Basic; no-throw if the operations in the <i>Throws</i> section do not throw anything.
+ \par Iterator Invalidation
+ Invalidates iterators pointing to the elements before the insertion point (towards the beginning and
+ excluding <code>pos</code>). It also invalidates iterators pointing to the overwritten element.
+ \par Complexity
+ Linear (in <code>std::distance(begin(), pos)</code>).
+ \sa <code>\link rinsert(iterator, size_type, param_value_type)
+ rinsert(iterator, size_type, value_type)\endlink</code>,
+ <code>rinsert(iterator, InputIterator, InputIterator)</code>,
+ <code>\link insert(iterator, param_value_type) insert(iterator, value_type)\endlink</code>,
+ <code>\link insert(iterator, size_type, param_value_type)
+ insert(iterator, size_type, value_type)\endlink</code>,
+ <code>insert(iterator, InputIterator, InputIterator)</code>
+ */
+ iterator rinsert(iterator pos, rvalue_type item) {
+ return rinsert_impl<rvalue_type>(pos, boost::move(item));
+ }
+
+ //! Insert an element before the specified position.
+ /*!
+ \pre <code>pos</code> is a valid iterator pointing to the <code>circular_buffer</code> or its end.
+ \post The <code>item</code> will be inserted before the position <code>pos</code>.<br>
+ If the <code>circular_buffer</code> is full, the last element will be overwritten. If the
+ <code>circular_buffer</code> is full and the <code>pos</code> points to <code>end()</code>, then the
+ <code>item</code> will not be inserted. If the capacity is <code>0</code>, nothing will be inserted.
+ \param pos An iterator specifying the position before which the <code>item</code> will be inserted.
+ \return Iterator to the inserted element or <code>end()</code> if the <code>item</code> is not inserted. (See
+ the <i>Effect</i>.)
+ \throws Whatever <code>T::T()</code> throws.
+ Whatever <code>T::T(T&&)</code> throws.
+ Whatever <code>T::operator = (T&&)</code> throws.
+ <a href="circular_buffer/implementation.html#circular_buffer.implementation.exceptions_of_move_if_noexcept_t">Exceptions of move_if_noexcept(T&)</a>.
+ \par Exception Safety
+ Basic; no-throw if the operations in the <i>Throws</i> section do not throw anything.
+ \par Iterator Invalidation
+ Invalidates iterators pointing to the elements before the insertion point (towards the beginning and
+ excluding <code>pos</code>). It also invalidates iterators pointing to the overwritten element.
+ \par Complexity
+ Linear (in <code>std::distance(begin(), pos)</code>).
+ \sa <code>\link rinsert(iterator, size_type, param_value_type)
+ rinsert(iterator, size_type, value_type)\endlink</code>,
+ <code>rinsert(iterator, InputIterator, InputIterator)</code>,
+ <code>\link insert(iterator, param_value_type) insert(iterator, value_type)\endlink</code>,
+ <code>\link insert(iterator, size_type, param_value_type)
+ insert(iterator, size_type, value_type)\endlink</code>,
+ <code>insert(iterator, InputIterator, InputIterator)</code>
+ */
+ iterator rinsert(iterator pos) {
+ value_type temp;
+ return rinsert(pos, boost::move(temp));
+ }
+
//! Insert <code>n</code> copies of the <code>item</code> before the specified position.
/*!
\pre <code>pos</code> is a valid iterator pointing to the <code>circular_buffer</code> or its end.
@@ -1716,7 +1998,8 @@ public:
\param n The number of <code>item</code>s the to be inserted.
\param item The element whose copies will be inserted.
\throws Whatever <code>T::T(const T&)</code> throws.
- \throws Whatever <code>T::operator = (const T&)</code> throws.
+ Whatever <code>T::operator = (const T&)</code> throws.
+ <a href="circular_buffer/implementation.html#circular_buffer.implementation.exceptions_of_move_if_noexcept_t">Exceptions of move_if_noexcept(T&)</a>.
\par Exception Safety
Basic; no-throw if the operations in the <i>Throws</i> section do not throw anything.
\par Iterator Invalidation
@@ -1728,7 +2011,7 @@ public:
Consider a <code>circular_buffer</code> with the capacity of 6 and the size of 4. Its internal buffer may
look like the one below.<br><br>
<code>|1|2|3|4| | |</code><br>
- <code>p ---^</code><br><br>After inserting 5 elements before the position <code>p</code>:<br><br>
+ <code>p ___^</code><br><br>After inserting 5 elements before the position <code>p</code>:<br><br>
<code>rinsert(p, (size_t)5, 0);</code><br><br>actually only 4 elements get inserted and elements
<code>3</code> and <code>4</code> are overwritten. This is due to the fact the rinsert operation preserves
the capacity. After insertion the internal buffer looks like this:<br><br><code>|1|2|0|0|0|0|</code><br>
@@ -1759,8 +2042,10 @@ public:
\param pos An iterator specifying the position where the range will be inserted.
\param first The beginning of the range to be inserted.
\param last The end of the range to be inserted.
- \throws Whatever <code>T::T(const T&)</code> throws.
- \throws Whatever <code>T::operator = (const T&)</code> throws.
+ \throws Whatever <code>T::T(const T&)</code> throws if the <code>InputIterator</code> is not a move iterator.
+ Whatever <code>T::operator = (const T&)</code> throws if the <code>InputIterator</code> is not a move iterator.
+ Whatever <code>T::T(T&&)</code> throws if the <code>InputIterator</code> is a move iterator.
+ Whatever <code>T::operator = (T&&)</code> throws if the <code>InputIterator</code> is a move iterator.
\par Exception Safety
Basic; no-throw if the operations in the <i>Throws</i> section do not throw anything.
\par Iterator Invalidation
@@ -1775,7 +2060,7 @@ public:
Consider a <code>circular_buffer</code> with the capacity of 6 and the size of 4. Its internal buffer may
look like the one below.<br><br>
<code>|1|2|3|4| | |</code><br>
- <code>p ---^</code><br><br>After inserting a range of elements before the position <code>p</code>:<br><br>
+ <code>p ___^</code><br><br>After inserting a range of elements before the position <code>p</code>:<br><br>
<code>int array[] = { 5, 6, 7, 8, 9 };</code><br><code>insert(p, array, array + 5);</code><br><br>
actually only elements <code>5</code>, <code>6</code>, <code>7</code> and <code>8</code> from the
specified range get inserted and elements <code>3</code> and <code>4</code> are overwritten. This is due
@@ -1805,7 +2090,7 @@ public:
\param pos An iterator pointing at the element to be removed.
\return Iterator to the first element remaining beyond the removed element or <code>end()</code> if no such
element exists.
- \throws Whatever <code>T::operator = (const T&)</code> throws.
+ \throws <a href="circular_buffer/implementation.html#circular_buffer.implementation.exceptions_of_move_if_noexcept_t">Exceptions of move_if_noexcept(T&)</a>.
\par Exception Safety
Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything.
\par Iterator Invalidation
@@ -1823,7 +2108,7 @@ public:
pointer next = pos.m_it;
increment(next);
for (pointer p = pos.m_it; next != m_last; p = next, increment(next))
- replace(p, *next);
+ replace(p, boost::move_if_noexcept(*next));
decrement(m_last);
destroy_item(m_last);
--m_size;
@@ -1843,7 +2128,7 @@ public:
\param last The end of the range to be removed.
\return Iterator to the first element remaining beyond the removed elements or <code>end()</code> if no such
element exists.
- \throws Whatever <code>T::operator = (const T&)</code> throws.
+ \throws <a href="circular_buffer/implementation.html#circular_buffer.implementation.exceptions_of_move_if_noexcept_t">Exceptions of move_if_noexcept(T&)</a>.
\par Exception Safety
Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything.
\par Iterator Invalidation
@@ -1862,7 +2147,7 @@ public:
return first;
pointer p = first.m_it;
while (last.m_it != 0)
- replace((first++).m_it, *last++);
+ replace((first++).m_it, boost::move_if_noexcept(*last++));
do {
decrement(m_last);
destroy_item(m_last);
@@ -1879,7 +2164,7 @@ public:
\param pos An iterator pointing at the element to be removed.
\return Iterator to the first element remaining in front of the removed element or <code>begin()</code> if no
such element exists.
- \throws Whatever <code>T::operator = (const T&)</code> throws.
+ \throws <a href="circular_buffer/implementation.html#circular_buffer.implementation.exceptions_of_move_if_noexcept_t">Exceptions of move_if_noexcept(T&)</a>.
\par Exception Safety
Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything.
\par Iterator Invalidation
@@ -1900,7 +2185,7 @@ public:
pointer prev = pos.m_it;
pointer p = prev;
for (decrement(prev); p != m_first; p = prev, decrement(prev))
- replace(p, *prev);
+ replace(p, boost::move_if_noexcept(*prev));
destroy_item(m_first);
increment(m_first);
--m_size;
@@ -1920,7 +2205,7 @@ public:
\param last The end of the range to be removed.
\return Iterator to the first element remaining in front of the removed elements or <code>begin()</code> if no
such element exists.
- \throws Whatever <code>T::operator = (const T&)</code> throws.
+ \throws <a href="circular_buffer/implementation.html#circular_buffer.implementation.exceptions_of_move_if_noexcept_t">Exceptions of move_if_noexcept(T&)</a>.
\par Exception Safety
Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything.
\par Iterator Invalidation
@@ -1945,7 +2230,7 @@ public:
while (first.m_it != m_first) {
decrement(first.m_it);
decrement(p);
- replace(p, *first.m_it);
+ replace(p, boost::move_if_noexcept(*first.m_it));
}
do {
destroy_item(m_first);
@@ -1963,7 +2248,7 @@ public:
\pre <code>n \<= size()</code>
\post The <code>n</code> elements at the beginning of the <code>circular_buffer</code> will be removed.
\param n The number of elements to be removed.
- \throws Whatever <code>T::operator = (const T&)</code> throws. (Does not throw anything in case of scalars.)
+ \throws <a href="circular_buffer/implementation.html#circular_buffer.implementation.exceptions_of_move_if_noexcept_t">Exceptions of move_if_noexcept(T&)</a>.
\par Exception Safety
Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything. (I.e. no throw in
case of scalars.)
@@ -1995,7 +2280,7 @@ public:
\pre <code>n \<= size()</code>
\post The <code>n</code> elements at the end of the <code>circular_buffer</code> will be removed.
\param n The number of elements to be removed.
- \throws Whatever <code>T::operator = (const T&)</code> throws. (Does not throw anything in case of scalars.)
+ \throws <a href="circular_buffer/implementation.html#circular_buffer.implementation.exceptions_of_move_if_noexcept_t">Exceptions of move_if_noexcept(T&)</a>.
\par Exception Safety
Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything. (I.e. no throw in
case of scalars.)
@@ -2037,7 +2322,7 @@ public:
<code>rerase(iterator)</code>, <code>rerase(iterator, iterator)</code>,
<code>erase_begin(size_type)</code>, <code>erase_end(size_type)</code>
*/
- void clear() {
+ void clear() BOOST_NOEXCEPT {
destroy_content();
m_size = 0;
}
@@ -2086,11 +2371,11 @@ private:
if (n > max_size())
throw_exception(std::length_error("circular_buffer"));
#if BOOST_CB_ENABLE_DEBUG
- pointer p = (n == 0) ? 0 : m_alloc.allocate(n, 0);
- std::memset(p, cb_details::UNINITIALIZED, sizeof(value_type) * n);
+ pointer p = (n == 0) ? 0 : m_alloc.allocate(n);
+ cb_details::do_fill_uninitialized_memory(p, sizeof(value_type) * n);
return p;
#else
- return (n == 0) ? 0 : m_alloc.allocate(n, 0);
+ return (n == 0) ? 0 : m_alloc.allocate(n);
#endif
}
@@ -2101,7 +2386,7 @@ private:
}
//! Does the pointer point to the uninitialized memory?
- bool is_uninitialized(const_pointer p) const {
+ bool is_uninitialized(const_pointer p) const BOOST_NOEXCEPT {
return p >= m_last && (m_first < m_last || p < m_first);
}
@@ -2113,6 +2398,14 @@ private:
#endif
}
+ //! Replace an element.
+ void replace(pointer pos, rvalue_type item) {
+ *pos = boost::move(item);
+#if BOOST_CB_ENABLE_DEBUG
+ invalidate_iterators(iterator(this, pos));
+#endif
+ }
+
//! Construct or replace an element.
/*!
<code>construct</code> has to be set to <code>true</code> if and only if
@@ -2120,17 +2413,29 @@ private:
*/
void construct_or_replace(bool construct, pointer pos, param_value_type item) {
if (construct)
- m_alloc.construct(pos, item);
+ boost::container::allocator_traits<Alloc>::construct(m_alloc, boost::addressof(*pos), item);
else
replace(pos, item);
}
+ //! Construct or replace an element.
+ /*!
+ <code>construct</code> has to be set to <code>true</code> if and only if
+ <code>pos</code> points to an uninitialized memory.
+ */
+ void construct_or_replace(bool construct, pointer pos, rvalue_type item) {
+ if (construct)
+ boost::container::allocator_traits<Alloc>::construct(m_alloc, boost::addressof(*pos), boost::move(item));
+ else
+ replace(pos, boost::move(item));
+ }
+
//! Destroy an item.
void destroy_item(pointer p) {
- m_alloc.destroy(p);
+ boost::container::allocator_traits<Alloc>::destroy(m_alloc, boost::addressof(*p));
#if BOOST_CB_ENABLE_DEBUG
invalidate_iterators(iterator(this, p));
- std::memset(p, cb_details::UNINITIALIZED, sizeof(value_type));
+ cb_details::do_fill_uninitialized_memory(p, sizeof(value_type));
#endif
}
@@ -2161,7 +2466,7 @@ private:
}
//! Destroy content and free allocated memory.
- void destroy() {
+ void destroy() BOOST_NOEXCEPT {
destroy_content();
deallocate(m_buff, capacity());
#if BOOST_CB_ENABLE_DEBUG
@@ -2203,9 +2508,9 @@ private:
void initialize(Iterator first, Iterator last, const false_type&) {
BOOST_CB_IS_CONVERTIBLE(Iterator, value_type); // check for invalid iterator type
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581))
- initialize(first, last, BOOST_ITERATOR_CATEGORY<Iterator>::type());
+ initialize(first, last, iterator_category<Iterator>::type());
#else
- initialize(first, last, BOOST_DEDUCED_TYPENAME BOOST_ITERATOR_CATEGORY<Iterator>::type());
+ initialize(first, last, BOOST_DEDUCED_TYPENAME iterator_category<Iterator>::type());
#endif
}
@@ -2216,7 +2521,7 @@ private:
// for containers
std::deque<value_type, allocator_type> tmp(first, last, m_alloc);
size_type distance = tmp.size();
- initialize(distance, tmp.begin(), tmp.end(), distance);
+ initialize(distance, boost::make_move_iterator(tmp.begin()), boost::make_move_iterator(tmp.end()), distance);
}
//! Specialized initialize method.
@@ -2242,9 +2547,9 @@ private:
void initialize(capacity_type buffer_capacity, Iterator first, Iterator last, const false_type&) {
BOOST_CB_IS_CONVERTIBLE(Iterator, value_type); // check for invalid iterator type
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581))
- initialize(buffer_capacity, first, last, BOOST_ITERATOR_CATEGORY<Iterator>::type());
+ initialize(buffer_capacity, first, last, iterator_category<Iterator>::type());
#else
- initialize(buffer_capacity, first, last, BOOST_DEDUCED_TYPENAME BOOST_ITERATOR_CATEGORY<Iterator>::type());
+ initialize(buffer_capacity, first, last, BOOST_DEDUCED_TYPENAME iterator_category<Iterator>::type());
#endif
}
@@ -2260,7 +2565,7 @@ private:
if (buffer_capacity == 0)
return;
while (first != last && !full()) {
- m_alloc.construct(m_last, *first++);
+ boost::container::allocator_traits<Alloc>::construct(m_alloc, boost::addressof(*m_last), *first++);
increment(m_last);
++m_size;
}
@@ -2296,7 +2601,7 @@ private:
m_size = distance;
}
BOOST_TRY {
- m_last = cb_details::uninitialized_copy_with_alloc(first, last, m_buff, m_alloc);
+ m_last = cb_details::uninitialized_copy(first, last, m_buff, m_alloc);
} BOOST_CATCH(...) {
deallocate(m_buff, buffer_capacity);
BOOST_RETHROW
@@ -2316,7 +2621,7 @@ private:
}
//! Specialized method for swapping the allocator.
- void swap_allocator(circular_buffer<T, Alloc>& cb, const true_type&) {
+ void swap_allocator(circular_buffer<T, Alloc>&, const true_type&) {
// Swap is not needed because allocators have no state.
}
@@ -2336,9 +2641,9 @@ private:
void assign(Iterator first, Iterator last, const false_type&) {
BOOST_CB_IS_CONVERTIBLE(Iterator, value_type); // check for invalid iterator type
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581))
- assign(first, last, BOOST_ITERATOR_CATEGORY<Iterator>::type());
+ assign(first, last, iterator_category<Iterator>::type());
#else
- assign(first, last, BOOST_DEDUCED_TYPENAME BOOST_ITERATOR_CATEGORY<Iterator>::type());
+ assign(first, last, BOOST_DEDUCED_TYPENAME iterator_category<Iterator>::type());
#endif
}
@@ -2350,8 +2655,8 @@ private:
std::deque<value_type, allocator_type> tmp(first, last, m_alloc);
size_type distance = tmp.size();
assign_n(distance, distance,
- cb_details::assign_range<BOOST_DEDUCED_TYPENAME std::deque<value_type, allocator_type>::iterator,
- allocator_type>(tmp.begin(), tmp.end(), m_alloc));
+ cb_details::make_assign_range
+ (boost::make_move_iterator(tmp.begin()), boost::make_move_iterator(tmp.end()), m_alloc));
}
//! Specialized assign method.
@@ -2359,7 +2664,7 @@ private:
void assign(ForwardIterator first, ForwardIterator last, const std::forward_iterator_tag&) {
BOOST_CB_ASSERT(std::distance(first, last) >= 0); // check for wrong range
size_type distance = std::distance(first, last);
- assign_n(distance, distance, cb_details::assign_range<ForwardIterator, allocator_type>(first, last, m_alloc));
+ assign_n(distance, distance, cb_details::make_assign_range(first, last, m_alloc));
}
//! Specialized assign method.
@@ -2373,9 +2678,9 @@ private:
void assign(capacity_type new_capacity, Iterator first, Iterator last, const false_type&) {
BOOST_CB_IS_CONVERTIBLE(Iterator, value_type); // check for invalid iterator type
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581))
- assign(new_capacity, first, last, BOOST_ITERATOR_CATEGORY<Iterator>::type());
+ assign(new_capacity, first, last, iterator_category<Iterator>::type());
#else
- assign(new_capacity, first, last, BOOST_DEDUCED_TYPENAME BOOST_ITERATOR_CATEGORY<Iterator>::type());
+ assign(new_capacity, first, last, BOOST_DEDUCED_TYPENAME iterator_category<Iterator>::type());
#endif
}
@@ -2386,12 +2691,7 @@ private:
clear();
insert(begin(), first, last);
} else {
-#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
- circular_buffer<value_type, allocator_type> tmp(new_capacity, m_alloc);
- tmp.insert(begin(), first, last);
-#else
circular_buffer<value_type, allocator_type> tmp(new_capacity, first, last, m_alloc);
-#endif
tmp.swap(*this);
}
}
@@ -2407,7 +2707,7 @@ private:
distance = new_capacity;
}
assign_n(new_capacity, distance,
- cb_details::assign_range<ForwardIterator, allocator_type>(first, last, m_alloc));
+ cb_details::make_assign_range(first, last, m_alloc));
}
//! Helper assign method.
@@ -2441,10 +2741,11 @@ private:
}
//! Helper insert method.
- iterator insert_item(const iterator& pos, param_value_type item) {
+ template <class ValT>
+ iterator insert_item(const iterator& pos, ValT item) {
pointer p = pos.m_it;
if (p == 0) {
- construct_or_replace(!full(), m_last, item);
+ construct_or_replace(!full(), m_last, static_cast<ValT>(item));
p = m_last;
} else {
pointer src = m_last;
@@ -2453,11 +2754,11 @@ private:
BOOST_TRY {
while (src != p) {
decrement(src);
- construct_or_replace(construct, dest, *src);
+ construct_or_replace(construct, dest, boost::move_if_noexcept(*src));
decrement(dest);
construct = false;
}
- replace(p, item);
+ replace(p, static_cast<ValT>(item));
} BOOST_CATCH(...) {
if (!construct && !full()) {
increment(m_last);
@@ -2486,9 +2787,9 @@ private:
void insert(const iterator& pos, Iterator first, Iterator last, const false_type&) {
BOOST_CB_IS_CONVERTIBLE(Iterator, value_type); // check for invalid iterator type
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581))
- insert(pos, first, last, BOOST_ITERATOR_CATEGORY<Iterator>::type());
+ insert(pos, first, last, iterator_category<Iterator>::type());
#else
- insert(pos, first, last, BOOST_DEDUCED_TYPENAME BOOST_ITERATOR_CATEGORY<Iterator>::type());
+ insert(pos, first, last, BOOST_DEDUCED_TYPENAME iterator_category<Iterator>::type());
#endif
}
@@ -2497,7 +2798,7 @@ private:
void insert(iterator pos, InputIterator first, InputIterator last, const std::input_iterator_tag&) {
if (!full() || pos != begin()) {
for (;first != last; ++pos)
- pos = insert_item(pos, *first++);
+ pos = insert(pos, *first++);
}
}
@@ -2529,7 +2830,7 @@ private:
pointer p = m_last;
BOOST_TRY {
for (; ii < construct; ++ii, increment(p))
- m_alloc.construct(p, *wrapper());
+ boost::container::allocator_traits<Alloc>::construct(m_alloc, boost::addressof(*p), *wrapper());
for (;ii < n; ++ii, increment(p))
replace(p, *wrapper());
} BOOST_CATCH(...) {
@@ -2577,9 +2878,9 @@ private:
void rinsert(const iterator& pos, Iterator first, Iterator last, const false_type&) {
BOOST_CB_IS_CONVERTIBLE(Iterator, value_type); // check for invalid iterator type
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581))
- rinsert(pos, first, last, BOOST_ITERATOR_CATEGORY<Iterator>::type());
+ rinsert(pos, first, last, iterator_category<Iterator>::type());
#else
- rinsert(pos, first, last, BOOST_DEDUCED_TYPENAME BOOST_ITERATOR_CATEGORY<Iterator>::type());
+ rinsert(pos, first, last, BOOST_DEDUCED_TYPENAME iterator_category<Iterator>::type());
#endif
}
@@ -2623,7 +2924,7 @@ private:
for (;ii > construct; --ii, increment(p))
replace(p, *wrapper());
for (; ii > 0; --ii, increment(p))
- m_alloc.construct(p, *wrapper());
+ boost::container::allocator_traits<Alloc>::construct(m_alloc, boost::addressof(*p), *wrapper());
} BOOST_CATCH(...) {
size_type constructed = ii < construct ? construct - ii : 0;
m_last = add(m_last, constructed);
@@ -2810,7 +3111,7 @@ inline bool operator >= (const circular_buffer<T, Alloc>& lhs, const circular_bu
\sa <code>\link circular_buffer::swap(circular_buffer<T, Alloc>&) swap(circular_buffer<T, Alloc>&)\endlink</code>
*/
template <class T, class Alloc>
-inline void swap(circular_buffer<T, Alloc>& lhs, circular_buffer<T, Alloc>& rhs) {
+inline void swap(circular_buffer<T, Alloc>& lhs, circular_buffer<T, Alloc>& rhs) BOOST_NOEXCEPT {
lhs.swap(rhs);
}