-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrange_iterator.hpp
100 lines (86 loc) · 2.63 KB
/
range_iterator.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#pragma once
#include <iterator>
#include <type_traits>
namespace base
{
// RagneItrator allows to write for loops as follows:
// for (auto const i : range(N))
// ...
// for (auto const i : range(M, N))
// ...
// And initialize stl containers like this:
// vector<int> mySequence(MakeRangeIterator(0), MakeRangeIterator(10));
template <typename TCounter>
struct RangeIterator
{
explicit RangeIterator(TCounter const current) : m_current(current) {}
RangeIterator & operator++() { ++m_current; return *this; }
RangeIterator operator++(int) { return RangeIterator(m_current++); }
RangeIterator & operator--() { --m_current; return *this; }
RangeIterator operator--(int) { return RangeIterator(m_current--); }
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 = std::remove_cv_t<TCounter>;
using iterator_base = RangeIterator<value_type>;
using iterator = std::conditional_t<forward, iterator_base, std::reverse_iterator<iterator_base>>;
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;
};
// Use this helper to iterate through 0 to `to'.
template <typename TCounter>
RangeWrapper<TCounter, true> UpTo(TCounter const to)
{
return {{}, to};
}
// Use this helper to iterate through `from' to `to'.
template <typename TCounter>
RangeWrapper<TCounter, true> UpTo(TCounter const from, TCounter const to)
{
return {from, to};
}
// Use this helper to iterate through `from' to 0.
template <typename TCounter>
RangeWrapper<TCounter, false> DownTo(TCounter const from)
{
return {from, {}};
}
// Use this helper to iterate through `from' to `to'.
template <typename TCounter>
RangeWrapper<TCounter, false> DownTo(TCounter const from, TCounter const to)
{
return {to, from};
}
template <typename TCounter>
RangeIterator<TCounter> MakeRangeIterator(TCounter const counter)
{
return RangeIterator<TCounter>(counter);
}
} // namespace base