emilib
irange.hpp
1 // By Emil Ernerfeldt 2014-2016
2 // LICENSE:
3 // This software is dual-licensed to the public domain and under the following
4 // license: you are granted a perpetual, irrevocable license to copy, modify,
5 // publish, and distribute this file as you see fit.
6 // HISTORY:
7 // Created 2014 for Ghostel.
8 
9 /* Crash-course:
10  for (const auto ix : irange(end)) { CHECK_F(0 <= ix && ix < end); }
11  for (const auto ix : irange(begin, end)) { CHECK_F(begin <= ix && ix < end); }
12  for (const auto ix : indices(some_vector)) { CHECK_F(0 <= ix && ix < some_vector.size(); }
13  for (const char ch : emilib::cstr_range("hello world!"))
14  for (auto& value : it_range(begin, end)) { std::cout << value; }
15 */
16 
17 #pragma once
18 
19 #include <iterator>
20 #include <type_traits>
21 
22 #include <loguru.hpp>
23 
24 namespace emilib {
25 
26 template<typename Integer>
27 class Range
28 {
29 public:
30  static_assert(std::is_integral<Integer>::value, "Range should only be used for integers.");
31 
32  Range() : _begin(0), _end(0) { }
33 
34  Range(Integer begin, Integer end) : _begin(begin), _end(end)
35  {
36  DCHECK_LE_F(begin, end);
37  }
38 
39  struct iterator : public std::iterator<std::input_iterator_tag, Integer>
40  {
41  Integer value;
42 
43  explicit iterator(Integer v) : value(v) {}
44 
45  Integer operator*() const { return value; }
46 
47  iterator& operator++()
48  {
49  ++value;
50  return *this;
51  }
52 
53  friend bool operator!=(const iterator& a, const iterator& b)
54  {
55  return a.value != b.value;
56  }
57  };
58 
59  Integer operator[](size_t ix) const { return _begin + ix; }
60 
61  iterator begin() const { return iterator{ _begin }; }
62  iterator end() const { return iterator{ _end }; }
63 
64  Integer size() const { return _end - _begin; }
65 
66  Integer front() const { return _begin; }
67  Integer back() const { return _end - 1; }
68 
69 private:
70  Integer _begin, _end;
71 };
72 
74 template<typename Integer>
75 Range<Integer> irange(Integer end)
76 {
77  return {0, end};
78 }
79 
81 template<typename Integer>
82 Range<Integer> irange(Integer begin, Integer end)
83 {
84  return {begin, end};
85 }
86 
88 template<typename Integer>
89 Range<Integer> irange_inclusive(Integer first, Integer last)
90 {
91  return {first, last + 1};
92 }
93 
95 template<typename Integer = size_t, typename Container>
96 Range<Integer> indices(const Container& container)
97 {
98  return {0, static_cast<Integer>(container.size())};
99 }
100 
101 // -----------------------------------------------------------------------
102 
103 template<typename Integer, typename Visitor>
104 void repeat(Integer count, const Visitor& visitor)
105 {
106  CHECK_GE_F(count, static_cast<Integer>(0));
107  while (count != 0) {
108  visitor();
109  count -= 1;
110  }
111 }
112 
113 // -----------------------------------------------------------------------
114 
115 template<typename It>
117 {
118  It _begin, _end;
119 public:
120  IteratorRange(It begin, It end) : _begin(begin), _end(end) { }
121 
122  struct iterator
123  {
124  It _it;
125 
126  auto&& operator*() const { return *_it; }
127  auto&& operator->() const { return &*_it; }
128 
129  iterator& operator++()
130  {
131  ++_it;
132  return *this;
133  }
134 
135  friend bool operator!=(const iterator& a, const iterator& b)
136  {
137  return a._it != b._it;
138  }
139  };
140 
141  iterator begin() const { return { _begin }; }
142  iterator end() const { return { _end }; }
143 
144  bool empty() const { return _begin == _end; }
145  size_t size() const { return std::distance(_begin, _end); }
146 };
147 
149 template<typename It>
150 auto it_range(It begin, It end) { return IteratorRange<It>(begin, end); }
151 
152 // -----------------------------------------------------------------------
153 
154 template<typename Chr>
156 {
157  Chr* _begin;
158 public:
159  CStrRange(const Chr* c) : _begin(c) { }
160 
161  struct iterator
162  {
163  Chr* _ptr;
164 
165  Chr operator*() const { return *_ptr; }
166 
167  iterator& operator++()
168  {
169  ++_ptr;
170  return *this;
171  }
172 
173  friend bool operator!=(const iterator& a, const iterator& b)
174  {
175  return *a._ptr != *b._ptr;
176  }
177  };
178 
179  iterator begin() const
180  {
181  return { _begin };
182  }
183  iterator end() const
184  {
185  static Chr zero = 0;
186  return { &zero };
187  }
188 };
189 
191 template<typename Chr>
192 inline CStrRange<Chr> cstr_range(Chr* str) { return CStrRange<Chr>(str); }
193 
194 } // namespace emilib
Definition: irange.hpp:155
Definition: irange.hpp:122
Definition: irange.hpp:161
Definition: irange.hpp:116
Definition: irange.hpp:27
Definition: irange.hpp:39
Definition: coroutine.hpp:18