17 #ifndef OPENKALMAN_COMPATIBILITY_COMMON_HPP 18 #define OPENKALMAN_COMPATIBILITY_COMMON_HPP 24 #if __cplusplus >= 202002L 25 using std::common_reference;
26 using std::common_reference_t;
27 using std::common_reference_with;
28 using std::common_with;
32 template<
typename From,
typename To>
33 using copy_cv = std::conditional_t<
34 std::is_const_v<From>,
35 std::conditional_t<std::is_volatile_v<From>,
const volatile To,
const To>,
36 std::conditional_t<std::is_volatile_v<From>,
volatile To, To>
39 template<
typename A,
typename B>
40 using cond_res = decltype(
false ? std::declval<A(&)()>()() : std::declval<B(&)()>()());
42 template<
typename A,
typename B>
43 using cond_res_cvref = cond_res<copy_cv<A, B>&, copy_cv<B, A>&>;
46 template<
typename,
typename,
typename =
void>
49 template<
typename A,
typename B>
52 template<
typename A,
typename B>
53 struct common_ref<A&, B&, std::void_t<cond_res_cvref<A, B>>> : std::enable_if<
54 std::is_reference_v<cond_res_cvref<A, B>>, cond_res_cvref<A, B>> {};
56 template<
typename A,
typename B>
57 using common_ref_C = std::remove_reference_t<common_ref_t<A&, B&>>&&;
59 template<
typename A,
typename B>
60 struct common_ref<A&&, B&&, std::enable_if_t<convertible_to<A&&, common_ref_C<A, B>> and convertible_to<B&&, common_ref_C<A, B>>>>
61 {
using type = common_ref_C<A, B>; };
63 template<
typename A,
typename B>
64 using common_ref_D = common_ref_t<const A&, B&>;
66 template<
typename A,
typename B>
67 struct common_ref<A&&, B&, std::enable_if_t<convertible_to<A&&, common_ref_D<A, B>>>>
68 {
using type = common_ref_D<A, B>; };
70 template<
typename A,
typename B>
74 template<
typename T1,
typename T2,
int b = 1,
typename =
void>
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&>; };
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&&>; };
83 template<
typename T1,
typename T2>
84 struct common_reference_impl<T1&, T2&&, 1, std::void_t<common_ref_t<T1&, T2&&>>> {
using type = common_ref_t<T1&, T2&&>; };
86 template<
typename T1,
typename T2>
87 struct common_reference_impl<T1&&, T2&, 1, std::void_t<common_ref_t<T1&&, T2&>>> {
using type = common_ref_t<T1&&, T2&>; };
89 template<
typename T1,
typename T2>
92 template<
typename T1,
typename T2>
95 template<
typename T1,
typename T2>
101 template<
typename...T>
112 template<
typename T1,
typename T2,
typename = void,
typename...Ts>
115 template<
typename T1,
typename T2,
typename...Ts>
120 template<
typename T1,
typename T2,
typename...Ts>
124 template<
typename...T>
128 template<
typename T,
typename U>
129 inline constexpr
bool 130 common_reference_with =
131 same_as<common_reference_t<T, U>, common_reference_t<U, T>> and
132 stdex::convertible_to<T, common_reference_t<T, U>> and
133 stdex::convertible_to<U, common_reference_t<T, U>>;
137 template<
typename T,
typename U,
typename =
void>
140 template<
typename T,
typename U>
142 (same_as<typename std::common_type<T, U>::type, typename std::common_type<U, T>::type>)>> : std::true_type {};
144 template<
typename T,
typename U,
typename =
void>
147 template<
typename T,
typename U>
149 decltype(static_cast<typename std::common_type<T, U>::type>(std::declval<T>())),
150 decltype(static_cast<typename std::common_type<T, U>::type>(std::declval<U>()))>> : std::true_type {};
152 template<
typename T,
typename U,
typename =
void>
155 template<
typename T,
typename U>
157 (common_reference_with<std::add_lvalue_reference_t<typename std::common_type<T, U>::type>,
158 common_reference_t<std::add_lvalue_reference_t<const T>, std::add_lvalue_reference_t<const U>>>)>> : std::true_type {};
162 template<
typename T,
typename U>
163 inline constexpr
bool 167 stdex::common_reference_with<std::add_lvalue_reference_t<const T>, std::add_lvalue_reference_t<const U>> and
176 #ifdef __cpp_lib_concepts 177 using std::assignable_from;
181 template<
typename LHS,
typename RHS,
typename =
void>
184 template<
typename LHS,
typename RHS>
186 stdex::same_as<decltype(std::declval<LHS>() = std::declval<RHS&&>()), LHS>>> : std::true_type {};
190 template<
typename LHS,
typename RHS>
191 inline constexpr
bool 193 std::is_lvalue_reference_v<LHS> and
194 stdex::common_reference_with<const std::remove_reference_t<LHS>&,
const std::remove_reference_t<RHS>&> and
202 #if __cplusplus >= 202002L 203 using std::ranges::swap;
205 namespace detail_swap
207 template<
typename Tp>
208 inline constexpr
bool class_or_enum = std::is_class_v<Tp> or std::is_union_v<Tp> or std::is_enum_v<Tp>;
211 template<
typename Tp>
void swap(Tp&, Tp&) noexcept =
delete;
214 template<
typename Tp,
typename Up,
typename =
void>
217 template<
typename Tp,
typename Up>
219 decltype(swap(static_cast<Tp&&>(std::declval<Tp&>()), static_cast<Up&&>(std::declval<Up&>())))>> : std::true_type {};
222 template<
typename Tp,
typename Up>
223 inline constexpr
bool adl_swap =
224 (class_or_enum<std::remove_reference_t<Tp>> or class_or_enum<std::remove_reference_t<Up>>) and
230 template<
typename Tp,
typename Up>
231 static constexpr
bool S_noexcept()
233 if constexpr (adl_swap<Tp, Up>)
234 return noexcept(swap(std::declval<Tp>(), std::declval<Up>()));
236 return std::is_nothrow_move_constructible_v<std::remove_reference_t<Tp>> and
237 std::is_nothrow_move_assignable_v<std::remove_reference_t<Tp>>;
242 template<
typename Tp,
typename Up, std::enable_if_t<adl_swap<Tp, Up> or
243 (stdex::same_as<Tp, Up> && std::is_lvalue_reference_v<Tp> and
244 stdex::move_constructible<std::remove_reference_t<Tp>> and
245 stdex::assignable_from<Tp, std::remove_reference_t<Tp>>),
int> = 0>
247 operator()(Tp&& t, Up&& u)
const noexcept(S_noexcept<Tp, Up>())
249 if constexpr (adl_swap<Tp, Up>)
251 swap(static_cast<Tp&&>(t), static_cast<Up&&>(u));
255 auto tmp =
static_cast<std::remove_reference_t<Tp>&&
>(t);
256 t =
static_cast<std::remove_reference_t<Tp>&&
>(u);
257 u =
static_cast<std::remove_reference_t<Tp>&&
>(tmp);
261 template<
typename Tp,
typename Up,
size_t Num,
typename = std::void_t<
262 decltype(std::declval<const swap_impl&>()(std::declval<Tp&>(), std::declval<Up&>()))>>
264 operator()(Tp (&e1)[Num], Up (&e2)[Num])
const noexcept(noexcept(std::declval<const swap_impl&>()(*e1, *e2)))
266 for (
size_t n = 0; n < Num; ++n) (*
this)(e1[n], e2[n]);
279 #if __cplusplus >= 202002L 280 using std::swappable;
281 using std::swappable_with;
285 template<
typename T,
typename U,
typename =
void>
288 template<
typename T,
typename U>
289 struct swappable_impl<T, U,
std::void_t<decltype(stdex::ranges::swap(std::declval<T&>(), std::declval<U&>()))>> : std::true_type {};
291 template<
typename T,
typename U,
typename =
void>
294 template<
typename T,
typename U>
295 struct swappable_with_impl<T, U, std::void_t<decltype(stdex::ranges::swap(std::declval<T&&>(), std::declval<U&&>()))>> : std::true_type {};
303 template<
typename T,
typename U>
304 inline constexpr
bool swappable_with =
305 stdex::common_reference_with<T, U> and
Definition: common.hpp:47
Definition: common.hpp:113
Definition: common.hpp:292
Definition: common.hpp:138
Definition: common.hpp:215
Definition: common.hpp:153
Definition: common.hpp:200
Definition: common.hpp:75
Definitions relating to standard c++ library concepts.
Definition: common.hpp:286
Definition: common.hpp:102
Definition: common.hpp:145
Definition: basics.hpp:55
Definition: common.hpp:182
Definition: common.hpp:228