halcheck 1.0
Loading...
Searching...
No Matches
iota.hpp
1#ifndef HALCHECK_LIB_ITERATOR_IOTA_HPP
2#define HALCHECK_LIB_ITERATOR_IOTA_HPP
3
4// IWYU pragma: private, include <halcheck/lib/iterator.hpp>
5
6#include <halcheck/lib/iterator/base.hpp>
7#include <halcheck/lib/iterator/interface.hpp>
8#include <halcheck/lib/pp.hpp>
9#include <halcheck/lib/type_traits.hpp>
10
11#include <cstdint>
12#include <iterator>
13
14namespace halcheck { namespace lib {
15
21template<typename I, typename = void>
22struct iota_diff {};
23
24template<typename I>
25struct iota_diff<I, lib::enable_if_t<!std::is_integral<I>()>> {
26 using type = lib::iter_difference_t<I>;
27};
28
29template<typename I>
30struct iota_diff<I, lib::enable_if_t<(std::is_integral<I>() && sizeof(lib::iter_difference_t<I>) > sizeof(I))>> {
31 using type = lib::iter_difference_t<I>;
32};
33
34template<typename I>
35struct iota_diff<I, lib::enable_if_t<std::is_integral<I>() && (sizeof(std::int8_t) > sizeof(I))>> {
36 using type = std::int8_t;
37};
38
39template<typename I>
40struct iota_diff<I, lib::enable_if_t<std::is_integral<I>() && (sizeof(std::int16_t) > sizeof(I))>> {
41 using type = std::int16_t;
42};
43
44template<typename I>
45struct iota_diff<I, lib::enable_if_t<std::is_integral<I>() && (sizeof(std::int32_t) > sizeof(I))>> {
46 using type = std::int32_t;
47};
48
49template<typename I>
50struct iota_diff<I, lib::enable_if_t<std::is_integral<I>() && (sizeof(std::int64_t) > sizeof(I))>> {
51 using type = std::int64_t;
52};
53
54template<typename I>
55struct iota_diff<I, lib::enable_if_t<std::is_integral<I>() && sizeof(I) >= sizeof(std::int64_t)>> {
56 using type = std::intmax_t;
57};
58
64template<typename I>
66
72template<typename T>
73class iota_iterator : private lib::iterator_interface<iota_iterator<T>> {
74public:
75 static_assert(std::is_integral<T>(), "T must be an integral type");
76
77 using lib::iterator_interface<iota_iterator>::operator++;
78 using lib::iterator_interface<iota_iterator>::operator--;
79 using lib::iterator_interface<iota_iterator>::operator-=;
80 using lib::iterator_interface<iota_iterator>::operator[];
81
85 using value_type = T;
86
90 using reference = T;
91
95 using pointer = void;
96
101
106
110 constexpr iota_iterator() = default;
111
116 constexpr explicit iota_iterator(T value) : _value(std::move(value)) {}
117
122 constexpr value_type operator*() const noexcept { return _value; }
123
129 ++_value;
130 return *this;
131 }
132
138 --_value;
139 return *this;
140 }
141
147 template<typename U = T, HALCHECK_REQUIRE(std::is_unsigned<U>())>
149 if (n >= 0)
150 _value += static_cast<U>(n);
151 else
152 _value -= static_cast<U>(-n);
153 }
154
160 template<typename U = T, HALCHECK_REQUIRE(!std::is_unsigned<U>())>
162 _value += n;
163 }
164
165private:
167
173 friend bool operator==(const iota_iterator &lhs, const iota_iterator &rhs) { return lhs._value == rhs._value; }
174
180 friend difference_type operator-(const iota_iterator &lhs, const iota_iterator &rhs) {
181 using D = difference_type;
182
183 if (std::is_signed<T>())
184 return D(D(lhs._value) - D(rhs._value));
185 else if (rhs._value > lhs._value)
186 return D(-D(rhs._value) - D(lhs._value));
187 else
188 return D(lhs._value - rhs._value);
189 }
190
191 T _value;
192};
193
206 template<typename T>
207 lib::iota_iterator<T> operator()(T value) const {
208 return lib::iota_iterator<T>(std::move(value));
209 }
211
212template<typename T, HALCHECK_REQUIRE(std::is_integral<T>())>
213class iota_view : public lib::view_interface<iota_view<T>> {
214public:
215 iota_view() = default;
216 iota_view(T begin, T end) : _begin(std::move(begin)), _end(std::move(end)) {}
217
218 iota_iterator<T> begin() const { return iota_iterator<T>(_begin); }
219 iota_iterator<T> end() const { return iota_iterator<T>(_end); }
220
222 return _begin < 0 ? (_end < 0 ? lib::to_unsigned(-_begin) - lib::to_unsigned(-_end)
223 : lib::to_unsigned(_end) + lib::to_unsigned(-_begin))
224 : lib::to_unsigned(_end) - lib::to_unsigned(_begin);
225 }
226
227private:
228 T _begin{};
229 T _end{};
230};
231
233 template<typename T>
234 lib::iota_view<T> operator()(T begin, T end) const {
235 return lib::iota_view<T>(std::move(begin), std::move(end));
236 }
237
238 template<typename T>
239 lib::iota_view<T> operator()(T end) const {
240 return lib::iota_view<T>(0, std::move(end));
241 }
242} iota;
243
244}} // namespace halcheck::lib
245
246#endif
constexpr iota_iterator(T value)
Constructs an iota_iterator pointing to the specified value.
Definition iota.hpp:116
friend difference_type operator-(const iota_iterator &lhs, const iota_iterator &rhs)
Determines the distance between two iterators.
Definition iota.hpp:180
iota_iterator & operator--()
Advances this iterator backwards.
Definition iota.hpp:137
friend bool operator==(const iota_iterator &lhs, const iota_iterator &rhs)
Determines if two iterators are equal.
Definition iota.hpp:173
iota_iterator & operator++()
Advances this iterator.
Definition iota.hpp:128
constexpr value_type operator*() const noexcept
Obtains the value pointed to by this iterator.
Definition iota.hpp:122
An iterator pointing to an integral value.
Definition iota.hpp:73
void pointer
This type does not support operator->.
Definition iota.hpp:95
constexpr iota_iterator()=default
Constructs a default iota_iterator.
T value_type
The type of value pointed to by this iterator.
Definition iota.hpp:85
T reference
The return type of operator*.
Definition iota.hpp:90
lib::iota_diff_t< T > difference_type
The return type of operator-.
Definition iota.hpp:100
A utility class for easily defining new iterators.
Definition interface.hpp:40
HALCHECK_INLINE_CONSTEXPR struct halcheck::lib::@23 make_iota_iterator
Constructs an iota_iterator.
typename std::iterator_traits< I >::difference_type iter_difference_t
The return type of operator- for an iterator.
Definition base.hpp:32
typename iota_diff< I >::type iota_diff_t
Computes a type large enough to contain the difference between two instances of an iterator.
Definition iota.hpp:65
HALCHECK_INLINE_CONSTEXPR struct halcheck::lib::@25 size
Obtains the size of a range.
HALCHECK_INLINE_CONSTEXPR struct halcheck::lib::end_cpo::@28 end
Gets an iterator to past the end of a range.
lib::make_unsigned_t< T > to_unsigned(T value)
Converts an integral value into its equivalent unsigned version.
Definition numeric.hpp:55
#define HALCHECK_INLINE_CONSTEXPR
A backwards-compatible substitute for inline constexpr.
Definition pp.hpp:70
typename std::enable_if< Cond, T >::type enable_if_t
An implementation of std::enable_if_t.
Definition type_traits.hpp:93
typename std::make_unsigned< T >::type make_unsigned_t
An implementation of std::make_unsigned_t.
Definition type_traits.hpp:125
STL namespace.
Computes a type large enough to contain the difference between two instances of an iterator.
Definition iota.hpp:22