Question

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:

  • a counting_iterator of my Incrementable type,
  • or as the error says, for my Incrementable type (does this even make sense? my Incrementable type is not an iterator).

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.

Was it helpful?

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top