OpenKalman
range-concepts.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 
21 #ifndef OPENKALMAN_RANGES_RANGE_CONCEPTS_HPP
22 #define OPENKALMAN_RANGES_RANGE_CONCEPTS_HPP
23 
26 #include "range-access.hpp"
27 
29 {
30 #ifdef __cpp_lib_ranges
31  using std::ranges::range;
32 
33  using std::ranges::borrowed_range;
34  using std::ranges::dangling;
35  using std::ranges::borrowed_iterator_t;
36  using std::ranges::borrowed_subrange_t;
37 
38  using std::ranges::sized_range;
39  using std::ranges::input_range;
40  using std::ranges::output_range;
41  using std::ranges::forward_range;
42  using std::ranges::bidirectional_range;
43  using std::ranges::random_access_range;
44  using std::ranges::common_range;
45  using std::ranges::range_size_t;
46  using std::ranges::range_difference_t;
47  using std::ranges::range_value_t;
48  using std::ranges::range_reference_t;
49  using std::ranges::range_rvalue_reference_t;
50  //using std::ranges::range_common_reference_t; // Not available in certain c++23 versions of CGG and clang
51 #if __cplusplus >= 202302L
52  using std::ranges::range_const_reference_t;
53 #endif
54 
55 #else
56  // ---
57  // range
58  // ---
59 
60  namespace detail
61  {
62  template<typename T, typename = void>
63  struct is_range : std::false_type {};
64 
65  template<typename T>
66  struct is_range<T, std::void_t<iterator_t<T>, sentinel_t<T>>> : std::true_type {};
67  }
68 
69 
70  template<typename T>
71  inline constexpr bool range = detail::is_range<T>::value;
72 
73 
74  // ---
75  // borrowed_range, dangling, borrowed_iterator_t
76  // ---
77 
78  namespace detail_borrowed_range
79  {
80  template<typename R, typename = void>
81  struct is_borrowed_range : std::false_type {};
82 
83  template<typename R>
84  struct is_borrowed_range<R, std::enable_if_t<range<R> and
85  (std::is_lvalue_reference_v<R> or enable_borrowed_range<stdex::remove_cvref_t<R>>)>> : std::true_type {};
86  }
87 
88  template<typename T>
89  inline constexpr bool borrowed_range = detail_borrowed_range::is_borrowed_range<T>::value;
90 
91 
92  struct dangling
93  {
94  constexpr dangling() noexcept = default;
95 
96  template<typename...Args>
97  constexpr dangling(Args&&...) noexcept {}
98  };
99 
100 
101  template<typename R> // requires range<R>
102  using borrowed_iterator_t =
103  std::conditional_t<borrowed_range<R>, iterator_t<R>, dangling>;
104 
105 
106  // ---
107  // sized_range
108  // ---
109 
110  namespace detail
111  {
112  template<typename T, typename = void>
113  struct is_sized_range : std::false_type {};
114 
115  template<typename T>
116  struct is_sized_range<T, std::void_t<decltype(stdex::ranges::size(std::declval<T&>()))>> : std::true_type {};
117 
118  }
119 
120  template<typename T>
121  inline constexpr bool sized_range = range<T> and detail::is_sized_range<T>::value;
122 
123 
124  // ---
125  // input_range
126  // ---
127 
128  namespace detail
129  {
130  template<typename T, typename = void>
131  struct has_input_iterator : std::false_type {};
132 
133  template<typename T>
134  struct has_input_iterator<T, std::enable_if_t<input_iterator<iterator_t<T>>>> : std::true_type {};
135  }
136 
137 
138  template<typename T>
139  inline constexpr bool input_range = range<T> and detail::has_input_iterator<T>::value;
140 
141 
142  // ---
143  // output_range
144  // ---
145 
146  namespace detail
147  {
148  template<typename R, typename T, typename = void>
149  struct has_output_iterator : std::false_type {};
150 
151  template<typename R, typename T>
152  struct has_output_iterator<R, T, std::enable_if_t<output_iterator<iterator_t<R>, T>>> : std::true_type {};
153  }
154 
155 
156  template<typename R, typename T>
157  inline constexpr bool output_range = range<R> and detail::has_output_iterator<R, T>::value;
158 
159 
160  // ---
161  // forward_range
162  // ---
163 
164  namespace detail
165  {
166  template<typename T, typename = void>
167  struct has_forward_iterator : std::false_type {};
168 
169  template<typename T>
170  struct has_forward_iterator<T, std::enable_if_t<forward_iterator<iterator_t<T>>>> : std::true_type {};
171  }
172 
173 
174  template<typename T>
175  inline constexpr bool forward_range = input_range<T> and detail::has_forward_iterator<T>::value;
176 
177 
178  // ---
179  // bidirectional_range
180  // ---
181 
182  namespace detail
183  {
184  template<typename T, typename = void>
185  struct has_bidirectional_iterator : std::false_type {};
186 
187  template<typename T>
188  struct has_bidirectional_iterator<T, std::enable_if_t<bidirectional_iterator<iterator_t<T>>>> : std::true_type {};
189  }
190 
191 
192  template<typename T>
193  inline constexpr bool bidirectional_range = forward_range<T> and detail::has_bidirectional_iterator<T>::value;
194 
195 
196  // ---
197  // random_access_range
198  // ---
199 
200  namespace detail
201  {
202  template<typename T, typename = void>
203  struct has_random_access_iterator : std::false_type {};
204 
205  template<typename T>
206  struct has_random_access_iterator<T, std::enable_if_t<random_access_iterator<iterator_t<T>>>> : std::true_type {};
207  }
208 
209 
210  template<typename T>
211  inline constexpr bool random_access_range = bidirectional_range<T> and detail::has_random_access_iterator<T>::value;
212 
213 
214  // ---
215  // common_range
216  // ---
217 
218  namespace detail
219  {
220  template<typename T, typename = void>
221  struct is_common_range : std::false_type {};
222 
223  template<typename T>
224  struct is_common_range<T, std::enable_if_t<std::is_same_v<iterator_t<T>, sentinel_t<T>>>> : std::true_type {};
225  }
226 
227 
228  template<typename T>
229  inline constexpr bool common_range = range<T> and detail::is_common_range<T>::value;
230 
231 
232 
233  // ---
234  // Range primitives
235  // ---
236 
237  template<typename R, std::enable_if_t<sized_range<R>, int> = 0>
238  using range_size_t = decltype(size(std::declval<R&>()));
239 
240  template<typename R, std::enable_if_t<range<R>, int> = 0>
241  using range_difference_t = iter_difference_t<iterator_t<R>>;
242 
243  template<typename R, std::enable_if_t<range<R>, int> = 0>
244  using range_value_t = iter_value_t<iterator_t<R>>;
245 
246  template<typename R, std::enable_if_t<range<R>, int> = 0>
247  using range_reference_t = iter_reference_t<iterator_t<R>>;
248 
249  template<typename R, std::enable_if_t<range<R>, int> = 0>
250  using range_rvalue_reference_t = iter_rvalue_reference_t<iterator_t<R>>;
251 #endif
252 
253 
254  // range_common_reference_t is not available in at least some c++23 versions of GCC or clang
255  template<typename R, std::enable_if_t<range<R>, int> = 0>
256  using range_common_reference_t = iter_common_reference_t<iterator_t<R>>;
257 
258 
259 #if __cplusplus < 202302L
260  template<typename R, std::enable_if_t<range<R>, int> = 0>
261  using range_const_reference_t = iter_const_reference_t<iterator_t<R>>;
262 #endif
263 
264 }
265 
266 #endif
Definition: range-concepts.hpp:113
Definition: range-concepts.hpp:92
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
Definition: range-concepts.hpp:63
Definition: range-concepts.hpp:221