Compare commits

..

4 Commits

Author SHA1 Message Date
Beman Dawes
3916e22673 Release 1.45.0 beta 1
[SVN r66473]
2010-11-09 18:22:33 +00:00
Jan Gaspar
2bd298dec7 circular_buffer: applied patch to remove workaround for DEC C++ compiler - now all compilers will use this->invalidate_iterators_except
[SVN r61570]
2010-04-26 09:40:08 +00:00
Jan Gaspar
65810242ee circular_buffer: updated documentation
[SVN r60691]
2010-03-18 12:39:52 +00:00
Jan Gaspar
0282b8ee74 circular_buffer: constant complexity of clear method and destructor; added erase_begin and erase_end methods
[SVN r58681]
2010-01-04 15:54:37 +00:00
6 changed files with 595 additions and 41 deletions

View File

@@ -65,6 +65,9 @@
<dt>
<a href="#debug">Debug Support</a>
</dt>
<dt>
<a href="#interprocess">Compatibility with Interprocess library</a>
</dt>
<dt>
<a href="#examples">More Examples</a>
</dt>
@@ -338,6 +341,8 @@ public:
iterator <a href="#classboost_1_1circular__buffer_1b6d4ae77d7445f844e30e78592f1e06f">rerase</a>(iterator pos);
iterator <a href=
"#classboost_1_1circular__buffer_1b0f98ae303584ded5397f067bbfc911f">rerase</a>(iterator first, iterator last);
void <a href="#classboost_1_1circular__buffer_1b25d379cf66ace025036a47ddb344abd">erase_begin</a>(size_type n);
void <a href="#classboost_1_1circular__buffer_17485ee7f58b01363170114f2123a48d7">erase_end</a>(size_type n);
void <a href="#classboost_1_1circular__buffer_1826f5770a40b8b752eb9587378464d1e">clear</a>();
};
@@ -592,7 +597,18 @@ template &lt;class T, class Alloc&gt;
</p>
<p>
The debug support is enabled only in the debug mode (when the <code>NDEBUG</code> is not defined). It can also be
explicitly disabled by defining <code>BOOST_CB_DISABLE_DEBUG</code> macro.
explicitly disabled (only for <code>circular_buffer</code>) by defining <code>BOOST_CB_DISABLE_DEBUG</code>
macro.
</p>
<h2>
<a name="intreprocess" id="interprocess">Compatibility with Interprocess library</a>
</h2>
<p>
The <code>circular_buffer</code> is compatible with the <a href="../../../doc/html/interprocess.html">Boost
Interprocess</a> library used for interprocess communication. Considering that the <code>circular_buffer</code>'s
debug support relies on 'raw' pointers - which is not permited by the Interprocess library - the code has to
compiled with <code>-DBOOST_CB_DISABLE_DEBUG</code> or <code>-DNDEBUG</code> (which disables the
<a href="#debug">Debug Support</a>). Not doing that will cause the compilation to fail.
</p>
<h2>
<a name="examples" id="examples">More Examples</a>
@@ -1607,7 +1623,7 @@ template &lt;class T, class Alloc&gt;
<b>Complexity:</b>
</dt>
<dd>
Linear (in the size of the <code>circular_buffer</code>).
Constant (in the size of the <code>circular_buffer</code>) for scalar types; linear for other types.
</dd>
</dl>
<dl>
@@ -6110,7 +6126,10 @@ template &lt;class T, class Alloc&gt;
"#classboost_1_1circular__buffer_1b6d4ae77d7445f844e30e78592f1e06f">rerase(iterator)</a></code>,
<code><a href="#classboost_1_1circular__buffer_1b0f98ae303584ded5397f067bbfc911f">rerase(iterator,
iterator)</a></code>, <code><a href=
"#classboost_1_1circular__buffer_1826f5770a40b8b752eb9587378464d1e">clear()</a></code>
"#classboost_1_1circular__buffer_1b25d379cf66ace025036a47ddb344abd">erase_begin(size_type)</a></code>,
<code><a href=
"#classboost_1_1circular__buffer_17485ee7f58b01363170114f2123a48d7">erase_end(size_type)</a></code>,
<code><a href="#classboost_1_1circular__buffer_1826f5770a40b8b752eb9587378464d1e">clear()</a></code>
</dd>
</dl>
</td>
@@ -6222,7 +6241,10 @@ template &lt;class T, class Alloc&gt;
"#classboost_1_1circular__buffer_1b6d4ae77d7445f844e30e78592f1e06f">rerase(iterator)</a></code>,
<code><a href="#classboost_1_1circular__buffer_1b0f98ae303584ded5397f067bbfc911f">rerase(iterator,
iterator)</a></code>, <code><a href=
"#classboost_1_1circular__buffer_1826f5770a40b8b752eb9587378464d1e">clear()</a></code>
"#classboost_1_1circular__buffer_1b25d379cf66ace025036a47ddb344abd">erase_begin(size_type)</a></code>,
<code><a href=
"#classboost_1_1circular__buffer_17485ee7f58b01363170114f2123a48d7">erase_end(size_type)</a></code>,
<code><a href="#classboost_1_1circular__buffer_1826f5770a40b8b752eb9587378464d1e">clear()</a></code>
</dd>
</dl>
</td>
@@ -6335,7 +6357,10 @@ template &lt;class T, class Alloc&gt;
iterator)</a></code>, <code><a href=
"#classboost_1_1circular__buffer_1b0f98ae303584ded5397f067bbfc911f">rerase(iterator,
iterator)</a></code>, <code><a href=
"#classboost_1_1circular__buffer_1826f5770a40b8b752eb9587378464d1e">clear()</a></code>
"#classboost_1_1circular__buffer_1b25d379cf66ace025036a47ddb344abd">erase_begin(size_type)</a></code>,
<code><a href=
"#classboost_1_1circular__buffer_17485ee7f58b01363170114f2123a48d7">erase_end(size_type)</a></code>,
<code><a href="#classboost_1_1circular__buffer_1826f5770a40b8b752eb9587378464d1e">clear()</a></code>
</dd>
</dl>
</td>
@@ -6460,6 +6485,219 @@ template &lt;class T, class Alloc&gt;
<code><a href="#classboost_1_1circular__buffer_1a96415389509a18bd7d7b5d8e4dda9bd">erase(iterator,
iterator)</a></code>, <code><a href=
"#classboost_1_1circular__buffer_1b6d4ae77d7445f844e30e78592f1e06f">rerase(iterator)</a></code>,
<code><a href=
"#classboost_1_1circular__buffer_1b25d379cf66ace025036a47ddb344abd">erase_begin(size_type)</a></code>,
<code><a href=
"#classboost_1_1circular__buffer_17485ee7f58b01363170114f2123a48d7">erase_end(size_type)</a></code>,
<code><a href="#classboost_1_1circular__buffer_1826f5770a40b8b752eb9587378464d1e">clear()</a></code>
</dd>
</dl>
</td>
</tr>
<tr>
<td>
<a id="classboost_1_1circular__buffer_1b25d379cf66ace025036a47ddb344abd" name=
"classboost_1_1circular__buffer_1b25d379cf66ace025036a47ddb344abd"></a><code><b>void erase_begin(<a href=
"#classboost_1_1circular__buffer_19ba12c0142a21a7d960877c22fa3ea00">size_type</a> n);</b></code><br>
<br>
Remove first <code>n</code> elements (with constant complexity for scalar types).
<dl>
<dt>
<b>Precondition:</b>
</dt>
<dd>
<code>n &lt;= <a href=
"#classboost_1_1circular__buffer_15fa0edd153e2591dd6bf070eb663ee32">size()</a></code>
</dd>
</dl>
<dl>
<dt>
<b>Effect:</b>
</dt>
<dd>
The <code>n</code> elements at the beginning of the <code>circular_buffer</code> will be removed.
</dd>
</dl>
<dl>
<dt>
<b>Parameter(s):</b>
</dt>
<dd>
<dl compact>
<dt>
<code>n</code>
</dt>
<dd>
The number of elements to be removed.
</dd>
</dl>
</dd>
</dl>
<dl>
<dt>
<b>Throws:</b>
</dt>
<dd>
Whatever <code>T::operator = (const T&amp;)</code> throws. (Does not throw anything in case of
scalars.)
</dd>
</dl>
<dl>
<dt>
<b>Exception Safety:</b>
</dt>
<dd>
Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything. (I.e. no throw
in case of scalars.)
</dd>
</dl>
<dl>
<dt>
<b>Iterator Invalidation:</b>
</dt>
<dd>
Invalidates iterators pointing to the first <code>n</code> erased elements.
</dd>
</dl>
<dl>
<dt>
<b>Complexity:</b>
</dt>
<dd>
Constant (in <code>n</code>) for scalar types; linear for other types.
</dd>
</dl>
<dl>
<dt>
<b>Note:</b>
</dt>
<dd>
This method has been specially designed for types which do not require an explicit destructruction
(e.g. integer, float or a pointer). For these scalar types a call to a destructor is not required which
makes it possible to implement the "erase from beginning" operation with a constant complexity. For
non-sacalar types the complexity is linear (hence the explicit destruction is needed) and the
implementation is actually equivalent to <code><a href=
"#classboost_1_1circular__buffer_1b0f98ae303584ded5397f067bbfc911f">rerase(begin(), begin() +
n)</a></code>.
</dd>
</dl>
<dl>
<dt>
<b>See Also:</b>
</dt>
<dd>
<code><a href=
"#classboost_1_1circular__buffer_197155de712db1759e1698455b49a0be3">erase(iterator)</a></code>,
<code><a href="#classboost_1_1circular__buffer_1a96415389509a18bd7d7b5d8e4dda9bd">erase(iterator,
iterator)</a></code>, <code><a href=
"#classboost_1_1circular__buffer_1b6d4ae77d7445f844e30e78592f1e06f">rerase(iterator)</a></code>,
<code><a href="#classboost_1_1circular__buffer_1b0f98ae303584ded5397f067bbfc911f">rerase(iterator,
iterator)</a></code>, <code><a href=
"#classboost_1_1circular__buffer_17485ee7f58b01363170114f2123a48d7">erase_end(size_type)</a></code>,
<code><a href="#classboost_1_1circular__buffer_1826f5770a40b8b752eb9587378464d1e">clear()</a></code>
</dd>
</dl>
</td>
</tr>
<tr>
<td>
<a id="classboost_1_1circular__buffer_17485ee7f58b01363170114f2123a48d7" name=
"classboost_1_1circular__buffer_17485ee7f58b01363170114f2123a48d7"></a><code><b>void erase_end(<a href=
"#classboost_1_1circular__buffer_19ba12c0142a21a7d960877c22fa3ea00">size_type</a> n);</b></code><br>
<br>
Remove last <code>n</code> elements (with constant complexity for scalar types).
<dl>
<dt>
<b>Precondition:</b>
</dt>
<dd>
<code>n &lt;= <a href=
"#classboost_1_1circular__buffer_15fa0edd153e2591dd6bf070eb663ee32">size()</a></code>
</dd>
</dl>
<dl>
<dt>
<b>Effect:</b>
</dt>
<dd>
The <code>n</code> elements at the end of the <code>circular_buffer</code> will be removed.
</dd>
</dl>
<dl>
<dt>
<b>Parameter(s):</b>
</dt>
<dd>
<dl compact>
<dt>
<code>n</code>
</dt>
<dd>
The number of elements to be removed.
</dd>
</dl>
</dd>
</dl>
<dl>
<dt>
<b>Throws:</b>
</dt>
<dd>
Whatever <code>T::operator = (const T&amp;)</code> throws. (Does not throw anything in case of
scalars.)
</dd>
</dl>
<dl>
<dt>
<b>Exception Safety:</b>
</dt>
<dd>
Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything. (I.e. no throw
in case of scalars.)
</dd>
</dl>
<dl>
<dt>
<b>Iterator Invalidation:</b>
</dt>
<dd>
Invalidates iterators pointing to the last <code>n</code> erased elements.
</dd>
</dl>
<dl>
<dt>
<b>Complexity:</b>
</dt>
<dd>
Constant (in <code>n</code>) for scalar types; linear for other types.
</dd>
</dl>
<dl>
<dt>
<b>Note:</b>
</dt>
<dd>
This method has been specially designed for types which do not require an explicit destructruction
(e.g. integer, float or a pointer). For these scalar types a call to a destructor is not required which
makes it possible to implement the "erase from end" operation with a constant complexity. For
non-sacalar types the complexity is linear (hence the explicit destruction is needed) and the
implementation is actually equivalent to <code><a href=
"#classboost_1_1circular__buffer_1a96415389509a18bd7d7b5d8e4dda9bd">erase(end() - n, end())</a></code>.
</dd>
</dl>
<dl>
<dt>
<b>See Also:</b>
</dt>
<dd>
<code><a href=
"#classboost_1_1circular__buffer_197155de712db1759e1698455b49a0be3">erase(iterator)</a></code>,
<code><a href="#classboost_1_1circular__buffer_1a96415389509a18bd7d7b5d8e4dda9bd">erase(iterator,
iterator)</a></code>, <code><a href=
"#classboost_1_1circular__buffer_1b6d4ae77d7445f844e30e78592f1e06f">rerase(iterator)</a></code>,
<code><a href="#classboost_1_1circular__buffer_1b0f98ae303584ded5397f067bbfc911f">rerase(iterator,
iterator)</a></code>, <code><a href=
"#classboost_1_1circular__buffer_1b25d379cf66ace025036a47ddb344abd">erase_begin(size_type)</a></code>,
<code><a href="#classboost_1_1circular__buffer_1826f5770a40b8b752eb9587378464d1e">clear()</a></code>
</dd>
</dl>
@@ -6511,7 +6749,7 @@ template &lt;class T, class Alloc&gt;
<b>Complexity:</b>
</dt>
<dd>
Linear (in the size of the <code>circular_buffer</code>).
Constant (in the size of the <code>circular_buffer</code>) for scalar types; linear for other types.
</dd>
</dl>
<dl>
@@ -6527,7 +6765,10 @@ template &lt;class T, class Alloc&gt;
iterator)</a></code>, <code><a href=
"#classboost_1_1circular__buffer_1b6d4ae77d7445f844e30e78592f1e06f">rerase(iterator)</a></code>,
<code><a href="#classboost_1_1circular__buffer_1b0f98ae303584ded5397f067bbfc911f">rerase(iterator,
iterator)</a></code>
iterator)</a></code>, <code><a href=
"#classboost_1_1circular__buffer_1b25d379cf66ace025036a47ddb344abd">erase_begin(size_type)</a></code>,
<code><a href=
"#classboost_1_1circular__buffer_17485ee7f58b01363170114f2123a48d7">erase_end(size_type)</a></code>
</dd>
</dl>
</td>
@@ -7123,6 +7364,23 @@ template &lt;class T, class Alloc&gt;
<a name="relnotes" id="relnotes">Release Notes</a>
</h2>
<dl>
<dd>
<h3>
Boost 1.42
</h3>
</dd>
<dd>
<ul>
<li>Added methods <code>erase_begin(size_type)</code> and <code>erase_end(size_type)</code> with constant
complexity for such types of stored elements which do not need an explicit destruction e.g. <code>int</code>
or <code>double</code>.
</li>
<li>Similarly changed implementation of the <code>clear()</code> method and the destructor so their
complexity is now constant for such types of stored elements which do not require an explicit destruction
(the complexity for other types remains linear).
</li>
</ul>
</dd>
<dd>
<h3>
Boost 1.37

