Since iterator is deprecated, I began converting iterators in my code base to use non-deprecated constructs. I could not seem to make my indirect iterator compliant with the std::forward_iterator
concept unless I explicitly specified value_type
. I would like to know if this is expected.
Based on the definition of iter_value_t and indirectly_readible_traits, it seems like there is no automatic inference of std::iter_value_t
. Naively, I would have expected std::iter_value_t<Itr>
to be defined as std::remove_cvref_t<std::iter_reference_t<Itr>>
if no definition for value_type
is present (which is checked via has-member-value-type
in indirectly_readible_traits).
#include <vector>
template <std::forward_iterator Itr>
class IndirectItr {
public:
using value_type = std::iter_value_t<Itr>; // **do I need this?**
explicit IndirectItr(Itr itr = {}) : m_itr{itr} {}
bool operator==(const IndirectItr& rhs) const { return m_itr == rhs.m_itr; }
bool operator!=(const IndirectItr& rhs) const { return m_itr != rhs.m_itr; }
typename std::iter_reference_t<Itr> operator *() const { return *m_itr; }
IndirectItr& operator++() { ++m_itr; return *this; }
IndirectItr operator++(int) { auto ret = *this; ++(*this); return ret; }
typename std::iter_difference_t<Itr> operator-(const IndirectItr& rhs) const { return m_itr - rhs.m_itr; }
private:
Itr m_itr;
};
using Base = std::vector<int>::iterator;
static_assert(std::forward_iterator<IndirectItr<Base>>);
static_assert(std::same_as<std::iter_value_t<Base>, std::remove_cvref_t<std::iter_reference_t<Base>>>);
P.S. I have several indirect iterator definitions that wrap other iterators. The example above is representative of a custom indirect iterator. I don't have this exact class in my code.