OpenKalman
concat.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_VIEWS_CONCAT_HPP
17 #define OPENKALMAN_VIEWS_CONCAT_HPP
18 
20 
22 {
23  namespace detail
24  {
25  template<std::size_t i>
26  constexpr auto concat_tuple_view_indices()
27  {
28  return std::pair {std::integral_constant<std::size_t, 0_uz>{}, std::integral_constant<std::size_t, 0_uz>{}};
29  }
30 
31  template<std::size_t i, typename T, typename...Ts>
32  constexpr auto concat_tuple_view_indices()
33  {
34  constexpr std::size_t size = std::tuple_size_v<std::decay_t<T>>;
35  if constexpr (i < size) return std::pair {std::integral_constant<std::size_t, 0_uz>{}, std::integral_constant<std::size_t, i>{}};
36  else
37  {
38  auto [a, b] = concat_tuple_view_indices<i - size, Ts...>();
39  return std::pair {std::integral_constant<std::size_t, 1_uz + decltype(a)::value>{}, b};
40  }
41  }
42  };
43 
44 
50 #ifdef __cpp_concepts
51  template<tuple_like...Ts>
52 #else
53  template<typename...Ts>
54 #endif
56  {
57 #ifdef __cpp_concepts
58  constexpr concat_tuple_view() requires (... and std::default_initializable<Ts>) = default;
59 #else
60  template<typename Tup = std::tuple<Ts...>, std::enable_if_t<std::is_default_constructible_v<Tup>, int> = 0>
61  constexpr concat_tuple_view() {};
62 #endif
63 
64 
65 #ifdef __cpp_concepts
66  template<typename...Args> requires (... and std::constructible_from<Ts, Args&&>)
67 #else
68  template<typename...Args, std::enable_if_t<(... and std::is_constructible_v<Ts, Args&&>), int> = 0>
69 #endif
70  explicit constexpr concat_tuple_view(Args&&...args) : tup {std::forward<Args>(args)...} {}
71 
72 
76 #ifdef __cpp_concepts
77  template<std::size_t i> requires (i < (0_uz + ... + std::tuple_size_v<std::decay_t<Ts>>))
78 #else
79  template<std::size_t i, std::enable_if_t<(i < (0_uz + ... + std::tuple_size_v<std::decay_t<Ts>>)), int> = 0>
80 #endif
81  friend constexpr decltype(auto)
83  {
84  auto [element, index] = std::decay_t<decltype(detail::concat_tuple_view_indices<i, Ts...>())>();
85  return get(get(v.tup, element), index);
86  }
87 
88 
92 #ifdef __cpp_concepts
93  template<std::size_t i> requires (i < (0_uz + ... + std::tuple_size_v<std::decay_t<Ts>>))
94 #else
95  template<std::size_t i, std::enable_if_t<(i < (0_uz + ... + std::tuple_size_v<std::decay_t<Ts>>)), int> = 0>
96 #endif
97  friend constexpr decltype(auto)
99  {
100  auto [element, index] = std::decay_t<decltype(detail::concat_tuple_view_indices<i, Ts...>())>();
101  return get(get(std::move(v).tup, element), index);
102  }
103 
104  private:
105 
106  std::tuple<Ts...> tup;
107  };
108 
109 
113  template<typename...Args>
114  concat_tuple_view(Args&&...) -> concat_tuple_view<Args...>;
115 
116 }
117 
118 
119 namespace std
120 {
121  template<typename...Ts>
122  struct tuple_size<OpenKalman::collections::concat_tuple_view<Ts...>>
123  : std::integral_constant<std::size_t, (0_uz + ... + std::tuple_size_v<std::decay_t<Ts>>)> {};
124 
125 
126  template<std::size_t i, typename...Ts>
127  struct tuple_element<i, OpenKalman::collections::concat_tuple_view<Ts...>>
128  {
129  static_assert(i < (0_uz + ... + std::tuple_size_v<std::decay_t<Ts>>));
130  using indices = decltype(OpenKalman::collections::detail::concat_tuple_view_indices<i, Ts...>());
131  using element = std::tuple_element_t<0, indices>;
132  using index = std::tuple_element_t<1, indices>;
133  using type = std::tuple_element_t<index::value, std::decay_t<std::tuple_element_t<element::value, std::tuple<Ts...>>>>;
134  };
135 } // namespace std
136 
137 
139 {
140  namespace detail
141  {
143  {
144  #ifdef __cpp_concepts
145  template<viewable_collection...R> requires (sizeof...(R) > 0)
146  #else
147  template<typename...R, std::enable_if_t<(sizeof...(R) > 0) and (... and viewable_collection<R>), int> = 0>
148  #endif
149  constexpr auto
150  operator() (R&&...r) const
151  {
152 #if __cpp_lib_ranges_concat >= 202403L
153  namespace cv = std::ranges::views;
154 #else
155  namespace cv = ranges::views;
156 #endif
157  if constexpr (sizeof...(R) == 1)
158  return all(std::forward<R>(r)...);
159  else if constexpr ((... and tuple_like<R>))
160  return concat_tuple_view {all(std::forward<R>(r))...} | all;
161  else
162  return cv::concat(all(std::forward<R>(r))...) | all;
163  }
164 
165  };
166 
167  }
168 
169 
173  inline constexpr detail::concat_adaptor concat;
174 
175 }
176 
177 
178 #endif //OPENKALMAN_VIEWS_CONCAT_HPP
Definition for collections::tuple_like.
Namespace for collections.
Definition: collections.hpp:27
constexpr detail::concat_adaptor concat
a std::ranges::range_adaptor_closure for a set of concatenated collection objects.
Definition: concat.hpp:173
decltype(auto) constexpr get(Arg &&arg, I i)
A generalization of std::get.
Definition: get.hpp:62
A view to a concatenation of some number of other tuple_like object.
Definition: concat.hpp:55
Definition: tuple_reverse.hpp:103
constexpr bool value
T is numerical value or is reducible to a numerical value.
Definition: value.hpp:31
constexpr bool viewable_collection
A std::range or uniform_tuple_like object that can be converted into a collection_view by passing it ...
Definition: viewable_collection.hpp:37
concat_tuple_view(Args &&...) -> concat_tuple_view< Args... >
Deduction guide.
The root namespace for OpenKalman.
Definition: basics.hpp:34
constexpr bool size
T is either an index representing a size, or void which represents that there is no size...
Definition: size.hpp:32
Namespace for generalized views.
Definition: collections.hpp:33
constexpr bool tuple_like
T is a non-empty tuple, pair, array, or other type that acts like a tuple.
Definition: tuple_like.hpp:51
constexpr bool index
An object describing a collection of /ref values::index objects.
Definition: index.hpp:75