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 "values/values.hpp"
21 
23 {
24  namespace detail_get_size
25  {
26 #ifndef __cpp_concepts
27  template<typename T, typename = void>
28  struct has_tuple_size : std::false_type {};
29 
30  template<typename T>
31  struct has_tuple_size<T, std::void_t<decltype(std::tuple_size<std::decay_t<T>>::value)>> : std::true_type {};
32 #endif
33 
34 
35 #ifdef __cpp_concepts
36  template<typename T>
37 #else
38  template<typename T, typename = void>
39 #endif
40  struct range_extent_impl : std::integral_constant<std::size_t, stdex::dynamic_extent> {};
41 
42 
43 #ifdef __cpp_concepts
44  template<typename T> requires requires { std::tuple_size<T>::value; }
45  struct range_extent_impl<T>
46 #else
47  template<typename T>
48  struct range_extent_impl<T, std::enable_if_t<has_tuple_size<T>::value>>
49 #endif
50  : std::tuple_size<T> {};
51 
52 
53 #ifdef __cpp_concepts
54  template<typename T> requires values::fixed<decltype(stdex::ranges::size(std::declval<T>()))> and
55  (not requires { std::tuple_size<T>::value; })
57 #else
58  template<typename T>
59  struct range_extent_impl<T, std::enable_if_t<values::fixed<decltype(stdex::ranges::size(std::declval<T>()))> and
61 #endif
63 
64 
65  // If T has a static size() member function (e.g., ranges::empty_view and ranges::single_view)
66 #ifdef __cpp_concepts
67  template<typename T> requires std::bool_constant<(std::decay_t<T>::size(), true)>::value and
68  (not values::fixed<decltype(stdex::ranges::size(std::declval<T>()))>) and
69  (not requires { std::tuple_size<T>::value; })
71 #else
72  template<typename T>
73  struct range_extent_impl<T, std::enable_if_t<std::bool_constant<(std::decay_t<T>::size(), true)>::value and
74  (not values::fixed<decltype(stdex::ranges::size(std::declval<T>()))>) and
75  not has_tuple_size<T>::value>>
76 #endif
78 
79 
80  template<typename T>
82 
83  template<typename T>
84  struct range_extent<T[]> : std::integral_constant<std::size_t, 0> {};
85 
86  template<typename T, std::size_t N>
87  struct range_extent<T[N]> : std::integral_constant<std::size_t, N> {};
88 
89  //template<typename T>
90  //struct range_extent<stdex::ranges::empty_view<T>> : std::integral_constant<std::size_t, 0> {};
91 
92  //template<typename T>
93  //struct range_extent<stdex::ranges::single_view<T>> : std::integral_constant<std::size_t, 1> {};
94 
95  template<typename R>
96  struct range_extent<stdex::ranges::ref_view<R>> : range_extent<stdex::remove_cvref_t<R>> {};
97 
98  template<typename R>
99  struct range_extent<stdex::ranges::owning_view<R>> : range_extent<stdex::remove_cvref_t<R>> {};
100 
101  template<typename V, typename F>
102  struct range_extent<stdex::ranges::transform_view<V, F>> : range_extent<stdex::remove_cvref_t<V>> {};
103 
104  template<typename V>
105  struct range_extent<stdex::ranges::reverse_view<V>> : range_extent<stdex::remove_cvref_t<V>> {};
106 
107  template<typename...Views>
108  struct range_extent<stdex::ranges::concat_view<Views...>> : std::integral_constant<std::size_t,
109  (... or (range_extent<Views>::value == stdex::dynamic_extent)) ? stdex::dynamic_extent :
110  (0_uz + ... + range_extent<Views>::value)> {};
111 
112 #ifdef __cpp_lib_ranges
113  template<typename V>
114  struct range_extent<std::ranges::common_view<V>> : range_extent<stdex::remove_cvref_t<V>> {};
115 
116  template<typename V, std::size_t N>
117  struct range_extent<std::ranges::elements_view<V, N>> : range_extent<stdex::remove_cvref_t<V>> {};
118 #endif
119 
120 #ifdef __cpp_lib_ranges_as_rvalue
121  template<typename V>
122  struct range_extent<std::ranges::as_rvalue_view<V>> : range_extent<stdex::remove_cvref_t<V>> {};
123 #endif
124 
125 #ifdef __cpp_lib_ranges_as_const
126  template<typename V>
127  struct range_extent<std::ranges::as_const_view<V>> : range_extent<stdex::remove_cvref_t<V>> {};
128 #endif
129 
130 #ifdef __cpp_lib_ranges_enumerate
131  template<typename V>
132  struct range_extent<std::ranges::enumerate_view<V>> : range_extent<stdex::remove_cvref_t<V>> {};
133 #endif
134 
135 #ifdef __cpp_lib_ranges_zip
136  template<typename...Views>
137  struct range_extent<std::ranges::zip_view<Views...>> : std::integral_constant<std::size_t,
138  (... or (range_extent<Views>::value == stdex::dynamic_extent)) ? stdex::dynamic_extent :
139  std::min({range_extent<Views>::value...})> {};
140 
141  template<typename F, typename...Views>
142  struct range_extent<std::ranges::zip_transform_view<F, Views...>> : std::integral_constant<std::size_t,
143  (... or (range_extent<Views>::value == stdex::dynamic_extent)) ? stdex::dynamic_extent :
144  std::min({range_extent<Views>::value...})> {};
145 
146  template<typename View, std::size_t N>
147  struct range_extent<std::ranges::adjacent_view<View, N>>: std::integral_constant<std::size_t,
148  range_extent<View>::value == stdex::dynamic_extent ? stdex::dynamic_extent :
149  range_extent<View>::value >= N ? range_extent<View>::value - N + 1 : 0> {};
150 
151  template<typename View, typename F, std::size_t N>
152  struct range_extent<std::ranges::adjacent_transform_view<View, F, N>> : std::integral_constant<std::size_t,
153  range_extent<View>::value == stdex::dynamic_extent ? stdex::dynamic_extent :
154  range_extent<View>::value >= N ? range_extent<View>::value - N + 1 : 0> {};
155 #endif
156 
157 #ifdef __cpp_lib_ranges_cartesian_product
158  template<typename...Vs>
159  struct range_extent<std::ranges::cartesian_product_view<Vs...>> : std::integral_constant<std::size_t,
160  (... or (range_extent<Vs>::value == stdex::dynamic_extent)) ? stdex::dynamic_extent :
161  (1_uz * ... * range_extent<Vs>::value)> {};
162 #endif
163 
164 #ifdef __cpp_lib_ranges_cache_latest
165  template<typename V>
166  struct range_extent<std::ranges::cache_latest_view<V>> : range_extent<stdex::remove_cvref_t<V>> {};
167 #endif
168 
169 #ifdef __cpp_lib_ranges_to_input
170  template<typename V>
171  struct range_extent<std::ranges::to_input_view<V>> : range_extent<stdex::remove_cvref_t<V>> {};
172 #endif
173 
174 
175  }
176 
177 
181 #ifdef __cpp_concepts
182  template<sized Arg>
183  constexpr values::index auto
184 #else
185  template<typename Arg, std::enable_if_t<sized<Arg>, int> = 0>
186  constexpr auto
187 #endif
188  get_size(Arg&& arg)
189  {
191  if constexpr (Ex::value != stdex::dynamic_extent) { return values::cast_to<std::size_t>(Ex {}); }
192  else { return static_cast<std::size_t>(stdex::ranges::size(std::forward<Arg>(arg))); }
193  };
194 
195 
196 }
197 
198 
199 #endif
Namespace for collections.
Definition: collections.hpp:27
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
Definition for collections::sized.
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
constexpr bool index
T is an index value.
Definition: index.hpp:62
constexpr bool fixed
T is a value that is determinable at compile time.
Definition: fixed.hpp:66
constexpr auto get_size(Arg &&arg)
Get the size of a sized object (e.g, a collection)
Definition: get_size.hpp:188