View File

@@ -68,7 +68,7 @@ http://www.boost.org/LICENSE_1_0.txt)
</xsl:apply-templates>
</xsl:if>
</xsl:for-each>
<xsl:for-each select="$current[string-length(normalize-space(briefdescription)) &gt; 0]">
<xsl:for-each select="$current[string-length(normalize-space(briefdescription)) &gt; 0 and normalize-space(briefdescription) != 'no-comment']">
<xsl:apply-templates select="." mode="synopsis"/>
</xsl:for-each>
</xsl:template>
@@ -96,7 +96,7 @@ http://www.boost.org/LICENSE_1_0.txt)
</xsl:template>
<xsl:template name="member-functions-details">
<xsl:for-each select="sectiondef[@kind='public-func']/memberdef[type != '' and string-length(normalize-space(briefdescription)) &gt; 0]">
<xsl:for-each select="sectiondef[@kind='public-func']/memberdef[type != '' and string-length(normalize-space(briefdescription)) &gt; 0 and normalize-space(briefdescription) != 'no-comment']">
<xsl:apply-templates select="." mode="description"/>
</xsl:for-each>
</xsl:template>

View File

@@ -20,6 +20,7 @@
#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 <algorithm>
#include <utility>
#include <deque>
@@ -393,7 +394,7 @@ public:
Does not invalidate any iterators.
\par Complexity
Constant (in the size of the <code>circular_buffer</code>).
\sa <code>operator[]</code>
\sa <code>\link operator[](size_type) operator[] \endlink</code>
*/
reference at(size_type index) {
check_position(index);
@@ -1165,7 +1166,7 @@ public:
Invalidates all iterators pointing to the <code>circular_buffer</code> (including iterators equal to
<code>end()</code>).
\par Complexity
Linear (in the size of the <code>circular_buffer</code>).
Constant (in the size of the <code>circular_buffer</code>) for scalar types; linear for other types.
\sa <code>clear()</code>
*/
~circular_buffer() {
@@ -1231,7 +1232,8 @@ public:
<code>end()</code>).
\par Complexity
Linear (in the <code>n</code>).
\sa <code>operator=</code>, <code>\link assign(capacity_type, size_type, param_value_type)
\sa <code>\link operator=(const circular_buffer&) operator=\endlink</code>,
<code>\link assign(capacity_type, size_type, param_value_type)
assign(capacity_type, size_type, const_reference)\endlink</code>,
<code>assign(InputIterator, InputIterator)</code>,
<code>assign(capacity_type, InputIterator, InputIterator)</code>
@@ -1260,8 +1262,9 @@ public:
<code>end()</code>).
\par Complexity
Linear (in the <code>n</code>).
\sa <code>operator=</code>, <code>\link assign(size_type, param_value_type)
assign(size_type, const_reference)\endlink</code>, <code>assign(InputIterator, InputIterator)</code>,
\sa <code>\link operator=(const circular_buffer&) operator=\endlink</code>,
<code>\link assign(size_type, param_value_type) assign(size_type, const_reference)\endlink</code>,
<code>assign(InputIterator, InputIterator)</code>,
<code>assign(capacity_type, InputIterator, InputIterator)</code>
*/
void assign(capacity_type buffer_capacity, size_type n, param_value_type item) {
@@ -1291,8 +1294,8 @@ public:
<code>end()</code>).
\par Complexity
Linear (in the <code>std::distance(first, last)</code>).
\sa <code>operator=</code>, <code>\link assign(size_type, param_value_type)
assign(size_type, const_reference)\endlink</code>,
\sa <code>\link operator=(const circular_buffer&) operator=\endlink</code>,
<code>\link assign(size_type, param_value_type) assign(size_type, const_reference)\endlink</code>,
<code>\link assign(capacity_type, size_type, param_value_type)
assign(capacity_type, size_type, const_reference)\endlink</code>,
<code>assign(capacity_type, InputIterator, InputIterator)</code>
@@ -1330,8 +1333,8 @@ public:
Linear (in <code>std::distance(first, last)</code>; in
<code>min[capacity, std::distance(first, last)]</code> if the <code>InputIterator</code> is a
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a>).
\sa <code>operator=</code>, <code>\link assign(size_type, param_value_type)
assign(size_type, const_reference)\endlink</code>,
\sa <code>\link operator=(const circular_buffer&) operator=\endlink</code>,
<code>\link assign(size_type, param_value_type) assign(size_type, const_reference)\endlink</code>,
<code>\link assign(capacity_type, size_type, param_value_type)
assign(capacity_type, size_type, const_reference)\endlink</code>,
<code>assign(InputIterator, InputIterator)</code>
@@ -1805,7 +1808,8 @@ public:
\par Complexity
Linear (in <code>std::distance(pos, end())</code>).
\sa <code>erase(iterator, iterator)</code>, <code>rerase(iterator)</code>,
<code>rerase(iterator, iterator)</code>, <code>clear()</code>
<code>rerase(iterator, iterator)</code>, <code>erase_begin(size_type)</code>,
<code>erase_end(size_type)</code>, <code>clear()</code>
*/
iterator erase(iterator pos) {
BOOST_CB_ASSERT(pos.is_valid(this)); // check for uninitialized or invalidated iterator
@@ -1842,7 +1846,7 @@ public:
\par Complexity
Linear (in <code>std::distance(first, end())</code>).
\sa <code>erase(iterator)</code>, <code>rerase(iterator)</code>, <code>rerase(iterator, iterator)</code>,
<code>clear()</code>
<code>erase_begin(size_type)</code>, <code>erase_end(size_type)</code>, <code>clear()</code>
*/
iterator erase(iterator first, iterator last) {
BOOST_CB_ASSERT(first.is_valid(this)); // check for uninitialized or invalidated iterator
@@ -1881,7 +1885,8 @@ public:
<code>erase(iterator)</code> if the iterator <code>pos</code> is close to the beginning of the
<code>circular_buffer</code>. (See the <i>Complexity</i>.)
\sa <code>erase(iterator)</code>, <code>erase(iterator, iterator)</code>,
<code>rerase(iterator, iterator)</code>, <code>clear()</code>
<code>rerase(iterator, iterator)</code>, <code>erase_begin(size_type)</code>,
<code>erase_end(size_type)</code>, <code>clear()</code>
*/
iterator rerase(iterator pos) {
BOOST_CB_ASSERT(pos.is_valid(this)); // check for uninitialized or invalidated iterator
@@ -1921,7 +1926,7 @@ public:
<code>erase(iterator, iterator)</code> if <code>std::distance(begin(), first)</code> is lower that
<code>std::distance(last, end())</code>.
\sa <code>erase(iterator)</code>, <code>erase(iterator, iterator)</code>, <code>rerase(iterator)</code>,
<code>clear()</code>
<code>erase_begin(size_type)</code>, <code>erase_end(size_type)</code>, <code>clear()</code>
*/
iterator rerase(iterator first, iterator last) {
BOOST_CB_ASSERT(first.is_valid(this)); // check for uninitialized or invalidated iterator
@@ -1947,6 +1952,70 @@ public:
return iterator(this, last.m_it);
}
//! Remove first <code>n</code> elements (with constant complexity for scalar types).
/*!
\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.)
\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.)
\par Iterator Invalidation
Invalidates iterators pointing to the first <code>n</code> erased elements.
\par Complexity
Constant (in <code>n</code>) for scalar types; linear for other types.
\note This method has been specially designed for types which do not require an explicit destructruction (e.g.
integer, float or a pointer). For these scalar types a call to a destructor is not required which makes
it possible to implement the "erase from beginning" operation with a constant complexity. For non-sacalar
types the complexity is linear (hence the explicit destruction is needed) and the implementation is
actually equivalent to
<code>\link circular_buffer::rerase(iterator, iterator) rerase(begin(), begin() + n)\endlink</code>.
\sa <code>erase(iterator)</code>, <code>erase(iterator, iterator)</code>,
<code>rerase(iterator)</code>, <code>rerase(iterator, iterator)</code>,
<code>erase_end(size_type)</code>, <code>clear()</code>
*/
void erase_begin(size_type n) {
BOOST_CB_ASSERT(n <= size()); // check for n greater than size
#if BOOST_CB_ENABLE_DEBUG
erase_begin(n, false_type());
#else
erase_begin(n, is_scalar<value_type>());
#endif
}
//! Remove last <code>n</code> elements (with constant complexity for scalar types).
/*!
\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.)
\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.)
\par Iterator Invalidation
Invalidates iterators pointing to the last <code>n</code> erased elements.
\par Complexity
Constant (in <code>n</code>) for scalar types; linear for other types.
\note This method has been specially designed for types which do not require an explicit destructruction (e.g.
integer, float or a pointer). For these scalar types a call to a destructor is not required which makes
it possible to implement the "erase from end" operation with a constant complexity. For non-sacalar
types the complexity is linear (hence the explicit destruction is needed) and the implementation is
actually equivalent to
<code>\link circular_buffer::erase(iterator, iterator) erase(end() - n, end())\endlink</code>.
\sa <code>erase(iterator)</code>, <code>erase(iterator, iterator)</code>,
<code>rerase(iterator)</code>, <code>rerase(iterator, iterator)</code>,
<code>erase_begin(size_type)</code>, <code>clear()</code>
*/
void erase_end(size_type n) {
BOOST_CB_ASSERT(n <= size()); // check for n greater than size
#if BOOST_CB_ENABLE_DEBUG
erase_end(n, false_type());
#else
erase_end(n, is_scalar<value_type>());
#endif
}
//! Remove all stored elements from the <code>circular_buffer</code>.
/*!
\post <code>size() == 0</code>
@@ -1957,9 +2026,10 @@ public:
Invalidates all iterators pointing to the <code>circular_buffer</code> (except iterators equal to
<code>end()</code>).
\par Complexity
Linear (in the size of the <code>circular_buffer</code>).
Constant (in the size of the <code>circular_buffer</code>) for scalar types; linear for other types.
\sa <code>~circular_buffer()</code>, <code>erase(iterator)</code>, <code>erase(iterator, iterator)</code>,
<code>rerase(iterator)</code>, <code>rerase(iterator, iterator)</code>
<code>rerase(iterator)</code>, <code>rerase(iterator, iterator)</code>,
<code>erase_begin(size_type)</code>, <code>erase_end(size_type)</code>
*/
void clear() {
destroy_content();
@@ -2066,6 +2136,20 @@ private:
//! Destroy the whole content of the circular buffer.
void destroy_content() {
#if BOOST_CB_ENABLE_DEBUG
destroy_content(false_type());
#else
destroy_content(is_scalar<value_type>());
#endif
}
//! Specialized destroy_content method.
void destroy_content(const true_type&) {
m_first = add(m_first, size());
}
//! Specialized destroy_content method.
void destroy_content(const false_type&) {
for (size_type ii = 0; ii < size(); ++ii, increment(m_first))
destroy_item(m_first);
}
@@ -2564,6 +2648,30 @@ private:
m_last = sub(m_last, n - construct);
m_size += construct;
}
//! Specialized erase_begin method.
void erase_begin(size_type n, const true_type&) {
m_first = add(m_first, n);
m_size -= n;
}
//! Specialized erase_begin method.
void erase_begin(size_type n, const false_type&) {
iterator b = begin();
rerase(b, b + n);
}
//! Specialized erase_end method.
void erase_end(size_type n, const true_type&) {
m_last = sub(m_last, n);
m_size -= n;
}
//! Specialized erase_end method.
void erase_end(size_type n, const false_type&) {
iterator e = end();
erase(e - n, e);
}
};
// Non-member functions

View File

@@ -189,9 +189,9 @@ public:
\par Complexity
Linear (in <code>min[size(), capacity_ctrl.%capacity()]</code>).
\note To explicitly clear the extra allocated memory use the <b>shrink-to-fit</b> technique:<br><br>
<code>boost::%circular_buffer_space_optimized\<int\> cb(1000);<br>
<code>%boost::%circular_buffer_space_optimized\<int\> cb(1000);<br>
...<br>
boost::%circular_buffer_space_optimized\<int\>(cb).swap(cb);</code><br><br>
%boost::%circular_buffer_space_optimized\<int\>(cb).swap(cb);</code><br><br>
For more information about the shrink-to-fit technique in STL see
<a href="http://www.gotw.ca/gotw/054.htm">http://www.gotw.ca/gotw/054.htm</a>.
\sa <code>rset_capacity(const capacity_type&)</code>,
@@ -513,6 +513,12 @@ public:
*/
~circular_buffer_space_optimized();
//! no-comment
void erase_begin(size_type n);
//! no-comment
void erase_end(size_type n);
#endif // #if defined(BOOST_CB_NEVER_DEFINED)
//! The assign operator.
@@ -565,7 +571,8 @@ public:
equal to <code>end()</code>).
\par Complexity
Linear (in the <code>n</code>).
\sa <code>operator=</code>, <code>\link assign(capacity_type, size_type, param_value_type)
\sa <code>\link operator=(const circular_buffer_space_optimized&) operator=\endlink</code>,
<code>\link assign(capacity_type, size_type, param_value_type)
assign(capacity_type, size_type, const_reference)\endlink</code>,
<code>assign(InputIterator, InputIterator)</code>,
<code>assign(capacity_type, InputIterator, InputIterator)</code>
@@ -597,8 +604,9 @@ public:
equal to <code>end()</code>).
\par Complexity
Linear (in the <code>n</code>).
\sa <code>operator=</code>, <code>\link assign(size_type, param_value_type)
assign(size_type, const_reference)\endlink</code>, <code>assign(InputIterator, InputIterator)</code>,
\sa <code>\link operator=(const circular_buffer_space_optimized&) operator=\endlink</code>,
<code>\link assign(size_type, param_value_type) assign(size_type, const_reference)\endlink</code>,
<code>assign(InputIterator, InputIterator)</code>,
<code>assign(capacity_type, InputIterator, InputIterator)</code>
*/
void assign(capacity_type capacity_ctrl, size_type n, param_value_type item) {
@@ -630,8 +638,8 @@ public:
equal to <code>end()</code>).
\par Complexity
Linear (in the <code>std::distance(first, last)</code>).
\sa <code>operator=</code>, <code>\link assign(size_type, param_value_type)
assign(size_type, const_reference)\endlink</code>,
\sa <code>\link operator=(const circular_buffer_space_optimized&) operator=\endlink</code>,
<code>\link assign(size_type, param_value_type) assign(size_type, const_reference)\endlink</code>,
<code>\link assign(capacity_type, size_type, param_value_type)
assign(capacity_type, size_type, const_reference)\endlink</code>,
<code>assign(capacity_type, InputIterator, InputIterator)</code>
@@ -672,8 +680,8 @@ public:
Linear (in <code>std::distance(first, last)</code>; in
<code>min[capacity_ctrl.%capacity(), std::distance(first, last)]</code> if the <code>InputIterator</code>
is a <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a>).
\sa <code>operator=</code>, <code>\link assign(size_type, param_value_type)
assign(size_type, const_reference)\endlink</code>,
\sa <code>\link operator=(const circular_buffer_space_optimized&) operator=\endlink</code>,
<code>\link assign(size_type, param_value_type) assign(size_type, const_reference)\endlink</code>,
<code>\link assign(capacity_type, size_type, param_value_type)
assign(capacity_type, size_type, const_reference)\endlink</code>,
<code>assign(InputIterator, InputIterator)</code>
@@ -1252,11 +1260,7 @@ private:
ensure_reserve(new_capacity, new_size));
}
#if BOOST_CB_ENABLE_DEBUG
# if BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(70190006))
this->invalidate_iterators_except(end());
# else
invalidate_iterators_except(end());
# endif
#endif
}
@@ -1276,11 +1280,7 @@ private:
circular_buffer<T, Alloc>::set_capacity(
ensure_reserve(new_capacity, size()));
#if BOOST_CB_ENABLE_DEBUG
# if BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(70190006))
this->invalidate_iterators_except(end());
# else
invalidate_iterators_except(end());
# endif
#endif
}

