halcheck 1.0
Loading...
Searching...
No Matches
interface.hpp
1#ifndef HALCHECK_LIB_ITERATOR_INTERFACE_HPP
2#define HALCHECK_LIB_ITERATOR_INTERFACE_HPP
3
4// IWYU pragma: private, include <halcheck/lib/iterator.hpp>
5
6#include <halcheck/lib/iterator/base.hpp>
7#include <halcheck/lib/iterator/range.hpp>
8#include <halcheck/lib/numeric.hpp>
9#include <halcheck/lib/type_traits.hpp>
10
11namespace halcheck { namespace lib {
12
13namespace detail {
14template<typename I>
15using dereference = decltype(*std::declval<I &>());
16
17template<typename I>
18using equality = lib::boolean_testable<decltype(std::declval<const I &>() == std::declval<const I &>())>;
19
20template<typename I, typename D = decltype(std::declval<const I &>() - std::declval<const I &>())>
22
23template<typename I>
24using increment = decltype(++std::declval<I &>());
25
26template<typename I>
27using decrement = decltype(--std::declval<I &>());
28
29template<typename I, typename N>
30using addition = lib::same<decltype(std::declval<I &>() += std::declval<const N &>()), I &>;
31} // namespace detail
32
39template<typename Self>
41protected:
42 iterator_interface() = default;
43
44public:
51 template<
52 typename I = Self,
56 return *(static_cast<const I &>(*this) + n);
57 }
58
65 template<
66 typename I = Self,
69 I operator++(int) {
70 I &self = *static_cast<I *>(this);
71 auto output = self;
72 ++self;
73 return output;
74 }
75
81 template<
82 typename I = Self,
85 void operator++(int) {
86 ++*static_cast<I *>(this);
87 }
88
95 template<
96 typename I = Self,
99 I operator--(int) {
100 I &self = *static_cast<I *>(this);
101 auto output = self;
102 --self;
103 return output;
104 }
105
111 template<
112 typename I = Self,
115 void operator--(int) {
116 --*static_cast<I *>(this);
117 }
118
126 template<typename I = Self, HALCHECK_REQUIRE(lib::is_detected<detail::addition, I, lib::iter_difference_t<I>>())>
128 I &self = *static_cast<I *>(this);
129 self += -n;
130 return self;
131 }
132
133private:
140 template<typename I = Self, HALCHECK_REQUIRE(lib::is_detected<detail::equality, I>())>
141 friend bool operator!=(const Self &lhs, const Self &rhs) {
142 return !bool(lhs == rhs);
143 }
144
151 template<typename I = Self, HALCHECK_REQUIRE(lib::is_detected<detail::difference, I>())>
152 friend bool operator<(const Self &lhs, const Self &rhs) {
153 return (lhs - rhs) < 0;
154 }
155
162 template<typename I = Self, HALCHECK_REQUIRE(lib::is_detected<detail::difference, I>())>
163 friend bool operator>(const Self &lhs, const Self &rhs) {
164 return rhs < lhs;
165 }
166
173 template<typename I = Self, HALCHECK_REQUIRE(lib::is_detected<detail::difference, I>())>
174 friend bool operator<=(const Self &lhs, const Self &rhs) {
175 return !(rhs < lhs);
176 }
177
184 template<typename I = Self, HALCHECK_REQUIRE(lib::is_detected<detail::difference, I>())>
185 friend bool operator>=(const Self &lhs, const Self &rhs) {
186 return !(lhs < rhs);
187 }
188
196 template<typename I = Self, HALCHECK_REQUIRE(lib::is_detected<detail::addition, I, lib::iter_difference_t<I>>())>
197 friend Self operator+(Self i, lib::iter_difference_t<I> n) {
198 i += n;
199 return i;
200 }
201
209 template<typename I = Self, HALCHECK_REQUIRE(lib::is_detected<detail::addition, I, lib::iter_difference_t<I>>())>
210 friend Self operator+(lib::iter_difference_t<I> n, Self i) {
211 i += n;
212 return i;
213 }
214
222 template<typename I = Self, HALCHECK_REQUIRE(lib::is_detected<detail::addition, I, lib::iter_difference_t<I>>())>
223 friend Self operator-(Self i, lib::iter_difference_t<I> n) {
224 i -= n;
225 return i;
226 }
227};
228
234template<
235 typename Self,
238class view_interface : public lib::view_base {
239private:
240 template<typename T = Self>
241 T &self() {
242 return static_cast<T &>(*this);
243 }
244
245 template<typename T = Self>
246 const T &self() const {
247 return static_cast<const T &>(*this);
248 }
249
250public:
251 template<typename T = Self, HALCHECK_REQUIRE(lib::is_sized_range<const T>())>
252 constexpr bool empty() const {
253 return lib::size(self()) == 0;
254 }
255
256 template<typename T = Self, HALCHECK_REQUIRE(!lib::is_sized_range<const T>() && lib::is_forward_range<const T>())>
257 constexpr bool empty() const {
258 return lib::begin(self()) == lib::end(self());
259 }
260
261 template<typename T = Self, HALCHECK_REQUIRE(lib::is_sized_range<T>())>
262 bool empty() {
263 return lib::size(self()) == 0;
264 }
265
266 template<typename T = Self, HALCHECK_REQUIRE(!lib::is_sized_range<T>() && lib::is_forward_range<T>())>
267 bool empty() {
268 return lib::begin(self()) == lib::end(self());
269 }
270
271 template<typename T = Self, HALCHECK_REQUIRE(lib::is_sized_range<const T>() || lib::is_forward_range<const T>())>
272 constexpr explicit operator bool() const {
273 return !empty();
274 }
275
276 template<typename T = Self, HALCHECK_REQUIRE(lib::is_sized_range<T>() || lib::is_forward_range<T>())>
277 explicit operator bool() {
278 return !empty();
279 }
280
281 template<typename T = Self, HALCHECK_REQUIRE(lib::is_random_access_range<const T>())>
282 constexpr auto size() const -> decltype(lib::to_unsigned(lib::end(self<T>()) - lib::begin(self<T>()))) {
283 return lib::to_unsigned(lib::end(self()) - lib::begin(self()));
284 }
285
286 template<typename T = Self, HALCHECK_REQUIRE(lib::is_random_access_range<T>())>
287 auto size() -> decltype(lib::to_unsigned(lib::end(self<T>()) - lib::begin(self<T>()))) {
288 return lib::to_unsigned(lib::end(self()) - lib::begin(self()));
289 }
290
291 template<typename T = Self, HALCHECK_REQUIRE(lib::is_forward_range<const T>())>
292 constexpr auto front() const -> decltype(*lib::begin(self<T>())) {
293 return *lib::begin(self());
294 }
295
296 template<typename T = Self, HALCHECK_REQUIRE(lib::is_forward_range<T>())>
297 auto front() -> decltype(*lib::begin(self<T>())) {
298 return *lib::begin(self());
299 }
300
301 template<typename T = Self, HALCHECK_REQUIRE(lib::is_bidirectional_range<const T>())>
302 constexpr auto back() const -> decltype(*std::prev(lib::end(self<T>()))) {
303 return *std::prev(lib::end(self()));
304 }
305
306 template<typename T = Self, HALCHECK_REQUIRE(lib::is_bidirectional_range<T>())>
307 auto back() -> decltype(*std::prev(lib::end(self<T>()))) {
308 return *std::prev(lib::end(self()));
309 }
310
311 template<typename T = Self, HALCHECK_REQUIRE(lib::is_random_access_range<const T>())>
312 constexpr auto operator[](lib::range_difference_t<T> n) const -> decltype(lib::begin(self<T>())[n]) {
313 return lib::begin(self<T>())[n];
314 }
315
316 template<typename T = Self, HALCHECK_REQUIRE(lib::is_random_access_range<T>())>
317 auto operator[](lib::range_difference_t<T> n) -> decltype(lib::begin(self<T>())[n]) {
318 return lib::begin(self<T>())[n];
319 }
320};
321
322}} // namespace halcheck::lib
323
324#endif
I & operator-=(lib::iter_difference_t< I > n)
Advances this iterator the specified number of steps backwards.
Definition interface.hpp:127
void operator++(int)
Advances this iterator.
Definition interface.hpp:85
friend Self operator+(Self i, lib::iter_difference_t< I > n)
Advances an iterator by a specified amount.
Definition interface.hpp:197
I operator--(int)
Advances this iterator a step backwards.
Definition interface.hpp:99
constexpr lib::iter_reference_t< I > operator[](lib::iter_difference_t< I > n) const
Access the element at the specified index.
Definition interface.hpp:55
friend Self operator+(lib::iter_difference_t< I > n, Self i)
Advances an iterator by a specified amount.
Definition interface.hpp:210
I operator++(int)
Advances this iterator.
Definition interface.hpp:69
void operator--(int)
Advances this iterator a step backwards.
Definition interface.hpp:115
friend Self operator-(Self i, lib::iter_difference_t< I > n)
Advances an iterator backwards by a specified amount.
Definition interface.hpp:223
A utility class for easily defining new iterators.
Definition interface.hpp:40
An implementation of std::ranges::view_interface.
Definition interface.hpp:238
T declval(T... args)
typename std::iterator_traits< I >::difference_type iter_difference_t
The return type of operator- for an iterator.
Definition base.hpp:32
typename std::iterator_traits< I >::reference iter_reference_t
The return type of operator* for an iterator.
Definition base.hpp:24
HALCHECK_INLINE_CONSTEXPR struct halcheck::lib::@25 size
Obtains the size of a range.
lib::iter_difference_t< lib::iterator_t< R > > range_difference_t
The type of value returned by operator- for a range type's iterators.
Definition range.hpp:324
lib::make_unsigned_t< T > to_unsigned(T value)
Converts an integral value into its equivalent unsigned version.
Definition numeric.hpp:55
typename std::remove_cv< T >::type remove_cv_t
An implementation of std::remove_cv_t.
Definition type_traits.hpp:109
typename std::enable_if< Cond, T >::type enable_if_t
An implementation of std::enable_if_t.
Definition type_traits.hpp:93
#define HALCHECK_REQUIRE(...)
Expands to a template argument that is only valid if the given argument evaluates to true.
Definition type_traits.hpp:24
T prev(T... args)
Determines if a type is copy constructible and copy assignable.
Definition type_traits.hpp:355
An implementation of std::experimental::is_detected.
Definition type_traits.hpp:247
Determines whether a type is a range whose iterators satisfy lib::is_forward_iterator.
Definition range.hpp:195