VCCC  2024.05
VisualCamp Common C++ library
cxx20_rel_ops.hpp
Go to the documentation of this file.
1 //
2 // Created by yonggyulee on 2023/12/26.
3 //
4 
5 #ifndef VCCC_UTILITY_CXX20_REL_OPS_HPP_
6 #define VCCC_UTILITY_CXX20_REL_OPS_HPP_
7 
8 #include <type_traits>
9 
15 
16 namespace vccc {
17 namespace rel_ops {
18 namespace detail {
19 
20 template<typename T, typename U, typename = void>
21 struct has_operator_equal_2 : std::false_type {};
22 template<typename T, typename U>
24  T, U,
25  void_t<decltype( std::declval<T>() == std::declval<U>() )>
26  > : std::is_convertible<decltype( std::declval<T>() == std::declval<U>() ), bool> {};
27 
28 template<typename T, typename U, typename = void>
29 struct has_operator_less_2 : std::false_type {};
30 template<typename T, typename U>
32  T, U,
33  void_t<decltype( std::declval<T>() < std::declval<U>() )>
34  > : std::is_convertible<decltype( std::declval<T>() < std::declval<U>() ), bool> {};
35 
36 } // namespace detail
37 
130 
131 #if __cplusplus < 202002L
132 
133 template<typename T, typename U, std::enable_if_t<conjunction<
134  negation<std::is_same<T, U>>,
135  detail::has_operator_equal_2<const U&, const T&>
136 >::value, int> = 0>
137 constexpr bool operator==(const T& a, const U& b) noexcept(noexcept(b == a)) {
138  return b == a;
139 }
140 
141 #endif // __cplusplus < 202002L
142 
143 namespace detail {
144 
145 struct is_equality_comparable_impl {
146  template<typename T, typename U>
147  static constexpr std::false_type test(...);
148  template<typename T, typename U>
149  static constexpr auto test(void_t<decltype( std::declval<T>() == std::declval<U>() )>* = nullptr)
150  -> std::is_convertible<decltype( std::declval<T>() == std::declval<U>() ), bool>;
151 
152  template<typename T, typename U>
153  using type = decltype(test<T, U>(0));
154 };
155 
156 } // namespace detail
157 
158 template<typename T, typename U>
159 struct is_equality_comparable : detail::is_equality_comparable_impl::type<T, U> {};
160 
161 
163 template<typename T, typename U, std::enable_if_t<conjunction<
164  negation<std::is_same<T, U>>,
165  is_equality_comparable<T, U>,
166  negation< detail::has_operator_less_2<const T&, const U&> >,
167  detail::has_operator_less_2<const U&, const T&>
168  >::value, int> = 0>
169 constexpr bool operator<(const T& a, const U& b) noexcept(noexcept(!( (b < a) || (a == b)))) {
170  // (a < b) -> !(a >= b) -> !( a > b || a == b) -> !( b < a || a == b)
171  return !( (b < a) || (a == b));
172 }
173 
174 namespace detail {
175 
176 struct is_less_than_comparable_impl {
177  template<typename T, typename U>
178  static constexpr std::false_type test(...);
179  template<typename T, typename U>
180  static constexpr auto test(void_t<decltype( std::declval<T>() < std::declval<U>() )>* = nullptr)
181  -> std::is_convertible<decltype( std::declval<T>() < std::declval<U>() ), bool>;
182 
183  template<typename T, typename U>
184  using type = decltype(test<T, U>(0));
185 };
186 
187 } // namespace detail
188 
189 template<typename T, typename U>
190 struct is_less_than_comparable : detail::is_less_than_comparable_impl::type<T, U> {};
191 
193 template<typename T, typename U, std::enable_if_t<is_equality_comparable<T, U>::value, int> = 0>
194 constexpr bool operator!=(const T& a, const U& b) noexcept(noexcept(!(a == b))) {
195  return !(a == b);
196 }
197 
199 template<typename T, typename U, std::enable_if_t<is_less_than_comparable<U, T>::value, int> = 0>
200 constexpr bool operator>(const T& a, const U& b) noexcept(noexcept(b < a)) {
201  return b < a; // (a > b) -> (b < a)
202 }
203 
205 template<typename T, typename U, std::enable_if_t<is_less_than_comparable<U, T>::value, int> = 0>
206 constexpr bool operator<=(const T& a, const U& b) noexcept(noexcept(!(b < a))) {
207  return !(b < a); // (a <= b) -> !(a > b) -> !(b < a)
208 }
209 
211 template<typename T, typename U, std::enable_if_t<is_less_than_comparable<T, U>::value, int> = 0>
212 constexpr bool operator>=(const T& a, const U& b) noexcept(noexcept(!(a < b))) {
213  return !(a < b); // (a >= b) -> !(a < b)
214 }
215 
216 namespace detail {
217 
218 struct is_non_equality_comparable_impl {
219  template<typename T, typename U>
220  static constexpr std::false_type test(...);
221  template<typename T, typename U>
222  static constexpr auto test(void_t<decltype( std::declval<T>() != std::declval<U>() )>* = nullptr)
223  -> std::is_convertible<decltype( std::declval<T>() != std::declval<U>() ), bool>;
224 
225  template<typename T, typename U>
226  using type = decltype(test<T, U>(0));
227 };
228 
229 struct is_less_equal_than_comparable_impl {
230  template<typename T, typename U>
231  static constexpr std::false_type test(...);
232  template<typename T, typename U>
233  static constexpr auto test(void_t<decltype( std::declval<T>() <= std::declval<U>() )>* = nullptr)
234  -> std::is_convertible<decltype( std::declval<T>() <= std::declval<U>() ), bool>;
235 
236  template<typename T, typename U>
237  using type = decltype(test<T, U>(0));
238 };
239 
240 struct is_greater_than_comparable_impl {
241  template<typename T, typename U>
242  static constexpr std::false_type test(...);
243  template<typename T, typename U>
244  static constexpr auto test(void_t<decltype( std::declval<T>() > std::declval<U>() )>* = nullptr)
245  -> std::is_convertible<decltype( std::declval<T>() > std::declval<U>() ), bool>;
246 
247  template<typename T, typename U>
248  using type = decltype(test<T, U>(0));
249 };
250 
251 struct is_greater_equal_than_comparable_impl {
252  template<typename T, typename U>
253  static constexpr std::false_type test(...);
254  template<typename T, typename U>
255  static constexpr auto test(void_t<decltype( std::declval<T>() >= std::declval<U>() )>* = nullptr)
256  -> std::is_convertible<decltype( std::declval<T>() >= std::declval<U>() ), bool>;
257 
258  template<typename T, typename U>
259  using type = decltype(test<T, U>(0));
260 };
261 
262 } // namespace detail
263 
264 template<typename T, typename U>
265 struct is_non_equality_comparable : detail::is_non_equality_comparable_impl::type<T, U> {};
266 template<typename T, typename U>
267 struct is_less_equal_than_comparable : detail::is_less_equal_than_comparable_impl::type<T, U> {};
268 template<typename T, typename U>
269 struct is_greater_than_comparable : detail::is_greater_than_comparable_impl::type<T, U> {};
270 template<typename T, typename U>
271 struct is_greater_equal_than_comparable : detail::is_greater_equal_than_comparable_impl::type<T, U> {};
272 
275 
276 } // namespace rel_ops
277 } // namespace vccc
278 
279 #endif // VCCC_UTILITY_CXX20_REL_OPS_HPP_
void void_t
Definition: void_t.hpp:19
Definition: matrix.hpp:495
Definition: directory.h:12
Definition: cxx20_rel_ops.hpp:21
Definition: cxx20_rel_ops.hpp:29