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_COLLECTIONS_VIEWS_CONCAT_HPP
17 #define OPENKALMAN_COLLECTIONS_VIEWS_CONCAT_HPP
18 
19 #include "values/values.hpp"
23 
25 {
26  namespace detail
27  {
28  template<std::size_t i>
29  constexpr auto concat_tuple_view_indices()
30  {
31  return std::pair {std::integral_constant<std::size_t, 0_uz>{}, std::integral_constant<std::size_t, 0_uz>{}};
32  }
33 
34  template<std::size_t i, typename T, typename...Ts>
35  constexpr auto concat_tuple_view_indices()
36  {
37  constexpr std::size_t size = size_of_v<T>;
38  if constexpr (i < size)
39  {
40  return std::pair {std::integral_constant<std::size_t, 0_uz>{}, std::integral_constant<std::size_t, i>{}};
41  }
42  else
43  {
44  auto [a, b] = concat_tuple_view_indices<i - size, Ts...>();
45  return std::pair {std::integral_constant<std::size_t, 1_uz + decltype(a)::value>{}, b};
46  }
47  }
48  };
49 
50 
56 #ifdef __cpp_concepts
57  template<uniformly_gettable...Ts>
58 #else
59  template<typename...Ts>
60 #endif
62  {
63 #ifdef __cpp_concepts
64  constexpr concat_tuple_view() requires (... and std::default_initializable<Ts>) = default;
65 #else
66  template<bool Enable = true, std::enable_if_t<Enable and (... and stdex::default_initializable<Ts>), int> = 0>
67  constexpr concat_tuple_view() {};
68 #endif
69 
70 
71 #ifdef __cpp_concepts
72  template<typename...Args> requires (... and std::constructible_from<Ts, Args&&>)
73 #else
74  template<typename...Args, std::enable_if_t<(... and stdex::constructible_from<Ts, Args&&>), int> = 0>
75 #endif
76  explicit constexpr concat_tuple_view(Args&&...args) : tup {std::forward<Args>(args)...} {}
77 
78 
82 #ifdef __cpp_explicit_this_parameter
83  template<std::size_t i>
84  constexpr decltype(auto)
85  get(this auto&& self) noexcept
86  {
87  static_assert(i < (0_uz + ... + size_of_v<Ts>), "Index out of range");
88  auto [element, index] = std::decay_t<decltype(detail::concat_tuple_view_indices<i, Ts...>())>();
89  return get_element(get_element(std::forward<decltype(self)>(self).tup, element).get(), index);
90  }
91 #else
92  template<std::size_t i>
93  constexpr decltype(auto)
94  get() &
95  {
96  static_assert(i < (0_uz + ... + size_of_v<Ts>), "Index out of range");
97  auto [element, index] = std::decay_t<decltype(detail::concat_tuple_view_indices<i, Ts...>())>();
98  return get_element(get_element(tup, element).get(), index);
99  }
100 
101  template<std::size_t i>
102  constexpr decltype(auto)
103  get() const &
104  {
105  static_assert(i < (0_uz + ... + size_of_v<Ts>), "Index out of range");
106  auto [element, index] = std::decay_t<decltype(detail::concat_tuple_view_indices<i, Ts...>())>();
107  return get_element(get_element(tup, element).get(), index);
108  }
109 
110  template<std::size_t i>
111  constexpr decltype(auto)
112  get() && noexcept
113  {
114  static_assert(i < (0_uz + ... + size_of_v<Ts>), "Index out of range");
115  auto [element, index] = std::decay_t<decltype(detail::concat_tuple_view_indices<i, Ts...>())>();
116  return get_element(get_element(std::move(*this).tup, element).get(), index);
117  }
118 
119  template<std::size_t i>
120  constexpr decltype(auto)
121  get() const && noexcept
122  {
123  static_assert(i < (0_uz + ... + size_of_v<Ts>), "Index out of range");
124  auto [element, index] = std::decay_t<decltype(detail::concat_tuple_view_indices<i, Ts...>())>();
125  return get_element(get_element(std::move(*this).tup, element).get(), index);
126  }
127 #endif
128 
129  private:
130 
131  std::tuple<internal::movable_wrapper<Ts>...> tup;
132  };
133 
134 
138  template<typename...Args>
139  concat_tuple_view(Args&&...) -> concat_tuple_view<Args...>;
140 
141 }
142 
143 
144 namespace std
145 {
146  template<typename...Ts>
147  struct tuple_size<OpenKalman::collections::concat_tuple_view<Ts...>>
148  : std::integral_constant<std::size_t, (0 + ... + OpenKalman::collections::size_of_v<Ts>)> {};
149 
150 
151  template<std::size_t i, typename...Ts>
152  struct tuple_element<i, OpenKalman::collections::concat_tuple_view<Ts...>>
153  {
154  private:
155  static_assert(i < (0 + ... + OpenKalman::collections::size_of_v<Ts>));
156  using indices = decltype(OpenKalman::collections::detail::concat_tuple_view_indices<i, Ts...>());
159  public:
162  };
163 }
164 
165 
167 {
168  namespace detail
169  {
171  {
172  #ifdef __cpp_concepts
173  template<viewable_collection...R> requires (sizeof...(R) > 0)
174  #else
175  template<typename...R, std::enable_if_t<(sizeof...(R) > 0) and (... and viewable_collection<R>), int> = 0>
176  #endif
177  constexpr decltype(auto)
178  operator() (R&&...r) const
179  {
180  if constexpr (sizeof...(R) == 1)
181  return all(std::forward<R>(r)...);
182  else if constexpr ((... and (uniformly_gettable<R>)))
183  return concat_tuple_view {std::forward<R>(r)...} | all;
184  else
185  return stdex::ranges::views::concat(all(std::forward<R>(r))...) | all;
186  }
187 
188  };
189 
190  }
191 
192 
196  inline constexpr detail::concat_adaptor concat;
197 
198 }
199 
200 
201 #endif
Namespace for collections.
Definition: collections.hpp:27
constexpr bool uniformly_gettable
T is a fixed-size object that is gettable for all indices.
Definition: uniformly_gettable.hpp:55
constexpr detail_get::get_impl< i > get
A generalization of std::get, where the index is known at compile time.
Definition: get.hpp:50
Header file for code relating to values (e.g., scalars and indices)
A view to a concatenation of some number of other uniformly_gettable object.
Definition: concat.hpp:61
constexpr bool value
T is a fixed or dynamic value that is reducible to a number.
Definition: value.hpp:45
constexpr bool viewable_collection
A std::range or viewable_tuple_like object that can be converted into a collection_view by passing it...
Definition: viewable_collection.hpp:32
concat_tuple_view(Args &&...) -> concat_tuple_view< Args... >
Deduction guide.
The root namespace for OpenKalman.
Definition: basics.hpp:34
constexpr detail::concat_adaptor concat
a std::ranges::range_adaptor_closure for a set of concatenated pattern objects.
Definition: concat.hpp:56
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
Namespace for generalized views.
Definition: collections.hpp:33
typename collection_element< i, T >::type collection_element_t
Helper template for collection_element.
Definition: collection_element.hpp:116
decltype(auto) constexpr get_element(Arg &&arg, I i)
A generalization of std::get and the range subscript operator.
Definition: get_element.hpp:122
Definition for collections::uniformly_gettable.
Definition for collections::collection_element.
constexpr bool index
An object describing a collection of /ref values::index objects.
Definition: index.hpp:77