diff --git a/counting_iterator.htm b/counting_iterator.htm index d56ddd0..3224785 100644 --- a/counting_iterator.htm +++ b/counting_iterator.htm @@ -15,7 +15,7 @@ align="center" width="277" height="86">

Counting Iterator Adaptor

Defined in header -boost/counting_iterator.hpp +boost/counting_iterator.hpp

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 operator++()). The following -pseudo-code shows the general idea of how the counting iterator is -implemented. +type that is incrementable (see type requirements below). The +following pseudo-code shows the general idea of how the +counting iterator is implemented.

@@ -47,6 +47,9 @@ fashion as the incrementable base type.
 
 
 namespace boost {
+  template <class Incrementable>
+  struct counting_iterator_traits;
+
   template <class Incrementable>
   struct counting_iterator_generator;
 
@@ -58,6 +61,36 @@ namespace boost {
 
 
+

Counting Iterator Traits

+ +The counting iterator adaptor needs to know the appropriate +difference_type and iterator_category to use +depending on the Incrementable type supplied by the user. +The counting_iterator_traits class provides these types. If +the Incrementable 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 +counting_iterator_traits for their type, or add nested +typedefs to their type to fulfill the needs of + +std::iterator_traits. + +
+template <class Incrementable>
+struct counting_iterator_traits
+{
+  if (numeric_limits<Incrementable>::is_specialized == true) {
+    typedef detail::numeric_traits<Incrementable>::difference_type difference_type;
+    typedef std::random_access_iterator_tag iterator_category;   
+  } else {
+    typedef std::iterator_traits<Incrementable>::difference_type difference_type;
+    typedef std::iterator_traits<Incrementable>::iterator_category iterator_category;
+  }    
+};
+
+ +
+

The Counting Iterator Type Generator

@@ -126,6 +159,36 @@ Access Iterator. If the Incrementable type has less functionality, then the counting iterator will have correspondingly less functionality. +

Type Requirements

+ +The Incrementable type must be Default +Constructible, Copy +Constructible, and Assignable. +Furthermore, if you wish to create a counting iterator that is a Forward +Iterator, then the following expressions must be valid: +
+Incrementable i, j;
+++i         // pre-increment
+i == j      // operator equal
+
+If you wish to create a counting iterator that is a +Bidirectional Iterator, then pre-decrement is also required: +
+--i
+
+If you wish to create a counting iterator that is a Random +Access Iterator, then these additional expressions are also required: +
+counting_iterator_traits<Incrementable>::difference_type n;
+i += n
+n = i - j
+i < j
+
+

Members

The counting iterator type implements the member functions and @@ -231,5 +294,5 @@ any purpose.

- diff --git a/counting_iterator_test.cpp b/counting_iterator_test.cpp index 5f385ae..7fd3e1b 100644 --- a/counting_iterator_test.cpp +++ b/counting_iterator_test.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -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 { + 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(); + test_integer(); + test_integer(); + // Test the built-in integer types. test_integer(); test_integer(); @@ -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; }