OpenKalman
get_size.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 
16 #ifndef OPENKALMAN_COLLECTIONS_GET_SIZE_HPP
17 #define OPENKALMAN_COLLECTIONS_GET_SIZE_HPP
18 
19 #include <variant>
20 #include "values/values.hpp"
21 #include "collections/traits/std-extents.hpp"
22 
24 {
25  namespace detail_get_size
26  {
27 #ifdef __cpp_concepts
28  template<typename T>
29  struct range_extent {};
30 
31 
32  template<typename T> requires requires { std::tuple_size<T>::value; }
33  struct range_extent<T> : std::tuple_size<T> {};
34 
35 
36  template<typename T> requires values::fixed<decltype(stdex::ranges::size(std::declval<T>()))> and
37  (not requires { std::tuple_size<T>::value; })
38  struct range_extent<T>
39  : values::fixed_value_of<decltype(stdex::ranges::size(std::declval<T>()))> {};
40 
41 
42  // If T has a static size() member function (e.g., ranges::empty_view and ranges::single_view)
43  template<typename T> requires std::bool_constant<(std::decay_t<T>::size(), true)>::value and
44  (not values::fixed<decltype(stdex::ranges::size(std::declval<T>()))>) and
45  (not requires { std::tuple_size<T>::value; })
46  struct range_extent<T>
47  : std::integral_constant<std::size_t, std::decay_t<T>::size()> {};
48 #else
49  template<typename T, typename = void>
50  struct has_tuple_size : std::false_type {};
51 
52  template<typename T>
53  struct has_tuple_size<T, std::void_t<decltype(std::tuple_size<std::decay_t<T>>::value)>> : std::true_type {};
54 
55 
56  template<typename T, typename = void>
57  struct range_extent_impl {};
58 
59  template<typename T>
60  struct range_extent_impl<T, std::enable_if_t<has_tuple_size<T>::value>>
61  : std::tuple_size<T> {};
62 
63  template<typename T>
64  struct range_extent_impl<T, std::enable_if_t<values::fixed<decltype(stdex::ranges::size(std::declval<T>()))> and
65  not has_tuple_size<T>::value>>
66  : values::fixed_value_of<decltype(stdex::ranges::size(std::declval<T>()))> {};
67 
68  template<typename T>
69  struct range_extent_impl<T, std::enable_if_t<std::bool_constant<(std::decay_t<T>::size(), true)>::value and
70  (not values::fixed<decltype(stdex::ranges::size(std::declval<T>()))>) and
71  not has_tuple_size<T>::value>>
72  : std::integral_constant<std::size_t, std::decay_t<T>::size()> {};
73 
74 
75  template<typename T, typename = void>
77 #endif
78 
79 
80  template<typename T>
81  constexpr std::size_t
82  ext_val = []
83  {
85  else return 0_uz;
86  }();
87 
88 
89  template<typename IndexType, std::size_t...Extents>
90  struct range_extent<stdex::extents<IndexType, Extents...>> : std::integral_constant<std::size_t, sizeof...(Extents)> {};
91 
92 
93  template<typename T>
94  struct range_extent<T[]> : std::integral_constant<std::size_t, 0> {};
95 
96 
97  template<typename T, std::size_t N>
98  struct range_extent<T[N]> : std::integral_constant<std::size_t, N> {};
99 
100 
101  //template<typename T>
102  //struct range_extent<stdex::ranges::empty_view<T>> : std::integral_constant<std::size_t, 0> {};
103 
104 
105  //template<typename T>
106  //struct range_extent<stdex::ranges::single_view<T>> : std::integral_constant<std::size_t, 1> {};
107 
108 
109  template<typename R>
110  struct range_extent<stdex::ranges::ref_view<R>> : range_extent<stdex::remove_cvref_t<R>> {};
111 
112 
113  template<typename R>
114  struct range_extent<stdex::ranges::owning_view<R>> : range_extent<stdex::remove_cvref_t<R>> {};
115 
116 
117  template<typename V, typename F>
118  struct range_extent<stdex::ranges::transform_view<V, F>> : range_extent<stdex::remove_cvref_t<V>> {};
119 
120 
121  template<typename V>
122  struct range_extent<stdex::ranges::reverse_view<V>> : range_extent<stdex::remove_cvref_t<V>> {};
123 
124 
125  template<typename...Views>
126  struct range_extent<stdex::ranges::concat_view<Views...>>
127  : std::conditional_t<
128  (... and values::index<range_extent<Views>>),
129  std::integral_constant<std::size_t, (0_uz + ... + ext_val<Views>)>,
130  std::monostate> {};
131 
132 
133 #ifdef __cpp_lib_ranges
134  template<typename V>
135  struct range_extent<std::ranges::common_view<V>> : range_extent<stdex::remove_cvref_t<V>> {};
136 
137  template<typename V, std::size_t N>
138  struct range_extent<std::ranges::elements_view<V, N>> : range_extent<stdex::remove_cvref_t<V>> {};
139 #endif
140 
141 
142 #ifdef __cpp_lib_ranges_as_rvalue
143  template<typename V>
144  struct range_extent<std::ranges::as_rvalue_view<V>> : range_extent<stdex::remove_cvref_t<V>> {};
145 #endif
146 
147 
148 #ifdef __cpp_lib_ranges_as_const
149  template<typename V>
150  struct range_extent<std::ranges::as_const_view<V>> : range_extent<stdex::remove_cvref_t<V>> {};
151 #endif
152 
153 
154 #ifdef __cpp_lib_ranges_enumerate
155  template<typename V>
156  struct range_extent<std::ranges::enumerate_view<V>> : range_extent<stdex::remove_cvref_t<V>> {};
157 #endif
158 
159 
160 #ifdef __cpp_lib_ranges_zip
161  template<typename...Views>
162  struct range_extent<std::ranges::zip_view<Views...>>
163  : std::conditional_t<
164  (... and values::index<range_extent<Views>>),
165  std::integral_constant<std::size_t, std::min({ext_val<Views>...})>,
166  std::monostate> {};
167 
168  template<typename F, typename...Views>
169  struct range_extent<std::ranges::zip_transform_view<F, Views...>>
170  : std::conditional_t<
171  (... and values::index<range_extent<Views>>),
172  std::integral_constant<std::size_t, std::min({ext_val<Views>...})>,
173  std::monostate> {};
174 
175  template<typename View, std::size_t N>
176  struct range_extent<std::ranges::adjacent_view<View, N>>
177  : std::conditional_t<
178  values::index<range_extent<View>>,
179  std::integral_constant<std::size_t, ext_val<View> >= N ? ext_val<View> - N + 1 : 0>,
180  std::monostate> {};
181 
182  template<typename View, typename F, std::size_t N>
183  struct range_extent<std::ranges::adjacent_transform_view<View, F, N>>
184  : std::conditional_t<
185  values::index<range_extent<View>>,
186  std::integral_constant<std::size_t, ext_val<View> >= N ? ext_val<View> - N + 1 : 0>,
187  std::monostate> {};
188 #endif
189 
190 
191 #ifdef __cpp_lib_ranges_cartesian_product
192  template<typename...Vs>
193  struct range_extent<std::ranges::cartesian_product_view<Vs...>>
194  : std::conditional_t<
195  (... and values::index<range_extent<Vs>>),
196  std::integral_constant<std::size_t, (1_uz * ... * ext_val<Vs>)>,
197  std::monostate> {};
198 #endif
199 
200 
201 #ifdef __cpp_lib_ranges_cache_latest
202  template<typename V>
203  struct range_extent<std::ranges::cache_latest_view<V>> : range_extent<stdex::remove_cvref_t<V>> {};
204 #endif
205 
206 
207 #ifdef __cpp_lib_ranges_to_input
208  template<typename V>
209  struct range_extent<std::ranges::to_input_view<V>> : range_extent<stdex::remove_cvref_t<V>> {};
210 #endif
211 
212  }
213 
214 
218  template<typename Arg>
219 #ifdef __cpp_concepts
220  constexpr values::size auto
221 #else
222  constexpr auto
223 #endif
224  get_size(Arg&& arg)
225  {
227  if constexpr (values::index<Ex>)
228  return values::cast_to<std::size_t>(Ex{});
229  else if constexpr (stdex::ranges::sized_range<Arg>)
230  return static_cast<std::size_t>(stdex::ranges::size(std::forward<Arg>(arg)));
231  else
232  return values::unbounded_size;
233  };
234 
235 
236 }
237 
238 
239 #endif
Namespace for collections.
Definition: collections.hpp:27
constexpr auto get_size(Arg &&arg)
Get the size of a sized object (e.g, a collection)
Definition: get_size.hpp:224
Header file for code relating to values (e.g., scalars and indices)
The fixed value associated with a fixed.
Definition: fixed_value_of.hpp:44
constexpr bool value
T is a fixed or dynamic value that is reducible to a number.
Definition: value.hpp:45
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:71
constexpr bool index
T is an index value.
Definition: index.hpp:62
constexpr unbounded_size_t unbounded_size
An instance of unbounded_size_t;.
Definition: size.hpp:60
constexpr bool fixed
T has a value that is determinable at compile time.
Definition: fixed.hpp:65