[libcxx-commits] [libcxx] [libc++][ranges] Avoid using `distance` in `ranges::contains_subrange` (PR #87155)
A. Jiang via libcxx-commits
libcxx-commits at lists.llvm.org
Sat Mar 30 07:34:11 PDT 2024
https://github.com/frederick-vs-ja updated https://github.com/llvm/llvm-project/pull/87155
>From 629a4fa6bf701f646360bf5e28ca5988834a27a5 Mon Sep 17 00:00:00 2001
From: "A. Jiang" <de34 at live.cn>
Date: Sat, 30 Mar 2024 22:33:51 +0800
Subject: [PATCH] [libc++][ranges] Avoid using `std::distance` in
`ranges::contains_subrange`
Either `std::distance` or `ranges::distance` are inefficient for
non-sized ranges. Also, calculation the range in `int` type is seriously
problematic.
This patch avoids using `distance` and calculation of the length of
non-sized ranges.
---
.../include/__algorithm/ranges_contains_subrange.h | 14 ++++++--------
.../alg.contains/ranges.contains_subrange.pass.cpp | 4 ++++
2 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/libcxx/include/__algorithm/ranges_contains_subrange.h b/libcxx/include/__algorithm/ranges_contains_subrange.h
index 4cd03cbb537060..bc5a86ce3d696a 100644
--- a/libcxx/include/__algorithm/ranges_contains_subrange.h
+++ b/libcxx/include/__algorithm/ranges_contains_subrange.h
@@ -15,11 +15,11 @@
#include <__functional/ranges_operations.h>
#include <__functional/reference_wrapper.h>
#include <__iterator/concepts.h>
-#include <__iterator/distance.h>
#include <__iterator/indirectly_comparable.h>
#include <__iterator/projected.h>
#include <__ranges/access.h>
#include <__ranges/concepts.h>
+#include <__ranges/size.h>
#include <__ranges/subrange.h>
#include <__utility/move.h>
@@ -53,8 +53,7 @@ struct __fn {
_Pred __pred = {},
_Proj1 __proj1 = {},
_Proj2 __proj2 = {}) {
- auto __n2 = ranges::distance(__first2, __last2);
- if (__n2 == 0)
+ if (__first2 == __last2)
return true;
auto __ret = ranges::search(
@@ -70,14 +69,13 @@ struct __fn {
requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>, _Pred, _Proj1, _Proj2>
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr bool static
operator()(_Range1&& __range1, _Range2&& __range2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) {
- auto __n2 = 0;
if constexpr (sized_range<_Range2>) {
- __n2 = ranges::size(__range2);
+ if (ranges::size(__range2) == 0)
+ return true;
} else {
- __n2 = std::distance(cbegin(__range2), cend(__range2));
+ if (ranges::begin(__range2) == ranges::end(__range2))
+ return true;
}
- if (__n2 == 0)
- return true;
auto __ret = ranges::search(__range1, __range2, __pred, std::ref(__proj1), std::ref(__proj2));
return __ret.empty() == false;
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.contains/ranges.contains_subrange.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.contains/ranges.contains_subrange.pass.cpp
index d48ee9e4e7e02e..761691c2afdcb9 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.contains/ranges.contains_subrange.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.contains/ranges.contains_subrange.pass.cpp
@@ -309,6 +309,10 @@ constexpr bool test() {
});
});
+ assert(std::ranges::contains_subrange(
+ std::views::iota(0, 5), std::views::iota(0, 5) | std::views::filter([](int) { return true; })));
+ assert(!std::ranges::contains_subrange(std::views::iota(0ULL, 42ULL), std::views::iota(0ULL, 1ULL << 32)));
+
return true;
}
More information about the libcxx-commits
mailing list