iterator: add dereference_adapter for iterators
This commit is contained in:
parent
bf535de083
commit
edc245e2d1
89
iterator.hpp
89
iterator.hpp
@ -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
|
||||
|
@ -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**)
|
||||
|
Loading…
Reference in New Issue
Block a user