mirror of
https://github.com/boostorg/utility.git
synced 2025-05-09 02:44:10 +00:00
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:
parent
4a563fa266
commit
7e25450054
@ -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 <class Incrementable>
|
||||
struct counting_iterator_traits;
|
||||
|
||||
template <class Incrementable>
|
||||
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 <class Incrementable>
|
||||
struct counting_iterator_traits
|
||||
{
|
||||
<i>if (numeric_limits<Incrementable>::is_specialized == true) {</i>
|
||||
typedef <i>detail::numeric_traits</i><Incrementable>::difference_type difference_type;
|
||||
typedef std::random_access_iterator_tag iterator_category;
|
||||
<i>} else {</i>
|
||||
typedef std::iterator_traits<Incrementable>::difference_type difference_type;
|
||||
typedef std::iterator_traits<Incrementable>::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<Incrementable>::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
|
||||
-->
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user