mirror of
https://github.com/boostorg/utility.git
synced 2025-05-09 15:04:00 +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>
|
<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 <class Incrementable>
|
||||||
|
struct counting_iterator_traits;
|
||||||
|
|
||||||
template <class Incrementable>
|
template <class Incrementable>
|
||||||
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 <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
|
<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<Incrementable>::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
|
||||||
-->
|
-->
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user