OpenKalman
AdapterBase.hpp
1 /* This file is part of OpenKalman, a header-only C++ library for
2  * Kalman filters and other recursive filters.
3  *
4  * Copyright (c) 2019-2024 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 
17 #ifndef OPENKALMAN_ADAPTERBASE_HPP
18 #define OPENKALMAN_ADAPTERBASE_HPP
19 
20 
21 namespace OpenKalman::internal
22 {
30 #ifdef __cpp_concepts
31  template<typename Derived, indexible NestedObject, indexible LibraryObject = NestedObject> requires
32  (not std::is_rvalue_reference_v<NestedObject>)
33 #else
34  template<typename Derived, typename NestedObject, typename LibraryObject = NestedObject>
35 #endif
36  struct AdapterBase : internal::library_base_t<Derived, LibraryObject>
37  {
38 
39 #ifndef __cpp_concepts
40  static_assert(indexible<NestedObject>);
41  static_assert(indexible<LibraryObject>);
42  static_assert(not std::is_rvalue_reference_v<NestedObject>);
43 #endif
44 
48 #ifdef __cpp_concepts
49  constexpr AdapterBase() requires std::default_initializable<NestedObject>
50 #else
52  constexpr AdapterBase()
53 #endif
54  : m_nested_object {} {}
55 
56 
60 #if defined(__cpp_concepts) and OPENKALMAN_CPP_FEATURE_CONCEPTS_2
61  template<indexible Arg> requires (not std::is_base_of_v<Derived, std::decay_t<Arg>>) and
62  std::constructible_from<NestedObject, Arg&&>
63  constexpr explicit AdapterBase(Arg&& arg) : m_nested_object {std::forward<Arg>(arg)} {}
64 #else
65  template<typename Arg, std::enable_if_t<indexible<Arg> and (not std::is_base_of_v<Derived, std::decay_t<Arg>>), int> = 0>
66  constexpr explicit AdapterBase(Arg&& arg, typename std::enable_if<std::is_constructible<NestedObject, Arg&&>::value>::type* = 0)
67  : m_nested_object {std::forward<Arg>(arg)} {}
68 #endif
69 
70  protected:
71 
75 #ifdef __cpp_concepts
76  template<indexible Arg> requires (not std::is_base_of_v<Derived, std::decay_t<Arg>>) and
77  std::assignable_from<std::add_lvalue_reference_t<NestedObject>, Arg&&>
78 #else
79  template<typename Arg, std::enable_if_t<(not std::is_base_of_v<Derived, std::decay_t<Arg>>) and
80  std::is_assignable_v<std::add_lvalue_reference_t<NestedObject>, Arg&&>, int> = 0>
81 #endif
82  constexpr AdapterBase& operator=(Arg&& arg)
83  {
84  m_nested_object = std::forward<Arg>(arg);
85  return *this;
86  }
87 
88  public:
89 
93 #ifdef __cpp_explicit_this_parameter
94  template<typename Self>
95  constexpr NestedObject& nested_object(this Self&& self) { return std::forward<Self>(self).m_nested_object; }
96 #else
97  constexpr NestedObject& nested_object() & { return m_nested_object; }
98 
100  constexpr const NestedObject& nested_object() const & { return m_nested_object; }
101 
103  constexpr NestedObject&& nested_object() && { return std::move(*this).m_nested_object; }
104 
106  constexpr const NestedObject&& nested_object() const && { return std::move(*this).m_nested_object; }
107 #endif
108 
109 
114 #ifdef __cpp_explicit_this_parameter
115  template<typename Self, typename Indices> requires
116  requires(Self&& self, const Indices& indices) {
117  {get_component(std::forward<Self>(self), indices)} -> values::scalar; }
118  constexpr values::scalar auto operator[](this Self&& self, const Indices& indices)
119  {
120  if constexpr (writable_by_component<Self, Indices>) return ElementAccessor(std::forward<Self>(self), indices);
121  else return get_component(std::forward<Self>(self), indices);
122  }
123 #else
124 #ifdef __cpp_lib_concepts
125  template<typename Indices> requires
126  requires(Derived& derived, const Indices& indices) {{get_component(derived, indices)} -> values::scalar; }
127 #else
128  template<typename Indices, std::enable_if_t<
129  values::scalar<decltype(get_component(std::declval<Derived&>(), std::declval<const Indices&>()))>, int> = 0>
130 #endif
131  constexpr auto operator[](const Indices& indices) &
132  {
133  if constexpr (writable_by_component<Derived, Indices>) return ElementAccessor(static_cast<Derived&>(*this), indices);
134  else return get_component(static_cast<Derived&>(*this), indices);
135  }
136 
138 #ifdef __cpp_lib_concepts
139  template<typename Indices> requires
140  requires(Derived&& derived, const Indices& indices) {{get_component(derived, indices)} -> values::scalar; }
141 #else
142  template<typename Indices, std::enable_if_t<
143  values::scalar<decltype(get_component(std::declval<Derived&&>(), std::declval<const Indices&>()))>, int> = 0>
144 #endif
145  constexpr auto operator[](const Indices& indices) &&
146  {
147  if constexpr (writable_by_component<Derived&&>) return ElementAccessor(static_cast<Derived&&>(*this), indices);
148  else return get_component(static_cast<Derived&&>(*this), indices);
149  }
150 
152 #ifdef __cpp_lib_concepts
153  template<typename Indices> requires
154  requires(const Derived& derived, const Indices& indices) {{get_component(derived, indices)} -> values::scalar; }
155 #else
156  template<typename Indices, std::enable_if_t<
157  values::scalar<decltype(get_component(std::declval<const Derived&>(), std::declval<const Indices&>()))>, int> = 0>
158 #endif
159  constexpr auto operator[](const Indices& indices) const &
160  {
161  return get_component(static_cast<const Derived&>(*this), indices);
162  }
163 
165 #ifdef __cpp_lib_concepts
166  template<typename Indices> requires
167  requires(const Derived&& derived, const Indices& indices) {{get_component(derived, indices)} -> values::scalar; }
168 #else
169  template<typename Indices, std::enable_if_t<
170  values::scalar<decltype(get_component(std::declval<const Derived&&>(), std::declval<const Indices&>()))>, int> = 0>
171 #endif
172  constexpr auto operator[](const Indices& indices) const &&
173  {
174  return get_component(static_cast<const Derived&&>(*this), indices);
175  }
176 #endif
177 
178 
179 #if defined(__cpp_explicit_this_parameter) and defined(__cpp_multidimensional_subscript)
180 
184  template<typename Self, values::index...I> requires
185  requires(Self&& self, const std::array<std::size_t, sizeof...(I)>& indices) {
186  {get_component(std::forward<Self>(self), indices)} -> values::scalar; }
187  constexpr values::scalar auto operator[](this Self&& self, I&&...i)
188  {
189  auto indices = std::array<std::size_t, sizeof...(I)> {static_cast<std::size_t>(std::forward<I>(i))...};
190  if constexpr (writable_by_component<Self, std::array<std::size_t, sizeof...(I)>>)
191  return ElementAccessor(std::forward<Self>(self), indices);
192  else
193  return get_component(std::forward<Self>(self), indices);
194  }
195 #endif
196 
197  private:
198 
199  NestedObject m_nested_object; //< The nested matrix.
200 
201  };
202 
203 }
204 
205 #endif //OPENKALMAN_BASEMATRIX_HPP
Definition: ElementAccessor.hpp:34
constexpr AdapterBase(Arg &&arg, typename std::enable_if< std::is_constructible< NestedObject, Arg &&>::value >::type *=0)
Construct from a compatible indexible type.
Definition: AdapterBase.hpp:66
constexpr NestedObject & nested_object() &
Get the nested object.
Definition: AdapterBase.hpp:97
constexpr const NestedObject && nested_object() const &&
Definition: AdapterBase.hpp:106
constexpr NestedObject && nested_object() &&
Definition: AdapterBase.hpp:103
constexpr AdapterBase & operator=(Arg &&arg)
Assign from another compatible indexible object.
Definition: AdapterBase.hpp:82
constexpr auto operator[](const Indices &indices) const &&
Definition: AdapterBase.hpp:172
constexpr auto operator[](const Indices &indices) &&
Definition: AdapterBase.hpp:145
constexpr bool value
T is numerical value or is reducible to a numerical value.
Definition: value.hpp:31
Definition: AdapterBase.hpp:36
constexpr auto operator[](const Indices &indices) const &
Definition: AdapterBase.hpp:159
constexpr auto operator[](const Indices &indices) &
Access a component at a set of indices.
Definition: AdapterBase.hpp:131
constexpr const NestedObject & nested_object() const &
Definition: AdapterBase.hpp:100
constexpr bool index
T is an index value.
Definition: index.hpp:56
decltype(auto) constexpr get_component(Arg &&arg, const Indices &indices)
Get a component of an object at a particular set of indices.
Definition: get_component.hpp:54
constexpr AdapterBase()
Default constructor.
Definition: AdapterBase.hpp:52
Definition: basics.hpp:48
constexpr bool writable_by_component
Specifies that a type has components that can be set with Indices (an std::ranges::input_range) of ty...
Definition: writable_by_component.hpp:36