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 #ifdef __cpp_lib_ranges
20 #include <ranges>
21 #endif
26 
28 {
29  namespace detail_get_size
30  {
31 #ifdef __cpp_lib_remove_cvref
32  using std::remove_cvref_t;
33 #endif
34 #ifdef __cpp_lib_ranges
35  namespace ranges = std::ranges;
36 #endif
37 
38 
39 #ifndef __cpp_concepts
40  template<typename T, typename = void>
41  struct has_tuple_size : std::false_type {};
42 
43  template<typename T>
44  struct has_tuple_size<T, std::void_t<decltype(std::tuple_size<std::decay_t<T>>::value)>> : std::true_type {};
45 #endif
46 
47 
48 #ifdef __cpp_concepts
49  template<typename T>
50 #else
51  template<typename T, typename = void>
52 #endif
53  struct range_extent_impl : std::integral_constant<std::size_t, dynamic_size> {};
54 
55 
56 #ifdef __cpp_concepts
57  template<typename T> requires requires { std::tuple_size<T>::value; }
58  struct range_extent_impl<T>
59 #else
60  template<typename T>
61  struct range_extent_impl<T, std::enable_if_t<has_tuple_size<T>::value>>
62 #endif
63  : std::tuple_size<T> {};
64 
65 
66 #ifdef __cpp_concepts
67  template<typename T> requires values::fixed<decltype(ranges::size(std::declval<T>()))> and
68  (not requires { std::tuple_size<T>::value; })
70 #else
71  template<typename T>
72  struct range_extent_impl<T, std::enable_if_t<values::fixed<decltype(ranges::size(std::declval<T>()))> and
74 #endif
76 
77 
78  template<typename T>
80 
81  template<typename T>
82  struct range_extent<T[]> : std::integral_constant<std::size_t, 0> {};
83 
84  template<typename T, std::size_t N>
85  struct range_extent<T[N]> : std::integral_constant<std::size_t, N> {};
86 
87  template<typename T>
88  struct range_extent<ranges::empty_view<T>> : std::integral_constant<std::size_t, 0> {};
89 
90  template<typename T>
91  struct range_extent<ranges::single_view<T>> : std::integral_constant<std::size_t, 1> {};
92 
93  template<typename R>
94  struct range_extent<ranges::ref_view<R>> : range_extent<remove_cvref_t<R>> {};
95 
96  template<typename R>
97  struct range_extent<ranges::owning_view<R>> : range_extent<remove_cvref_t<R>> {};
98 
99  template<typename V, typename F>
100  struct range_extent<ranges::transform_view<V, F>> : range_extent<remove_cvref_t<V>> {};
101 
102  template<typename V>
103  struct range_extent<ranges::reverse_view<V>> : range_extent<remove_cvref_t<V>> {};
104 
105 #ifdef __cpp_lib_ranges_concat
106  namespace rg = std::ranges;
107 #else
108  namespace rg = OpenKalman::ranges;
109 #endif
110 
111  template<typename...Views>
112  struct range_extent<rg::concat_view<Views...>> : std::integral_constant<std::size_t,
113  (... or (range_extent<Views>::value == dynamic_size)) ? dynamic_size :
114  (0_uz + ... + range_extent<Views>::value)> {};
115 
116 #ifdef __cpp_lib_ranges
117  template<typename V>
118  struct range_extent<std::ranges::common_view<V>> : range_extent<std::remove_cvref_t<V>> {};
119 
120  template<typename V, std::size_t N>
121  struct range_extent<std::ranges::elements_view<V, N>> : range_extent<std::remove_cvref_t<V>> {};
122 #endif
123 
124 #ifdef __cpp_lib_ranges_as_rvalue
125  template<typename V>
126  struct range_extent<std::ranges::as_rvalue_view<V>> : range_extent<std::remove_cvref_t<V>> {};
127 #endif
128 
129 #ifdef __cpp_lib_ranges_as_const
130  template<typename V>
131  struct range_extent<std::ranges::as_const_view<V>> : range_extent<std::remove_cvref_t<V>> {};
132 #endif
133 
134 #ifdef __cpp_lib_ranges_enumerate
135  template<typename V>
136  struct range_extent<std::ranges::enumerate_view<V>> : range_extent<std::remove_cvref_t<V>> {};
137 #endif
138 
139 #ifdef __cpp_lib_ranges_zip
140  template<typename...Views>
141  struct range_extent<std::ranges::zip_view<Views...>> : std::integral_constant<std::size_t,
142  (... or (range_extent<Views>::value == dynamic_size)) ? dynamic_size :
143  std::min({range_extent<Views>::value...})> {};
144 
145  template<typename F, typename...Views>
146  struct range_extent<std::ranges::zip_transform_view<F, Views...>> : std::integral_constant<std::size_t,
147  (... or (range_extent<Views>::value == dynamic_size)) ? dynamic_size :
148  std::min({range_extent<Views>::value...})> {};
149 
150  template<typename View, std::size_t N>
151  struct range_extent<std::ranges::adjacent_view<View, N>>: std::integral_constant<std::size_t,
152  range_extent<View>::value == dynamic_size ? dynamic_size :
153  range_extent<View>::value >= N ? range_extent<View>::value - N + 1 : 0> {};
154 
155  template<typename View, typename F, std::size_t N>
156  struct range_extent<std::ranges::adjacent_transform_view<View, F, N>> : std::integral_constant<std::size_t,
157  range_extent<View>::value == dynamic_size ? dynamic_size :
158  range_extent<View>::value >= N ? range_extent<View>::value - N + 1 : 0> {};
159 #endif
160 
161 #ifdef __cpp_lib_ranges_cartesian_product
162  template<typename...Vs>
163  struct range_extent<std::ranges::cartesian_product_view<Vs...>> : std::integral_constant<std::size_t,
164  (... or (range_extent<Vs>::value == dynamic_size)) ? dynamic_size :
165  (1_uz * ... * range_extent<Vs>::value)> {};
166 #endif
167 
168 #ifdef __cpp_lib_ranges_cache_latest
169  template<typename V>
170  struct range_extent<std::ranges::cache_latest_view<V>> : range_extent<std::remove_cvref_t<V>> {};
171 #endif
172 
173 #ifdef __cpp_lib_ranges_to_input
174  template<typename V>
175  struct range_extent<std::ranges::to_input_view<V>> : range_extent<std::remove_cvref_t<V>> {};
176 #endif
177 
178 
179  }
180 
181 
185 #ifdef __cpp_concepts
186  template<sized Arg>
187 #else
188  template<typename Arg, std::enable_if_t<sized<Arg>, int> = 0>
189 #endif
190  constexpr auto
191  get_size(Arg&& arg)
192  {
193 #ifdef __cpp_lib_remove_cvref
194  using std::remove_cvref_t;
195 #endif
196 #ifdef __cpp_lib_ranges
197  using std::ranges::size;
198 #else
200 #endif
201 
203 
204  if constexpr (Ex::value != dynamic_size) { return Ex {}; }
205  else { return size(std::forward<Arg>(arg)); }
206  };
207 
208 
209 } // OpenKalman::collections
210 
211 
212 #endif //OPENKALMAN_COLLECTIONS_GET_SIZE_HPP
Namespace for collections.
Definition: collections.hpp:27
Definition: tuple_reverse.hpp:103
constexpr bool value
T is numerical value or is reducible to a numerical value.
Definition: value.hpp:31
Definition for collections::sized.
Definition: range-access.hpp:25
Definitions relating to the availability of c++ language features.
The fixed number associated with a values::fixed.
Definition: fixed_number_of.hpp:45
constexpr bool size
T is either an index representing a size, or void which represents that there is no size...
Definition: size.hpp:32
Definition for ::fixed.
constexpr bool fixed
T is a values::value that is determinable at compile time.
Definition: fixed.hpp:60
constexpr std::size_t dynamic_size
A constant indicating that a size or index is dynamic.
Definition: global-definitions.hpp:33
constexpr auto get_size(Arg &&arg)
Get the size of a sized object (e.g, a collection)
Definition: get_size.hpp:191