From 6ff792db80be1f3df943299a3136f2d880eec786 Mon Sep 17 00:00:00 2001 From: Andrew Sukach Date: Sat, 4 May 2024 17:24:25 -0400 Subject: [PATCH] [libc++] ranges::find_last --- libcxx/include/CMakeLists.txt | 1 + libcxx/include/__algorithm/ranges_find_last.h | 82 +++++++++++++++++++ libcxx/include/algorithm | 1 + libcxx/include/module.modulemap | 1 + .../gn/secondary/libcxx/include/BUILD.gn | 1 + 5 files changed, 86 insertions(+) create mode 100644 libcxx/include/__algorithm/ranges_find_last.h diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index fd7eb125e007b..56cce0a42ca77 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -113,6 +113,7 @@ set(files __algorithm/ranges_find_first_of.h __algorithm/ranges_find_if.h __algorithm/ranges_find_if_not.h + __algorithm/ranges_find_last.h __algorithm/ranges_for_each.h __algorithm/ranges_for_each_n.h __algorithm/ranges_generate.h diff --git a/libcxx/include/__algorithm/ranges_find_last.h b/libcxx/include/__algorithm/ranges_find_last.h new file mode 100644 index 0000000000000..38122c4a5d066 --- /dev/null +++ b/libcxx/include/__algorithm/ranges_find_last.h @@ -0,0 +1,82 @@ +//===----------------------------------------------------------------------===// +// +// 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___ALGORITHM_RANGES_FIND_LAST_H +#define _LIBCPP___ALGORITHM_RANGES_FIND_LAST_H + +#include <__algorithm/ranges_find.h> +#include <__concepts/same_as.h> +#include <__config> +#include <__functional/identity.h> +#include <__functional/ranges_operations.h> +#include <__iterator/concepts.h> +#include <__iterator/projected.h> +#include <__iterator/reverse_iterator.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <__ranges/dangling.h> +#include <__ranges/subrange.h> +#include <__utility/move.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +#if _LIBCPP_STD_VER >= 23 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace ranges { + +namespace __find_last { +struct __fn { + template _Sent, typename _Tp, typename _Proj = identity> + requires indirect_binary_predicate, const _Tp*> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange<_It> + operator()(_It __first, _Sent __last, const _Tp& __value, _Proj __proj = {}) const { + if constexpr (same_as<_It, _Sent> && bidirectional_iterator<_It>) { + const auto __found{find(reverse_iterator{__last}, reverse_iterator{__first}, __value, std::move(__proj)).base()}; + if (__found == __first) + return {__last, __last}; + return {prev(__found), __last}; + } else { + auto __found{find(__first, __last, __value, __proj)}; + if (__found == __last) + return {__last, __last}; + + for (__first = __found;; __found = __first++) + if ((__first == find(__first, __last, __value, __proj)) == __last) + return {__found, __last}; + } + } + + template + requires indirect_binary_predicate, _Proj>, const _Tp*> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const { + return this->operator()(begin(__r), end(__r), __value, std::move(__proj)); + } +}; + +} // namespace __find_last + +inline namespace __cpo { +inline constexpr __find_last::__fn find_last{}; +} // namespace __cpo +} // namespace ranges + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___ALGORITHM_RANGES_FIND_LAST_H diff --git a/libcxx/include/algorithm b/libcxx/include/algorithm index 869fc19737b57..508579c75610a 100644 --- a/libcxx/include/algorithm +++ b/libcxx/include/algorithm @@ -2004,6 +2004,7 @@ template # include <__algorithm/fold.h> # include <__algorithm/ranges_contains_subrange.h> # include <__algorithm/ranges_ends_with.h> +# include <__algorithm/ranges_find_last.h> # include <__algorithm/ranges_starts_with.h> #endif // _LIBCPP_STD_VER >= 23 diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap index 2974d12500c4c..f354bca3ca45b 100644 --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -787,6 +787,7 @@ module std_private_algorithm_ranges_find_end [system module std_private_algorithm_ranges_find_first_of [system] { header "__algorithm/ranges_find_first_of.h" } module std_private_algorithm_ranges_find_if [system] { header "__algorithm/ranges_find_if.h" } module std_private_algorithm_ranges_find_if_not [system] { header "__algorithm/ranges_find_if_not.h" } +module std_private_algorithm_ranges_find_last [system] { header "__algorithm/ranges_find_last.h" } module std_private_algorithm_ranges_for_each [system] { header "__algorithm/ranges_for_each.h" export std_private_algorithm_in_fun_result diff --git a/llvm/utils/gn/secondary/libcxx/include/BUILD.gn b/llvm/utils/gn/secondary/libcxx/include/BUILD.gn index 9645bff18ae72..789d03e66d3c3 100644 --- a/llvm/utils/gn/secondary/libcxx/include/BUILD.gn +++ b/llvm/utils/gn/secondary/libcxx/include/BUILD.gn @@ -183,6 +183,7 @@ if (current_toolchain == default_toolchain) { "__algorithm/ranges_find_first_of.h", "__algorithm/ranges_find_if.h", "__algorithm/ranges_find_if_not.h", + "__algorithm/ranges_find_last.h", "__algorithm/ranges_for_each.h", "__algorithm/ranges_for_each_n.h", "__algorithm/ranges_generate.h",