Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r85003 - in trunk: boost/circular_buffer libs/circular_buffer/test
From: antoshkka_at_[hidden]
Date: 2013-07-11 10:55:24


Author: apolukhin
Date: 2013-07-11 10:55:24 EDT (Thu, 11 Jul 2013)
New Revision: 85003
URL: http://svn.boost.org/trac/boost/changeset/85003

Log:
Improved rvalues move support for elements of circular_buffer (refs #7888):
* all `erase` methods now use move construction to to move elements
* space optimized circullar buffer now has move constructor, move assignment and functions that work with rvalues
* more methods marked as BOOST_NOEXCEPT
* much more tests

Text files modified:
   trunk/boost/circular_buffer/base.hpp | 20 +-
   trunk/boost/circular_buffer/space_optimized.hpp | 316 ++++++++++++++++++++++++++++++++++-
   trunk/libs/circular_buffer/test/base_test.cpp | 230 +------------------------
   trunk/libs/circular_buffer/test/common.ipp | 353 ++++++++++++++++++++++++++++++++++++++++
   4 files changed, 685 insertions(+), 234 deletions(-)

Modified: trunk/boost/circular_buffer/base.hpp
==============================================================================
--- trunk/boost/circular_buffer/base.hpp Thu Jul 11 06:27:49 2013 (r85002)
+++ trunk/boost/circular_buffer/base.hpp 2013-07-11 10:55:24 EDT (Thu, 11 Jul 2013) (r85003)
@@ -1031,8 +1031,7 @@
     /*!
         \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
@@ -1046,7 +1045,7 @@
         \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.
@@ -1283,15 +1282,16 @@
     }
 
 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- /*! \brief Move constructs a <code>circular_buffer</code> from <code>cb</code>, leaving <code>cb</code> empty.
+ /*! \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 Constant.
+ \par Complexity
+ Constant.
     */
     circular_buffer<T, Alloc>& operator = (circular_buffer<T, Alloc>&& cb) BOOST_NOEXCEPT {
- swap(cb); // now `this` holds `cb`
+ 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;
@@ -2145,7 +2145,7 @@
         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, this_type::move_if_noexcept(*next));
         decrement(m_last);
         destroy_item(m_last);
         --m_size;
@@ -2184,7 +2184,7 @@
             return first;
         pointer p = first.m_it;
         while (last.m_it != 0)
- replace((first++).m_it, *last++);
+ replace((first++).m_it, this_type::move_if_noexcept(*last++));
         do {
             decrement(m_last);
             destroy_item(m_last);
@@ -2222,7 +2222,7 @@
         pointer prev = pos.m_it;
         pointer p = prev;
         for (decrement(prev); p != m_first; p = prev, decrement(prev))
- replace(p, *prev);
+ replace(p, this_type::move_if_noexcept(*prev));
         destroy_item(m_first);
         increment(m_first);
         --m_size;
@@ -2267,7 +2267,7 @@
         while (first.m_it != m_first) {
             decrement(first.m_it);
             decrement(p);
- replace(p, *first.m_it);
+ replace(p, this_type::move_if_noexcept(*first.m_it));
         }
         do {
             destroy_item(m_first);

Modified: trunk/boost/circular_buffer/space_optimized.hpp
==============================================================================
--- trunk/boost/circular_buffer/space_optimized.hpp Thu Jul 11 06:27:49 2013 (r85002)
+++ trunk/boost/circular_buffer/space_optimized.hpp 2013-07-11 10:55:24 EDT (Thu, 11 Jul 2013) (r85003)
@@ -2,6 +2,7 @@
 
 // Copyright (c) 2003-2008 Jan Gaspar
 // Copyright (c) 2013 Paul A. Bristow // Doxygen comments changed for new version of documentation.
+// Copyright (c) 2013 Antony Polukhin // Move semantics implementation.
 
 // Use, modification, and distribution is subject to the Boost Software
 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -49,6 +50,7 @@
     typedef typename circular_buffer<T, Alloc>::array_range array_range;
     typedef typename circular_buffer<T, Alloc>::const_array_range const_array_range;
     typedef typename circular_buffer<T, Alloc>::param_value_type param_value_type;
+ typedef typename circular_buffer<T, Alloc>::rvalue_type rvalue_type;
     //typedef typename circular_buffer<T, Alloc>::return_value_type return_value_type;
 
 /* <pre> is not passed through to html or pdf. So <br> is used in code section below. Ugly :-(
@@ -146,7 +148,7 @@
              Constant (in the size of the <code>circular_buffer_space_optimized</code>).
         \sa <code>empty()</code>
     */
- bool full() const { return m_capacity_ctrl == size(); }
+ bool full() const BOOST_NOEXCEPT { return m_capacity_ctrl == size(); }
 
     /*! \brief Get the maximum number of elements which can be inserted into the
                <code>circular_buffer_space_optimized</code> without overwriting any of already stored elements.
@@ -160,7 +162,7 @@
              Constant (in the size of the <code>circular_buffer_space_optimized</code>).
         \sa <code>capacity()</code>, <code>size()</code>, <code>max_size()</code>
     */
- size_type reserve() const { return m_capacity_ctrl - size(); }
+ size_type reserve() const BOOST_NOEXCEPT { return m_capacity_ctrl - size(); }
 
     //! Get the capacity of the <code>circular_buffer_space_optimized</code>.
     /*!
@@ -176,7 +178,7 @@
         \sa <code>reserve()</code>, <code>size()</code>, <code>max_size()</code>,
             <code>set_capacity(const capacity_type&)</code>
     */
- const capacity_type& capacity() const { return m_capacity_ctrl; }
+ const capacity_type& capacity() const BOOST_NOEXCEPT { return m_capacity_ctrl; }
 
 #if defined(BOOST_CB_TEST)
 
@@ -185,7 +187,7 @@
        \note This method is not intended to be used directly by the user.
              It is defined only for testing purposes.
     */
- size_type internal_capacity() const { return circular_buffer<T, Alloc>::capacity(); }
+ size_type internal_capacity() const BOOST_NOEXCEPT { return circular_buffer<T, Alloc>::capacity(); }
 
 #endif // #if defined(BOOST_CB_TEST)
 
@@ -345,7 +347,7 @@
         \warning Since Boost version 1.36 the behaviour of this constructor has changed. Now it creates a space
                  optimized circular buffer with zero capacity.
     */
- explicit circular_buffer_space_optimized(const allocator_type& alloc = allocator_type())
+ explicit circular_buffer_space_optimized(const allocator_type& alloc = allocator_type()) BOOST_NOEXCEPT
     : circular_buffer<T, Alloc>(0, alloc)
     , m_capacity_ctrl(0) {}
 
@@ -453,6 +455,23 @@
     : circular_buffer<T, Alloc>(cb.begin(), cb.end(), cb.get_allocator())
     , m_capacity_ctrl(cb.m_capacity_ctrl) {}
 
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ //! The move constructor.
+ /*! \brief Move constructs a <code>circular_buffer_space_optimized</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_space_optimized(circular_buffer_space_optimized<T, Alloc>&& cb) BOOST_NOEXCEPT
+ : circular_buffer<T, Alloc>()
+ , m_capacity_ctrl(0) {
+ cb.swap(*this);
+ }
+#endif // BOOST_NO_CXX11_RVALUE_REFERENCES
+
     //! Create a full space optimized circular buffer filled with a copy of the range.
     /*!
         \pre Valid range <code>[first, last)</code>.<br>
@@ -573,6 +592,24 @@
         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_space_optimized<T, Alloc>& operator = (circular_buffer_space_optimized<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 space optimized circular buffer.
     /*!
         The content of the <code>circular_buffer_space_optimized</code> will be removed and replaced with
@@ -736,7 +773,7 @@
     */
     // Note link does not work right. Asked on Doxygen forum for advice 23 May 2103.
 
- void swap(circular_buffer_space_optimized<T, Alloc>& cb) {
+ void swap(circular_buffer_space_optimized<T, Alloc>& cb) BOOST_NOEXCEPT {
         std::swap(m_capacity_ctrl, cb.m_capacity_ctrl);
         circular_buffer<T, Alloc>::swap(cb);
     }
@@ -761,11 +798,61 @@
         \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()) {
+ void push_back(param_value_type item) {
         check_low_capacity();
         circular_buffer<T, Alloc>::push_back(item);
     }
 
+ //! Insert a new element at the end of the space optimized circular buffer.
+ /*!
+ \post if <code>capacity().%capacity() > 0</code> then <code>back() == item</code><br>
+ If the <code>circular_buffer_space_optimized</code> is full, the first element will be removed. If the
+ capacity is <code>0</code>, nothing will be inserted.<br><br>
+ The amount of allocated memory in the internal buffer may be predictively increased.
+ \param item The element to be inserted.
+ \throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
+ used).
+ \throws Whatever <code>T::T(T&&)</code> throws.
+ \par Exception Safety
+ Basic.
+ \par Iterator Invalidation
+ Invalidates all iterators pointing to the <code>circular_buffer_space_optimized</code> (except iterators
+ equal to <code>end()</code>).
+ \par Complexity
+ Linear (in the size of the <code>circular_buffer_space_optimized</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) {
+ check_low_capacity();
+ circular_buffer<T, Alloc>::push_back(boost::move(item));
+ }
+
+ //! Insert a new element at the end of the space optimized circular buffer.
+ /*!
+ \post if <code>capacity().%capacity() > 0</code> then <code>back() == item</code><br>
+ If the <code>circular_buffer_space_optimized</code> is full, the first element will be removed. If the
+ capacity is <code>0</code>, nothing will be inserted.<br><br>
+ The amount of allocated memory in the internal buffer may be predictively increased.
+ \throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
+ used).
+ \throws Whatever <code>T::T()</code> throws.
+ \throws Whatever <code>T::T(T&&)</code> throws.
+ \par Exception Safety
+ Basic.
+ \par Iterator Invalidation
+ Invalidates all iterators pointing to the <code>circular_buffer_space_optimized</code> (except iterators
+ equal to <code>end()</code>).
+ \par Complexity
+ Linear (in the size of the <code>circular_buffer_space_optimized</code>).
+ \sa <code>\link push_front() push_front(const_reference)\endlink</code>, <code>pop_back()</code>,
+ <code>pop_front()</code>
+ */
+ void push_back() {
+ check_low_capacity();
+ circular_buffer<T, Alloc>::push_back();
+ }
+
     //! Insert a new element at the beginning of the space optimized circular buffer.
     /*!
         \post if <code>capacity().%capacity() > 0</code> then <code>front() == item</code><br>
@@ -786,11 +873,62 @@
         \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()) {
+ void push_front(param_value_type item) {
         check_low_capacity();
         circular_buffer<T, Alloc>::push_front(item);
     }
 
+ //! Insert a new element at the beginning of the space optimized circular buffer.
+ /*!
+ \post if <code>capacity().%capacity() > 0</code> then <code>front() == item</code><br>
+ If the <code>circular_buffer_space_optimized</code> is full, the last element will be removed. If the
+ capacity is <code>0</code>, nothing will be inserted.<br><br>
+ The amount of allocated memory in the internal buffer may be predictively increased.
+ \param item The element to be inserted.
+ \throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
+ used).
+ \throws Whatever <code>T::T(T&&)</code> throws.
+ \par Exception Safety
+ Basic.
+ \par Iterator Invalidation
+ Invalidates all iterators pointing to the <code>circular_buffer_space_optimized</code> (except iterators
+ equal to <code>end()</code>).
+ \par Complexity
+ Linear (in the size of the <code>circular_buffer_space_optimized</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) {
+ check_low_capacity();
+ circular_buffer<T, Alloc>::push_front(boost::move(item));
+ }
+
+ //! Insert a new element at the beginning of the space optimized circular buffer.
+ /*!
+ \post if <code>capacity().%capacity() > 0</code> then <code>front() == item</code><br>
+ If the <code>circular_buffer_space_optimized</code> is full, the last element will be removed. If the
+ capacity is <code>0</code>, nothing will be inserted.<br><br>
+ The amount of allocated memory in the internal buffer may be predictively increased.
+ \param item The element to be inserted.
+ \throws "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
+ used).
+ \throws Whatever <code>T::T()</code> throws.
+ \throws Whatever <code>T::T(T&&)</code> throws.
+ \par Exception Safety
+ Basic.
+ \par Iterator Invalidation
+ Invalidates all iterators pointing to the <code>circular_buffer_space_optimized</code> (except iterators
+ equal to <code>end()</code>).
+ \par Complexity
+ Linear (in the size of the <code>circular_buffer_space_optimized</code>).
+ \sa <code>\link push_back() push_back(const_reference)\endlink</code>, <code>pop_back()</code>,
+ <code>pop_front()</code>
+ */
+ void push_front() {
+ check_low_capacity();
+ circular_buffer<T, Alloc>::push_front();
+ }
+
     //! Remove the last element from the space optimized circular buffer.
     /*!
         \pre <code>!empty()</code>
@@ -868,12 +1006,90 @@
             rinsert(iterator, size_type, value_type)\endlink</code>,
             <code>rinsert(iterator, InputIterator, InputIterator)</code>
     */
- iterator insert(iterator pos, param_value_type item = value_type()) {
+ iterator insert(iterator pos, param_value_type item) {
         size_type index = pos - begin();
         check_low_capacity();
         return circular_buffer<T, Alloc>::insert(begin() + index, item);
     }
 
+ //! Insert an element at the specified position.
+ /*!
+ \pre <code>pos</code> is a valid iterator pointing to the <code>circular_buffer_space_optimized</code> or its
+ end.
+ \post The <code>item</code> will be inserted at the position <code>pos</code>.<br>
+ If the <code>circular_buffer_space_optimized</code> is full, the first element will be overwritten. If
+ the <code>circular_buffer_space_optimized</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.<br><br>
+ The amount of allocated memory in the internal buffer may be predictively increased.
+ \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 "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
+ used).
+ \throws Whatever <code>T::T(T&&)</code> throws.
+ \throws Whatever <code>T::operator = (T&&)</code> throws.
+ \par Exception Safety
+ Basic.
+ \par Iterator Invalidation
+ Invalidates all iterators pointing to the <code>circular_buffer_space_optimized</code> (except iterators
+ equal to <code>end()</code>).
+ \par Complexity
+ Linear (in the size of the <code>circular_buffer_space_optimized</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) {
+ size_type index = pos - begin();
+ check_low_capacity();
+ return circular_buffer<T, Alloc>::insert(begin() + index, boost::move(item));
+ }
+
+ //! Insert an element at the specified position.
+ /*!
+ \pre <code>pos</code> is a valid iterator pointing to the <code>circular_buffer_space_optimized</code> or its
+ end.
+ \post The <code>item</code> will be inserted at the position <code>pos</code>.<br>
+ If the <code>circular_buffer_space_optimized</code> is full, the first element will be overwritten. If
+ the <code>circular_buffer_space_optimized</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.<br><br>
+ The amount of allocated memory in the internal buffer may be predictively increased.
+ \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 "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
+ used).
+ \throws Whatever <code>T::T()</code> throws.
+ \throws Whatever <code>T::T(T&&)</code> throws.
+ \throws Whatever <code>T::operator = (T&&)</code> throws.
+ \par Exception Safety
+ Basic.
+ \par Iterator Invalidation
+ Invalidates all iterators pointing to the <code>circular_buffer_space_optimized</code> (except iterators
+ equal to <code>end()</code>).
+ \par Complexity
+ Linear (in the size of the <code>circular_buffer_space_optimized</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) {
+ size_type index = pos - begin();
+ check_low_capacity();
+ return circular_buffer<T, Alloc>::insert(begin() + index);
+ }
+
     //! Insert <code>n</code> copies of the <code>item</code> at the specified position.
     /*!
         \pre <code>pos</code> is a valid iterator pointing to the <code>circular_buffer_space_optimized</code> or its
@@ -1004,12 +1220,90 @@
             insert(iterator, size_type, value_type)\endlink</code>,
             <code>insert(iterator, InputIterator, InputIterator)</code>
     */
- iterator rinsert(iterator pos, param_value_type item = value_type()) {
+ iterator rinsert(iterator pos, param_value_type item) {
         size_type index = pos - begin();
         check_low_capacity();
         return circular_buffer<T, Alloc>::rinsert(begin() + index, item);
     }
 
+ //! Insert an element before the specified position.
+ /*!
+ \pre <code>pos</code> is a valid iterator pointing to the <code>circular_buffer_space_optimized</code> or its
+ end.
+ \post The <code>item</code> will be inserted before the position <code>pos</code>.<br>
+ If the <code>circular_buffer_space_optimized</code> is full, the last element will be overwritten. If the
+ <code>circular_buffer_space_optimized</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.<br><br>
+ The amount of allocated memory in the internal buffer may be predictively increased.
+ \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 "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
+ used).
+ \throws Whatever <code>T::T(T&&)</code> throws.
+ \throws Whatever <code>T::operator = (T&&)</code> throws.
+ \par Exception Safety
+ Basic.
+ \par Iterator Invalidation
+ Invalidates all iterators pointing to the <code>circular_buffer_space_optimized</code> (except iterators
+ equal to <code>end()</code>).
+ \par Complexity
+ Linear (in the size of the <code>circular_buffer_space_optimized</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) {
+ size_type index = pos - begin();
+ check_low_capacity();
+ return circular_buffer<T, Alloc>::rinsert(begin() + index, boost::move(item));
+ }
+
+ //! Insert an element before the specified position.
+ /*!
+ \pre <code>pos</code> is a valid iterator pointing to the <code>circular_buffer_space_optimized</code> or its
+ end.
+ \post The <code>item</code> will be inserted before the position <code>pos</code>.<br>
+ If the <code>circular_buffer_space_optimized</code> is full, the last element will be overwritten. If the
+ <code>circular_buffer_space_optimized</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.<br><br>
+ The amount of allocated memory in the internal buffer may be predictively increased.
+ \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 "An allocation error" if memory is exhausted (<code>std::bad_alloc</code> if the standard allocator is
+ used).
+ \throws Whatever <code>T::T()</code> throws.
+ \throws Whatever <code>T::T(T&&)</code> throws.
+ \throws Whatever <code>T::operator = (T&&)</code> throws.
+ \par Exception Safety
+ Basic.
+ \par Iterator Invalidation
+ Invalidates all iterators pointing to the <code>circular_buffer_space_optimized</code> (except iterators
+ equal to <code>end()</code>).
+ \par Complexity
+ Linear (in the size of the <code>circular_buffer_space_optimized</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) {
+ size_type index = pos - begin();
+ check_low_capacity();
+ return circular_buffer<T, Alloc>::rinsert(begin() + index);
+ }
+
     //! 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_space_optimized</code> or its
@@ -1439,7 +1733,7 @@
 //! Swap the contents of two space optimized circular buffers.
 template <class T, class Alloc>
 inline void swap(circular_buffer_space_optimized<T, Alloc>& lhs,
- circular_buffer_space_optimized<T, Alloc>& rhs) {
+ circular_buffer_space_optimized<T, Alloc>& rhs) BOOST_NOEXCEPT {
     lhs.swap(rhs);
 }
 

Modified: trunk/libs/circular_buffer/test/base_test.cpp
==============================================================================
--- trunk/libs/circular_buffer/test/base_test.cpp Thu Jul 11 06:27:49 2013 (r85002)
+++ trunk/libs/circular_buffer/test/base_test.cpp 2013-07-11 10:55:24 EDT (Thu, 11 Jul 2013) (r85003)
@@ -1,6 +1,7 @@
 // Test of the base circular buffer container.
 
 // Copyright (c) 2003-2008 Jan Gaspar
+// Copyright (c) 2013 Antony Polukhin
 
 // Use, modification, and distribution is subject to the Boost Software
 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -738,219 +739,14 @@
 #endif // #if !defined(BOOST_NO_EXCEPTIONS)
 }
 
-void move_container_on_cpp11() {
-#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- CB_CONTAINER<MyInteger> cb1(10);
- cb1.push_back(1);
- cb1.push_back(2);
- cb1.push_back(3);
- cb1.push_back(4);
- cb1.push_back(5);
- cb1.push_back(6);
-
- // Checking move constructor
- CB_CONTAINER<MyInteger> cb2(static_cast<CB_CONTAINER<MyInteger>&& >(cb1));
- CB_CONTAINER<MyInteger>::iterator it2 = cb2.begin() + 1;
-
- BOOST_CHECK(cb1.empty());
- BOOST_CHECK(!cb2.empty());
- BOOST_CHECK(it2[0] == 2);
- BOOST_CHECK(it2[-1] == 1);
- BOOST_CHECK(it2[2] == 4);
-
- // Checking move assignment
- cb1 = static_cast<CB_CONTAINER<MyInteger>&& >(cb2);
- CB_CONTAINER<MyInteger>::iterator it1 = cb1.begin() + 1;
-
- BOOST_CHECK(!cb1.empty());
- BOOST_CHECK(cb2.empty());
- BOOST_CHECK(it1[0] == 2);
- BOOST_CHECK(it1[-1] == 1);
- BOOST_CHECK(it1[2] == 4);
-#endif
-}
 
-
-struct noncopyable_movable_test_t
- : private boost::noncopyable // required, until there will be no support for is_copy_constructible added to Boost.Move
-{
-private:
- BOOST_MOVABLE_BUT_NOT_COPYABLE(noncopyable_movable_test_t)
- bool is_moved_;
- int value_;
-public:
- static int next_value;
-
- explicit noncopyable_movable_test_t()
- : is_moved_(false)
- , value_(next_value ++)
- {}
-
- noncopyable_movable_test_t(BOOST_RV_REF(noncopyable_movable_test_t) x) BOOST_NOEXCEPT {
- is_moved_ = x.is_moved_;
- value_ = x.value_;
- x.is_moved_ = true;
- }
-
- noncopyable_movable_test_t& operator=(BOOST_RV_REF(noncopyable_movable_test_t) x) BOOST_NOEXCEPT {
- is_moved_ = x.is_moved_;
- value_ = x.value_;
- x.is_moved_ = true;
- return *this;
- }
-
- bool is_moved() const {
- return is_moved_;
- }
-
- int value() const {
- return value_;
- }
-
- void reinit() { is_moved_ = false; value_ = next_value ++; }
-};
-
-int noncopyable_movable_test_t::next_value = 1;
-
-void move_container_values() {
- noncopyable_movable_test_t::next_value = 1;
-
- CB_CONTAINER<noncopyable_movable_test_t> cb1(40);
- noncopyable_movable_test_t var;
- cb1.push_back(boost::move(var));
- BOOST_CHECK(!cb1.back().is_moved());
- BOOST_CHECK(cb1.back().value() == 1);
- BOOST_CHECK(var.is_moved());
- BOOST_CHECK(cb1.size() == 1);
-
- var.reinit();
- cb1.push_front(boost::move(var));
- BOOST_CHECK(!cb1.front().is_moved());
- BOOST_CHECK(cb1.front().value() == 2);
- BOOST_CHECK(var.is_moved());
- BOOST_CHECK(cb1.size() == 2);
-
- cb1.push_back();
- BOOST_CHECK(!cb1.back().is_moved());
- BOOST_CHECK(cb1.back().value() == 3);
- BOOST_CHECK(cb1.size() == 3);
-
- cb1.push_front();
- BOOST_CHECK(!cb1.front().is_moved());
- BOOST_CHECK(cb1.front().value() == 4);
- BOOST_CHECK(cb1.size() == 4);
-
- cb1.insert(cb1.begin());
- BOOST_CHECK(!cb1.front().is_moved());
- BOOST_CHECK(cb1.front().value() == 5);
- BOOST_CHECK(cb1.size() == 5);
-
- var.reinit();
- cb1.insert(cb1.begin(), boost::move(var));
- BOOST_CHECK(!cb1.front().is_moved());
- BOOST_CHECK(cb1.front().value() == 6);
- BOOST_CHECK(cb1.size() == 6);
-
- cb1.rinsert(cb1.begin());
- BOOST_CHECK(!cb1.front().is_moved());
- BOOST_CHECK(cb1.front().value() == 7);
- BOOST_CHECK(cb1.size() == 7);
-
- var.reinit();
- cb1.rinsert(cb1.begin(), boost::move(var));
- BOOST_CHECK(!cb1.front().is_moved());
- BOOST_CHECK(cb1.front().value() == 8);
- BOOST_CHECK(cb1.size() == 8);
-
-
- BOOST_CHECK(cb1[0].value() == 8);
- BOOST_CHECK(cb1[1].value() == 7);
- BOOST_CHECK(cb1[2].value() == 6);
- BOOST_CHECK(cb1[3].value() == 5);
- BOOST_CHECK(cb1[4].value() == 4);
- BOOST_CHECK(cb1[5].value() == 2);
- BOOST_CHECK(cb1[6].value() == 1);
- BOOST_CHECK(cb1[7].value() == 3);
- cb1.rotate(cb1.begin() + 2);
- BOOST_CHECK(cb1[0].value() == 6);
- BOOST_CHECK(cb1[1].value() == 5);
- BOOST_CHECK(cb1[2].value() == 4);
- BOOST_CHECK(cb1[3].value() == 2);
- BOOST_CHECK(cb1[4].value() == 1);
- BOOST_CHECK(cb1[5].value() == 3);
- BOOST_CHECK(cb1[6].value() == 8);
- BOOST_CHECK(cb1[7].value() == 7);
-
- BOOST_CHECK(!cb1[0].is_moved());
- BOOST_CHECK(!cb1[1].is_moved());
- BOOST_CHECK(!cb1[2].is_moved());
- BOOST_CHECK(!cb1[3].is_moved());
- BOOST_CHECK(!cb1[4].is_moved());
- BOOST_CHECK(!cb1[5].is_moved());
- BOOST_CHECK(!cb1[6].is_moved());
- BOOST_CHECK(!cb1[7].is_moved());
-
-
- cb1.linearize();
- BOOST_CHECK(!cb1[0].is_moved());
- BOOST_CHECK(!cb1[1].is_moved());
- BOOST_CHECK(!cb1[2].is_moved());
- BOOST_CHECK(!cb1[3].is_moved());
- BOOST_CHECK(!cb1[4].is_moved());
- BOOST_CHECK(!cb1[5].is_moved());
- BOOST_CHECK(!cb1[6].is_moved());
- BOOST_CHECK(!cb1[7].is_moved());
-
-#ifndef BOOST_NO_CXX11_NOEXCEPT
- cb1.set_capacity(100);
- BOOST_CHECK(!cb1[0].is_moved());
- BOOST_CHECK(!cb1[1].is_moved());
- BOOST_CHECK(!cb1[2].is_moved());
- BOOST_CHECK(!cb1[3].is_moved());
- BOOST_CHECK(!cb1[4].is_moved());
- BOOST_CHECK(!cb1[5].is_moved());
- BOOST_CHECK(!cb1[6].is_moved());
- BOOST_CHECK(!cb1[7].is_moved());
- BOOST_CHECK(cb1[0].value() == 6);
- BOOST_CHECK(cb1[1].value() == 5);
- BOOST_CHECK(cb1[2].value() == 4);
- BOOST_CHECK(cb1[3].value() == 2);
- BOOST_CHECK(cb1[4].value() == 1);
- BOOST_CHECK(cb1[5].value() == 3);
- BOOST_CHECK(cb1[6].value() == 8);
- BOOST_CHECK(cb1[7].value() == 7);
-
- cb1.rset_capacity(101);
- BOOST_CHECK(!cb1[0].is_moved());
- BOOST_CHECK(!cb1[1].is_moved());
- BOOST_CHECK(!cb1[2].is_moved());
- BOOST_CHECK(!cb1[3].is_moved());
- BOOST_CHECK(!cb1[4].is_moved());
- BOOST_CHECK(!cb1[5].is_moved());
- BOOST_CHECK(!cb1[6].is_moved());
- BOOST_CHECK(!cb1[7].is_moved());
- BOOST_CHECK(cb1[0].value() == 6);
- BOOST_CHECK(cb1[1].value() == 5);
- BOOST_CHECK(cb1[2].value() == 4);
- BOOST_CHECK(cb1[3].value() == 2);
- BOOST_CHECK(cb1[4].value() == 1);
- BOOST_CHECK(cb1[5].value() == 3);
- BOOST_CHECK(cb1[6].value() == 8);
- BOOST_CHECK(cb1[7].value() == 7);
-
- cb1.set_capacity(2);
- BOOST_CHECK(!cb1[0].is_moved());
- BOOST_CHECK(!cb1[1].is_moved());
- BOOST_CHECK(cb1[0].value() == 6);
- BOOST_CHECK(cb1[1].value() == 5);
-
- cb1.rset_capacity(1);
- BOOST_CHECK(!cb1[0].is_moved());
- BOOST_CHECK(cb1[0].value() == 5);
-#endif
+void move_container_values_except() {
+ move_container_values_impl<noncopyable_movable_except_t>();
 }
 
-void move_container_values_resetting() {
+template <class T>
+void move_container_values_resetting_impl() {
+ typedef T noncopyable_movable_test_t;
     CB_CONTAINER<noncopyable_movable_test_t> cb1(1);
     noncopyable_movable_test_t var;
     cb1.push_back();
@@ -1036,6 +832,14 @@
     BOOST_CHECK(cb1[0].value() == val);
 }
 
+void move_container_values_resetting_except() {
+ move_container_values_resetting_impl<noncopyable_movable_except_t>();
+}
+
+void move_container_values_resetting_noexcept() {
+ move_container_values_resetting_impl<noncopyable_movable_noexcept_t>();
+}
+
 // test main
 test_suite* init_unit_test_suite(int /*argc*/, char* /*argv*/[]) {
 
@@ -1053,9 +857,9 @@
     tests->add(BOOST_TEST_CASE(&iterator_comparison_test));
     tests->add(BOOST_TEST_CASE(&iterator_invalidation_test));
     tests->add(BOOST_TEST_CASE(&exception_safety_test));
- tests->add(BOOST_TEST_CASE(&move_container_on_cpp11));
- tests->add(BOOST_TEST_CASE(&move_container_values));
- tests->add(BOOST_TEST_CASE(&move_container_values_resetting));
+ tests->add(BOOST_TEST_CASE(&move_container_values_except));
+ tests->add(BOOST_TEST_CASE(&move_container_values_resetting_except));
+ tests->add(BOOST_TEST_CASE(&move_container_values_resetting_noexcept));
 
     return tests;
 }

Modified: trunk/libs/circular_buffer/test/common.ipp
==============================================================================
--- trunk/libs/circular_buffer/test/common.ipp Thu Jul 11 06:27:49 2013 (r85002)
+++ trunk/libs/circular_buffer/test/common.ipp 2013-07-11 10:55:24 EDT (Thu, 11 Jul 2013) (r85003)
@@ -1,11 +1,16 @@
 // Common tests for the circular buffer and its adaptor.
 
 // Copyright (c) 2003-2008 Jan Gaspar
+// Copyright (c) 2013 Antony Polukhin
 
 // Use, modification, and distribution is subject to the Boost Software
 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
+#include <boost/type_traits/is_nothrow_move_constructible.hpp>
+#include <boost/type_traits/is_nothrow_move_assignable.hpp>
+#include <boost/type_traits/has_nothrow_constructor.hpp>
+
 void generic_test(CB_CONTAINER<MyInteger>& cb) {
 
     vector<int> v;
@@ -1949,6 +1954,350 @@
 int MyInteger::ms_exception_trigger = 0;
 int InstanceCounter::ms_count = 0;
 
+void move_container_on_cpp11() {
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ CB_CONTAINER<MyInteger> cb1(10);
+ cb1.push_back(1);
+ cb1.push_back(2);
+ cb1.push_back(3);
+ cb1.push_back(4);
+ cb1.push_back(5);
+ cb1.push_back(6);
+
+ // Checking move constructor
+ CB_CONTAINER<MyInteger> cb2(static_cast<CB_CONTAINER<MyInteger>&& >(cb1));
+ CB_CONTAINER<MyInteger>::iterator it2 = cb2.begin() + 1;
+
+ BOOST_CHECK(cb1.empty());
+ BOOST_CHECK(!cb2.empty());
+ BOOST_CHECK(it2[0] == 2);
+ BOOST_CHECK(it2[-1] == 1);
+ BOOST_CHECK(it2[2] == 4);
+
+ // Checking move assignment
+ cb1 = static_cast<CB_CONTAINER<MyInteger>&& >(cb2);
+ CB_CONTAINER<MyInteger>::iterator it1 = cb1.begin() + 1;
+
+ BOOST_CHECK(!cb1.empty());
+ BOOST_CHECK(cb2.empty());
+ BOOST_CHECK(it1[0] == 2);
+ BOOST_CHECK(it1[-1] == 1);
+ BOOST_CHECK(it1[2] == 4);
+#endif
+}
+
+
+struct noncopyable_movable_except_t
+ : private boost::noncopyable // required, until there will be no support for is_copy_constructible added to Boost.Move
+{
+private:
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(noncopyable_movable_except_t)
+ bool is_moved_;
+ int value_;
+public:
+ static int next_value;
+
+ explicit noncopyable_movable_except_t()
+ : is_moved_(false)
+ , value_(next_value ++)
+ {}
+
+ noncopyable_movable_except_t(BOOST_RV_REF(noncopyable_movable_except_t) x) {
+ is_moved_ = x.is_moved_;
+ value_ = x.value_;
+ x.is_moved_ = true;
+ }
+
+ noncopyable_movable_except_t& operator=(BOOST_RV_REF(noncopyable_movable_except_t) x) {
+ is_moved_ = x.is_moved_;
+ value_ = x.value_;
+ x.is_moved_ = true;
+ return *this;
+ }
+
+ bool is_moved() const {
+ return is_moved_;
+ }
+
+ int value() const {
+ return value_;
+ }
+
+ void reinit() { is_moved_ = false; value_ = next_value ++; }
+};
+
+struct noncopyable_movable_noexcept_t
+ : private boost::noncopyable // required, until there will be no support for is_copy_constructible added to Boost.Move
+{
+private:
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(noncopyable_movable_noexcept_t)
+ bool is_moved_;
+ int value_;
+public:
+ static int next_value;
+
+ explicit noncopyable_movable_noexcept_t()
+ : is_moved_(false)
+ , value_(next_value ++)
+ {}
+
+ noncopyable_movable_noexcept_t(BOOST_RV_REF(noncopyable_movable_noexcept_t) x) BOOST_NOEXCEPT {
+ is_moved_ = x.is_moved_;
+ value_ = x.value_;
+ x.is_moved_ = true;
+ }
+
+ noncopyable_movable_noexcept_t& operator=(BOOST_RV_REF(noncopyable_movable_noexcept_t) x) BOOST_NOEXCEPT {
+ is_moved_ = x.is_moved_;
+ value_ = x.value_;
+ x.is_moved_ = true;
+ return *this;
+ }
+
+ bool is_moved() const {
+ return is_moved_;
+ }
+
+ int value() const {
+ return value_;
+ }
+
+ void reinit() { is_moved_ = false; value_ = next_value ++; }
+};
+
+#ifdef BOOST_NO_CXX11_NOEXCEPT
+namespace boost {
+ template <>
+ struct is_nothrow_move_constructible<noncopyable_movable_noexcept_t>
+ : boost::true_type
+ {};
+}
+#endif
+
+int noncopyable_movable_noexcept_t::next_value = 1;
+int noncopyable_movable_except_t::next_value = 1;
+
+template <class T>
+void move_container_values_impl() {
+ typedef T noncopyable_movable_test_t;
+ noncopyable_movable_test_t::next_value = 1;
+
+ CB_CONTAINER<noncopyable_movable_test_t> cb1(40);
+ noncopyable_movable_test_t var;
+ cb1.push_back(boost::move(var));
+ BOOST_CHECK(!cb1.back().is_moved());
+ BOOST_CHECK(cb1.back().value() == 1);
+ BOOST_CHECK(var.is_moved());
+ BOOST_CHECK(cb1.size() == 1);
+
+ var.reinit();
+ cb1.push_front(boost::move(var));
+ BOOST_CHECK(!cb1.front().is_moved());
+ BOOST_CHECK(cb1.front().value() == 2);
+ BOOST_CHECK(var.is_moved());
+ BOOST_CHECK(cb1.size() == 2);
+
+ cb1.push_back();
+ BOOST_CHECK(!cb1.back().is_moved());
+ BOOST_CHECK(cb1.back().value() == 3);
+ BOOST_CHECK(cb1.size() == 3);
+
+ cb1.push_front();
+ BOOST_CHECK(!cb1.front().is_moved());
+ BOOST_CHECK(cb1.front().value() == 4);
+ BOOST_CHECK(cb1.size() == 4);
+
+ cb1.insert(cb1.begin());
+ BOOST_CHECK(!cb1.front().is_moved());
+ BOOST_CHECK(cb1.front().value() == 5);
+ BOOST_CHECK(cb1.size() == 5);
+
+ var.reinit();
+ cb1.insert(cb1.begin(), boost::move(var));
+ BOOST_CHECK(!cb1.front().is_moved());
+ BOOST_CHECK(cb1.front().value() == 6);
+ BOOST_CHECK(cb1.size() == 6);
+
+ cb1.rinsert(cb1.begin());
+ BOOST_CHECK(!cb1.front().is_moved());
+ BOOST_CHECK(cb1.front().value() == 7);
+ BOOST_CHECK(cb1.size() == 7);
+
+ var.reinit();
+ cb1.rinsert(cb1.begin(), boost::move(var));
+ BOOST_CHECK(!cb1.front().is_moved());
+ BOOST_CHECK(cb1.front().value() == 8);
+ BOOST_CHECK(cb1.size() == 8);
+
+
+ BOOST_CHECK(cb1[0].value() == 8);
+ BOOST_CHECK(cb1[1].value() == 7);
+ BOOST_CHECK(cb1[2].value() == 6);
+ BOOST_CHECK(cb1[3].value() == 5);
+ BOOST_CHECK(cb1[4].value() == 4);
+ BOOST_CHECK(cb1[5].value() == 2);
+ BOOST_CHECK(cb1[6].value() == 1);
+ BOOST_CHECK(cb1[7].value() == 3);
+ cb1.rotate(cb1.begin() + 2);
+ BOOST_CHECK(cb1[0].value() == 6);
+ BOOST_CHECK(cb1[1].value() == 5);
+ BOOST_CHECK(cb1[2].value() == 4);
+ BOOST_CHECK(cb1[3].value() == 2);
+ BOOST_CHECK(cb1[4].value() == 1);
+ BOOST_CHECK(cb1[5].value() == 3);
+ BOOST_CHECK(cb1[6].value() == 8);
+ BOOST_CHECK(cb1[7].value() == 7);
+
+ BOOST_CHECK(!cb1[0].is_moved());
+ BOOST_CHECK(!cb1[1].is_moved());
+ BOOST_CHECK(!cb1[2].is_moved());
+ BOOST_CHECK(!cb1[3].is_moved());
+ BOOST_CHECK(!cb1[4].is_moved());
+ BOOST_CHECK(!cb1[5].is_moved());
+ BOOST_CHECK(!cb1[6].is_moved());
+ BOOST_CHECK(!cb1[7].is_moved());
+
+ cb1.linearize();
+ BOOST_CHECK(!cb1[0].is_moved());
+ BOOST_CHECK(!cb1[1].is_moved());
+ BOOST_CHECK(!cb1[2].is_moved());
+ BOOST_CHECK(!cb1[3].is_moved());
+ BOOST_CHECK(!cb1[4].is_moved());
+ BOOST_CHECK(!cb1[5].is_moved());
+ BOOST_CHECK(!cb1[6].is_moved());
+ BOOST_CHECK(!cb1[7].is_moved());
+ BOOST_CHECK(cb1[0].value() == 6);
+ BOOST_CHECK(cb1[1].value() == 5);
+ BOOST_CHECK(cb1[2].value() == 4);
+ BOOST_CHECK(cb1[3].value() == 2);
+ BOOST_CHECK(cb1[4].value() == 1);
+ BOOST_CHECK(cb1[5].value() == 3);
+ BOOST_CHECK(cb1[6].value() == 8);
+ BOOST_CHECK(cb1[7].value() == 7);
+
+ cb1.erase(cb1.begin());
+ BOOST_CHECK(!cb1[0].is_moved());
+ BOOST_CHECK(!cb1[1].is_moved());
+ BOOST_CHECK(!cb1[2].is_moved());
+ BOOST_CHECK(!cb1[3].is_moved());
+ BOOST_CHECK(!cb1[4].is_moved());
+ BOOST_CHECK(!cb1[5].is_moved());
+ BOOST_CHECK(!cb1[6].is_moved());
+ BOOST_CHECK(cb1[0].value() == 5);
+ BOOST_CHECK(cb1[1].value() == 4);
+ BOOST_CHECK(cb1[2].value() == 2);
+ BOOST_CHECK(cb1[3].value() == 1);
+ BOOST_CHECK(cb1[4].value() == 3);
+ BOOST_CHECK(cb1[5].value() == 8);
+ BOOST_CHECK(cb1[6].value() == 7);
+
+ cb1.rerase(cb1.begin());
+ BOOST_CHECK(!cb1[0].is_moved());
+ BOOST_CHECK(!cb1[1].is_moved());
+ BOOST_CHECK(!cb1[2].is_moved());
+ BOOST_CHECK(!cb1[3].is_moved());
+ BOOST_CHECK(!cb1[4].is_moved());
+ BOOST_CHECK(!cb1[5].is_moved());
+ BOOST_CHECK(cb1[0].value() == 4);
+ BOOST_CHECK(cb1[1].value() == 2);
+ BOOST_CHECK(cb1[2].value() == 1);
+ BOOST_CHECK(cb1[3].value() == 3);
+ BOOST_CHECK(cb1[4].value() == 8);
+ BOOST_CHECK(cb1[5].value() == 7);
+
+ cb1.erase(cb1.begin(), cb1.begin() + 1);
+ BOOST_CHECK(!cb1[0].is_moved());
+ BOOST_CHECK(!cb1[1].is_moved());
+ BOOST_CHECK(!cb1[2].is_moved());
+ BOOST_CHECK(!cb1[3].is_moved());
+ BOOST_CHECK(!cb1[4].is_moved());
+ BOOST_CHECK(cb1[0].value() == 2);
+ BOOST_CHECK(cb1[1].value() == 1);
+ BOOST_CHECK(cb1[2].value() == 3);
+ BOOST_CHECK(cb1[3].value() == 8);
+ BOOST_CHECK(cb1[4].value() == 7);
+
+ cb1.rerase(cb1.begin(), cb1.begin() + 1);
+ BOOST_CHECK(!cb1[0].is_moved());
+ BOOST_CHECK(!cb1[1].is_moved());
+ BOOST_CHECK(!cb1[2].is_moved());
+ BOOST_CHECK(!cb1[3].is_moved());
+ BOOST_CHECK(cb1[0].value() == 1);
+ BOOST_CHECK(cb1[1].value() == 3);
+ BOOST_CHECK(cb1[2].value() == 8);
+ BOOST_CHECK(cb1[3].value() == 7);
+}
+
+void move_container_values_noexcept() {
+ move_container_values_impl<noncopyable_movable_noexcept_t>();
+
+ typedef noncopyable_movable_noexcept_t noncopyable_movable_test_t;
+ noncopyable_movable_test_t::next_value = 1;
+ CB_CONTAINER<noncopyable_movable_test_t> cb1(40);
+ cb1.push_back();
+ cb1.push_back();
+ cb1.push_back();
+ cb1.push_back();
+ cb1.push_back();
+ cb1.push_back();
+ cb1.push_back();
+ cb1.push_back();
+
+ cb1.set_capacity(100);
+ BOOST_CHECK(!cb1[0].is_moved());
+ BOOST_CHECK(!cb1[1].is_moved());
+ BOOST_CHECK(!cb1[2].is_moved());
+ BOOST_CHECK(!cb1[3].is_moved());
+ BOOST_CHECK(!cb1[4].is_moved());
+ BOOST_CHECK(!cb1[5].is_moved());
+ BOOST_CHECK(!cb1[6].is_moved());
+ BOOST_CHECK(!cb1[7].is_moved());
+ BOOST_CHECK(cb1[0].value() == 1);
+ BOOST_CHECK(cb1[1].value() == 2);
+ BOOST_CHECK(cb1[2].value() == 3);
+ BOOST_CHECK(cb1[3].value() == 4);
+ BOOST_CHECK(cb1[4].value() == 5);
+ BOOST_CHECK(cb1[5].value() == 6);
+ BOOST_CHECK(cb1[6].value() == 7);
+ BOOST_CHECK(cb1[7].value() == 8);
+
+ cb1.rset_capacity(101);
+ BOOST_CHECK(!cb1[0].is_moved());
+ BOOST_CHECK(!cb1[1].is_moved());
+ BOOST_CHECK(!cb1[2].is_moved());
+ BOOST_CHECK(!cb1[3].is_moved());
+ BOOST_CHECK(!cb1[4].is_moved());
+ BOOST_CHECK(!cb1[5].is_moved());
+ BOOST_CHECK(!cb1[6].is_moved());
+ BOOST_CHECK(!cb1[7].is_moved());
+ BOOST_CHECK(cb1[0].value() == 1);
+ BOOST_CHECK(cb1[1].value() == 2);
+ BOOST_CHECK(cb1[2].value() == 3);
+ BOOST_CHECK(cb1[3].value() == 4);
+ BOOST_CHECK(cb1[4].value() == 5);
+ BOOST_CHECK(cb1[5].value() == 6);
+ BOOST_CHECK(cb1[6].value() == 7);
+ BOOST_CHECK(cb1[7].value() == 8);
+
+ cb1.set_capacity(2);
+ BOOST_CHECK(!cb1[0].is_moved());
+ BOOST_CHECK(!cb1[1].is_moved());
+ BOOST_CHECK(cb1[0].value() == 1);
+ BOOST_CHECK(cb1[1].value() == 2);
+
+ cb1.rset_capacity(1);
+ BOOST_CHECK(!cb1[0].is_moved());
+ BOOST_CHECK(cb1[0].value() == 2);
+}
+
+void check_containers_exception_specifications() {
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ BOOST_CHECK(boost::is_nothrow_move_constructible<CB_CONTAINER<int> >::value);
+ BOOST_CHECK(boost::is_nothrow_move_assignable<CB_CONTAINER<int> >::value);
+ BOOST_CHECK(boost::has_nothrow_constructor<CB_CONTAINER<int> >::value);
+#endif
+}
+
 // add common tests into a test suite
 void add_common_tests(test_suite* tests) {
     tests->add(BOOST_TEST_CASE(&basic_test));
@@ -1994,4 +2343,8 @@
     tests->add(BOOST_TEST_CASE(&element_destruction_test));
     tests->add(BOOST_TEST_CASE(&const_methods_test));
     tests->add(BOOST_TEST_CASE(&rotate_test));
+ tests->add(BOOST_TEST_CASE(&move_container_on_cpp11));
+ tests->add(BOOST_TEST_CASE(&move_container_values_noexcept));
+ tests->add(BOOST_TEST_CASE(&check_containers_exception_specifications));
 }
+


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk