From c025a934b199d069510bb68ee552ae58a4394916 Mon Sep 17 00:00:00 2001 From: Derek Mauro Date: Tue, 21 May 2024 09:57:36 -0700 Subject: Fix missing #include for std::uniform_int_distribution Fixes #1676 PiperOrigin-RevId: 635840902 Change-Id: Ifc4099175f1c5f040f55a9f5a47fe0c996af79d1 --- absl/algorithm/container.h | 1 + 1 file changed, 1 insertion(+) (limited to 'absl/algorithm/container.h') diff --git a/absl/algorithm/container.h b/absl/algorithm/container.h index c7bafae1..a2d126b7 100644 --- a/absl/algorithm/container.h +++ b/absl/algorithm/container.h @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From 63d4b2fe1e0d4bd6a7b916f398643db40c35624b Mon Sep 17 00:00:00 2001 From: Abseil Team 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(+) (limited to 'absl/algorithm/container.h') 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_find(C& c, T&& value) { std::forward(value)); } +// c_contains() +// +// Container-based version of the `std::ranges::contains()` C++23 +// function to search a container for a value. +template +bool c_contains(const Sequence& sequence, T&& value) { + return absl::c_find(sequence, std::forward(value)) != + container_algorithm_internal::c_end(sequence); +} + // c_find_if() // // Container-based version of the `std::find_if()` function to find @@ -427,6 +437,26 @@ container_algorithm_internal::ContainerIter c_search( std::forward(pred)); } +// c_contains_subrange() +// +// Container-based version of the `std::ranges::contains_subrange()` +// C++23 function to search a container for a subsequence. +template +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 +bool c_contains_subrange(Sequence1& sequence, Sequence2& subsequence, + BinaryPredicate&& pred) { + return absl::c_search(sequence, subsequence, + std::forward(pred)) != + container_algorithm_internal::c_end(sequence); +} + // c_search_n() // // Container-based version of the `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&>(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 From 37ebde53cfcf400ef01b59c80ae3f72039cd90f2 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Mon, 1 Jul 2024 11:33:54 -0700 Subject: Make c_begin, c_end, and c_distance conditionally constexpr. This allows them to be used in constexpr expressions, such as the following: ``` constexpr int distance = absl::c_distance(std::array()); ``` Requires at least C++17 to be constexpr. PiperOrigin-RevId: 648435141 Change-Id: I8136e351a6dc4c25f06ef895fb449f4f11048480 --- absl/algorithm/BUILD.bazel | 2 ++ absl/algorithm/CMakeLists.txt | 2 ++ absl/algorithm/container.h | 14 ++++++++------ absl/algorithm/container_test.cc | 11 +++++++++++ absl/base/config.h | 21 +++++++++++++++++++++ 5 files changed, 44 insertions(+), 6 deletions(-) (limited to 'absl/algorithm/container.h') 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 5a025e46..352ac46c 100644 --- a/absl/algorithm/container.h +++ b/absl/algorithm/container.h @@ -52,6 +52,7 @@ #include #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" @@ -93,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 -ContainerIter c_begin(C& c) { +ABSL_CONSTEXPR_SINCE_CXX17 ContainerIter c_begin(C& c) { return begin(c); } template -ContainerIter c_end(C& c) { +ABSL_CONSTEXPR_SINCE_CXX17 ContainerIter c_end(C& c) { return end(c); } @@ -146,8 +147,9 @@ bool c_linear_search(const C& c, EqualityComparable&& value) { // Container-based version of the `std::distance()` function to // return the number of elements within a container. template -container_algorithm_internal::ContainerDifferenceType c_distance( - const C& c) { +ABSL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerDifferenceType + c_distance(const C& c) { return std::distance(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c)); } diff --git a/absl/algorithm/container_test.cc b/absl/algorithm/container_test.cc index 7e54e2b2..e5e2bf3d 100644 --- a/absl/algorithm/container_test.cc +++ b/absl/algorithm/container_test.cc @@ -15,6 +15,7 @@ #include "absl/algorithm/container.h" #include +#include #include #include #include @@ -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" @@ -1160,4 +1162,13 @@ 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()) == 3); +} +#endif // defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && + // ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L + } // namespace diff --git a/absl/base/config.h b/absl/base/config.h index a8f2eab5..13263f9d 100644 --- a/absl/base/config.h +++ b/absl/base/config.h @@ -941,6 +941,27 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' || #define ABSL_HAVE_CONSTANT_EVALUATED 1 #endif +// ABSL_CONSTEXPR_SINCE_CXXYY is used to conditionally define constexpr for +// different C++ versions. +#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \ + ABSL_INTERNAL_CPLUSPLUS_LANG >= 201402L +#define ABSL_CONSTEXPR_SINCE_CXX14 constexpr +#else +#define ABSL_CONSTEXPR_SINCE_CXX14 +#endif +#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \ + ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L +#define ABSL_CONSTEXPR_SINCE_CXX17 constexpr +#else +#define ABSL_CONSTEXPR_SINCE_CXX17 +#endif +#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \ + ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L +#define ABSL_CONSTEXPR_SINCE_CXX20 constexpr +#else +#define ABSL_CONSTEXPR_SINCE_CXX20 +#endif + // ABSL_INTERNAL_EMSCRIPTEN_VERSION combines Emscripten's three version macros // into an integer that can be compared against. #ifdef ABSL_INTERNAL_EMSCRIPTEN_VERSION -- cgit v1.2.3 From 074a32af66648c74dd0104e251e44ace5b59f7fa Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Wed, 3 Jul 2024 22:07:51 -0700 Subject: Mark c_min_element, c_max_element, and c_minmax_element as constexpr in C++17. This allows them to be used in constant expressions, such as static_asserts. PiperOrigin-RevId: 649292841 Change-Id: I76e31a94b933fa357276fee534b81c00c28c8b23 --- absl/algorithm/container.h | 36 +++++++++++++++++++++--------------- absl/algorithm/container_test.cc | 36 ++++++++++++++++++++++++++++++++++++ absl/base/config.h | 24 ++++++++++++------------ 3 files changed, 69 insertions(+), 27 deletions(-) (limited to 'absl/algorithm/container.h') diff --git a/absl/algorithm/container.h b/absl/algorithm/container.h index 352ac46c..6bbe3b5a 100644 --- a/absl/algorithm/container.h +++ b/absl/algorithm/container.h @@ -99,12 +99,12 @@ using ContainerPointerType = // These are meant for internal use only. template -ABSL_CONSTEXPR_SINCE_CXX17 ContainerIter c_begin(C& c) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 ContainerIter c_begin(C& c) { return begin(c); } template -ABSL_CONSTEXPR_SINCE_CXX17 ContainerIter c_end(C& c) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 ContainerIter c_end(C& c) { return end(c); } @@ -147,7 +147,7 @@ bool c_linear_search(const C& c, EqualityComparable&& value) { // Container-based version of the `std::distance()` function to // return the number of elements within a container. template -ABSL_CONSTEXPR_SINCE_CXX17 +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 container_algorithm_internal::ContainerDifferenceType c_distance(const C& c) { return std::distance(container_algorithm_internal::c_begin(c), @@ -1533,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 -container_algorithm_internal::ContainerIter c_min_element( - Sequence& sequence) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIter + c_min_element(Sequence& sequence) { return std::min_element(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence)); } @@ -1542,8 +1543,9 @@ container_algorithm_internal::ContainerIter c_min_element( // Overload of c_min_element() for performing a `comp` comparison other than // `operator<`. template -container_algorithm_internal::ContainerIter c_min_element( - Sequence& sequence, LessThan&& comp) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIter + 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(comp)); @@ -1555,8 +1557,9 @@ container_algorithm_internal::ContainerIter c_min_element( // to return an iterator pointing to the element with the largest value, using // `operator<` to make the comparisons. template -container_algorithm_internal::ContainerIter c_max_element( - Sequence& sequence) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIter + c_max_element(Sequence& sequence) { return std::max_element(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence)); } @@ -1564,8 +1567,9 @@ container_algorithm_internal::ContainerIter c_max_element( // Overload of c_max_element() for performing a `comp` comparison other than // `operator<`. template -container_algorithm_internal::ContainerIter c_max_element( - Sequence& sequence, LessThan&& comp) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIter + 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(comp)); @@ -1578,8 +1582,9 @@ container_algorithm_internal::ContainerIter c_max_element( // smallest and largest values, respectively, using `operator<` to make the // comparisons. template -container_algorithm_internal::ContainerIterPairType c_minmax_element( - C& c) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIterPairType + c_minmax_element(C& c) { return std::minmax_element(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c)); } @@ -1587,8 +1592,9 @@ container_algorithm_internal::ContainerIterPairType c_minmax_element( // Overload of c_minmax_element() for performing `comp` comparisons other than // `operator<`. template -container_algorithm_internal::ContainerIterPairType c_minmax_element( - C& c, LessThan&& comp) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIterPairType + 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(comp)); diff --git a/absl/algorithm/container_test.cc b/absl/algorithm/container_test.cc index e5e2bf3d..50122249 100644 --- a/absl/algorithm/container_test.cc +++ b/absl/algorithm/container_test.cc @@ -1168,6 +1168,42 @@ TEST(ConstexprTest, Distance) { // Works at compile time with constexpr containers. static_assert(absl::c_distance(std::array()) == 3); } + +TEST(ConstexprTest, MinElement) { + constexpr std::array kArray = {1, 2, 3}; + static_assert(*absl::c_min_element(kArray) == 1); +} + +TEST(ConstexprTest, MinElementWithPredicate) { + constexpr std::array kArray = {1, 2, 3}; + static_assert(*absl::c_min_element(kArray, std::greater()) == 3); +} + +TEST(ConstexprTest, MaxElement) { + constexpr std::array kArray = {1, 2, 3}; + static_assert(*absl::c_max_element(kArray) == 3); +} + +TEST(ConstexprTest, MaxElementWithPredicate) { + constexpr std::array kArray = {1, 2, 3}; + static_assert(*absl::c_max_element(kArray, std::greater()) == 1); +} + +TEST(ConstexprTest, MinMaxElement) { + static constexpr std::array 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 kArray = {1, 2, 3}; + constexpr auto kMinMaxPair = + absl::c_minmax_element(kArray, std::greater()); + static_assert(*kMinMaxPair.first == 3); + static_assert(*kMinMaxPair.second == 1); +} + #endif // defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && // ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L diff --git a/absl/base/config.h b/absl/base/config.h index 13263f9d..97c9a22a 100644 --- a/absl/base/config.h +++ b/absl/base/config.h @@ -941,25 +941,25 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' || #define ABSL_HAVE_CONSTANT_EVALUATED 1 #endif -// ABSL_CONSTEXPR_SINCE_CXXYY is used to conditionally define constexpr for -// different C++ versions. -#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \ - ABSL_INTERNAL_CPLUSPLUS_LANG >= 201402L -#define ABSL_CONSTEXPR_SINCE_CXX14 constexpr -#else -#define ABSL_CONSTEXPR_SINCE_CXX14 -#endif +// ABSL_INTERNAL_CONSTEXPR_SINCE_CXXYY is used to conditionally define constexpr +// for different C++ versions. +// +// These macros are an implementation detail and will be unconditionally removed +// once the minimum supported C++ version catches up to a given version. +// +// For this reason, this symbol is considered INTERNAL and code outside of +// Abseil must not use it. #if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \ ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L -#define ABSL_CONSTEXPR_SINCE_CXX17 constexpr +#define ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 constexpr #else -#define ABSL_CONSTEXPR_SINCE_CXX17 +#define ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 #endif #if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \ ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L -#define ABSL_CONSTEXPR_SINCE_CXX20 constexpr +#define ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 constexpr #else -#define ABSL_CONSTEXPR_SINCE_CXX20 +#define ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 #endif // ABSL_INTERNAL_EMSCRIPTEN_VERSION combines Emscripten's three version macros -- cgit v1.2.3