OpenKalman
movable_box.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 
17 #ifndef OPENKALMAN_COMPATIBILITY_MOVABLE_BOX_HPP
18 #define OPENKALMAN_COMPATIBILITY_MOVABLE_BOX_HPP
19 
20 #include <optional>
21 #include <type_traits>
23 
24 namespace OpenKalman::internal
25 {
26  namespace detail
27  {
28  template<typename T>
29 #ifdef __cpp_lib_concepts
30  concept boxable = std::copy_constructible<T> and std::is_object_v<T>;
31 #else
32  inline constexpr bool boxable = copy_constructible<T> and std::is_object_v<T>;
33 #endif
34 
35 
36  template<typename T>
37 #ifdef __cpp_lib_concepts
38  concept boxable_copyable =
39  std::copy_constructible<T> and (std::movable<T> or std::is_nothrow_move_constructible_v<T>);
40 #else
41  inline constexpr bool boxable_copyable =
42  copy_constructible<T> and
43  (copyable<T> or (std::is_nothrow_move_constructible_v<T> or std::is_nothrow_copy_constructible_v<T>));
44 #endif
45 
46 
47  template<typename T>
48 #ifdef __cpp_lib_concepts
49  concept boxable_movable =
50  (not std::copy_constructible<T>) and (std::movable<T> or std::is_nothrow_move_constructible_v<T>);
51 #else
52  inline constexpr bool boxable_movable =
53  (not copy_constructible<T>) and (movable<T> or std::is_nothrow_move_constructible_v<T>);
54 #endif
55  }
56 
57 
58 #ifdef __cpp_lib_concepts
59  template<detail::boxable>
60 #else
61  template<typename T, typename = void>
62 #endif
63  struct movable_box;
64 
65 
66 #ifdef __cpp_lib_concepts
67  template<detail::boxable T>
68  struct movable_box
69 #else
70  template<typename T>
71  struct movable_box<T, std::enable_if_t<detail::boxable<T> and
72  not detail::boxable_movable<T> and not detail::boxable_copyable<T>>>
73 #endif
74  : std::optional<T>
75  {
76  using std::optional<T>::optional;
77 
78 
79 #ifdef __cpp_lib_concepts
80  constexpr
81  movable_box() noexcept(std::is_nothrow_default_constructible_v<T>) requires std::default_initializable<T>
82 #else
83  template<bool Enable = true, std::enable_if_t<Enable and std::is_default_constructible_v<T>, int> = 0>
84  constexpr
85  movable_box() noexcept(std::is_nothrow_default_constructible_v<T>)
86 #endif
87  : std::optional<T>{std::in_place} {}
88 
89 
90  movable_box(const movable_box&) = default;
91 
92 
93  movable_box(movable_box&&) = default;
94 
95 
96  using std::optional<T>::operator=;
97 
98 
99 #ifdef __cpp_lib_concepts
100  constexpr movable_box&
101  operator=(const movable_box& that) noexcept(std::is_nothrow_copy_constructible_v<T>)
102  requires (not std::copyable<T>) && std::copy_constructible<T>
103 #else
104  template<bool Enable = true, std::enable_if_t<Enable and (not copyable<T>) && copy_constructible<T>, int> = 0>
105  constexpr movable_box&
106  operator=(const movable_box& that) noexcept(std::is_nothrow_copy_constructible_v<T>)
107 #endif
108  {
109  if (this != std::addressof(that))
110  {
111  if ((bool) that) this->emplace(*that);
112  else this->reset();
113  }
114  return *this;
115  }
116 
117 
118 #ifdef __cpp_lib_concepts
119  constexpr movable_box&
120  operator=(movable_box&& that) noexcept(std::is_nothrow_move_constructible_v<T>) requires (not std::movable<T>)
121 #else
122  template<bool Enable = true, std::enable_if_t<Enable and (not movable<T>), int> = 0>
123  constexpr movable_box&
124  operator=(movable_box&& that) noexcept(std::is_nothrow_move_constructible_v<T>)
125 #endif
126  {
127  if (this != std::addressof(that))
128  {
129  if ((bool) that) this->emplace(std::move(*that));
130  else this->reset();
131  }
132  return *this;
133  }
134  };
135 
136 
137 #ifdef __cpp_lib_concepts
138  template<detail::boxable T> requires detail::boxable_movable<T> or detail::boxable_copyable<T>
139  struct movable_box<T>
140 #else
141  template<typename T>
142  struct movable_box<T, std::enable_if_t<detail::boxable<T> and (detail::boxable_movable<T> or detail::boxable_copyable<T>)>>
143 #endif
144  {
145  private:
146 
147  [[no_unique_address]] T M_value = T();
148 
149  public:
150 
151 #ifdef __cpp_lib_concepts
152  movable_box() requires std::default_initializable<T> = default;
153 #else
154  template<bool Enable = true, std::enable_if_t<Enable and std::is_default_constructible_v<T>, int> = 0>
155  movable_box() {};
156 #endif
157 
158 
159 #ifdef __cpp_lib_concepts
160  constexpr explicit
161  movable_box(const T& t) noexcept(std::is_nothrow_copy_constructible_v<T>) requires std::copy_constructible<T>
162 #else
163  template<bool Enable = true, std::enable_if_t<Enable and copy_constructible<T>, int> = 0>
164  constexpr explicit
165  movable_box(const T& t) noexcept(std::is_nothrow_copy_constructible_v<T>)
166 #endif
167  : M_value(t) {}
168 
169 
170  constexpr explicit
171  movable_box(T&& t) noexcept(std::is_nothrow_move_constructible_v<T>) : M_value(std::move(t)) {}
172 
173 
174 #ifdef __cpp_lib_concepts
175  template<typename...Args> requires std::constructible_from<T, Args...>
176 #else
177  template<typename...Args, std::enable_if_t<constructible_from<T, Args...>, int> = 0>
178 #endif
179  constexpr explicit
180  movable_box(std::in_place_t, Args&&...args) noexcept(std::is_nothrow_constructible_v<T, Args...>)
181  : M_value(std::forward<Args>(args)...) {}
182 
183 
184  movable_box(const movable_box&) = default;
185 
186  movable_box(movable_box&&) = default;
187 
188 #ifdef __cpp_lib_concepts
189  movable_box& operator=(const movable_box&) requires std::copyable<T> = default;
190 #else
191  template<bool Enable = true, std::enable_if_t<Enable and copyable<T>, int> = 0>
192  constexpr movable_box& operator=(const movable_box&) {};
193 #endif
194 
195 
196 #ifdef __cpp_lib_concepts
197  movable_box& operator=(movable_box&&) requires std::movable<T> = default;
198 #else
199  template<bool Enable = true, std::enable_if_t<Enable and movable<T>, int> = 0>
200  constexpr movable_box& operator=(movable_box&&) {};
201 #endif
202 
203 
204 #ifdef __cpp_lib_concepts
205  constexpr movable_box&
206  operator=(const movable_box& that) noexcept requires (not std::copyable<T>) and std::copy_constructible<T>
207 #else
208  template<bool Enable = true, std::enable_if_t<Enable and (not copyable<T>) and copy_constructible<T>, int> = 0>
209  constexpr movable_box&
210  operator=(const movable_box& that) noexcept
211 #endif
212  {
213  static_assert(std::is_nothrow_copy_constructible_v<T>);
214  if (this != std::addressof(that))
215  {
216  M_value.~T();
217 #if __cplusplus >= 202002L
218  std::construct_at(std::addressof(M_value), *that);
219 #else
220  if constexpr (std::is_array_v<T>) return ::new (static_cast<void*>(std::addressof(M_value))) T[1]();
221  else return ::new (static_cast<void*>(std::addressof(M_value))) T(*that);
222 #endif
223  }
224  return *this;
225  }
226 
227  // Likewise for move assignment.
228 #ifdef __cpp_lib_concepts
229  constexpr movable_box&
230  operator=(movable_box&& that) noexcept requires (not std::movable<T>)
231 #else
232  template<bool Enable = true, std::enable_if_t<Enable and (not movable<T>), int> = 0>
233  constexpr movable_box&
234  operator=(movable_box&& that) noexcept
235 #endif
236  {
237  static_assert(std::is_nothrow_move_constructible_v<T>);
238  if (this != std::addressof(that))
239  {
240  M_value.~T();
241 #if __cplusplus >= 202002L
242  std::construct_at(std::addressof(M_value), *that);
243 #else
244  if constexpr (std::is_array_v<T>) return ::new (static_cast<void*>(std::addressof(M_value))) T[1]();
245  else return ::new (static_cast<void*>(std::addressof(M_value))) T(std::move(*that));
246 #endif
247  }
248  return *this;
249  }
250 
251  constexpr bool
252  has_value() const noexcept { return true; };
253 
254  constexpr T&
255  operator*() & noexcept { return M_value; }
256 
257  constexpr const T&
258  operator*() const & noexcept { return M_value; }
259 
260  constexpr T&&
261  operator*() && noexcept { return std::move(M_value); }
262 
263  constexpr const T&&
264  operator*() const && noexcept { return std::move(M_value); }
265 
266  constexpr T *
267  operator->() noexcept { return std::addressof(M_value); }
268 
269  constexpr const T *
270  operator->() const noexcept { return std::__addressof(M_value); }
271 
272  };
273 
274 }
275 
276 #endif //OPENKALMAN_COMPATIBILITY_MOVABLE_BOX_HPP
Definition: movable_box.hpp:63
Definition: tuple_reverse.hpp:103
Definitions relating to the availability of c++ language features.
Definition: basics.hpp:48