Make TransformView iterator's category match its underlying's
In particular, this make gathering a transformed range to a vector faster because we can use the random access nature of underlying iterator to get the size to allocate in the vector upfront.
This commit is contained in:
parent
62fa783bfd
commit
0919679e0d
|
@ -82,8 +82,8 @@ struct FilterView
|
||||||
struct Iterator : std::iterator<std::forward_iterator_tag,
|
struct Iterator : std::iterator<std::forward_iterator_tag,
|
||||||
typename std::iterator_traits<RangeIt>::value_type>
|
typename std::iterator_traits<RangeIt>::value_type>
|
||||||
{
|
{
|
||||||
Iterator(const FilterView& view, RangeIt it, RangeIt end)
|
Iterator(Filter& filter, RangeIt it, RangeIt end)
|
||||||
: m_it{std::move(it)}, m_end{std::move(end)}, m_view{&view}
|
: m_it{std::move(it)}, m_end{std::move(end)}, m_filter{&filter}
|
||||||
{
|
{
|
||||||
do_filter();
|
do_filter();
|
||||||
}
|
}
|
||||||
|
@ -107,17 +107,17 @@ struct FilterView
|
||||||
private:
|
private:
|
||||||
void do_filter()
|
void do_filter()
|
||||||
{
|
{
|
||||||
while (m_it != m_end and not m_view->m_filter(*m_it))
|
while (m_it != m_end and not (*m_filter)(*m_it))
|
||||||
++m_it;
|
++m_it;
|
||||||
}
|
}
|
||||||
|
|
||||||
RangeIt m_it;
|
RangeIt m_it;
|
||||||
RangeIt m_end;
|
RangeIt m_end;
|
||||||
const FilterView* m_view;
|
Filter* m_filter;
|
||||||
};
|
};
|
||||||
|
|
||||||
Iterator begin() const { return {*this, std::begin(m_range), std::end(m_range)}; }
|
Iterator begin() const { return {m_filter, std::begin(m_range), std::end(m_range)}; }
|
||||||
Iterator end() const { return {*this, std::end(m_range), std::end(m_range)}; }
|
Iterator end() const { return {m_filter, std::end(m_range), std::end(m_range)}; }
|
||||||
|
|
||||||
Range m_range;
|
Range m_range;
|
||||||
mutable Filter m_filter;
|
mutable Filter m_filter;
|
||||||
|
@ -138,34 +138,45 @@ struct TransformView
|
||||||
using RangeIt = IteratorOf<Range>;
|
using RangeIt = IteratorOf<Range>;
|
||||||
using ResType = decltype(std::declval<Transform>()(*std::declval<RangeIt>()));
|
using ResType = decltype(std::declval<Transform>()(*std::declval<RangeIt>()));
|
||||||
|
|
||||||
struct Iterator : std::iterator<std::forward_iterator_tag, std::remove_reference_t<ResType>>
|
struct Iterator
|
||||||
{
|
{
|
||||||
Iterator(const TransformView& view, RangeIt it)
|
using iterator_category = typename std::iterator_traits<RangeIt>::iterator_category;
|
||||||
: m_it{std::move(it)}, m_view{&view} {}
|
using value_type = std::remove_reference_t<ResType>;
|
||||||
|
using difference_type = typename std::iterator_traits<RangeIt>::difference_type;
|
||||||
|
using pointer = value_type*;
|
||||||
|
using reference = value_type&;
|
||||||
|
|
||||||
|
Iterator(Transform& transform, RangeIt it)
|
||||||
|
: m_it{std::move(it)}, m_transform{&transform} {}
|
||||||
|
|
||||||
|
decltype(auto) operator*() { return (*m_transform)(*m_it); }
|
||||||
|
decltype(auto) operator[](difference_type i) const { return (*m_transform)(m_it[i]); }
|
||||||
|
|
||||||
decltype(auto) operator*() { return m_view->m_transform(*m_it); }
|
|
||||||
Iterator& operator++() { ++m_it; return *this; }
|
Iterator& operator++() { ++m_it; return *this; }
|
||||||
Iterator operator++(int) { auto copy = *this; ++m_it; return copy; }
|
Iterator operator++(int) { auto copy = *this; ++m_it; return copy; }
|
||||||
|
|
||||||
friend bool operator==(const Iterator& lhs, const Iterator& rhs)
|
Iterator& operator--() { --m_it; return *this; }
|
||||||
{
|
Iterator operator--(int) { auto copy = *this; --m_it; return copy; }
|
||||||
return lhs.m_it == rhs.m_it;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend bool operator!=(const Iterator& lhs, const Iterator& rhs)
|
Iterator& operator+=(difference_type diff) { m_it += diff; return *this; }
|
||||||
{
|
Iterator& operator-=(difference_type diff) { m_it -= diff; return *this; }
|
||||||
return not (lhs == rhs);
|
|
||||||
}
|
Iterator operator+(difference_type diff) { return {*m_transform, m_it + diff}; }
|
||||||
|
Iterator operator-(difference_type diff) { return {*m_transform, m_it - diff}; }
|
||||||
|
|
||||||
|
friend bool operator==(const Iterator& lhs, const Iterator& rhs) { return lhs.m_it == rhs.m_it; }
|
||||||
|
friend bool operator!=(const Iterator& lhs, const Iterator& rhs) { return not (lhs == rhs); }
|
||||||
|
friend difference_type operator-(const Iterator& lhs, const Iterator& rhs) { return lhs.m_it - rhs.m_it; }
|
||||||
|
|
||||||
RangeIt base() const { return m_it; }
|
RangeIt base() const { return m_it; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RangeIt m_it;
|
RangeIt m_it;
|
||||||
const TransformView* m_view;
|
Transform* m_transform;
|
||||||
};
|
};
|
||||||
|
|
||||||
Iterator begin() const { return {*this, std::begin(m_range)}; }
|
Iterator begin() const { return {m_transform, std::begin(m_range)}; }
|
||||||
Iterator end() const { return {*this, std::end(m_range)}; }
|
Iterator end() const { return {m_transform, std::end(m_range)}; }
|
||||||
|
|
||||||
Range m_range;
|
Range m_range;
|
||||||
mutable Transform m_transform;
|
mutable Transform m_transform;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user