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.
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.