c++boostiteratorboost-iterators

Using boost counting_iterator with Incrementable type


I'm trying to use an Incrementable type with a boost::counting_iterator.

The boost::counting_iterator documentation says that the iterator works for Incrementable types, i.e. types that are CopyConstructible, Assignable, PreIncrementable, and EqualityComparable.

My Incrementable type:

template<class T> struct Incrementable {
  // CopyConstructible:
  Incrementable() : value(0) {}
  Incrementable(const Incrementable& other) : value(other.value) {}
  explicit Incrementable(const T& other) : value(other) {}
  // Assignable:
  inline Incrementable& operator=(const Incrementable& other) {
    value = other.value;
    return *this;
  }
  // PreIncrementable:
  inline Incrementable& operator++() {
    ++value;
    return *this;
  }
  // EqualityComparable:
  friend 
  inline bool operator==(const Incrementable& a, const Incrementable& b) {
    return a.value == b.value;
  }

  T value;
};

This fails to compile:

#include <boost/iterator/counting_iterator.hpp>
#include "incrementable.h"
int main() {
  boost::counting_iterator<Incrementable<int>> a(Incrementable<int>(0));
  return 0;
}

The error:

usr/local/include/boost/iterator/iterator_categories.hpp:161:60: error: no type named 'iterator_category' in 'boost::detail::iterator_traits<Incrementable<int> >'
        typename boost::detail::iterator_traits<Iterator>::iterator_category

I'd guess that I need to implement an iterator_category either for:

Neither is clear from the documentation (which omits this topic completely), and I fail to find any information about it in the other parts of the library.

So I added the following to boost::detail namespace:

namespace boost { namespace detail {
template <class T> struct is_numeric<Incrementable<T>>
    : mpl::true_ {};
}} // boost::detail namespace

and now everything compiles and works as expected. Still, I really doubt that the library was intended to be used this way.

Anyone knows the proper/clean way to implement this?

Steve Jessop's suggestion: specializing std::numeric_limits also works:

namespace std {
template<class T>
class numeric_limits<Incrementable<T>> : public numeric_limits<T> {
public:
  static const bool is_specialized = true;
};
}

Still I don't know if this is the right thing to do for an incrementable type.


Solution

  • I'm not sure whether Boost defines "incrementable type" as you say. If it does define it as you say, then there's a documentation bug, it shouldn't say that counting_iterator works for "any incrementable type", because those aren't the whole requirements. Or I suppose it's true if "provided that you specify the other template parameters correctly" goes without saying.

    The requirements on the Incrementable template parameter for counting_iterator are given in the document you link to (starting from "iterator_category is defined as follows...", because the actual requirements section refers back to iterator_category).

    You should not specialize boost::detail::is_numeric. You should specialize std::numeric_limits. But in your example, I think you've actually narrowed the interface of T too much to claim that your type is numeric (it doesn't have arithmetic). If your type is neither numeric nor an iterator, I think you're supposed to specify CategoryOrTraversal as forward_iterator_tag. I may have missed something.