1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef _LIBCPP___UTILITY_DEFAULT_THREE_WAY_COMPARATOR_H
10#define _LIBCPP___UTILITY_DEFAULT_THREE_WAY_COMPARATOR_H
11
12#include <__config>
13#include <__type_traits/enable_if.h>
14#include <__type_traits/is_arithmetic.h>
15
16#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
17# pragma GCC system_header
18#endif
19
20_LIBCPP_BEGIN_NAMESPACE_STD
21
22// This struct can be specialized to provide a three way comparator between _LHS and _RHS.
23// The return value should be
24// - less than zero if (lhs_val < rhs_val)
25// - greater than zero if (rhs_val < lhs_val)
26// - zero otherwise
27template <class _LHS, class _RHS, class = void>
28struct __default_three_way_comparator;
29
30template <class _LHS, class _RHS>
31struct __default_three_way_comparator<_LHS,
32 _RHS,
33 __enable_if_t<is_arithmetic<_LHS>::value && is_arithmetic<_RHS>::value> > {
34 _LIBCPP_HIDE_FROM_ABI static int operator()(_LHS __lhs, _RHS __rhs) {
35 if (__lhs < __rhs)
36 return -1;
37 if (__lhs > __rhs)
38 return 1;
39 return 0;
40 }
41};
42
43#if _LIBCPP_STD_VER >= 20 && __has_builtin(__builtin_lt_synthesizes_from_spaceship)
44template <class _LHS, class _RHS>
45struct __default_three_way_comparator<
46 _LHS,
47 _RHS,
48 __enable_if_t<!(is_arithmetic<_LHS>::value && is_arithmetic<_RHS>::value) &&
49 __builtin_lt_synthesizes_from_spaceship(const _LHS&, const _RHS&)>> {
50 _LIBCPP_HIDE_FROM_ABI static int operator()(const _LHS& __lhs, const _RHS& __rhs) {
51 auto __res = __lhs <=> __rhs;
52 if (__res < 0)
53 return -1;
54 if (__res > 0)
55 return 1;
56 return 0;
57 }
58};
59#endif
60
61template <class _LHS, class _RHS, bool = true>
62struct __has_default_three_way_comparator : false_type {};
63
64template <class _LHS, class _RHS>
65struct __has_default_three_way_comparator<_LHS, _RHS, sizeof(__default_three_way_comparator<_LHS, _RHS>) >= 0>
66 : true_type {};
67
68_LIBCPP_END_NAMESPACE_STD
69
70#endif // _LIBCPP___UTILITY_DEFAULT_THREE_WAY_COMPARATOR_H