added discusion of counting_iterator_traits, and added type requirements

for the Incrementable type.

added uses of user-defined types to the test


[SVN r9204]
This commit is contained in:
Jeremy Siek 2001-02-15 05:53:10 +00:00
parent 4a563fa266
commit 7e25450054
2 changed files with 130 additions and 5 deletions

View File

@ -15,7 +15,7 @@ align="center" width="277" height="86">
<h1>Counting Iterator Adaptor</h1>
Defined in header
<a href="../../boost/couting_iterator.hpp">boost/counting_iterator.hpp</a>
<a href="../../boost/counting_iterator.hpp">boost/counting_iterator.hpp</a>
<p>
Sometimes it would be nice if one could treat an integer like an
@ -27,9 +27,9 @@ only iterator operation missing from builtin integer types is an
value of the integer. The counting iterator adaptor provides this
functionality, though it is a bit more generalized. One can use the
counting iterator adaptor not only with integer types, but with any
type that is incrementable (has <tt>operator++()</tt>). The following
<b>pseudo-code</b> shows the general idea of how the counting iterator is
implemented.
type that is incrementable (see type requirements below). The
following <b>pseudo-code</b> shows the general idea of how the
counting iterator is implemented.
</p>
<pre>
@ -47,6 +47,9 @@ fashion as the incrementable base type.
<pre>
namespace boost {
template &lt;class Incrementable&gt;
struct counting_iterator_traits;
template &lt;class Incrementable&gt;
struct counting_iterator_generator;
@ -58,6 +61,36 @@ namespace boost {
<hr>
<h2><a name="counting_iterator_traits">Counting Iterator Traits</a></h2>
The counting iterator adaptor needs to know the appropriate
<tt>difference_type</tt> and <tt>iterator_category</tt> to use
depending on the <tt>Incrementable</tt> type supplied by the user.
The <tt>counting_iterator_traits</tt> class provides these types. If
the <tt>Incrementable</tt> type is a numeric type or is an iterator
then these types will be correctly deduced by the below counting
iterator traits. Otherwise, the user must specialize
<tt>counting_iterator_traits</tt> for their type, or add nested
typedefs to their type to fulfill the needs of
<a href="http://www.sgi.com/tech/stl/iterator_traits.html">
<tt>std::iterator_traits</tt></a>.
<pre>
template &lt;class Incrementable&gt;
struct counting_iterator_traits
{
<i>if (numeric_limits&lt;Incrementable&gt::is_specialized == true) {</i>
typedef <i>detail::numeric_traits</i>&lt;Incrementable&gt;::difference_type difference_type;
typedef std::random_access_iterator_tag iterator_category;
<i>} else {</i>
typedef std::iterator_traits&lt;Incrementable&gt;::difference_type difference_type;
typedef std::iterator_traits&lt;Incrementable&gt;::iterator_category iterator_category;
<i>}</i>
};
</pre>
<hr>
<h2><a name="counting_iterator_generator">The Counting Iterator Type
Generator</a></h2>
@ -126,6 +159,36 @@ Access Iterator</a>. If the <tt>Incrementable</tt> type has less
functionality, then the counting iterator will have correspondingly
less functionality.
<h3>Type Requirements</h3>
The <tt>Incrementable</tt> type must be <a
href="http://www.sgi.com/tech/stl/DefaultConstructible.html">Default
Constructible</a>, <a href="./CopyConstructible.html">Copy
Constructible</a>, and <a href="./Assignable.html">Assignable</a>.
Furthermore, if you wish to create a counting iterator that is a <a
href="http://www.sgi.com/tech/stl/ForwardIterator.html"> Forward
Iterator</a>, then the following expressions must be valid:
<pre>
Incrementable i, j;
++i // pre-increment
i == j // operator equal
</pre>
If you wish to create a counting iterator that is a <a
href="http://www.sgi.com/tech/stl/BidirectionalIterator.html">
Bidirectional Iterator</a>, then pre-decrement is also required:
<pre>
--i
</pre>
If you wish to create a counting iterator that is a <a
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html"> Random
Access Iterator</a>, then these additional expressions are also required:
<pre>
counting_iterator_traits&lt;Incrementable&gt;::difference_type n;
i += n
n = i - j
i < j
</pre>
<h3>Members</h3>
The counting iterator type implements the member functions and
@ -231,5 +294,5 @@ any purpose.</p>
</html>
<!-- LocalWords: html charset alt gif hpp incrementable const namespace htm
-->
<!-- LocalWords: struct typename iostream int Siek
<!-- LocalWords: struct typename iostream int Siek CopyConstructible pre
-->

View File

@ -21,6 +21,7 @@
#include <boost/pending/iterator_tests.hpp>
#include <boost/counting_iterator.hpp>
#include <boost/detail/iterator.hpp>
#include <iostream>
#include <climits>
#include <iterator>
#include <stdlib.h>
@ -162,8 +163,68 @@ void test_container(Container* = 0) // default arg works around MSVC bug
test(const_iterator(start), const_iterator(finish));
}
class my_int1 {
public:
my_int1() { }
my_int1(int x) : m_int(x) { }
my_int1& operator++() { ++m_int; return *this; }
bool operator==(const my_int1& x) const { return m_int == x.m_int; }
private:
int m_int;
};
namespace boost {
template <>
struct counting_iterator_traits<my_int1> {
typedef std::ptrdiff_t difference_type;
typedef std::forward_iterator_tag iterator_category;
};
}
class my_int2 {
public:
typedef void value_type;
typedef void pointer;
typedef void reference;
typedef std::ptrdiff_t difference_type;
typedef std::bidirectional_iterator_tag iterator_category;
my_int2() { }
my_int2(int x) : m_int(x) { }
my_int2& operator++() { ++m_int; return *this; }
my_int2& operator--() { ++m_int; return *this; }
bool operator==(const my_int2& x) const { return m_int == x.m_int; }
private:
int m_int;
};
class my_int3 {
public:
typedef void value_type;
typedef void pointer;
typedef void reference;
typedef std::ptrdiff_t difference_type;
typedef std::random_access_iterator_tag iterator_category;
my_int3() { }
my_int3(int x) : m_int(x) { }
my_int3& operator++() { ++m_int; return *this; }
my_int3& operator+=(std::ptrdiff_t n) { m_int += n; return *this; }
std::ptrdiff_t operator-(const my_int3& x) { return m_int - x.m_int; }
my_int3& operator--() { ++m_int; return *this; }
bool operator==(const my_int3& x) const { return m_int == x.m_int; }
bool operator<(const my_int3& x) const { return m_int < x.m_int; }
private:
int m_int;
};
int main()
{
// Test user-defined type.
test_integer<my_int1>();
test_integer<my_int2>();
test_integer<my_int3>();
// Test the built-in integer types.
test_integer<char>();
test_integer<unsigned char>();
@ -195,5 +256,6 @@ int main()
int array[2000];
test(boost::make_counting_iterator(array), boost::make_counting_iterator(array+2000-1));
#endif
std::cout << "test successful " << std::endl;
return 0;
}