OpenKalman
common_reference.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_COMMON_REFERENCE_HPP
18 #define OPENKALMAN_COMPATIBILITY_COMMON_REFERENCE_HPP
19 
20 #if __cplusplus < 202002L
21 
22 namespace OpenKalman
23 {
24  namespace detail
25  {
26  template<typename From, typename To>
27  using copy_cv = std::conditional_t<
28  std::is_const_v<From>,
29  std::conditional_t<std::is_volatile_v<From>, const volatile To, const To>,
30  std::conditional_t<std::is_volatile_v<From>, volatile To, To>
31  >;
32 
33  template<typename A, typename B>
34  using cond_res = decltype(false ? std::declval<A(&)()>()() : std::declval<B(&)()>()());
35 
36  template<typename A, typename B>
37  using cond_res_cvref = cond_res<copy_cv<A, B>&, copy_cv<B, A>&>;
38 
39 
40  template<typename, typename, typename = void>
41  struct common_ref {};
42 
43  template<typename A, typename B>
44  using common_ref_t = typename common_ref<A, B>::type;
45 
46  template<typename A, typename B>
47  struct common_ref<A&, B&, std::void_t<cond_res_cvref<A, B>>> : std::enable_if<
48  std::is_reference_v<cond_res_cvref<A, B>>, cond_res_cvref<A, B>> {};
49 
50  template<typename A, typename B>
51  using common_ref_C = std::remove_reference_t<common_ref_t<A&, B&>>&&;
52 
53  template<typename A, typename B>
54  struct common_ref<A&&, B&&, std::enable_if_t<std::is_convertible_v<A&&, common_ref_C<A, B>> and std::is_convertible_v<B&&, common_ref_C<A, B>>>>
55  { using type = common_ref_C<A, B>; };
56 
57  template<typename A, typename B>
58  using common_ref_D = common_ref_t<const A&, B&>;
59 
60  template<typename A, typename B>
61  struct common_ref<A&&, B&, std::enable_if_t<std::is_convertible_v<A&&, common_ref_D<A, B>>>>
62  { using type = common_ref_D<A, B>; };
63 
64  template<typename A, typename B>
65  struct common_ref<A&, B&&> : common_ref<B&&, A&> {};
66 
67 
68  template<typename T1, typename T2, int b = 1, typename = void>
69  struct common_reference_impl : common_reference_impl<T1, T2, b + 1> {};
70 
71  template<typename T1, typename T2>
72  struct common_reference_impl<T1&, T2&, 1, std::void_t<common_ref_t<T1&, T2&>>> { using type = common_ref_t<T1&, T2&>; };
73 
74  template<typename T1, typename T2>
75  struct common_reference_impl<T1&&, T2&&, 1, std::void_t<common_ref_t<T1&&, T2&&>>> { using type = common_ref_t<T1&&, T2&&>; };
76 
77  template<typename T1, typename T2>
78  struct common_reference_impl<T1&, T2&&, 1, std::void_t<common_ref_t<T1&, T2&&>>> { using type = common_ref_t<T1&, T2&&>; };
79 
80  template<typename T1, typename T2>
81  struct common_reference_impl<T1&&, T2&, 1, std::void_t<common_ref_t<T1&&, T2&>>> { using type = common_ref_t<T1&&, T2&>; };
82 
83  template<typename T1, typename T2>
84  struct common_reference_impl<T1, T2, 3, std::void_t<cond_res<T1, T2>>> { using type = cond_res<T1, T2>; };
85 
86  template<typename T1, typename T2>
87  struct common_reference_impl<T1, T2, 4, std::void_t<std::common_type_t<T1, T2>>> { using type = std::common_type_t<T1, T2>; };
88 
89  template<typename T1, typename T2>
90  struct common_reference_impl<T1, T2, 5, void> {};
91 
92  }
93 
94 
95  template<typename...T>
97 
98  template<>
99  struct common_reference<> {};
100 
101  template<typename T>
102  struct common_reference<T> { using type = T; };
103 
104  template<typename T1, typename T2, typename...Ts>
105  struct common_reference<T1, T2, Ts...> : common_reference<detail::common_reference_impl<T1, T2>, Ts...> {};
106 
107 
108  template<typename...T>
109  using common_reference_t = typename common_reference<T...>::type;
110 
111 }
112 
113 #endif
114 
115 #endif //OPENKALMAN_COMPATIBILITY_COMMON_REFERENCE_HPP
Definition: common_reference.hpp:96
Definition: tuple_reverse.hpp:103
Definition: common_reference.hpp:69
The root namespace for OpenKalman.
Definition: basics.hpp:34
Definition: common_reference.hpp:41