iterator.hpp
Go to the documentation of this file.
1 
14 #ifndef CORE_ITERATOR_HPP
15 #define CORE_ITERATOR_HPP
16 
17 #include <functional>
18 #include <iterator>
19 #include <ostream>
20 
21 #include "type_traits.hpp"
22 #include "utility.hpp"
23 
24 namespace core {
25 inline namespace v2 {
26 
27 /* capacity */
28 template <class Container>
29 constexpr auto size (Container const& container) noexcept -> decltype(
30  container.size()
31 ) { return container.size(); }
32 
33 template <class T, ::std::size_t N>
34 constexpr ::std::size_t size (T const (&)[N]) noexcept { return N; }
35 
36 template <class Container>
37 constexpr bool empty (Container const& container) noexcept {
38  return container.empty();
39 }
40 
41 template <class T, std::size_t N>
42 constexpr bool empty (T const (&)[N]) noexcept { return false; }
43 
44 /* element access */
45 template <class Container>
46 constexpr auto front (Container const& container) -> decltype(
47  container.front()
48 ) { return container.front(); }
49 
50 template <class Container>
51 constexpr auto front (Container& container) -> decltype(container.front()) {
52  return container.front();
53 }
54 
55 template <class T, ::std::size_t N>
56 constexpr T const& front (T const (&array)[N]) noexcept { return array[0]; }
57 
58 template <class T, ::std::size_t N>
59 constexpr T& front (T (&array)[N]) noexcept { return array[0]; }
60 
61 template <class Container>
62 constexpr auto back (Container const& container) -> decltype(
63  container.back()
64 ) { return container.back(); }
65 
66 template <class Container>
67 constexpr auto back (Container& container) -> decltype(container.back()) {
68  return container.back();
69 }
70 
71 template <class T, ::std::size_t N>
72 constexpr T const& back (T const (&array)[N]) noexcept { return array[N - 1]; }
73 
74 template <class T, ::std::size_t N>
75 constexpr T& back (T (&array)[N]) noexcept { return array[N - 1]; }
76 
77 /* data access */
78 template <class Container>
79 constexpr auto data (Container const& container) noexcept -> decltype(
80  container.data()
81 ) { return container.data(); }
82 
83 template <class Container>
84 constexpr auto data (Container& container) noexcept -> decltype(
85  container.data()
86 ) { return container.data(); }
87 
88 template <class T, ::std::size_t N>
89 constexpr T const* data (T const (&array)[N]) noexcept { return array; }
90 
91 template <class T, ::std::size_t N>
92 constexpr T* data (T (&array)[N]) noexcept { return array; }
93 
94 /* iteration */
95 template <class Container>
96 auto cbegin (Container const& container) -> decltype(::std::begin(container)) {
97  return ::std::begin(container);
98 }
99 
100 template <class Container>
101 auto cend (Container const& container) -> decltype(::std::end(container)) {
102  return ::std::end(container);
103 }
104 
105 template <class Container>
106 auto rbegin (Container const& container) -> decltype(container.rbegin()) {
107  return container.rbegin();
108 }
109 
110 template <class Container>
111 auto rbegin (Container& container) -> decltype(container.rbegin()) {
112  return container.rbegin();
113 }
114 
115 template <class Container>
116 auto crbegin (Container const& container) -> decltype(rbegin(container)) {
117  return rbegin(container);
118 }
119 
120 template <class Container>
121 auto rend (Container const& container) -> decltype(container.rend()) {
122  return container.rend();
123 }
124 
125 template <class Container>
126 auto rend (Container& container) -> decltype(container.rend()) {
127  return container.rend();
128 }
129 
130 template <class Container>
131 auto crend (Container const& container) -> decltype(rend(container)) {
132  return rend(container);
133 }
134 
135 template <class Iterator>
136 ::std::reverse_iterator<Iterator> make_reverse_iterator (Iterator iter) {
137  return ::std::reverse_iterator<Iterator>(iter);
138 }
139 
140 template <
141  class DelimT,
142  class CharT=char,
143  class Traits=::std::char_traits<CharT>
144 > struct ostream_joiner final : ::std::iterator<
145  ::std::output_iterator_tag,
146  void,
147  void,
148  void,
149  void
150 > {
151  using delimiter_type = DelimT;
152  using ostream_type = ::std::basic_ostream<CharT, Traits>;
153  using traits_type = Traits;
154  using char_type = CharT;
155 
156  ostream_joiner (ostream_type& stream, delimiter_type const& delimiter) :
157  stream(stream),
158  delimiter { delimiter }
159  { }
160 
161  ostream_joiner (ostream_type& stream, delimiter_type&& delimiter) :
162  stream(stream),
163  delimiter { ::core::move(delimiter) },
164  first { true }
165  { }
166 
167  template <class T>
168  ostream_joiner& operator = (T const& item) {
169  if (not first and delimiter) { this->stream << delimiter; }
170  this->stream << item;
171  this->first = false;
172  return *this;
173  }
174 
175  ostream_joiner& operator ++ (int) noexcept { return *this; }
176  ostream_joiner& operator ++ () noexcept { return *this; }
177  ostream_joiner& operator * () noexcept { return *this; }
178 
179 private:
180  ostream_type& stream;
181  delimiter_type delimiter;
182  bool first;
183 };
184 
185 template <class T>
187  using iterator_category = ::std::bidirectional_iterator_tag;
188  using difference_type = T;
189  using value_type = T;
192 
193  static_assert(::std::is_integral<value_type>::value, "");
194 
195  explicit number_iterator (value_type value, value_type step=1) noexcept :
196  value { value },
197  step { step }
198  { }
199 
200  number_iterator (number_iterator const&) noexcept = default;
201  number_iterator () noexcept = default;
202  ~number_iterator () noexcept = default;
203 
204  number_iterator& operator = (number_iterator const&) noexcept = default;
205 
206  void swap (number_iterator& that) noexcept {
207  ::std::swap(this->value, that.value);
208  ::std::swap(this->step, that.step);
209  }
210 
211  reference operator * () noexcept { return this->value; }
212 
214  this->value += this->step;
215  return *this;
216  }
217 
218  number_iterator& operator -- () noexcept {
219  this->value -= this->step;
220  return *this;
221  }
222 
223  number_iterator operator ++ (int) const noexcept {
224  return number_iterator { this->value + this->step };
225  }
226 
227  number_iterator operator -- (int) const noexcept {
228  return number_iterator { this->value - this->step };
229  }
230 
231  bool operator == (number_iterator const& that) const noexcept {
232  return this->value == that.value and this->step == that.step;
233  }
234 
235  bool operator != (number_iterator const& that) const noexcept {
236  return this->value != that.value and this->step == that.step;
237  }
238 
239 private:
240  value_type value { };
241  value_type step { static_cast<value_type>(1) };
242 };
243 
244 template <class T>
245 void swap (number_iterator<T>& lhs, number_iterator<T>& rhs) noexcept {
246  lhs.swap(rhs);
247 }
248 
249 template <class CharT, class Traits, class DelimT>
251  ::std::basic_ostream<CharT, Traits>& stream,
252  DelimT&& delimiter
253 ) {
254  return ostream_joiner<decay_t<DelimT>, CharT, Traits> {
255  stream,
256  ::core::forward<DelimT>(delimiter)
257  };
258 }
259 
260 template <class T>
261 number_iterator<T> make_number_iterator (T value, T step) noexcept {
262  return number_iterator<T> { value, step };
263 }
264 
265 template <class T>
267  return number_iterator<T> { value };
268 }
269 
270 }} /* namespace core::v2 */
271 
272 #endif /* CORE_ITERATOR_HPP */
constexpr bool empty(Container const &container) noexcept
Definition: iterator.hpp:37
number_iterator< T > make_number_iterator(T value, T step) noexcept
Definition: iterator.hpp:261
auto rbegin(Container const &container) -> decltype(container.rbegin())
Definition: iterator.hpp:106
constexpr auto size(Container const &container) noexcept -> decltype(container.size())
Definition: iterator.hpp:29
auto cend(Container const &container) -> decltype(::std::end(container))
Definition: iterator.hpp:101
Copyright © 2013 - 2015 MNMLSTC.
Definition: algorithm.hpp:23
add_pointer_t< T > pointer
Definition: iterator.hpp:191
::std::bidirectional_iterator_tag iterator_category
Definition: iterator.hpp:187
typename ::std::add_lvalue_reference< T >::type add_lvalue_reference_t
ostream_joiner(ostream_type &stream, delimiter_type &&delimiter)
Definition: iterator.hpp:161
number_iterator(value_type value, value_type step=1) noexcept
Definition: iterator.hpp:195
::std::reverse_iterator< Iterator > make_reverse_iterator(Iterator iter)
Definition: iterator.hpp:136
ostream_joiner(ostream_type &stream, delimiter_type const &delimiter)
Definition: iterator.hpp:156
constexpr auto data(Container const &container) noexcept -> decltype(container.data())
Definition: iterator.hpp:79
ostream_joiner< decay_t< DelimT >, CharT, Traits > make_ostream_joiner(::std::basic_ostream< CharT, Traits > &stream, DelimT &&delimiter)
Definition: iterator.hpp:250
ostream_joiner & operator*() noexcept
Definition: iterator.hpp:177
bool operator==(basic_string_view< CharT, Traits > lhs, basic_string_view< CharT, Traits > rhs) noexcept
auto crend(Container const &container) -> decltype(rend(container))
Definition: iterator.hpp:131
void swap(any &lhs, any &rhs) noexcept
Definition: any.hpp:333
auto cbegin(Container const &container) -> decltype(::std::begin(container))
Definition: iterator.hpp:96
ostream_joiner & operator++() noexcept
Definition: iterator.hpp:176
constexpr auto front(Container const &container) -> decltype(container.front())
Definition: iterator.hpp:46
typename ::std::add_pointer< T >::type add_pointer_t
void swap(number_iterator< T > &lhs, number_iterator< T > &rhs) noexcept
Definition: iterator.hpp:245
constexpr auto back(Container const &container) -> decltype(container.back())
Definition: iterator.hpp:62
auto crbegin(Container const &container) -> decltype(rbegin(container))
Definition: iterator.hpp:116
ostream_joiner & operator=(T const &item)
Definition: iterator.hpp:168
add_lvalue_reference_t< T > reference
Definition: iterator.hpp:190
bool operator!=(basic_string_view< CharT, Traits > lhs, basic_string_view< CharT, Traits > rhs) noexcept
void swap(number_iterator &that) noexcept
Definition: iterator.hpp:206
auto rend(Container const &container) -> decltype(container.rend())
Definition: iterator.hpp:121
auto move(Range &&rng, OutputIt &&it) -> enable_if_t< is_range< Range >::value, decay_t< OutputIt > >
Definition: algorithm.hpp:736
::std::basic_ostream< CharT, Traits > ostream_type
Definition: iterator.hpp:152