Я пытаюсь использовать инкрементный тип с boost::counting_iterator
,
boost::counting_iterator
документация говорит что итератор работает с типами Incrementable, то есть с типами CopyConstructible, Assignable, PreIncrementable и EqualityComparable.
Мой тип увеличения:
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;
};
Это не в состоянии скомпилировать:
#include <boost/iterator/counting_iterator.hpp>
#include "incrementable.h"int main() {
boost::counting_iterator<Incrementable<int>> a(Incrementable<int>(0));
return 0;
}
Ошибка:
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
Я предполагаю, что мне нужно реализовать iterator_category либо для:
Ни то, ни другое не ясно из документации (которая полностью исключает эту тему), и я не могу найти какую-либо информацию об этом в других частях библиотеки.
Поэтому я добавил следующее boost::detail
Пространство имен:
namespace boost { namespace detail {
template <class T> struct is_numeric<Incrementable<T>>
: mpl::true_ {};
}} // boost::detail namespace
и теперь все компилируется и работает как положено. Тем не менее, я действительно сомневаюсь, что библиотека была предназначена для использования таким образом.
Кто-нибудь знает правильный / чистый способ реализации этого?
Предложение Стива Джессопа: специализация std::numeric_limits
также работает:
namespace std {
template<class T>
class numeric_limits<Incrementable<T>> : public numeric_limits<T> {
public:
static const bool is_specialized = true;
};
}
Тем не менее, я не знаю, правильно ли это делать для инкрементного типа.
Я не уверен, что Boost определяет «тип с приращением», как вы говорите. Если он определяет это как вы говорите, то есть ошибка документации, это не должно сказать, что counting_iterator
работает для «любого возрастающего типа», потому что это не все требования. Или я полагаю, что это правда, если «при условии, что вы правильно указали другие параметры шаблона», само собой разумеется.
Требования к Incrementable
параметр шаблона для counting_iterator
приведены в документе, на который вы ссылаетесь (начиная с «iterator_category
определяется следующим образом … «, потому что фактический раздел требований относится к iterator_category
).
Вы не должны специализироваться boost::detail::is_numeric
, Вы должны специализироваться std::numeric_limits
, Но в вашем примере, я думаю, вы на самом деле сузили интерфейс T
слишком много, чтобы утверждать, что ваш тип числовой (у него нет арифметики). Если ваш тип не является ни числовым, ни итератором, я думаю, вы должны указать CategoryOrTraversal
как forward_iterator_tag
, Возможно, я что-то пропустил.
Других решений пока нет …