From 63d4b2fe1e0d4bd6a7b916f398643db40c35624b Mon Sep 17 00:00:00 2001
From: Abseil Team <absl-team@google.com>
Date: Wed, 26 Jun 2024 14:45:44 -0700
Subject: Add `c_contains()` and `c_contains_subrange()` to
 `absl/algorithm/container.h`.

These functions are based on the C++23's `std::ranges::contains()` and `std::ranges::contains_subrange()` functions, see: https://en.cppreference.com/w/cpp/algorithm/ranges/contains

PiperOrigin-RevId: 647084955
Change-Id: If5a01784e3cf1cc4d88e7f2fef92a3701fafc886
---
 absl/algorithm/container.h       | 30 ++++++++++++++++++++++++++++++
 absl/algorithm/container_test.cc | 16 ++++++++++++++++
 2 files changed, 46 insertions(+)

diff --git a/absl/algorithm/container.h b/absl/algorithm/container.h
index a2d126b7..5a025e46 100644
--- a/absl/algorithm/container.h
+++ b/absl/algorithm/container.h
@@ -211,6 +211,16 @@ container_algorithm_internal::ContainerIter<C> c_find(C& c, T&& value) {
                    std::forward<T>(value));
 }
 
+// c_contains()
+//
+// Container-based version of the <algorithm> `std::ranges::contains()` C++23
+// function to search a container for a value.
+template <typename Sequence, typename T>
+bool c_contains(const Sequence& sequence, T&& value) {
+  return absl::c_find(sequence, std::forward<T>(value)) !=
+         container_algorithm_internal::c_end(sequence);
+}
+
 // c_find_if()
 //
 // Container-based version of the <algorithm> `std::find_if()` function to find
@@ -427,6 +437,26 @@ container_algorithm_internal::ContainerIter<Sequence1> c_search(
                      std::forward<BinaryPredicate>(pred));
 }
 
+// c_contains_subrange()
+//
+// Container-based version of the <algorithm> `std::ranges::contains_subrange()`
+// C++23 function to search a container for a subsequence.
+template <typename Sequence1, typename Sequence2>
+bool c_contains_subrange(Sequence1& sequence, Sequence2& subsequence) {
+  return absl::c_search(sequence, subsequence) !=
+         container_algorithm_internal::c_end(sequence);
+}
+
+// Overload of c_contains_subrange() for using a predicate evaluation other than
+// `==` as the function's test condition.
+template <typename Sequence1, typename Sequence2, typename BinaryPredicate>
+bool c_contains_subrange(Sequence1& sequence, Sequence2& subsequence,
+                         BinaryPredicate&& pred) {
+  return absl::c_search(sequence, subsequence,
+                        std::forward<BinaryPredicate>(pred)) !=
+         container_algorithm_internal::c_end(sequence);
+}
+
 // c_search_n()
 //
 // Container-based version of the <algorithm> `std::search_n()` function to
diff --git a/absl/algorithm/container_test.cc b/absl/algorithm/container_test.cc
index c01f5fc0..7e54e2b2 100644
--- a/absl/algorithm/container_test.cc
+++ b/absl/algorithm/container_test.cc
@@ -113,6 +113,11 @@ TEST_F(NonMutatingTest, FindReturnsCorrectType) {
   absl::c_find(absl::implicit_cast<const std::list<int>&>(sequence_), 3);
 }
 
+TEST_F(NonMutatingTest, Contains) {
+  EXPECT_TRUE(absl::c_contains(container_, 3));
+  EXPECT_FALSE(absl::c_contains(container_, 4));
+}
+
 TEST_F(NonMutatingTest, FindIf) { absl::c_find_if(container_, Predicate); }
 
 TEST_F(NonMutatingTest, FindIfNot) {
@@ -305,6 +310,17 @@ TEST_F(NonMutatingTest, SearchWithPredicate) {
   absl::c_search(vector_, sequence_, BinPredicate);
 }
 
+TEST_F(NonMutatingTest, ContainsSubrange) {
+  EXPECT_TRUE(absl::c_contains_subrange(sequence_, vector_));
+  EXPECT_TRUE(absl::c_contains_subrange(vector_, sequence_));
+  EXPECT_TRUE(absl::c_contains_subrange(array_, sequence_));
+}
+
+TEST_F(NonMutatingTest, ContainsSubrangeWithPredicate) {
+  EXPECT_TRUE(absl::c_contains_subrange(sequence_, vector_, Equals));
+  EXPECT_TRUE(absl::c_contains_subrange(vector_, sequence_, Equals));
+}
+
 TEST_F(NonMutatingTest, SearchN) { absl::c_search_n(sequence_, 3, 1); }
 
 TEST_F(NonMutatingTest, SearchNWithPredicate) {
-- 
cgit v1.2.3