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