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> <h1>Counting Iterator Adaptor</h1>
Defined in header 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> <p>
Sometimes it would be nice if one could treat an integer like an 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 value of the integer. The counting iterator adaptor provides this
functionality, though it is a bit more generalized. One can use the functionality, though it is a bit more generalized. One can use the
counting iterator adaptor not only with integer types, but with any counting iterator adaptor not only with integer types, but with any
type that is incrementable (has <tt>operator++()</tt>). The following type that is incrementable (see type requirements below). The
<b>pseudo-code</b> shows the general idea of how the counting iterator is following <b>pseudo-code</b> shows the general idea of how the
implemented. counting iterator is implemented.
</p> </p>
<pre> <pre>
@ -47,6 +47,9 @@ fashion as the incrementable base type.
<pre> <pre>
namespace boost { namespace boost {
template &lt;class Incrementable&gt;
struct counting_iterator_traits;
template &lt;class Incrementable&gt; template &lt;class Incrementable&gt;
struct counting_iterator_generator; struct counting_iterator_generator;
@ -58,6 +61,36 @@ namespace boost {
<hr> <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 <h2><a name="counting_iterator_generator">The Counting Iterator Type
Generator</a></h2> 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 functionality, then the counting iterator will have correspondingly
less functionality. 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> <h3>Members</h3>
The counting iterator type implements the member functions and The counting iterator type implements the member functions and
@ -231,5 +294,5 @@ any purpose.</p>
</html> </html>
<!-- LocalWords: html charset alt gif hpp incrementable const namespace htm <!-- 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/pending/iterator_tests.hpp>
#include <boost/counting_iterator.hpp> #include <boost/counting_iterator.hpp>
#include <boost/detail/iterator.hpp> #include <boost/detail/iterator.hpp>
#include <iostream>
#include <climits> #include <climits>
#include <iterator> #include <iterator>
#include <stdlib.h> #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)); 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() 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 the built-in integer types.
test_integer<char>(); test_integer<char>();
test_integer<unsigned char>(); test_integer<unsigned char>();
@ -195,5 +256,6 @@ int main()
int array[2000]; int array[2000];
test(boost::make_counting_iterator(array), boost::make_counting_iterator(array+2000-1)); test(boost::make_counting_iterator(array), boost::make_counting_iterator(array+2000-1));
#endif #endif
std::cout << "test successful " << std::endl;
return 0; return 0;
} }