OpenKalman
iterator.hpp
Go to the documentation of this file.
1 /* This file is part of OpenKalman, a header-only C++ library for
2  * Kalman filters and other recursive filters.
3  *
4  * Copyright (c) 2025 Christopher Lee Ogden <ogden@gatech.edu>
5  *
6  * This Source Code Form is subject to the terms of the Mozilla Public
7  * License, v. 2.0. If a copy of the MPL was not distributed with this
8  * file, You can obtain one at https://mozilla.org/MPL/2.0/.
9  */
10 
17 #ifndef OPENKALMAN_COMPATIBILITY_ITERATOR_HPP
18 #define OPENKALMAN_COMPATIBILITY_ITERATOR_HPP
19 
20 #ifndef __cpp_lib_ranges
21 
22 #include <iterator>
23 #include "language-features.hpp"
24 #include "common_reference.hpp"
25 
26 namespace OpenKalman
27 {
28  // ---
29  // indirectly_readable_traits
30  // ---
31 
32  namespace detail_indirectly_readable
33  {
34  struct no_value_type {};
35 
36  template<typename, typename = void>
37  struct cond_value_type {};
38 
39  template<typename T>
40  struct cond_value_type<T, std::enable_if_t<std::is_object_v<T>>> { using value_type = std::remove_cv_t<T>; };
41 
42  template<typename, typename = void>
43  struct has_member_value_type_impl : std::false_type {};
44 
45  template<typename T>
46  struct has_member_value_type_impl<T, std::void_t<typename T::value_type>> : std::true_type {};
47 
48  template<typename T>
49  inline constexpr bool has_member_value_type = has_member_value_type_impl<T>::value;
50 
51  template<typename, typename = void>
52  struct has_member_element_type_impl : std::false_type {};
53 
54  template<typename T>
55  struct has_member_element_type_impl<T, std::void_t<typename T::element_type>> : std::true_type {};
56 
57  template<typename T>
58  inline constexpr bool has_member_element_type = has_member_element_type_impl<T>::value;
59  }
60 
61 
62  template<typename I, typename = void>
64 
65  template<typename T>
67 
68  template<typename I>
69  struct indirectly_readable_traits<I, std::enable_if_t<std::is_array_v<I>>>
70  { using value_type = std::remove_cv_t<std::remove_extent_t<I>>; };
71 
72  template<typename T>
74 
75  template<typename T>
76  struct indirectly_readable_traits<T, std::enable_if_t<
77  detail_indirectly_readable::has_member_value_type<T> and
78  not detail_indirectly_readable::has_member_element_type<T>>>
79  : detail_indirectly_readable::cond_value_type<typename T::value_type> {};
80 
81  template<typename T>
82  struct indirectly_readable_traits<T, std::enable_if_t<
83  not detail_indirectly_readable::has_member_value_type<T> and
84  detail_indirectly_readable::has_member_element_type<T>>>
85  : detail_indirectly_readable::cond_value_type<typename T::element_type> {};
86 
87  template<typename T>
88  struct indirectly_readable_traits<T, std::enable_if_t<
89  detail_indirectly_readable::has_member_value_type<T> and
90  detail_indirectly_readable::has_member_element_type<T>>>
91  : std::conditional_t<
92  std::is_same_v<std::remove_cv_t<typename T::element_type>, std::remove_cv_t<typename T::value_type>>,
93  detail_indirectly_readable::cond_value_type<typename T::value_type>,
94  detail_indirectly_readable::no_value_type> {};
95 
96 
97  // ---
98  // incrementable_traits
99  // ---
100 
101  namespace detail
102  {
103  template<typename, typename = void>
104  struct has_member_difference_type : std::false_type {};
105 
106  template<typename T>
107  struct has_member_difference_type<T, std::void_t<typename T::difference_type>> : std::true_type {};
108  }
109 
110 
111  template<typename I, typename = void>
113 
114  template<typename T>
115  struct incrementable_traits<T*, std::enable_if_t<std::is_object_v<T>>>
116  {
117  using difference_type = std::ptrdiff_t;
118  };
119 
120  template<typename T>
122 
123  template<typename T>
124  struct incrementable_traits<T, std::enable_if_t<detail::has_member_difference_type<T>::value>>
125  {
126  using difference_type = typename T::difference_type;
127  };
128 
129  template<typename T>
130  struct incrementable_traits<T, std::enable_if_t<not detail::has_member_difference_type<T>::value and
131  std::is_integral_v<decltype(std::declval<const T&>() - std::declval<const T&>())>>>
132  {
133  using difference_type = std::make_signed_t<decltype(std::declval<T>() - std::declval<T>())>;
134  };
135 
136 
137  // ---
138  // primitives
139  // ---
140 
141  namespace detail
142  {
143  template<typename T, typename = void>
145 
146  template<typename T>
147  struct iter_value_impl<T, std::void_t<typename std::iterator_traits<T>::value_type>> : std::iterator_traits<T> {};
148 
149 
150  template<typename T, typename = void>
152 
153  template<typename T>
154  struct iter_difference_impl<T, std::void_t<typename std::iterator_traits<T>::difference_type>> : std::iterator_traits<T> {};
155  }
156 
157 
158  template<typename I>
159  using iter_value_t = typename detail::iter_value_impl<remove_cvref_t<I>>::value_type;
160 
161  template<typename I>
162  using iter_reference_t = decltype(*std::declval<I&>());
163 
164  template<typename I>
165  using iter_difference_t = typename detail::iter_difference_impl<remove_cvref_t<I>>::difference_type;
166 
167  template<typename I>
168  using iter_rvalue_reference_t = decltype(std::move(*std::declval<I&>()));
169 
170 
171  // ---
172  // indirectly_readable
173  // ---
174 
175  namespace detail
176  {
177  template<typename I, typename = void, typename = void>
178  struct is_indirectly_readable : std::false_type {};
179 
180  template<typename I>
182  std::void_t<iter_value_t<I>, iter_reference_t<I>, iter_rvalue_reference_t<I>>,
183  std::enable_if_t<std::is_same<decltype(*std::declval<I>()), iter_reference_t<I>>::value>> : std::true_type {};
184  }
185 
186 
187  template<typename I>
188  inline constexpr bool indirectly_readable = detail::is_indirectly_readable<remove_cvref_t<I>>::value;
189 
190 
191  template<typename T, std::enable_if_t<indirectly_readable<T>, int > = 0>
192  using iter_const_reference_t = common_reference_t<const iter_value_t<T>&&, iter_reference_t<T>>;
193 
194  template<typename T, std::enable_if_t<indirectly_readable<T>, int > = 0>
195  using iter_common_reference_t = common_reference_t<iter_reference_t<T>, iter_value_t<T>&>;
196 
197 
198  // ---
199  // indirectly_writable
200  // ---
201 
202  namespace detail
203  {
204  template<typename Out, typename T, typename = void>
205  struct is_indirectly_writable : std::false_type {};
206 
207  template<typename Out, typename T>
208  struct is_indirectly_writable<Out, T,
209  std::void_t<
210  decltype(*std::declval<Out&>() = std::declval<T&&>()),
211  decltype(*std::declval<Out&&>() = std::declval<T&&>()),
212  decltype(const_cast<const iter_reference_t<Out>&&>(*std::declval<Out&>()) = std::declval<T&&>()),
213  decltype(const_cast<const iter_reference_t<Out>&&>(*std::declval<Out&&>()) = std::declval<T&&>())
214  >> : std::true_type {};
215  }
216 
217 
218  template<typename Out, typename T>
219  inline constexpr bool indirectly_writable = detail::is_indirectly_readable<Out, T>::value;
220 
221 
222  // ---
223  // weakly_incrementable
224  // ---
225 
226  namespace detail
227  {
228  template<typename I, typename = void, typename = void>
229  struct is_weakly_incrementable : std::false_type {};
230 
231  template<typename I>
232  struct is_weakly_incrementable<I, std::void_t<iter_difference_t<I>, decltype(std::declval<I&>()++)>,
233  std::enable_if_t<std::is_same<decltype(++std::declval<I&>()), I&>::value>> : std::true_type {};
234  }
235 
236 
237  template<typename I>
238  inline constexpr bool weakly_incrementable = detail::is_weakly_incrementable<I>::value;
239 
240 
241  // ---
242  // input_or_output_iterator
243  // ---
244 
245  namespace detail
246  {
247  template<typename I, typename = void, typename = void>
248  struct is_input_or_output_iterator : std::false_type {};
249 
250  template<typename I>
252  std::void_t<iter_value_t<I>, iter_reference_t<I>, iter_rvalue_reference_t<I>>,
253  std::enable_if_t<std::is_same<decltype(*std::declval<I>()), iter_reference_t<I>>::value>> : std::true_type {};
254  }
255 
256 
257  template<typename I>
258  inline constexpr bool input_or_output_iterator = detail::is_input_or_output_iterator<I>::value and weakly_incrementable<I>;
259 
260 
261  // ---
262  // input_iterator
263  // ---
264 
265  template<typename I>
266  inline constexpr bool input_iterator =
267  input_or_output_iterator<I> and
268  indirectly_readable<I>;
269 
270 
271  // ---
272  // output_iterator
273  // ---
274 
275  namespace detail
276  {
277  template<typename I, typename T, typename = void>
278  struct output_iterator_impl : std::false_type {};
279 
280  template<typename I, typename T>
281  struct output_iterator_impl<I, T, std::void_t<decltype(*std::declval<I&>()++ = std::declval<T&&>())>> : std::true_type {};
282  }
283 
284 
285  template<typename I, typename T>
286  inline constexpr bool output_iterator =
287  input_or_output_iterator<I> and
288  indirectly_writable<I, T> and
290 
291 
292  // ---
293  // incrementable
294  // ---
295 
296  namespace detail
297  {
298  template<typename I, typename = void>
299  struct is_incrementable : std::false_type {};
300 
301  template<typename I>
302  struct is_incrementable<I, std::enable_if_t<std::is_same<decltype(std::declval<I&>()++), I>::value>> : std::true_type {};
303  }
304 
305 
306  template<typename I>
307  inline constexpr bool incrementable =
308  std::is_copy_constructible_v<I> and
309  std::is_object_v<I> and
310  std::is_move_constructible_v<I> and
311  std::is_assignable_v<I&, I> and
312  std::is_assignable_v<I&, I&> and
313  std::is_assignable_v<I&, const I&> and
314  std::is_assignable_v<I&, const I> and
315  std::is_default_constructible_v<I> and
316  weakly_incrementable<I> and
318 
319 
320  // ---
321  // forward_iterator
322  // ---
323 
324  template<typename I>
325  inline constexpr bool forward_iterator =
326  input_iterator<I> and
327  incrementable<I>;
328 
329 
330  // ---
331  // bidirectional_iterator
332  // ---
333 
334  namespace detail
335  {
336  template<typename I, typename = void>
337  struct is_bidirectional_iterator : std::false_type {};
338 
339  template<typename I>
340  struct is_bidirectional_iterator<I, std::enable_if_t<
341  std::is_same<decltype(--std::declval<I&>()), I&>::value and
342  std::is_same<decltype(std::declval<I&>()--), I>::value>> : std::true_type {};
343  }
344 
345 
346  template<typename I>
347  inline constexpr bool bidirectional_iterator =
348  forward_iterator<I> and
350 
351 
352  // ---
353  // random_access_iterator
354  // ---
355 
356  namespace detail
357  {
358  template<typename I, typename = void>
359  struct is_random_access_iterator : std::false_type {};
360 
361  template<typename I>
362  struct is_random_access_iterator<I, std::enable_if_t<
363  std::is_same_v<decltype(std::declval<I&>() += std::declval<iter_difference_t<I>>()), I&> and
364  std::is_same_v<decltype(std::declval<const I&>() + std::declval<iter_difference_t<I>>()), I> and
365  std::is_same_v<decltype(std::declval<iter_difference_t<I>>() + std::declval<const I&>()), I> and
366  std::is_same_v<decltype(std::declval<I&>() -= std::declval<iter_difference_t<I>>()), I&> and
367  std::is_same_v<decltype(std::declval<const I&>() - std::declval<iter_difference_t<I>>()), I> and
368  std::is_same_v<decltype(std::declval<const I&>()[std::declval<iter_difference_t<I>>()]), iter_reference_t<I>>
369  >> : std::true_type {};
370  }
371 
372 
373  template<typename I>
374  inline constexpr bool random_access_iterator =
375  bidirectional_iterator<I> and
377 
378 
379  // ---
380  // sentinel_for, sized_sentinel_for
381  // ---
382 
383  namespace detail
384  {
385  template<typename T, typename U, typename = void>
386  struct WeaklyEqualityComparableWith : std::false_type {};
387 
388  template<typename T, typename U>
389  struct WeaklyEqualityComparableWith<T, U, std::enable_if_t<
390  std::is_convertible_v<decltype(std::declval<const T&>() == std::declval<const U&>()), bool> and
391  std::is_convertible_v<decltype(std::declval<const T&>() != std::declval<const U&>()), bool> and
392  std::is_convertible_v<decltype(std::declval<const U&>() == std::declval<const T&>()), bool> and
393  std::is_convertible_v<decltype(std::declval<const U&>() != std::declval<const T&>()), bool>
394  >> : std::true_type {};
395 
396  template<typename T, typename U, typename = void>
397  struct subtractable : std::false_type {};
398 
399  template<typename I, typename S>
400  struct subtractable<I, S, std::enable_if_t<
401  std::is_same_v<decltype(std::declval<const S&>() - std::declval<const I&>()), iter_difference_t<I>> and
402  std::is_same_v<decltype(std::declval<const I&>() - std::declval<const S&>()), iter_difference_t<I>>
403  >> : std::true_type {};
404 
405  }
406 
407 
408  template<typename S, typename I>
409  inline constexpr bool sentinel_for =
410  semiregular<S> and input_or_output_iterator<I> and detail::WeaklyEqualityComparableWith<S, I>::value;
411 
412 
413  template<typename S, typename I>
414  inline constexpr bool sized_sentinel_for = sentinel_for<S, I> and
415  /*not std::disable_sized_sentinel_for<std::remove_cv_t<S>, std::remove_cv_t<I>> and */
417 
418 
419  // ---
420  // unreachable_sentinel_t, unreachable_sentinel
421  // ---
422 
424  {
425  template<typename I, std::enable_if_t<weakly_incrementable<I>, int> = 0>
426  friend constexpr bool
427  operator==(unreachable_sentinel_t, unreachable_sentinel_t) noexcept { return false; };
428 
429  template<typename I, std::enable_if_t<weakly_incrementable<I>, int> = 0>
430  friend constexpr bool
431  operator==(unreachable_sentinel_t, const I&) noexcept { return false; };
432 
433  template<typename I, std::enable_if_t<weakly_incrementable<I>, int> = 0>
434  friend constexpr bool
435  operator==(const I&, unreachable_sentinel_t) noexcept { return false; };
436  };
437 
438 
439  inline constexpr unreachable_sentinel_t unreachable_sentinel {};
440 
441 
442 }
443 
444 #endif
445 
446 #endif //OPENKALMAN_COMPATIBILITY_ITERATOR_HPP
Definition: iterator.hpp:63
Definition: iterator.hpp:278
Definition: tuple_reverse.hpp:103
constexpr bool value
T is numerical value or is reducible to a numerical value.
Definition: value.hpp:31
Definition: iterator.hpp:423
Definition: iterator.hpp:151
The root namespace for OpenKalman.
Definition: basics.hpp:34
Definitions relating to the availability of c++ language features.
Definition: iterator.hpp:205
Definition: iterator.hpp:112
Definition: iterator.hpp:178
Definition: iterator.hpp:299
Definition: iterator.hpp:144
Definition: iterator.hpp:397