OpenKalman
repeat.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_VIEWS_REPEAT_HPP
18 #define OPENKALMAN_COMPATIBILITY_VIEWS_REPEAT_HPP
19 
20 #ifndef __cpp_lib_ranges_repeat
21 
22 #include <type_traits>
23 #ifdef __cpp_lib_ranges
24 #include <ranges>
25 #else
27 #include "view_interface.hpp"
28 #endif
30 #include "basics/compatibility/ranges/range-access.hpp"
33 
34 namespace OpenKalman::ranges
35 {
39 #ifdef __cpp_lib_ranges
40  template<std::move_constructible W, std::semiregular Bound = unreachable_sentinel_t> requires
41  std::is_object_v<W> and std::same_as<W, std::remove_cv_t<W>> and
42  (OpenKalman::internal::is_signed_integer_like<Bound> or
43  (OpenKalman::internal::is_integer_like<Bound> and weakly_incrementable<Bound> or
44  std::same_as<Bound, std::unreachable_sentinel_t>))
45  struct repeat_view : std::ranges::view_interface<repeat_view<W, Bound>>
46 #else
47  template<typename W, typename Bound = unreachable_sentinel_t>
48  struct repeat_view : view_interface<repeat_view<W, Bound>>
49 #endif
50  {
51  struct iterator
52  {
53  private:
54 
55 #ifdef __cpp_lib_ranges
56  using index_type = std::conditional_t<std::is_same_v<Bound, std::unreachable_sentinel_t>, std::ptrdiff_t, Bound>;
57 #else
58  using index_type = std::conditional_t<std::is_same_v<Bound, unreachable_sentinel_t>, std::ptrdiff_t, Bound>;
59 #endif
60 
61  template<typename I>
62  using iota_diff_t = std::conditional_t<
63  not std::is_integral_v<I> or (sizeof(iter_difference_t<I>) > sizeof(I)), iter_difference_t<I>, std::ptrdiff_t>;
64 
65  public:
66 
67  using iterator_concept = std::random_access_iterator_tag;
68  using iterator_category = std::random_access_iterator_tag;
69  using value_type = W;
70  using difference_type = std::conditional_t<OpenKalman::internal::is_signed_integer_like<index_type>,
71  index_type, iota_diff_t<index_type>>;
72  using reference = W;
73  using pointer = void;
74 
75  iterator() = default;
76 
77  constexpr explicit iterator(const W* value, index_type b = index_type{}) : value_ {value}, current_ {b} {}
78 
79  constexpr const W& operator*() const noexcept { return *value_; }
80 
81  constexpr const W& operator[](difference_type n) const noexcept { return *(*this + n); }
82 
83  constexpr iterator& operator++() { ++current_; return *this; }
84 
85  constexpr auto operator++(int) { auto tmp = *this; ++*this; return tmp; }
86 
87  constexpr iterator& operator--() { --current_; return *this; }
88 
89  constexpr auto operator--(int) { auto tmp = *this; --*this; return tmp; }
90 
91  constexpr iterator& operator+=(difference_type n) { current_ += n; return *this; }
92 
93  constexpr iterator& operator-=(difference_type n) { current_ -= n; return *this; }
94 
95  friend constexpr bool operator==(const iterator& x, const iterator& y) { return x.current_ == y.current_; }
96 
97 #ifdef __cpp_impl_three_way_comparison
98  friend constexpr auto operator<=>(const iterator& x, const iterator& y) { return x.current_ <=> y.current_; }
99 #else
100  friend constexpr bool operator!=(const iterator& x, const iterator& y) { return x.current_ != y.current_; }
101  friend constexpr bool operator<(const iterator& x, const iterator& y) { return x.current_ < y.current_; }
102  friend constexpr bool operator>(const iterator& x, const iterator& y) { return x.current_ > y.current_; }
103  friend constexpr bool operator<=(const iterator& x, const iterator& y) { return x.current_ <= y.current_; }
104  friend constexpr bool operator>=(const iterator& x, const iterator& y) { return x.current_ >= y.current_; }
105 #endif
106 
107  friend constexpr auto operator+(iterator i, difference_type n) { i += n; return i; }
108 
109  friend constexpr auto operator+(difference_type n, iterator i) { i += n; return i; }
110 
111  friend constexpr auto operator-(iterator i, difference_type n) { i -= n; return i; }
112 
113  friend constexpr auto operator-(const iterator& x, const iterator& y)
114  {
115  return static_cast<difference_type>(x.current_) - static_cast<difference_type>(y.current_);
116  }
117 
118  private:
119 
120  const W* value_;
121  index_type current_;
122 
123  };
124 
125 
126 #ifdef __cpp_lib_concepts
127  repeat_view() requires std::default_initializable<W> = default;
128 #else
129  template<bool Enable = true, std::enable_if_t<Enable and std::is_default_constructible_v<W>, int> = 0>
130  constexpr repeat_view() {};
131 #endif
132 
133 
134  constexpr explicit
135  repeat_view(const W& value, Bound bound = {}) : value_ {value}, bound_ {bound} {}
136 
137 
138  constexpr explicit
139  repeat_view(W&& value, Bound bound = {}) : value_ {std::move(value)}, bound_ {bound} {}
140 
141 
142 #ifdef __cpp_lib_concepts
143  template <typename...WArgs, typename...BoundArgs> requires
144  std::constructible_from<W, WArgs...> and std::constructible_from<Bound, BoundArgs...>
145 #else
146  template<typename...WArgs, typename...BoundArgs, std::enable_if_t<
147  constructible_from<W, WArgs...> and constructible_from<Bound, BoundArgs...>, int> = 0>
148 #endif
149  constexpr explicit
150  repeat_view(std::piecewise_construct_t, std::tuple<WArgs...> value_args, std::tuple<BoundArgs...> bound_args = std::tuple<>{})
151  : value_ {std::make_from_tuple<W>(std::move(value_args))}, bound_ {std::make_from_tuple<Bound>(std::move(bound_args))} {}
152 
153 
154  constexpr iterator
155  begin() const { return iterator {std::addressof(*value_)}; }
156 
157 
158  template<bool Enable = true, std::enable_if_t<Enable and not std::is_same_v<Bound, unreachable_sentinel_t>, int> = 0>
159  constexpr iterator
160  end() const { return iterator {std::addressof(*value_), bound_}; }
161 
162 
163  constexpr unreachable_sentinel_t
164  end() const { return {}; }
165 
166 
167 #ifdef __cpp_lib_concepts
168  constexpr auto
169  size() const requires (not std::same_as<Bound, std::unreachable_sentinel_t>)
170 #else
171  template<bool Enable = true, std::enable_if_t<Enable and not std::is_same_v<Bound, unreachable_sentinel_t>, int> = 0>
172  constexpr auto size() const
173 #endif
174  {
175  if constexpr (std::is_integral_v<Bound>) return static_cast<std::make_unsigned_t<Bound>>(bound_);
176  else return static_cast<std::size_t>(bound_);
177  }
178 
179  private:
180 
182 
183  Bound bound_;
184 
185  }; // struct repeat_view
186 
187 
188  template<typename W, typename Bound = unreachable_sentinel_t>
189  repeat_view(W, Bound = {}) -> repeat_view<W, Bound>;
190 
191 }
192 
193 
195 {
196  namespace detail
197  {
199  {
200 #ifdef __cpp_lib_concepts
201  template<std::move_constructible W, std::semiregular Bound = unreachable_sentinel_t> requires
202  std::is_object_v<W> and std::same_as<W, std::remove_cv_t<W>> and
203  (OpenKalman::internal::is_signed_integer_like<Bound> or
204  (OpenKalman::internal::is_integer_like<Bound> and weakly_incrementable<Bound> or
205  std::same_as<Bound, std::unreachable_sentinel_t>))
206 #else
207  template<typename W, typename Bound = unreachable_sentinel_t>
208 #endif
209  constexpr auto
210  operator() [[nodiscard]] (W&& value, Bound&& bound = {}) const
211  {
212  return repeat_view<std::decay_t<W>, std::decay_t<Bound>> {std::forward<W>(value), std::forward<Bound>(bound)};
213  }
214  };
215  }
216 
217 
222  inline constexpr detail::repeat_adapter repeat;
223 
224 }
225 
226 #endif
227 
228 #endif
Equivalent to std::ranges::repeat_view.
Definition: repeat.hpp:48
Definition: view_interface.hpp:32
constexpr detail::repeat_adaptor repeat
a std::ranges::range_adaptor_closure for a set of repeatenated collection objects.
Definition: repeat.hpp:150
constexpr bool value
T is numerical value or is reducible to a numerical value.
Definition: value.hpp:31
Definition: iterator.hpp:423
Definition: range-access.hpp:25
Definitions relating to the availability of c++ language features.
Definition: all.hpp:35
Definitions implementing features of the c++ ranges library for compatibility.