OpenKalman
movable_wrapper.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_MOVABLE_WRAPPER_HPP
18 #define OPENKALMAN_MOVABLE_WRAPPER_HPP
19 
20 #include <functional>
23 
25 {
26  //
27  // -- General specialization -- //
28  //
29 
35 #ifdef __cpp_concepts
36  template<typename T>
37 #else
38  template<typename T, typename = void>
39 #endif
41  {
45  using type = T;
46 
47 
51  constexpr
52  movable_wrapper() noexcept = default;
53 
54 
58  explicit constexpr
59  movable_wrapper(T&& t) noexcept : t_ {std::forward<T>(t)} {}
60 
61 
65  constexpr T& get() & noexcept { return t_; }
67  constexpr const T& get() const & noexcept { return t_; }
69  constexpr T&& get() && noexcept { return std::move(t_); }
71  constexpr const T&& get() const && noexcept { return std::move(t_); }
72 
73 
77  constexpr operator T& () & noexcept { return t_; }
79  constexpr operator const T& () const & noexcept { return t_; }
81  constexpr operator T () && noexcept { return std::move(t_); }
83  constexpr operator const T () const && noexcept { return std::move(t_); }
84 
85 
89  template<typename...ArgTypes>
90  constexpr std::invoke_result_t<T&, ArgTypes...>
91  operator () (ArgTypes&&...args) & noexcept(std::is_nothrow_invocable_v<T&, ArgTypes...>)
92  {
93 #if __cplusplus >= 202002L
94  return std::invoke(t_, std::forward<ArgTypes>(args)...);
95 #else
96  return OpenKalman::invoke(t_, std::forward<ArgTypes>(args)...);
97 #endif
98  }
99 
101  template<typename...ArgTypes>
102  std::invoke_result_t<T&, ArgTypes...>
103  constexpr operator () (ArgTypes&&...args) const & noexcept(std::is_nothrow_invocable_v<T&, ArgTypes...>)
104  {
105 #if __cplusplus >= 202002L
106  return std::invoke(t_, std::forward<ArgTypes>(args)...);
107 #else
108  return OpenKalman::invoke(t_, std::forward<ArgTypes>(args)...);
109 #endif
110  }
111 
113  template<typename...ArgTypes>
114  std::invoke_result_t<T&, ArgTypes...>
115  constexpr operator () (ArgTypes&&...args) && noexcept(std::is_nothrow_invocable_v<T&, ArgTypes...>)
116  {
117 #if __cplusplus >= 202002L
118  return std::invoke(std::move(t_), std::forward<ArgTypes>(args)...);
119 #else
120  return OpenKalman::invoke(std::move(t_), std::forward<ArgTypes>(args)...);
121 #endif
122  }
123 
125  template<typename...ArgTypes>
126  std::invoke_result_t<T&, ArgTypes...>
127  constexpr operator () (ArgTypes&&...args) const && noexcept(std::is_nothrow_invocable_v<T&, ArgTypes...>)
128  {
129 #if __cplusplus >= 202002L
130  return std::invoke(std::move(t_), std::forward<ArgTypes>(args)...);
131 #else
132  return OpenKalman::invoke(std::move(t_), std::forward<ArgTypes>(args)...);
133 #endif
134  }
135 
136  private:
137 
138  T t_;
139 
140  };
141 
142 
143  //
144  // -- Reference specialization -- //
145  //
146 
150  template<typename T>
151  struct movable_wrapper<T&>
152  {
153  private:
154 
155 #if __cplusplus >= 202002L
156  using T_ = std::reference_wrapper<std::remove_reference_t<T>>;
157 #else
159 #endif
160 
161  public:
162 
166  using type = T&;
167 
168 
172 #ifdef __cpp_concepts
173  template<typename Arg>
174  explicit constexpr
175  movable_wrapper(Arg&& arg) noexcept requires std::constructible_from<T_, Arg&&>
176 #else
177  template<typename Arg, std::enable_if_t<std::is_constructible_v<T_, Arg&&>, int> = 0>
178  explicit constexpr movable_wrapper(Arg&& arg) noexcept
179 #endif
180  : t_ {std::forward<Arg>(arg)} {}
181 
182 
186  constexpr T& get() const noexcept { return t_; }
187 
188 
192  constexpr operator T& () const noexcept { return t_; }
193 
194 
198  template<typename...ArgTypes>
199  constexpr std::invoke_result_t<T&, ArgTypes...>
200  operator () (ArgTypes&&...args) const noexcept(std::is_nothrow_invocable_v<T&, ArgTypes...>)
201  {
202  return t_(std::forward<ArgTypes>(args)...);
203  }
204 
205  private:
206 
207  T_ t_;
208 
209  };
210 
211 
212  //
213  // -- Tuple specialization -- //
214  //
215 
219 #ifdef __cpp_concepts
220  template<tuple_like T> requires (not std::movable<T>)
221  struct movable_wrapper<T>
222 #else
223  template<typename T>
224  struct movable_wrapper<T, std::enable_if_t<not std::is_lvalue_reference_v<T> and tuple_like<T> and not movable<T>>>
225 #endif
226  {
227  private:
228 
229  template<typename U>
230  static constexpr decltype(auto)
231  make_element(U&& u)
232  {
233  if constexpr (std::is_lvalue_reference_v<U>) return movable_wrapper<U> {u};
234  else return std::forward<U>(u);
235  }
236 
237 
238  template<typename U, std::size_t...i>
239  static constexpr auto
240  fill_tuple(U&& u, std::index_sequence<i...>)
241  {
242  return std::tuple { make_element(OpenKalman::internal::generalized_std_get<i>(std::forward<U>(u)))...};
243  }
244 
245 
246  using T_ = decltype(fill_tuple(std::declval<T>(), std::make_index_sequence<std::tuple_size_v<T>>{}));
247 
248  public:
249 
253  using type = T;
254 
255 
259  constexpr
260  movable_wrapper() noexcept = default;
261 
262 
266  explicit constexpr
267  movable_wrapper(T&& t) noexcept
268  : t_ {fill_tuple(std::forward<T>(t), std::make_index_sequence<std::tuple_size_v<T>>{})} {}
269 
270 
274  constexpr T_& get() & noexcept { return t_; }
276  constexpr const T_& get() const & noexcept { return t_; }
278  constexpr T_&& get() && noexcept { return std::move(t_); }
280  constexpr const T_&& get() const && noexcept { return std::move(t_); }
281 
282  private:
283 
284  T_ t_;
285 
286  };
287 
288 
292  template<typename T>
294 
295 
300 #ifdef __cpp_concepts
301  template<std::size_t i, typename T> requires tuple_like<T>
302 #else
303  template<std::size_t i, typename T, std::enable_if_t<tuple_like<T>, int> = 0>
304 #endif
305  constexpr decltype(auto)
306  get(movable_wrapper<T>& arg) noexcept
307  {
308  static_assert(i < std::tuple_size_v<std::decay_t<T>>, "Index out of range");
309  return OpenKalman::internal::generalized_std_get<i>(arg.get());
310  }
311 
312 
313 #ifdef __cpp_concepts
314  template<std::size_t i, typename T> requires tuple_like<T>
315 #else
316  template<std::size_t i, typename T, std::enable_if_t<tuple_like<T>, int> = 0>
317 #endif
318  constexpr decltype(auto)
319  get(const movable_wrapper<T>& arg) noexcept
320  {
321  static_assert(i < std::tuple_size_v<std::decay_t<T>>, "Index out of range");
322  return OpenKalman::internal::generalized_std_get<i>(arg.get());
323  }
324 
325 
326 #ifdef __cpp_concepts
327  template<std::size_t i, typename T> requires tuple_like<T>
328 #else
329  template<std::size_t i, typename T, std::enable_if_t<tuple_like<T>, int> = 0>
330 #endif
331  constexpr decltype(auto)
332  get(movable_wrapper<T>&& arg) noexcept
333  {
334  static_assert(i < std::tuple_size_v<std::decay_t<T>>, "Index out of range");
335  return OpenKalman::internal::generalized_std_get<i>(std::move(arg).get());
336  }
337 
338 
339 #ifdef __cpp_concepts
340  template<std::size_t i, typename T> requires tuple_like<T>
341 #else
342  template<std::size_t i, typename T, std::enable_if_t<tuple_like<T>, int> = 0>
343 #endif
344  constexpr decltype(auto)
345  get(const movable_wrapper<T>&& arg) noexcept
346  {
347  static_assert(i < std::tuple_size_v<std::decay_t<T>>, "Index out of range");
348  return OpenKalman::internal::generalized_std_get<i>(std::move(arg).get());
349  }
350 
351 
352 #ifdef __cpp_impl_three_way_comparison
353  template<typename T>
354  constexpr bool operator==(const movable_wrapper<T>& lhs, const movable_wrapper<T>& rhs) noexcept
355  requires requires { {lhs.get() == rhs.get()} -> std::convertible_to<bool>; }
356  {
357  return lhs.get() == rhs.get();
358  }
359 
360  template<typename T>
361  constexpr bool operator==(const movable_wrapper<T>& lhs, const movable_wrapper<const T>& rhs) noexcept
362  requires (not std::is_const_v<T>) and requires { {lhs.get() == rhs.get()} -> std::convertible_to<bool>; }
363  {
364  return lhs.get() == rhs.get();
365  }
366 
367  template<typename T>
368  constexpr bool operator==(const movable_wrapper<T>& lhs, const T& ref) noexcept
369  requires requires { {lhs.get() == ref} -> std::convertible_to<bool>; }
370  {
371  return lhs.get() == ref;
372  }
373 
374  template<typename T>
375  constexpr auto operator<=>(const movable_wrapper<T>& lhs, const movable_wrapper<T>& rhs) noexcept
376  requires requires { {lhs.get() < rhs.get()} -> std::convertible_to<bool>; {lhs.get() > rhs.get()} -> std::convertible_to<bool>; }
377  {
378  return lhs.get() <=> rhs.get();
379  }
380 
381  template<typename T>
382  constexpr auto operator<=>(const movable_wrapper<T>& lhs, const movable_wrapper<const T>& rhs) noexcept requires
383  (not std::is_const_v<T>) and
384  requires { {lhs.get() < rhs.get()} -> std::convertible_to<bool>; {lhs.get() > rhs.get()} -> std::convertible_to<bool>; }
385  {
386  return lhs.get() <=> rhs.get();
387  }
388 
389  template<typename T>
390  constexpr auto operator<=>(const movable_wrapper<T>& lhs, const T& ref) noexcept
391  requires requires { {lhs.get() < ref} -> std::convertible_to<bool>; {lhs.get() > ref} -> std::convertible_to<bool>; }
392  {
393  return lhs.get() <=> ref;
394  }
395 #else
396  template<typename T, std::enable_if_t<
397  std::is_convertible<decltype(std::declval<const movable_wrapper<T>&>().get() == std::declval<const movable_wrapper<T>&>().get()), bool>::value, int> = 0>
398  constexpr bool operator==(const movable_wrapper<T>& lhs, const movable_wrapper<T>& rhs) noexcept
399  { return lhs.get() == rhs.get(); }
400 
401  template<typename T, std::enable_if_t<(not std::is_const_v<T>) and
402  std::is_convertible<decltype(std::declval<const movable_wrapper<T>&>().get() == std::declval<movable_wrapper<T>&>().get()), bool>::value, int> = 0>
403  constexpr bool operator==(const movable_wrapper<T>& lhs, const movable_wrapper<const T>& rhs) noexcept
404  { return lhs.get() == rhs.get(); }
405 
406  template<typename T, std::enable_if_t<(not std::is_const_v<T>) and
407  std::is_convertible<decltype(std::declval<movable_wrapper<T>&>().get() == std::declval<movable_wrapper<T>&>().get()), bool>::value, int> = 0>
408  constexpr bool operator==(const movable_wrapper<const T>& lhs, const movable_wrapper<T>& rhs) noexcept
409  { return lhs.get() == rhs.get(); }
410 
411  template<typename T, std::enable_if_t<
412  std::is_convertible<decltype(std::declval<movable_wrapper<T>&>().get() == std::declval<const T&>()), bool>::value, int> = 0>
413  constexpr bool operator==(const movable_wrapper<T>& lhs, const T& ref) noexcept
414  { return lhs.get() == ref; }
415 
416  template<typename T, std::enable_if_t<
417  std::is_convertible<decltype(std::declval<const T&>() == std::declval<movable_wrapper<T>&>().get()), bool>::value, int> = 0>
418  constexpr bool operator==(const T& ref, const movable_wrapper<T>& lhs) noexcept
419  { return ref == lhs.get(); }
420 
421 
422  template<typename T, std::enable_if_t<
423  std::is_convertible<decltype(std::declval<const movable_wrapper<T>&>().get() == std::declval<const movable_wrapper<T>&>().get()), bool>::value, int> = 0>
424  constexpr bool operator!=(const movable_wrapper<T>& lhs, const movable_wrapper<T>& rhs) noexcept
425  { return lhs.get() != rhs.get(); }
426 
427  template<typename T, std::enable_if_t<(not std::is_const_v<T>) and
428  std::is_convertible<decltype(std::declval<movable_wrapper<T>&>().get() != std::declval<movable_wrapper<T>&>().get()), bool>::value, int> = 0>
429  constexpr bool operator!=(const movable_wrapper<T>& lhs, const movable_wrapper<const T>& rhs) noexcept
430  { return lhs.get() != rhs.get(); }
431 
432  template<typename T, std::enable_if_t<(not std::is_const_v<T>) and
433  std::is_convertible<decltype(std::declval<movable_wrapper<T>&>().get() != std::declval<movable_wrapper<T>&>().get()), bool>::value, int> = 0>
434  constexpr bool operator!=(const movable_wrapper<const T>& lhs, const movable_wrapper<T>& rhs) noexcept
435  { return lhs.get() != rhs.get(); }
436 
437  template<typename T, std::enable_if_t<
438  std::is_convertible<decltype(std::declval<movable_wrapper<T>&>().get() != std::declval<const T&>()), bool>::value, int> = 0>
439  constexpr bool operator!=(const movable_wrapper<T>& lhs, const T& ref) noexcept
440  { return lhs.get() != ref; }
441 
442  template<typename T, std::enable_if_t<
443  std::is_convertible<decltype(std::declval<const T&>() != std::declval<movable_wrapper<T>&>().get()), bool>::value, int> = 0>
444  constexpr bool operator!=(const T& ref, const movable_wrapper<T>& lhs) noexcept
445  { return ref != lhs.get(); }
446 
447 
448 template<typename T, std::enable_if_t<
449  std::is_convertible<decltype(std::declval<const movable_wrapper<T>&>().get() == std::declval<const movable_wrapper<T>&>().get()), bool>::value, int> = 0>
450 constexpr bool operator<(const movable_wrapper<T>& lhs, const movable_wrapper<T>& rhs) noexcept
451  { return lhs.get() < rhs.get(); }
452 
453  template<typename T, std::enable_if_t<(not std::is_const_v<T>) and
454  std::is_convertible<decltype(std::declval<movable_wrapper<T>&>().get() < std::declval<movable_wrapper<T>&>().get()), bool>::value, int> = 0>
455  constexpr bool operator<(const movable_wrapper<T>& lhs, const movable_wrapper<const T>& rhs) noexcept
456  { return lhs.get() < rhs.get(); }
457 
458  template<typename T, std::enable_if_t<(not std::is_const_v<T>) and
459  std::is_convertible<decltype(std::declval<movable_wrapper<T>&>().get() < std::declval<movable_wrapper<T>&>().get()), bool>::value, int> = 0>
460  constexpr bool operator<(const movable_wrapper<const T>& lhs, const movable_wrapper<T>& rhs) noexcept
461  { return lhs.get() < rhs.get(); }
462 
463  template<typename T, std::enable_if_t<
464  std::is_convertible<decltype(std::declval<movable_wrapper<T>&>().get() < std::declval<const T&>()), bool>::value, int> = 0>
465  constexpr bool operator<(const movable_wrapper<T>& lhs, const T& ref) noexcept
466  { return lhs.get() < ref; }
467 
468  template<typename T, std::enable_if_t<
469  std::is_convertible<decltype(std::declval<const T&>() < std::declval<movable_wrapper<T>&>().get()), bool>::value, int> = 0>
470  constexpr bool operator<(const T& ref, const movable_wrapper<T>& lhs) noexcept
471  { return ref < lhs.get(); }
472 
473 
474 template<typename T, std::enable_if_t<
475  std::is_convertible<decltype(std::declval<const movable_wrapper<T>&>().get() == std::declval<const movable_wrapper<T>&>().get()), bool>::value, int> = 0>
476 constexpr bool operator>(const movable_wrapper<T>& lhs, const movable_wrapper<T>& rhs) noexcept
477  { return lhs.get() > rhs.get(); }
478 
479  template<typename T, std::enable_if_t<(not std::is_const_v<T>) and
480  std::is_convertible<decltype(std::declval<movable_wrapper<T>&>().get() > std::declval<movable_wrapper<T>&>().get()), bool>::value, int> = 0>
481  constexpr bool operator>(const movable_wrapper<T>& lhs, const movable_wrapper<const T>& rhs) noexcept
482  { return lhs.get() > rhs.get(); }
483 
484  template<typename T, std::enable_if_t<(not std::is_const_v<T>) and
485  std::is_convertible<decltype(std::declval<movable_wrapper<T>&>().get() > std::declval<movable_wrapper<T>&>().get()), bool>::value, int> = 0>
486  constexpr bool operator>(const movable_wrapper<const T>& lhs, const movable_wrapper<T>& rhs) noexcept
487  { return lhs.get() > rhs.get(); }
488 
489  template<typename T, std::enable_if_t<
490  std::is_convertible<decltype(std::declval<movable_wrapper<T>&>().get() > std::declval<const T&>()), bool>::value, int> = 0>
491  constexpr bool operator>(const movable_wrapper<T>& lhs, const T& ref) noexcept
492  { return lhs.get() > ref; }
493 
494  template<typename T, std::enable_if_t<
495  std::is_convertible<decltype(std::declval<const T&>() > std::declval<movable_wrapper<T>&>().get()), bool>::value, int> = 0>
496  constexpr bool operator>(const T& ref, const movable_wrapper<T>& lhs) noexcept
497  { return ref > lhs.get(); }
498 
499 
500 template<typename T, std::enable_if_t<
501  std::is_convertible<decltype(std::declval<const movable_wrapper<T>&>().get() == std::declval<const movable_wrapper<T>&>().get()), bool>::value, int> = 0>
502 constexpr bool operator<=(const movable_wrapper<T>& lhs, const movable_wrapper<T>& rhs) noexcept
503  { return lhs.get() <= rhs.get(); }
504 
505  template<typename T, std::enable_if_t<(not std::is_const_v<T>) and
506  std::is_convertible<decltype(std::declval<movable_wrapper<T>&>().get() <= std::declval<movable_wrapper<T>&>().get()), bool>::value, int> = 0>
507  constexpr bool operator<=(const movable_wrapper<T>& lhs, const movable_wrapper<const T>& rhs) noexcept
508  { return lhs.get() <= rhs.get(); }
509 
510  template<typename T, std::enable_if_t<(not std::is_const_v<T>) and
511  std::is_convertible<decltype(std::declval<movable_wrapper<T>&>().get() <= std::declval<movable_wrapper<T>&>().get()), bool>::value, int> = 0>
512  constexpr bool operator<=(const movable_wrapper<const T>& lhs, const movable_wrapper<T>& rhs) noexcept
513  { return lhs.get() <= rhs.get(); }
514 
515  template<typename T, std::enable_if_t<
516  std::is_convertible<decltype(std::declval<movable_wrapper<T>&>().get() <= std::declval<const T&>()), bool>::value, int> = 0>
517  constexpr bool operator<=(const movable_wrapper<T>& lhs, const T& ref) noexcept
518  { return lhs.get() <= ref; }
519 
520  template<typename T, std::enable_if_t<
521  std::is_convertible<decltype(std::declval<const T&>() <= std::declval<movable_wrapper<T>&>().get()), bool>::value, int> = 0>
522  constexpr bool operator<=(const T& ref, const movable_wrapper<T>& lhs) noexcept
523  { return ref <= lhs.get(); }
524 
525 
526 template<typename T, std::enable_if_t<
527  std::is_convertible<decltype(std::declval<const movable_wrapper<T>&>().get() == std::declval<const movable_wrapper<T>&>().get()), bool>::value, int> = 0>
528 constexpr bool operator>=(const movable_wrapper<T>& lhs, const movable_wrapper<T>& rhs) noexcept
529  { return lhs.get() >= rhs.get(); }
530 
531  template<typename T, std::enable_if_t<(not std::is_const_v<T>) and
532  std::is_convertible<decltype(std::declval<movable_wrapper<T>&>().get() >= std::declval<movable_wrapper<T>&>().get()), bool>::value, int> = 0>
533  constexpr bool operator>=(const movable_wrapper<T>& lhs, const movable_wrapper<const T>& rhs) noexcept
534  { return lhs.get() >= rhs.get(); }
535 
536  template<typename T, std::enable_if_t<(not std::is_const_v<T>) and
537  std::is_convertible<decltype(std::declval<movable_wrapper<T>&>().get() >= std::declval<movable_wrapper<T>&>().get()), bool>::value, int> = 0>
538  constexpr bool operator>=(const movable_wrapper<const T>& lhs, const movable_wrapper<T>& rhs) noexcept
539  { return lhs.get() >= rhs.get(); }
540 
541  template<typename T, std::enable_if_t<
542  std::is_convertible<decltype(std::declval<movable_wrapper<T>&>().get() >= std::declval<const T&>()), bool>::value, int> = 0>
543  constexpr bool operator>=(const movable_wrapper<T>& lhs, const T& ref) noexcept
544  { return lhs.get() >= ref; }
545 
546  template<typename T, std::enable_if_t<
547  std::is_convertible<decltype(std::declval<const T&>() >= std::declval<movable_wrapper<T>&>().get()), bool>::value, int> = 0>
548  constexpr bool operator>=(const T& ref, const movable_wrapper<T>& lhs) noexcept
549  { return ref >= lhs.get(); }
550 #endif
551 
552 
553 #if __cplusplus >= 202002L
554  namespace detail
555  {
556  template <class T>
557  inline constexpr bool is_movable_wrapper_ref = false;
558 
559  template <class T>
560  inline constexpr bool is_movable_wrapper_ref<movable_wrapper<T&>> = true;
561  }
562 
563 
564  template<typename R, typename T, typename RQ, typename TQ>
565  concept movable_wrapper_common_reference_exists_with =
566  detail::is_movable_wrapper_ref<R> and
567  requires { typename std::common_reference_t<typename R::type, TQ>; } and
568  std::convertible_to<RQ, std::common_reference_t<typename R::type, TQ>>
569  ;
570 #endif
571 
572 
573 #ifndef __cpp_concepts
574  template<typename T, typename = void>
575  struct maybe_tuple_size {};
576 
577  template<typename T>
578  struct maybe_tuple_size<T, std::void_t<decltype(std::tuple_size<T>::value)>>
579  : std::tuple_size<T> {};
580 
581 
582  template<std::size_t i, typename T, typename = void>
584 
585  template<std::size_t i, typename T>
586  struct maybe_tuple_element<i, T, std::void_t<typename std::tuple_element<i, T>::type>>
587  : std::tuple_element<i, T> {};
588 #endif
589 
590 }
591 
592 
593 namespace std
594 {
595 #ifdef __cpp_concepts
596  template<typename Tup> requires requires { tuple_size<std::decay_t<Tup>>::value; }
597  struct tuple_size<OpenKalman::collections::internal::movable_wrapper<Tup>> : tuple_size<std::decay_t<Tup>> {};
598 #else
599  template<typename Tup>
600  struct tuple_size<OpenKalman::collections::internal::movable_wrapper<Tup>>
602 #endif
603 
604 
605 #ifdef __cpp_concepts
606  template<std::size_t i, typename Tup> requires requires { typename tuple_element<i, std::decay_t<Tup>>::type; }
607  struct tuple_element<i, OpenKalman::collections::internal::movable_wrapper<Tup>> : tuple_element<i, std::decay_t<Tup>> {};
608 #else
609  template<std::size_t i, typename Tup>
610  struct tuple_element<i, OpenKalman::collections::internal::movable_wrapper<Tup>>
612 #endif
613 
614 
615 #if __cplusplus >= 202002L
616  template <typename R, typename T, template<typename> typename RQual, template<typename> typename TQual> requires
617  OpenKalman::collections::internal::movable_wrapper_common_reference_exists_with<R, T, RQual<R>, TQual<T>> and
618  (not OpenKalman::collections::internal::movable_wrapper_common_reference_exists_with<T, R, TQual<T>, RQual<R>>)
619  struct basic_common_reference<R, T, RQual, TQual>
620  {
621  using type = common_reference_t<typename R::type, TQual<T>>;
622  };
623 
624 
625  template <typename T, typename R, template <typename> typename TQual, template <typename> typename RQual> requires
626  OpenKalman::collections::internal::movable_wrapper_common_reference_exists_with<R, T, RQual<R>, TQual<T>> and
627  (not OpenKalman::collections::internal::movable_wrapper_common_reference_exists_with<T, R, TQual<T>, RQual<R>>)
628  struct basic_common_reference<T, R, TQual, RQual>
629  {
630  using type = common_reference_t<typename R::type, TQual<T>>;
631  };
632 #endif
633 
634 
635 } // namespace std
636 
637 #endif //OPENKALMAN_MOVABLE_WRAPPER_HPP
Definition for collections::tuple_like.
Definition: movable_wrapper.hpp:575
constexpr std::invoke_result_t< T &, ArgTypes... > operator()(ArgTypes &&...args) &noexcept(std::is_nothrow_invocable_v< T &, ArgTypes... >)
Call the callable object.
Definition: movable_wrapper.hpp:91
Definition: tuple_reverse.hpp:103
constexpr bool value
T is numerical value or is reducible to a numerical value.
Definition: value.hpp:31
Definitions relating to the availability of c++ language features.
F type
The wrapped type.
Definition: movable_wrapper.hpp:45
constexpr T & get() &noexcept
Retrieve the stored value.
Definition: movable_wrapper.hpp:65
constexpr movable_wrapper() noexcept=default
Default constructor.
Definition: tuple_like_to_tuple.hpp:24
T & type
The wrapped type.
Definition: movable_wrapper.hpp:166
Definition: movable_wrapper.hpp:40
constexpr movable_wrapper(Arg &&arg) noexcept
Construct from a value.
Definition: movable_wrapper.hpp:178