aboutsummaryrefslogtreecommitdiff
path: root/absl/algorithm
diff options
context:
space:
mode:
Diffstat (limited to 'absl/algorithm')
-rw-r--r--absl/algorithm/BUILD.bazel2
-rw-r--r--absl/algorithm/CMakeLists.txt2
-rw-r--r--absl/algorithm/container.h75
-rw-r--r--absl/algorithm/container_test.cc63
4 files changed, 124 insertions, 18 deletions
diff --git a/absl/algorithm/BUILD.bazel b/absl/algorithm/BUILD.bazel
index ddf9e11f..f20e7290 100644
--- a/absl/algorithm/BUILD.bazel
+++ b/absl/algorithm/BUILD.bazel
@@ -65,6 +65,7 @@ cc_library(
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":algorithm",
+ "//absl/base:config",
"//absl/base:core_headers",
"//absl/base:nullability",
"//absl/meta:type_traits",
@@ -79,6 +80,7 @@ cc_test(
deps = [
":container",
"//absl/base",
+ "//absl/base:config",
"//absl/base:core_headers",
"//absl/memory",
"//absl/types:span",
diff --git a/absl/algorithm/CMakeLists.txt b/absl/algorithm/CMakeLists.txt
index 5577164d..252b6b20 100644
--- a/absl/algorithm/CMakeLists.txt
+++ b/absl/algorithm/CMakeLists.txt
@@ -48,6 +48,7 @@ absl_cc_library(
${ABSL_DEFAULT_COPTS}
DEPS
absl::algorithm
+ absl::config
absl::core_headers
absl::meta
absl::nullability
@@ -64,6 +65,7 @@ absl_cc_test(
DEPS
absl::algorithm_container
absl::base
+ absl::config
absl::core_headers
absl::memory
absl::span
diff --git a/absl/algorithm/container.h b/absl/algorithm/container.h
index c7bafae1..6bbe3b5a 100644
--- a/absl/algorithm/container.h
+++ b/absl/algorithm/container.h
@@ -44,6 +44,7 @@
#include <cassert>
#include <iterator>
#include <numeric>
+#include <random>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
@@ -51,6 +52,7 @@
#include <vector>
#include "absl/algorithm/algorithm.h"
+#include "absl/base/config.h"
#include "absl/base/macros.h"
#include "absl/base/nullability.h"
#include "absl/meta/type_traits.h"
@@ -92,17 +94,17 @@ using ContainerPointerType =
// using std::end;
// std::foo(begin(c), end(c));
// becomes
-// std::foo(container_algorithm_internal::begin(c),
-// container_algorithm_internal::end(c));
+// std::foo(container_algorithm_internal::c_begin(c),
+// container_algorithm_internal::c_end(c));
// These are meant for internal use only.
template <typename C>
-ContainerIter<C> c_begin(C& c) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 ContainerIter<C> c_begin(C& c) {
return begin(c);
}
template <typename C>
-ContainerIter<C> c_end(C& c) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 ContainerIter<C> c_end(C& c) {
return end(c);
}
@@ -145,8 +147,9 @@ bool c_linear_search(const C& c, EqualityComparable&& value) {
// Container-based version of the <iterator> `std::distance()` function to
// return the number of elements within a container.
template <typename C>
-container_algorithm_internal::ContainerDifferenceType<const C> c_distance(
- const C& c) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
+ container_algorithm_internal::ContainerDifferenceType<const C>
+ c_distance(const C& c) {
return std::distance(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c));
}
@@ -210,6 +213,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
@@ -426,6 +439,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
@@ -1500,8 +1533,9 @@ c_is_heap_until(RandomAccessContainer& sequence, LessThan&& comp) {
// to return an iterator pointing to the element with the smallest value, using
// `operator<` to make the comparisons.
template <typename Sequence>
-container_algorithm_internal::ContainerIter<Sequence> c_min_element(
- Sequence& sequence) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
+ container_algorithm_internal::ContainerIter<Sequence>
+ c_min_element(Sequence& sequence) {
return std::min_element(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence));
}
@@ -1509,8 +1543,9 @@ container_algorithm_internal::ContainerIter<Sequence> c_min_element(
// Overload of c_min_element() for performing a `comp` comparison other than
// `operator<`.
template <typename Sequence, typename LessThan>
-container_algorithm_internal::ContainerIter<Sequence> c_min_element(
- Sequence& sequence, LessThan&& comp) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
+ container_algorithm_internal::ContainerIter<Sequence>
+ c_min_element(Sequence& sequence, LessThan&& comp) {
return std::min_element(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence),
std::forward<LessThan>(comp));
@@ -1522,8 +1557,9 @@ container_algorithm_internal::ContainerIter<Sequence> c_min_element(
// to return an iterator pointing to the element with the largest value, using
// `operator<` to make the comparisons.
template <typename Sequence>
-container_algorithm_internal::ContainerIter<Sequence> c_max_element(
- Sequence& sequence) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
+ container_algorithm_internal::ContainerIter<Sequence>
+ c_max_element(Sequence& sequence) {
return std::max_element(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence));
}
@@ -1531,8 +1567,9 @@ container_algorithm_internal::ContainerIter<Sequence> c_max_element(
// Overload of c_max_element() for performing a `comp` comparison other than
// `operator<`.
template <typename Sequence, typename LessThan>
-container_algorithm_internal::ContainerIter<Sequence> c_max_element(
- Sequence& sequence, LessThan&& comp) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
+ container_algorithm_internal::ContainerIter<Sequence>
+ c_max_element(Sequence& sequence, LessThan&& comp) {
return std::max_element(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence),
std::forward<LessThan>(comp));
@@ -1545,8 +1582,9 @@ container_algorithm_internal::ContainerIter<Sequence> c_max_element(
// smallest and largest values, respectively, using `operator<` to make the
// comparisons.
template <typename C>
-container_algorithm_internal::ContainerIterPairType<C, C> c_minmax_element(
- C& c) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
+ container_algorithm_internal::ContainerIterPairType<C, C>
+ c_minmax_element(C& c) {
return std::minmax_element(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c));
}
@@ -1554,8 +1592,9 @@ container_algorithm_internal::ContainerIterPairType<C, C> c_minmax_element(
// Overload of c_minmax_element() for performing `comp` comparisons other than
// `operator<`.
template <typename C, typename LessThan>
-container_algorithm_internal::ContainerIterPairType<C, C> c_minmax_element(
- C& c, LessThan&& comp) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
+ container_algorithm_internal::ContainerIterPairType<C, C>
+ c_minmax_element(C& c, LessThan&& comp) {
return std::minmax_element(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c),
std::forward<LessThan>(comp));
diff --git a/absl/algorithm/container_test.cc b/absl/algorithm/container_test.cc
index c01f5fc0..50122249 100644
--- a/absl/algorithm/container_test.cc
+++ b/absl/algorithm/container_test.cc
@@ -15,6 +15,7 @@
#include "absl/algorithm/container.h"
#include <algorithm>
+#include <array>
#include <functional>
#include <initializer_list>
#include <iterator>
@@ -31,6 +32,7 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/base/casts.h"
+#include "absl/base/config.h"
#include "absl/base/macros.h"
#include "absl/memory/memory.h"
#include "absl/types/span.h"
@@ -113,6 +115,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 +312,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) {
@@ -1144,4 +1162,49 @@ TEST(MutatingTest, PermutationOperations) {
EXPECT_EQ(initial, permuted);
}
+#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
+ ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
+TEST(ConstexprTest, Distance) {
+ // Works at compile time with constexpr containers.
+ static_assert(absl::c_distance(std::array<int, 3>()) == 3);
+}
+
+TEST(ConstexprTest, MinElement) {
+ constexpr std::array<int, 3> kArray = {1, 2, 3};
+ static_assert(*absl::c_min_element(kArray) == 1);
+}
+
+TEST(ConstexprTest, MinElementWithPredicate) {
+ constexpr std::array<int, 3> kArray = {1, 2, 3};
+ static_assert(*absl::c_min_element(kArray, std::greater<int>()) == 3);
+}
+
+TEST(ConstexprTest, MaxElement) {
+ constexpr std::array<int, 3> kArray = {1, 2, 3};
+ static_assert(*absl::c_max_element(kArray) == 3);
+}
+
+TEST(ConstexprTest, MaxElementWithPredicate) {
+ constexpr std::array<int, 3> kArray = {1, 2, 3};
+ static_assert(*absl::c_max_element(kArray, std::greater<int>()) == 1);
+}
+
+TEST(ConstexprTest, MinMaxElement) {
+ static constexpr std::array<int, 3> kArray = {1, 2, 3};
+ constexpr auto kMinMaxPair = absl::c_minmax_element(kArray);
+ static_assert(*kMinMaxPair.first == 1);
+ static_assert(*kMinMaxPair.second == 3);
+}
+
+TEST(ConstexprTest, MinMaxElementWithPredicate) {
+ static constexpr std::array<int, 3> kArray = {1, 2, 3};
+ constexpr auto kMinMaxPair =
+ absl::c_minmax_element(kArray, std::greater<int>());
+ static_assert(*kMinMaxPair.first == 3);
+ static_assert(*kMinMaxPair.second == 1);
+}
+
+#endif // defined(ABSL_INTERNAL_CPLUSPLUS_LANG) &&
+ // ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
+
} // namespace