Add range_iterator.

This commit is contained in:
Sergey Magidovich 2015-12-15 21:04:34 +03:00 committed by Sergey Yershov
parent 6c4b711fb4
commit a2b10e7042
4 changed files with 138 additions and 0 deletions

View file

@ -51,6 +51,7 @@ HEADERS += \
mutex.hpp \
object_tracker.hpp \
observer_list.hpp \
range_iterator.hpp \
regexp.hpp \
rolling_hash.hpp \
scope_guard.hpp \

View file

@ -24,6 +24,7 @@ SOURCES += \
matrix_test.cpp \
mem_trie_test.cpp \
observer_list_test.cpp \
range_iterator_test.cpp \
regexp_test.cpp \
rolling_hash_test.cpp \
scope_guard_test.cpp \

View file

@ -0,0 +1,43 @@
#include "testing/testing.hpp"
#include "base/range_iterator.hpp"
#include "std/vector.hpp"
UNIT_TEST(RangeIterator)
{
using namespace base;
{
vector<int> result;
for (auto const i : range(5))
result.push_back(i);
TEST_EQUAL(result, (vector<int>{0, 1, 2, 3, 4}), ());
}
{
vector<int> result;
for (auto const i : range(2, 5))
result.push_back(i);
TEST_EQUAL(result, (vector<int>{2, 3, 4}), ());
}
{
vector<int> result;
for (auto const i : reverse_range(5))
result.push_back(i);
TEST_EQUAL(result, (vector<int>{4, 3, 2, 1, 0}), ());
}
{
vector<int> result;
for (auto const i : reverse_range(2, 5))
result.push_back(i);
TEST_EQUAL(result, (vector<int>{4, 3, 2}), ());
}
{
TEST_EQUAL(std::vector<int>(MakeRangeIterator(0), MakeRangeIterator(5)),
(std::vector<int>{0, 1, 2, 3, 4}), ());
}
}

93
base/range_iterator.hpp Normal file
View file

@ -0,0 +1,93 @@
#include "std/iterator.hpp"
#include "std/type_traits.hpp"
namespace base
{
template <typename TCounter>
struct RangeIterator
{
explicit RangeIterator(TCounter const current):
m_current(current)
{
}
RangeIterator & operator++() { ++m_current; return *this; }
RangeIterator & operator--() { --m_current; return *this; }
bool operator==(RangeIterator const & it) const { return m_current == it.m_current; }
bool operator!=(RangeIterator const & it) const { return !(*this == it); }
TCounter operator*() const { return m_current; }
TCounter m_current;
};
} // namespace base
namespace std
{
template <typename T>
struct iterator_traits<base::RangeIterator<T>>
{
using difference_type = T;
using value_type = T;
using pointer = void;
using reference = T;
using iterator_category = std::bidirectional_iterator_tag;
};
} // namespace std
namespace base
{
template <typename TCounter, bool forward>
struct RangeWrapper
{
using value_type = typename std::remove_cv<TCounter>::type;
using iterator_base = RangeIterator<value_type>;
using iterator = typename std::conditional<forward,
iterator_base,
std::reverse_iterator<iterator_base>>::type;
RangeWrapper(TCounter const from, TCounter const to):
m_begin(from),
m_end(to)
{
}
iterator begin() const { return iterator(iterator_base(m_begin)); }
iterator end() const { return iterator(iterator_base(m_end)); }
value_type const m_begin;
value_type const m_end;
};
template <typename TCounter>
RangeWrapper<TCounter, true> range(TCounter const to)
{
return {{}, to};
}
template <typename TCounter>
RangeWrapper<TCounter, true> range(TCounter const from, TCounter const to)
{
return {from, to};
}
template <typename TCounter>
RangeWrapper<TCounter, false> reverse_range(TCounter const to)
{
return {to, {}};
}
template <typename TCounter>
RangeWrapper<TCounter, false> reverse_range(TCounter const from, TCounter const to)
{
return {to, from};
}
template <typename TCounter>
RangeIterator<TCounter> MakeRangeIterator(TCounter const counter)
{
return RangeIterator<TCounter>(counter);
}
} // namespace base