[libcxx-commits] [libcxx] [libc++] Optimize __tree::__find_equal (PR #155245)
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Aug 25 09:46:20 PDT 2025
================
@@ -0,0 +1,64 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___UTILITY_THREE_WAY_COMPARATOR_H
+#define _LIBCPP___UTILITY_THREE_WAY_COMPARATOR_H
+
+#include <__config>
+#include <__type_traits/desugars_to.h>
+#include <__type_traits/enable_if.h>
+#include <__type_traits/is_arithmetic.h>
+#include <__type_traits/remove_const_ref.h>
+#include <__type_traits/void_t.h>
+#include <__functional/operations.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+template <class _LHS, class _RHS, class = void>
+struct __three_way_comparison_traits {};
+
+template <class _Tp>
+struct __three_way_comparison_traits<_Tp, _Tp, __enable_if_t<is_arithmetic<_Tp>::value> > {
+ using __three_way_comparable = void;
+
+ _LIBCPP_HIDE_FROM_ABI static int operator()(_Tp __lhs, _Tp __rhs) {
+ if (__lhs < __rhs)
+ return -1;
+ if (__lhs > __rhs)
+ return 1;
+ return 0;
+ }
+};
+
+template <class _Comparator, class _LHS, class _RHS, class = void>
+struct __three_way_comparator {};
----------------
ldionne wrote:
I think there is a naming issue here. `__three_way_comparator` is effectively the more general "traits class", and what's currently named `__three_way_comparison_traits` is in fact a special case for implementing three-way comparison from a less-than operator.
How about:
```c++
template <class _Comparator, class _LHS, class _RHS, class = void>
struct __three_way_comparison_traits {};
template <class _Comparator, class _LHS, class _RHS, class = void>
struct __three_way_comparison_traits<_Comparator, _LHS, _RHS,
__enable_if_t<__desugars_to_v<__less_tag, _Comparator, _LHS, _RHS> && __has_three_way_comparison_from_less_than<_Comparator, _LHS, _RHS> > >
: __three_way_comparison_from_less_than<_Comparator, _LHS, _RHS>
{ };
// In the future
template <class _Comparator, class _LHS, class _RHS, class = void>
struct __three_way_comparison_traits<_Comparator, _LHS, _RHS,
__enable_if_t<__desugars_to_v<__greater_tag, _Comparator, _LHS, _RHS> && __has_three_way_comparison_from_less_than<_Comparator, _LHS, _RHS> > > {
_LIBCPP_HIDE_FROM_ABI static int operator()(_Tp __lhs, _Tp __rhs) {
return - __three_way_comparison_traits<__less_tag, _LHS, _RHS>()(__lhs, __rhs);
}
};
template <class _Tp>
struct __three_way_comparison_from_less_than<_Tp, _Tp, __enable_if_t<is_arithmetic<_Tp>::value> > {
_LIBCPP_HIDE_FROM_ABI static int operator()(_Tp __lhs, _Tp __rhs) {
if (__lhs < __rhs)
return -1;
if (__lhs > __rhs)
return 1;
return 0;
}
};
// same thing for string
```
Then, from `__tree`, you do:
```c++
static const bool __use_three_way = __has_three_way_comparison_traits<_Compare, _Key, value_type>;
int __comp_res;
if constexpr (__use_three_way) {
__comp_res = __three_way_comparison_traits<_Compare, _Key, value_type>()(__v, __nd->__get_value());
}
```
Then, gotta decide on the name for `__three_way_comparison_from_less_than`. I think this is basically a complicated rename.
I would also get rid of the `__three_way_comparable` typedef and just do `sizeof`.
https://github.com/llvm/llvm-project/pull/155245
More information about the libcxx-commits
mailing list