summaryrefslogtreecommitdiff
path: root/libcxx/include/__utility
diff options
context:
space:
mode:
Diffstat (limited to 'libcxx/include/__utility')
-rw-r--r--libcxx/include/__utility/default_three_way_comparator.h50
-rw-r--r--libcxx/include/__utility/in_place.h2
-rw-r--r--libcxx/include/__utility/lazy_synth_three_way_comparator.h90
-rw-r--r--libcxx/include/__utility/try_key_extraction.h114
4 files changed, 255 insertions, 1 deletions
diff --git a/libcxx/include/__utility/default_three_way_comparator.h b/libcxx/include/__utility/default_three_way_comparator.h
new file mode 100644
index 000000000000..ce423c6ce98e
--- /dev/null
+++ b/libcxx/include/__utility/default_three_way_comparator.h
@@ -0,0 +1,50 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_DEFAULT_THREE_WAY_COMPARATOR_H
+#define _LIBCPP___UTILITY_DEFAULT_THREE_WAY_COMPARATOR_H
+
+#include <__config>
+#include <__type_traits/enable_if.h>
+#include <__type_traits/is_arithmetic.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+// This struct can be specialized to provide a three way comparator between _LHS and _RHS.
+// The return value should be
+// - less than zero if (lhs_val < rhs_val)
+// - greater than zero if (rhs_val < lhs_val)
+// - zero otherwise
+template <class _LHS, class _RHS, class = void>
+struct __default_three_way_comparator;
+
+template <class _Tp>
+struct __default_three_way_comparator<_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;
+ }
+};
+
+template <class _LHS, class _RHS, bool = true>
+inline const bool __has_default_three_way_comparator_v = false;
+
+template <class _LHS, class _RHS>
+inline const bool
+ __has_default_three_way_comparator_v< _LHS, _RHS, sizeof(__default_three_way_comparator<_LHS, _RHS>) >= 0> = true;
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___UTILITY_DEFAULT_THREE_WAY_COMPARATOR_H
diff --git a/libcxx/include/__utility/in_place.h b/libcxx/include/__utility/in_place.h
index ade4b6685a11..c5bfa947058f 100644
--- a/libcxx/include/__utility/in_place.h
+++ b/libcxx/include/__utility/in_place.h
@@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER >= 17
-struct _LIBCPP_EXPORTED_FROM_ABI in_place_t {
+struct in_place_t {
explicit in_place_t() = default;
};
inline constexpr in_place_t in_place{};
diff --git a/libcxx/include/__utility/lazy_synth_three_way_comparator.h b/libcxx/include/__utility/lazy_synth_three_way_comparator.h
new file mode 100644
index 000000000000..ca98845f0419
--- /dev/null
+++ b/libcxx/include/__utility/lazy_synth_three_way_comparator.h
@@ -0,0 +1,90 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_LAZY_SYNTH_THREE_WAY_COMPARATOR_H
+#define _LIBCPP___UTILITY_LAZY_SYNTH_THREE_WAY_COMPARATOR_H
+
+#include <__config>
+#include <__type_traits/desugars_to.h>
+#include <__type_traits/enable_if.h>
+#include <__utility/default_three_way_comparator.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+// This file implements a __lazy_synth_three_way_comparator, which tries to build an efficient three way comparison from
+// a binary comparator. That is done in multiple steps:
+// 1) Check whether the comparator desugars to a less-than operator
+// If that is the case, check whether there exists a specialization of `__default_three_way_comparator`, which
+// can be specialized to implement a three way comparator for the specific types.
+// 2) Fall back to doing a lazy less than/greater than comparison
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+template <class _Comparator, class _LHS, class _RHS>
+struct __lazy_compare_result {
+ const _Comparator& __comp_;
+ const _LHS& __lhs_;
+ const _RHS& __rhs_;
+
+ _LIBCPP_HIDE_FROM_ABI
+ __lazy_compare_result(_LIBCPP_CTOR_LIFETIMEBOUND const _Comparator& __comp,
+ _LIBCPP_CTOR_LIFETIMEBOUND const _LHS& __lhs,
+ _LIBCPP_CTOR_LIFETIMEBOUND const _RHS& __rhs)
+ : __comp_(__comp), __lhs_(__lhs), __rhs_(__rhs) {}
+
+ _LIBCPP_HIDE_FROM_ABI bool __less() const { return __comp_(__lhs_, __rhs_); }
+ _LIBCPP_HIDE_FROM_ABI bool __greater() const { return __comp_(__rhs_, __lhs_); }
+};
+
+// This class provides three way comparison between _LHS and _RHS as efficiently as possible. This can be specialized if
+// a comparator only compares part of the object, potentially allowing an efficient three way comparison between the
+// subobjects. The specialization should use the __lazy_synth_three_way_comparator for the subobjects to achieve this.
+template <class _Comparator, class _LHS, class _RHS, class = void>
+struct __lazy_synth_three_way_comparator {
+ const _Comparator& __comp_;
+
+ _LIBCPP_HIDE_FROM_ABI __lazy_synth_three_way_comparator(_LIBCPP_CTOR_LIFETIMEBOUND const _Comparator& __comp)
+ : __comp_(__comp) {}
+
+ _LIBCPP_HIDE_FROM_ABI __lazy_compare_result<_Comparator, _LHS, _RHS>
+ operator()(_LIBCPP_LIFETIMEBOUND const _LHS& __lhs, _LIBCPP_LIFETIMEBOUND const _RHS& __rhs) const {
+ return __lazy_compare_result<_Comparator, _LHS, _RHS>(__comp_, __lhs, __rhs);
+ }
+};
+
+struct __eager_compare_result {
+ int __res_;
+
+ _LIBCPP_HIDE_FROM_ABI explicit __eager_compare_result(int __res) : __res_(__res) {}
+
+ _LIBCPP_HIDE_FROM_ABI bool __less() const { return __res_ < 0; }
+ _LIBCPP_HIDE_FROM_ABI bool __greater() const { return __res_ > 0; }
+};
+
+template <class _Comparator, class _LHS, class _RHS>
+struct __lazy_synth_three_way_comparator<_Comparator,
+ _LHS,
+ _RHS,
+ __enable_if_t<__desugars_to_v<__less_tag, _Comparator, _LHS, _RHS> &&
+ __has_default_three_way_comparator_v<_LHS, _RHS> > > {
+ // This lifetimebound annotation is technically incorrect, but other specializations actually capture the lifetime of
+ // the comparator.
+ _LIBCPP_HIDE_FROM_ABI __lazy_synth_three_way_comparator(_LIBCPP_CTOR_LIFETIMEBOUND const _Comparator&) {}
+
+ // Same comment as above.
+ _LIBCPP_HIDE_FROM_ABI static __eager_compare_result
+ operator()(_LIBCPP_LIFETIMEBOUND const _LHS& __lhs, _LIBCPP_LIFETIMEBOUND const _RHS& __rhs) {
+ return __eager_compare_result(__default_three_way_comparator<_LHS, _RHS>()(__lhs, __rhs));
+ }
+};
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___UTILITY_LAZY_SYNTH_THREE_WAY_COMPARATOR_H
diff --git a/libcxx/include/__utility/try_key_extraction.h b/libcxx/include/__utility/try_key_extraction.h
new file mode 100644
index 000000000000..755c08214019
--- /dev/null
+++ b/libcxx/include/__utility/try_key_extraction.h
@@ -0,0 +1,114 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_TRY_EXTRACT_KEY_H
+#define _LIBCPP___UTILITY_TRY_EXTRACT_KEY_H
+
+#include <__config>
+#include <__fwd/pair.h>
+#include <__fwd/tuple.h>
+#include <__type_traits/enable_if.h>
+#include <__type_traits/is_same.h>
+#include <__type_traits/remove_const.h>
+#include <__type_traits/remove_const_ref.h>
+#include <__utility/declval.h>
+#include <__utility/forward.h>
+#include <__utility/piecewise_construct.h>
+#include <__utility/priority_tag.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+template <class _KeyT, class _Ret, class _WithKey, class _WithoutKey, class... _Args>
+_LIBCPP_HIDE_FROM_ABI _Ret
+__try_key_extraction_impl(__priority_tag<0>, _WithKey, _WithoutKey __without_key, _Args&&... __args) {
+ return __without_key(std::forward<_Args>(__args)...);
+}
+
+template <class _KeyT,
+ class _Ret,
+ class _WithKey,
+ class _WithoutKey,
+ class _Arg,
+ __enable_if_t<is_same<_KeyT, __remove_const_ref_t<_Arg> >::value, int> = 0>
+_LIBCPP_HIDE_FROM_ABI _Ret
+__try_key_extraction_impl(__priority_tag<1>, _WithKey __with_key, _WithoutKey, _Arg&& __arg) {
+ return __with_key(__arg, std::forward<_Arg>(__arg));
+}
+
+template <class _KeyT,
+ class _Ret,
+ class _WithKey,
+ class _WithoutKey,
+ class _Arg,
+ __enable_if_t<__is_pair_v<__remove_const_ref_t<_Arg> > &&
+ is_same<__remove_const_t<typename __remove_const_ref_t<_Arg>::first_type>, _KeyT>::value,
+ int> = 0>
+_LIBCPP_HIDE_FROM_ABI _Ret
+__try_key_extraction_impl(__priority_tag<1>, _WithKey __with_key, _WithoutKey, _Arg&& __arg) {
+ return __with_key(__arg.first, std::forward<_Arg>(__arg));
+}
+
+template <class _KeyT,
+ class _Ret,
+ class _WithKey,
+ class _WithoutKey,
+ class _Arg1,
+ class _Arg2,
+ __enable_if_t<is_same<_KeyT, __remove_const_ref_t<_Arg1> >::value, int> = 0>
+_LIBCPP_HIDE_FROM_ABI _Ret
+__try_key_extraction_impl(__priority_tag<1>, _WithKey __with_key, _WithoutKey, _Arg1&& __arg1, _Arg2&& __arg2) {
+ return __with_key(__arg1, std::forward<_Arg1>(__arg1), std::forward<_Arg2>(__arg2));
+}
+
+#ifndef _LIBCPP_CXX03_LANG
+template <class _KeyT,
+ class _Ret,
+ class _WithKey,
+ class _WithoutKey,
+ class _PiecewiseConstruct,
+ class _Tuple1,
+ class _Tuple2,
+ __enable_if_t<is_same<__remove_const_ref_t<_PiecewiseConstruct>, piecewise_construct_t>::value &&
+ __is_tuple_v<_Tuple1> && tuple_size<_Tuple1>::value == 1 &&
+ is_same<__remove_const_ref_t<typename tuple_element<0, _Tuple1>::type>, _KeyT>::value,
+ int> = 0>
+_LIBCPP_HIDE_FROM_ABI _Ret __try_key_extraction_impl(
+ __priority_tag<1>,
+ _WithKey __with_key,
+ _WithoutKey,
+ _PiecewiseConstruct&& __pc,
+ _Tuple1&& __tuple1,
+ _Tuple2&& __tuple2) {
+ return __with_key(
+ std::get<0>(__tuple1),
+ std::forward<_PiecewiseConstruct>(__pc),
+ std::forward<_Tuple1>(__tuple1),
+ std::forward<_Tuple2>(__tuple2));
+}
+#endif // _LIBCPP_CXX03_LANG
+
+// This function tries extracting the given _KeyT from _Args...
+// If it succeeds to extract the key, it calls the `__with_key` function with the extracted key and all of the
+// arguments. Otherwise it calls the `__without_key` function with all of the arguments.
+//
+// Both `__with_key` and `__without_key` must take all arguments by reference.
+template <class _KeyT, class _WithKey, class _WithoutKey, class... _Args>
+_LIBCPP_HIDE_FROM_ABI decltype(std::declval<_WithoutKey>()(std::declval<_Args>()...))
+__try_key_extraction(_WithKey __with_key, _WithoutKey __without_key, _Args&&... __args) {
+ using _Ret = decltype(__without_key(std::forward<_Args>(__args)...));
+ return std::__try_key_extraction_impl<_KeyT, _Ret>(
+ __priority_tag<1>(), __with_key, __without_key, std::forward<_Args>(__args)...);
+}
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___UTILITY_TRY_EXTRACT_KEY_H