View File

@@ -25,5 +25,6 @@ test-suite "circular_buffer"
: [ run base_test.cpp : <threading>single : ]
[ run space_optimized_test.cpp : <threading>single : ]
[ run soft_iterator_invalidation.cpp : <threading>single : ]
[ run constant_erase_test.cpp : <threading>single : ]
[ compile bounded_buffer_comparison.cpp : <threading>multi : ]
;

View File

@@ -0,0 +1,187 @@
// Special tests for erase_begin, erase_end and clear methods.
// Copyright (c) 2009 Jan Gaspar
// 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)
#define BOOST_CB_DISABLE_DEBUG
#include "test.hpp"
int MyInteger::ms_exception_trigger = 0;
int InstanceCounter::ms_count = 0;
void erase_begin_test() {
circular_buffer<int> cb1(5);
cb1.push_back(1);
cb1.push_back(2);
cb1.push_back(3);
cb1.push_back(4);
cb1.push_back(5);
cb1.push_back(6);
circular_buffer<int>::pointer p = &cb1[0];
cb1.erase_begin(2);
BOOST_CHECK(cb1.size() == 3);
BOOST_CHECK(cb1[0] == 4);
BOOST_CHECK(cb1[1] == 5);
BOOST_CHECK(cb1[2] == 6);
cb1.erase_begin(3);
BOOST_CHECK(cb1.empty());
BOOST_CHECK(*p == 2);
BOOST_CHECK(*(p + 1) == 3);
BOOST_CHECK(*(p + 2) == 4);
cb1.push_back(10);
cb1.push_back(11);
cb1.push_back(12);
BOOST_CHECK(cb1.size() == 3);
BOOST_CHECK(cb1[0] == 10);
BOOST_CHECK(cb1[1] == 11);
BOOST_CHECK(cb1[2] == 12);
circular_buffer<InstanceCounter> cb2(5, InstanceCounter());
BOOST_CHECK(cb2.size() == 5);
BOOST_CHECK(InstanceCounter::count() == 5);
cb2.erase_begin(2);
BOOST_CHECK(cb2.size() == 3);
BOOST_CHECK(InstanceCounter::count() == 3);
circular_buffer<MyInteger> cb3(5);
cb3.push_back(1);
cb3.push_back(2);
cb3.push_back(3);
cb3.push_back(4);
cb3.push_back(5);
cb3.push_back(6);
cb3.erase_begin(2);
BOOST_CHECK(cb3.size() == 3);
BOOST_CHECK(cb3[0] == 4);
BOOST_CHECK(cb3[1] == 5);
BOOST_CHECK(cb3[2] == 6);
}
void erase_end_test() {
circular_buffer<int> cb1(5);
cb1.push_back(1);
cb1.push_back(2);
cb1.push_back(3);
cb1.push_back(4);
cb1.push_back(5);
cb1.push_back(6);
circular_buffer<int>::pointer p = &cb1[3];
cb1.erase_end(2);
BOOST_CHECK(cb1.size() == 3);
BOOST_CHECK(cb1[0] == 2);
BOOST_CHECK(cb1[1] == 3);
BOOST_CHECK(cb1[2] ==4);
cb1.erase_end(3);
BOOST_CHECK(cb1.empty());
BOOST_CHECK(*p == 5);
BOOST_CHECK(*(p - 1) == 4);
BOOST_CHECK(*(p - 2) == 3);
cb1.push_back(10);
cb1.push_back(11);
cb1.push_back(12);
BOOST_CHECK(cb1.size() == 3);
BOOST_CHECK(cb1[0] == 10);
BOOST_CHECK(cb1[1] == 11);
BOOST_CHECK(cb1[2] == 12);
circular_buffer<InstanceCounter> cb2(5, InstanceCounter());
BOOST_CHECK(cb2.size() == 5);
BOOST_CHECK(InstanceCounter::count() == 5);
cb2.erase_end(2);
BOOST_CHECK(cb2.size() == 3);
BOOST_CHECK(InstanceCounter::count() == 3);
circular_buffer<MyInteger> cb3(5);
cb3.push_back(1);
cb3.push_back(2);
cb3.push_back(3);
cb3.push_back(4);
cb3.push_back(5);
cb3.push_back(6);
cb3.erase_end(2);
BOOST_CHECK(cb3.size() == 3);
BOOST_CHECK(cb3[0] == 2);
BOOST_CHECK(cb3[1] == 3);
BOOST_CHECK(cb3[2] == 4);
}
void clear_test() {
circular_buffer<int> cb1(5);
cb1.push_back(1);
cb1.push_back(2);
cb1.push_back(3);
cb1.push_back(4);
cb1.push_back(5);
cb1.push_back(6);
circular_buffer<int>::pointer p = &cb1[0];
cb1.clear();
BOOST_CHECK(cb1.empty());
BOOST_CHECK(*p == 2);
BOOST_CHECK(*(p + 1) == 3);
BOOST_CHECK(*(p + 2) == 4);
BOOST_CHECK(*(p + 3) == 5);
BOOST_CHECK(*(p - 1) == 6);
circular_buffer<InstanceCounter> cb2(5, InstanceCounter());
BOOST_CHECK(cb2.size() == 5);
BOOST_CHECK(InstanceCounter::count() == 5);
cb2.clear();
BOOST_CHECK(cb2.empty());
BOOST_CHECK(InstanceCounter::count() == 0);
circular_buffer<MyInteger> cb3(5);
cb3.push_back(1);
cb3.push_back(2);
cb3.push_back(3);
cb3.push_back(4);
cb3.push_back(5);
cb3.push_back(6);
cb3.clear();
BOOST_CHECK(cb3.empty());
}
// test main
test_suite* init_unit_test_suite(int /*argc*/, char* /*argv*/[]) {
test_suite* tests = BOOST_TEST_SUITE("Unit tests for erase_begin/end and clear methods of the circular_buffer.");
tests->add(BOOST_TEST_CASE(&erase_begin_test));
tests->add(BOOST_TEST_CASE(&erase_end_test));
tests->add(BOOST_TEST_CASE(&clear_test));
return tests;
}