iterator: add dereference_adapter for iterators

This commit is contained in:
Danny Robson 2018-10-15 17:15:27 +11:00
parent bf535de083
commit edc245e2d1
2 changed files with 104 additions and 1 deletions

View File

@ -645,6 +645,93 @@ namespace cruft {
private:
std::size_t m_count = 0;
};
};
///////////////////////////////////////////////////////////////////////////
/// Adapts a supplied iterator by dereferencing any operations that deal
/// with the underlying value_type of the supplied iterator.
template <typename IteratorT>
struct dereference_adapter {
//---------------------------------------------------------------------
using difference_type = typename std::iterator_traits<IteratorT>::difference_type;
using iterator_category = typename std::iterator_traits<IteratorT>::iterator_category;
using value_type = std::remove_reference_t<
decltype(
*std::declval<
typename std::iterator_traits<IteratorT>::value_type
> ()
)
>;
using pointer = value_type*;
using reference = value_type&;
//---------------------------------------------------------------------
dereference_adapter (IteratorT _cursor)
: m_cursor (_cursor)
{ ; }
//---------------------------------------------------------------------
// Trivial conditional operations
decltype(auto)
operator== (dereference_adapter const &rhs) const
{
return m_cursor == rhs.m_cursor;
}
decltype(auto)
operator!= (dereference_adapter const &rhs) const
{
return !(*this == rhs);
}
//---------------------------------------------------------------------
// Iterator movement operations
dereference_adapter&
operator++ ()
{
++m_cursor;
return *this;
}
difference_type
operator- (dereference_adapter const &rhs) const
{
return m_cursor - rhs.m_cursor;
}
auto
operator+ (difference_type offset) const
{
return dereference_adapter { m_cursor + offset };
}
//---------------------------------------------------------------------
// value_type operations
decltype(auto)
operator= (value_type const &rhs)
{
return **m_cursor = rhs;
}
decltype(auto) operator* () { return **m_cursor; }
decltype(auto) operator-> () { return **m_cursor; }
decltype(auto) operator* () const { return **m_cursor; }
decltype(auto) operator-> () const { return **m_cursor; }
private:
IteratorT m_cursor;
};
}
#endif

View File

@ -19,6 +19,22 @@ test_counting_output_iterator (cruft::TAP::logger &tap)
}
void
test_dereference_iterator (cruft::TAP::logger &tap)
{
int values[4] { 0, 1, 2, 3 };
int const* pointers[4] = { values + 0, values + 1, values + 2, values + 3 };
auto const sum = std::accumulate (
cruft::dereference_adapter (std::cbegin (pointers)),
cruft::dereference_adapter (std::cend (pointers)),
0
);
tap.expect_eq (sum, 6, "dereference_adapter used in accumulate");
}
///////////////////////////////////////////////////////////////////////////////
int
main (int, char**)