diff --git a/absl/algorithm/algorithm.h b/absl/algorithm/algorithm.h index 59aeed7d..48f59504 100644 --- a/absl/algorithm/algorithm.h +++ b/absl/algorithm/algorithm.h @@ -53,8 +53,8 @@ using std::rotate; // n = (`last` - `first`) comparisons. A linear search over short containers // may be faster than a binary search, even when the container is sorted. template -bool linear_search(InputIterator first, InputIterator last, - const EqualityComparable& value) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool linear_search( + InputIterator first, InputIterator last, const EqualityComparable& value) { return std::find(first, last, value) != last; } diff --git a/absl/algorithm/algorithm_test.cc b/absl/algorithm/algorithm_test.cc index e6ee4695..1c1a3079 100644 --- a/absl/algorithm/algorithm_test.cc +++ b/absl/algorithm/algorithm_test.cc @@ -14,11 +14,9 @@ #include "absl/algorithm/algorithm.h" -#include -#include +#include #include -#include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/base/config.h" @@ -47,4 +45,16 @@ TEST_F(LinearSearchTest, linear_searchConst) { absl::linear_search(const_container->begin(), const_container->end(), 4)); } +#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \ + ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L + +TEST_F(LinearSearchTest, Constexpr) { + static constexpr std::array kArray = {1, 2, 3}; + static_assert(absl::linear_search(kArray.begin(), kArray.end(), 3)); + static_assert(!absl::linear_search(kArray.begin(), kArray.end(), 4)); +} + +#endif // defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && + // ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L + } // namespace diff --git a/absl/algorithm/container.h b/absl/algorithm/container.h index 6bbe3b5a..2c0426da 100644 --- a/absl/algorithm/container.h +++ b/absl/algorithm/container.h @@ -132,7 +132,8 @@ struct IsUnorderedContainer> // Container-based version of absl::linear_search() for performing a linear // search within a container. template -bool c_linear_search(const C& c, EqualityComparable&& value) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_linear_search( + const C& c, EqualityComparable&& value) { return linear_search(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(value)); @@ -163,7 +164,7 @@ ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 // Container-based version of the `std::all_of()` function to // test if all elements within a container satisfy a condition. template -bool c_all_of(const C& c, Pred&& pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_all_of(const C& c, Pred&& pred) { return std::all_of(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(pred)); @@ -174,7 +175,7 @@ bool c_all_of(const C& c, Pred&& pred) { // Container-based version of the `std::any_of()` function to // test if any element in a container fulfills a condition. template -bool c_any_of(const C& c, Pred&& pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_any_of(const C& c, Pred&& pred) { return std::any_of(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(pred)); @@ -185,7 +186,7 @@ bool c_any_of(const C& c, Pred&& pred) { // Container-based version of the `std::none_of()` function to // test if no elements in a container fulfill a condition. template -bool c_none_of(const C& c, Pred&& pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_none_of(const C& c, Pred&& pred) { return std::none_of(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(pred)); @@ -196,7 +197,8 @@ bool c_none_of(const C& c, Pred&& pred) { // Container-based version of the `std::for_each()` function to // apply a function to a container's elements. template -decay_t c_for_each(C&& c, Function&& f) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 decay_t c_for_each(C&& c, + Function&& f) { return std::for_each(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(f)); @@ -207,7 +209,9 @@ decay_t c_for_each(C&& c, Function&& f) { // Container-based version of the `std::find()` function to find // the first element containing the passed value within a container value. template -container_algorithm_internal::ContainerIter c_find(C& c, T&& value) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_find(C& c, T&& value) { return std::find(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(value)); @@ -218,7 +222,8 @@ container_algorithm_internal::ContainerIter c_find(C& c, T&& value) { // 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) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_contains(const Sequence& sequence, + T&& value) { return absl::c_find(sequence, std::forward(value)) != container_algorithm_internal::c_end(sequence); } @@ -228,7 +233,9 @@ bool c_contains(const Sequence& sequence, T&& value) { // Container-based version of the `std::find_if()` function to find // the first element in a container matching the given condition. template -container_algorithm_internal::ContainerIter c_find_if(C& c, Pred&& pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_find_if(C& c, Pred&& pred) { return std::find_if(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(pred)); @@ -239,8 +246,9 @@ container_algorithm_internal::ContainerIter c_find_if(C& c, Pred&& pred) { // Container-based version of the `std::find_if_not()` function to // find the first element in a container not matching the given condition. template -container_algorithm_internal::ContainerIter c_find_if_not(C& c, - Pred&& pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_find_if_not(C& c, Pred&& pred) { return std::find_if_not(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(pred)); @@ -251,8 +259,9 @@ container_algorithm_internal::ContainerIter c_find_if_not(C& c, // Container-based version of the `std::find_end()` function to // find the last subsequence within a container. template -container_algorithm_internal::ContainerIter c_find_end( - Sequence1& sequence, Sequence2& subsequence) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_find_end(Sequence1& sequence, Sequence2& subsequence) { return std::find_end(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), container_algorithm_internal::c_begin(subsequence), @@ -262,8 +271,10 @@ container_algorithm_internal::ContainerIter c_find_end( // Overload of c_find_end() for using a predicate evaluation other than `==` as // the function's test condition. template -container_algorithm_internal::ContainerIter c_find_end( - Sequence1& sequence, Sequence2& subsequence, BinaryPredicate&& pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_find_end(Sequence1& sequence, Sequence2& subsequence, + BinaryPredicate&& pred) { return std::find_end(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), container_algorithm_internal::c_begin(subsequence), @@ -277,8 +288,9 @@ container_algorithm_internal::ContainerIter c_find_end( // find the first element within the container that is also within the options // container. template -container_algorithm_internal::ContainerIter c_find_first_of(C1& container, - C2& options) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_find_first_of(C1& container, C2& options) { return std::find_first_of(container_algorithm_internal::c_begin(container), container_algorithm_internal::c_end(container), container_algorithm_internal::c_begin(options), @@ -288,8 +300,9 @@ container_algorithm_internal::ContainerIter c_find_first_of(C1& container, // Overload of c_find_first_of() for using a predicate evaluation other than // `==` as the function's test condition. template -container_algorithm_internal::ContainerIter c_find_first_of( - C1& container, C2& options, BinaryPredicate&& pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_find_first_of(C1& container, C2& options, BinaryPredicate&& pred) { return std::find_first_of(container_algorithm_internal::c_begin(container), container_algorithm_internal::c_end(container), container_algorithm_internal::c_begin(options), @@ -302,8 +315,9 @@ container_algorithm_internal::ContainerIter c_find_first_of( // Container-based version of the `std::adjacent_find()` function to // find equal adjacent elements within a container. template -container_algorithm_internal::ContainerIter c_adjacent_find( - Sequence& sequence) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_adjacent_find(Sequence& sequence) { return std::adjacent_find(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence)); } @@ -311,8 +325,9 @@ container_algorithm_internal::ContainerIter c_adjacent_find( // Overload of c_adjacent_find() for using a predicate evaluation other than // `==` as the function's test condition. template -container_algorithm_internal::ContainerIter c_adjacent_find( - Sequence& sequence, BinaryPredicate&& pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_adjacent_find(Sequence& sequence, BinaryPredicate&& pred) { return std::adjacent_find(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), std::forward(pred)); @@ -323,8 +338,9 @@ container_algorithm_internal::ContainerIter c_adjacent_find( // Container-based version of the `std::count()` function to count // values that match within a container. template -container_algorithm_internal::ContainerDifferenceType c_count( - const C& c, T&& value) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerDifferenceType + c_count(const C& c, T&& value) { return std::count(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(value)); @@ -335,8 +351,9 @@ container_algorithm_internal::ContainerDifferenceType c_count( // Container-based version of the `std::count_if()` function to // count values matching a condition within a container. template -container_algorithm_internal::ContainerDifferenceType c_count_if( - const C& c, Pred&& pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerDifferenceType + c_count_if(const C& c, Pred&& pred) { return std::count_if(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), std::forward(pred)); @@ -348,8 +365,9 @@ container_algorithm_internal::ContainerDifferenceType c_count_if( // return the first element where two ordered containers differ. Applies `==` to // the first N elements of `c1` and `c2`, where N = min(size(c1), size(c2)). template -container_algorithm_internal::ContainerIterPairType c_mismatch(C1& c1, - C2& c2) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIterPairType + c_mismatch(C1& c1, C2& c2) { return std::mismatch(container_algorithm_internal::c_begin(c1), container_algorithm_internal::c_end(c1), container_algorithm_internal::c_begin(c2), @@ -360,8 +378,9 @@ container_algorithm_internal::ContainerIterPairType c_mismatch(C1& c1, // the function's test condition. Applies `pred`to the first N elements of `c1` // and `c2`, where N = min(size(c1), size(c2)). template -container_algorithm_internal::ContainerIterPairType c_mismatch( - C1& c1, C2& c2, BinaryPredicate pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIterPairType + c_mismatch(C1& c1, C2& c2, BinaryPredicate pred) { return std::mismatch(container_algorithm_internal::c_begin(c1), container_algorithm_internal::c_end(c1), container_algorithm_internal::c_begin(c2), @@ -373,7 +392,7 @@ container_algorithm_internal::ContainerIterPairType c_mismatch( // Container-based version of the `std::equal()` function to // test whether two containers are equal. template -bool c_equal(const C1& c1, const C2& c2) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_equal(const C1& c1, const C2& c2) { return std::equal(container_algorithm_internal::c_begin(c1), container_algorithm_internal::c_end(c1), container_algorithm_internal::c_begin(c2), @@ -383,7 +402,8 @@ bool c_equal(const C1& c1, const C2& c2) { // Overload of c_equal() for using a predicate evaluation other than `==` as // the function's test condition. template -bool c_equal(const C1& c1, const C2& c2, BinaryPredicate&& pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_equal(const C1& c1, const C2& c2, + BinaryPredicate&& pred) { return std::equal(container_algorithm_internal::c_begin(c1), container_algorithm_internal::c_end(c1), container_algorithm_internal::c_begin(c2), @@ -396,7 +416,8 @@ bool c_equal(const C1& c1, const C2& c2, BinaryPredicate&& pred) { // Container-based version of the `std::is_permutation()` function // to test whether a container is a permutation of another. template -bool c_is_permutation(const C1& c1, const C2& c2) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_is_permutation(const C1& c1, + const C2& c2) { return std::is_permutation(container_algorithm_internal::c_begin(c1), container_algorithm_internal::c_end(c1), container_algorithm_internal::c_begin(c2), @@ -406,7 +427,8 @@ bool c_is_permutation(const C1& c1, const C2& c2) { // Overload of c_is_permutation() for using a predicate evaluation other than // `==` as the function's test condition. template -bool c_is_permutation(const C1& c1, const C2& c2, BinaryPredicate&& pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_is_permutation( + const C1& c1, const C2& c2, BinaryPredicate&& pred) { return std::is_permutation(container_algorithm_internal::c_begin(c1), container_algorithm_internal::c_end(c1), container_algorithm_internal::c_begin(c2), @@ -419,8 +441,9 @@ bool c_is_permutation(const C1& c1, const C2& c2, BinaryPredicate&& pred) { // Container-based version of the `std::search()` function to search // a container for a subsequence. template -container_algorithm_internal::ContainerIter c_search( - Sequence1& sequence, Sequence2& subsequence) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_search(Sequence1& sequence, Sequence2& subsequence) { return std::search(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), container_algorithm_internal::c_begin(subsequence), @@ -430,8 +453,10 @@ container_algorithm_internal::ContainerIter c_search( // Overload of c_search() for using a predicate evaluation other than // `==` as the function's test condition. template -container_algorithm_internal::ContainerIter c_search( - Sequence1& sequence, Sequence2& subsequence, BinaryPredicate&& pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_search(Sequence1& sequence, Sequence2& subsequence, + BinaryPredicate&& pred) { return std::search(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), container_algorithm_internal::c_begin(subsequence), @@ -444,7 +469,8 @@ container_algorithm_internal::ContainerIter c_search( // 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) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_contains_subrange( + Sequence1& sequence, Sequence2& subsequence) { return absl::c_search(sequence, subsequence) != container_algorithm_internal::c_end(sequence); } @@ -452,8 +478,8 @@ bool c_contains_subrange(Sequence1& sequence, Sequence2& subsequence) { // 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) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 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); @@ -464,8 +490,9 @@ bool c_contains_subrange(Sequence1& sequence, Sequence2& subsequence, // Container-based version of the `std::search_n()` function to // search a container for the first sequence of N elements. template -container_algorithm_internal::ContainerIter c_search_n( - Sequence& sequence, Size count, T&& value) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_search_n(Sequence& sequence, Size count, T&& value) { return std::search_n(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), count, std::forward(value)); @@ -475,8 +502,10 @@ container_algorithm_internal::ContainerIter c_search_n( // `==` as the function's test condition. template -container_algorithm_internal::ContainerIter c_search_n( - Sequence& sequence, Size count, T&& value, BinaryPredicate&& pred) { +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_search_n(Sequence& sequence, Size count, T&& value, + BinaryPredicate&& pred) { return std::search_n(container_algorithm_internal::c_begin(sequence), container_algorithm_internal::c_end(sequence), count, std::forward(value), diff --git a/absl/algorithm/container_test.cc b/absl/algorithm/container_test.cc index 50122249..fcb1cf51 100644 --- a/absl/algorithm/container_test.cc +++ b/absl/algorithm/container_test.cc @@ -1164,6 +1164,7 @@ TEST(MutatingTest, PermutationOperations) { #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); @@ -1203,8 +1204,216 @@ TEST(ConstexprTest, MinMaxElementWithPredicate) { static_assert(*kMinMaxPair.first == 3); static_assert(*kMinMaxPair.second == 1); } - #endif // defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && // ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L +#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \ + ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L + +TEST(ConstexprTest, LinearSearch) { + static constexpr std::array kArray = {1, 2, 3}; + static_assert(absl::c_linear_search(kArray, 3)); + static_assert(!absl::c_linear_search(kArray, 4)); +} + +TEST(ConstexprTest, AllOf) { + static constexpr std::array kArray = {1, 2, 3}; + static_assert(!absl::c_all_of(kArray, [](int x) { return x > 1; })); + static_assert(absl::c_all_of(kArray, [](int x) { return x > 0; })); +} + +TEST(ConstexprTest, AnyOf) { + static constexpr std::array kArray = {1, 2, 3}; + static_assert(absl::c_any_of(kArray, [](int x) { return x > 2; })); + static_assert(!absl::c_any_of(kArray, [](int x) { return x > 5; })); +} + +TEST(ConstexprTest, NoneOf) { + static constexpr std::array kArray = {1, 2, 3}; + static_assert(!absl::c_none_of(kArray, [](int x) { return x > 2; })); + static_assert(absl::c_none_of(kArray, [](int x) { return x > 5; })); +} + +TEST(ConstexprTest, ForEach) { + static constexpr std::array kArray = [] { + std::array array = {1, 2, 3}; + absl::c_for_each(array, [](int& x) { x += 1; }); + return array; + }(); + static_assert(kArray == std::array{2, 3, 4}); +} + +TEST(ConstexprTest, Find) { + static constexpr std::array kArray = {1, 2, 3}; + static_assert(absl::c_find(kArray, 1) == kArray.begin()); + static_assert(absl::c_find(kArray, 4) == kArray.end()); +} + +TEST(ConstexprTest, Contains) { + static constexpr std::array kArray = {1, 2, 3}; + static_assert(absl::c_contains(kArray, 1)); + static_assert(!absl::c_contains(kArray, 4)); +} + +TEST(ConstexprTest, FindIf) { + static constexpr std::array kArray = {1, 2, 3}; + static_assert(absl::c_find_if(kArray, [](int x) { return x > 2; }) == + kArray.begin() + 2); + static_assert(absl::c_find_if(kArray, [](int x) { return x > 5; }) == + kArray.end()); +} + +TEST(ConstexprTest, FindIfNot) { + static constexpr std::array kArray = {1, 2, 3}; + static_assert(absl::c_find_if_not(kArray, [](int x) { return x > 1; }) == + kArray.begin()); + static_assert(absl::c_find_if_not(kArray, [](int x) { return x > 0; }) == + kArray.end()); +} + +TEST(ConstexprTest, FindEnd) { + static constexpr std::array kHaystack = {1, 2, 3, 2, 3}; + static constexpr std::array kNeedle = {2, 3}; + static_assert(absl::c_find_end(kHaystack, kNeedle) == kHaystack.begin() + 3); +} + +TEST(ConstexprTest, FindFirstOf) { + static constexpr std::array kArray = {1, 2, 3}; + static_assert(absl::c_find_first_of(kArray, kArray) == kArray.begin()); +} + +TEST(ConstexprTest, AdjacentFind) { + static constexpr std::array kArray = {1, 2, 2, 3}; + static_assert(absl::c_adjacent_find(kArray) == kArray.begin() + 1); +} + +TEST(ConstexprTest, AdjacentFindWithPredicate) { + static constexpr std::array kArray = {1, 2, 3}; + static_assert(absl::c_adjacent_find(kArray, std::less()) == + kArray.begin()); +} + +TEST(ConstexprTest, Count) { + static constexpr std::array kArray = {1, 2, 3}; + static_assert(absl::c_count(kArray, 1) == 1); + static_assert(absl::c_count(kArray, 2) == 1); + static_assert(absl::c_count(kArray, 3) == 1); + static_assert(absl::c_count(kArray, 4) == 0); +} + +TEST(ConstexprTest, CountIf) { + static constexpr std::array kArray = {1, 2, 3}; + static_assert(absl::c_count_if(kArray, [](int x) { return x > 0; }) == 3); + static_assert(absl::c_count_if(kArray, [](int x) { return x > 1; }) == 2); +} + +TEST(ConstexprTest, Mismatch) { + static constexpr std::array kArray1 = {1, 2, 3}; + static constexpr std::array kArray2 = {1, 2, 3}; + static constexpr std::array kArray3 = {2, 3, 4}; + static_assert(absl::c_mismatch(kArray1, kArray2) == + std::pair{kArray1.end(), kArray2.end()}); + static_assert(absl::c_mismatch(kArray1, kArray3) == + std::pair{kArray1.begin(), kArray3.begin()}); +} + +TEST(ConstexprTest, MismatchWithPredicate) { + static constexpr std::array kArray1 = {1, 2, 3}; + static constexpr std::array kArray2 = {1, 2, 3}; + static constexpr std::array kArray3 = {2, 3, 4}; + static_assert(absl::c_mismatch(kArray1, kArray2, std::not_equal_to()) == + std::pair{kArray1.begin(), kArray2.begin()}); + static_assert(absl::c_mismatch(kArray1, kArray3, std::not_equal_to()) == + std::pair{kArray1.end(), kArray3.end()}); +} + +TEST(ConstexprTest, Equal) { + static constexpr std::array kArray1 = {1, 2, 3}; + static constexpr std::array kArray2 = {1, 2, 3}; + static constexpr std::array kArray3 = {2, 3, 4}; + static_assert(absl::c_equal(kArray1, kArray2)); + static_assert(!absl::c_equal(kArray1, kArray3)); +} + +TEST(ConstexprTest, EqualWithPredicate) { + static constexpr std::array kArray1 = {1, 2, 3}; + static constexpr std::array kArray2 = {1, 2, 3}; + static constexpr std::array kArray3 = {2, 3, 4}; + static_assert(!absl::c_equal(kArray1, kArray2, std::not_equal_to())); + static_assert(absl::c_equal(kArray1, kArray3, std::not_equal_to())); +} + +TEST(ConstexprTest, IsPermutation) { + static constexpr std::array kArray1 = {1, 2, 3}; + static constexpr std::array kArray2 = {3, 2, 1}; + static constexpr std::array kArray3 = {2, 3, 4}; + static_assert(absl::c_is_permutation(kArray1, kArray2)); + static_assert(!absl::c_is_permutation(kArray1, kArray3)); +} + +TEST(ConstexprTest, IsPermutationWithPredicate) { + static constexpr std::array kArray1 = {1, 2, 3}; + static constexpr std::array kArray2 = {3, 2, 1}; + static constexpr std::array kArray3 = {2, 3, 4}; + static_assert(absl::c_is_permutation(kArray1, kArray2, std::equal_to())); + static_assert( + !absl::c_is_permutation(kArray1, kArray3, std::equal_to())); +} + +TEST(ConstexprTest, Search) { + static constexpr std::array kArray1 = {1, 2, 3}; + static constexpr std::array kArray2 = {1, 2, 3}; + static constexpr std::array kArray3 = {2, 3, 4}; + static_assert(absl::c_search(kArray1, kArray2) == kArray1.begin()); + static_assert(absl::c_search(kArray1, kArray3) == kArray1.end()); +} + +TEST(ConstexprTest, SearchWithPredicate) { + static constexpr std::array kArray1 = {1, 2, 3}; + static constexpr std::array kArray2 = {1, 2, 3}; + static constexpr std::array kArray3 = {2, 3, 4}; + static_assert(absl::c_search(kArray1, kArray2, std::not_equal_to()) == + kArray1.end()); + static_assert(absl::c_search(kArray1, kArray3, std::not_equal_to()) == + kArray1.begin()); +} + +TEST(ConstexprTest, ContainsSubrange) { + static constexpr std::array kArray1 = {1, 2, 3}; + static constexpr std::array kArray2 = {1, 2, 3}; + static constexpr std::array kArray3 = {2, 3, 4}; + static_assert(absl::c_contains_subrange(kArray1, kArray2)); + static_assert(!absl::c_contains_subrange(kArray1, kArray3)); +} + +TEST(ConstexprTest, ContainsSubrangeWithPredicate) { + static constexpr std::array kArray1 = {1, 2, 3}; + static constexpr std::array kArray2 = {1, 2, 3}; + static constexpr std::array kArray3 = {2, 3, 4}; + static_assert( + !absl::c_contains_subrange(kArray1, kArray2, std::not_equal_to<>())); + static_assert( + absl::c_contains_subrange(kArray1, kArray3, std::not_equal_to<>())); +} + +TEST(ConstexprTest, SearchN) { + static constexpr std::array kArray = {1, 2, 2, 3}; + static_assert(absl::c_search_n(kArray, 1, 1) == kArray.begin()); + static_assert(absl::c_search_n(kArray, 2, 2) == kArray.begin() + 1); + static_assert(absl::c_search_n(kArray, 1, 4) == kArray.end()); +} + +TEST(ConstexprTest, SearchNWithPredicate) { + static constexpr std::array kArray = {1, 2, 2, 3}; + static_assert(absl::c_search_n(kArray, 1, 1, std::not_equal_to()) == + kArray.begin() + 1); + static_assert(absl::c_search_n(kArray, 2, 2, std::not_equal_to()) == + kArray.end()); + static_assert(absl::c_search_n(kArray, 1, 4, std::not_equal_to()) == + kArray.begin()); +} + +#endif // defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && + // ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L + } // namespace