Commit 00478de3 by Abseil Team Committed by Copybara-Service

Mark non-modifying container algorithms as constexpr for C++20.

This change marks Abseil's non-modifying sequence operations including
absl::linear_search and absl::c_linear_search as constexpr when building with
C++20.
PiperOrigin-RevId: 659812405
Change-Id: I8dc2cee873f30531b2eb8fb3da12085505a43a1a
parent 809e5de7
......@@ -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 <typename InputIterator, typename EqualityComparable>
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;
}
......
......@@ -14,11 +14,9 @@
#include "absl/algorithm/algorithm.h"
#include <algorithm>
#include <list>
#include <array>
#include <vector>
#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<int, 3> 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
......@@ -132,7 +132,8 @@ struct IsUnorderedContainer<std::unordered_set<Key, Hash, KeyEqual, Allocator>>
// Container-based version of absl::linear_search() for performing a linear
// search within a container.
template <typename C, typename EqualityComparable>
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<EqualityComparable>(value));
......@@ -163,7 +164,7 @@ ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
// Container-based version of the <algorithm> `std::all_of()` function to
// test if all elements within a container satisfy a condition.
template <typename C, typename Pred>
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>(pred));
......@@ -174,7 +175,7 @@ bool c_all_of(const C& c, Pred&& pred) {
// Container-based version of the <algorithm> `std::any_of()` function to
// test if any element in a container fulfills a condition.
template <typename C, typename Pred>
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>(pred));
......@@ -185,7 +186,7 @@ bool c_any_of(const C& c, Pred&& pred) {
// Container-based version of the <algorithm> `std::none_of()` function to
// test if no elements in a container fulfill a condition.
template <typename C, typename Pred>
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>(pred));
......@@ -196,7 +197,8 @@ bool c_none_of(const C& c, Pred&& pred) {
// Container-based version of the <algorithm> `std::for_each()` function to
// apply a function to a container's elements.
template <typename C, typename Function>
decay_t<Function> c_for_each(C&& c, Function&& f) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 decay_t<Function> 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<Function>(f));
......@@ -207,7 +209,9 @@ decay_t<Function> c_for_each(C&& c, Function&& f) {
// Container-based version of the <algorithm> `std::find()` function to find
// the first element containing the passed value within a container value.
template <typename C, typename T>
container_algorithm_internal::ContainerIter<C> c_find(C& c, T&& value) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
container_algorithm_internal::ContainerIter<C>
c_find(C& c, T&& value) {
return std::find(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c),
std::forward<T>(value));
......@@ -218,7 +222,8 @@ container_algorithm_internal::ContainerIter<C> c_find(C& c, T&& value) {
// 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) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_contains(const Sequence& sequence,
T&& value) {
return absl::c_find(sequence, std::forward<T>(value)) !=
container_algorithm_internal::c_end(sequence);
}
......@@ -228,7 +233,9 @@ bool c_contains(const Sequence& sequence, T&& value) {
// Container-based version of the <algorithm> `std::find_if()` function to find
// the first element in a container matching the given condition.
template <typename C, typename Pred>
container_algorithm_internal::ContainerIter<C> c_find_if(C& c, Pred&& pred) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
container_algorithm_internal::ContainerIter<C>
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>(pred));
......@@ -239,8 +246,9 @@ container_algorithm_internal::ContainerIter<C> c_find_if(C& c, Pred&& pred) {
// Container-based version of the <algorithm> `std::find_if_not()` function to
// find the first element in a container not matching the given condition.
template <typename C, typename Pred>
container_algorithm_internal::ContainerIter<C> c_find_if_not(C& c,
Pred&& pred) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
container_algorithm_internal::ContainerIter<C>
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>(pred));
......@@ -251,8 +259,9 @@ container_algorithm_internal::ContainerIter<C> c_find_if_not(C& c,
// Container-based version of the <algorithm> `std::find_end()` function to
// find the last subsequence within a container.
template <typename Sequence1, typename Sequence2>
container_algorithm_internal::ContainerIter<Sequence1> c_find_end(
Sequence1& sequence, Sequence2& subsequence) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
container_algorithm_internal::ContainerIter<Sequence1>
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<Sequence1> c_find_end(
// Overload of c_find_end() for using a predicate evaluation other than `==` as
// the function's test condition.
template <typename Sequence1, typename Sequence2, typename BinaryPredicate>
container_algorithm_internal::ContainerIter<Sequence1> c_find_end(
Sequence1& sequence, Sequence2& subsequence, BinaryPredicate&& pred) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
container_algorithm_internal::ContainerIter<Sequence1>
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<Sequence1> c_find_end(
// find the first element within the container that is also within the options
// container.
template <typename C1, typename C2>
container_algorithm_internal::ContainerIter<C1> c_find_first_of(C1& container,
C2& options) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
container_algorithm_internal::ContainerIter<C1>
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<C1> 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 <typename C1, typename C2, typename BinaryPredicate>
container_algorithm_internal::ContainerIter<C1> c_find_first_of(
C1& container, C2& options, BinaryPredicate&& pred) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
container_algorithm_internal::ContainerIter<C1>
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<C1> c_find_first_of(
// Container-based version of the <algorithm> `std::adjacent_find()` function to
// find equal adjacent elements within a container.
template <typename Sequence>
container_algorithm_internal::ContainerIter<Sequence> c_adjacent_find(
Sequence& sequence) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
container_algorithm_internal::ContainerIter<Sequence>
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<Sequence> c_adjacent_find(
// Overload of c_adjacent_find() for using a predicate evaluation other than
// `==` as the function's test condition.
template <typename Sequence, typename BinaryPredicate>
container_algorithm_internal::ContainerIter<Sequence> c_adjacent_find(
Sequence& sequence, BinaryPredicate&& pred) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
container_algorithm_internal::ContainerIter<Sequence>
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<BinaryPredicate>(pred));
......@@ -323,8 +338,9 @@ container_algorithm_internal::ContainerIter<Sequence> c_adjacent_find(
// Container-based version of the <algorithm> `std::count()` function to count
// values that match within a container.
template <typename C, typename T>
container_algorithm_internal::ContainerDifferenceType<const C> c_count(
const C& c, T&& value) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
container_algorithm_internal::ContainerDifferenceType<const C>
c_count(const C& c, T&& value) {
return std::count(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c),
std::forward<T>(value));
......@@ -335,8 +351,9 @@ container_algorithm_internal::ContainerDifferenceType<const C> c_count(
// Container-based version of the <algorithm> `std::count_if()` function to
// count values matching a condition within a container.
template <typename C, typename Pred>
container_algorithm_internal::ContainerDifferenceType<const C> c_count_if(
const C& c, Pred&& pred) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
container_algorithm_internal::ContainerDifferenceType<const C>
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>(pred));
......@@ -348,8 +365,9 @@ container_algorithm_internal::ContainerDifferenceType<const C> 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 <typename C1, typename C2>
container_algorithm_internal::ContainerIterPairType<C1, C2> c_mismatch(C1& c1,
C2& c2) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
container_algorithm_internal::ContainerIterPairType<C1, C2>
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<C1, C2> 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 <typename C1, typename C2, typename BinaryPredicate>
container_algorithm_internal::ContainerIterPairType<C1, C2> c_mismatch(
C1& c1, C2& c2, BinaryPredicate pred) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
container_algorithm_internal::ContainerIterPairType<C1, C2>
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<C1, C2> c_mismatch(
// Container-based version of the <algorithm> `std::equal()` function to
// test whether two containers are equal.
template <typename C1, typename C2>
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 <typename C1, typename C2, typename BinaryPredicate>
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 <algorithm> `std::is_permutation()` function
// to test whether a container is a permutation of another.
template <typename C1, typename C2>
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 <typename C1, typename C2, typename BinaryPredicate>
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 <algorithm> `std::search()` function to search
// a container for a subsequence.
template <typename Sequence1, typename Sequence2>
container_algorithm_internal::ContainerIter<Sequence1> c_search(
Sequence1& sequence, Sequence2& subsequence) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
container_algorithm_internal::ContainerIter<Sequence1>
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<Sequence1> c_search(
// Overload of c_search() for using a predicate evaluation other than
// `==` as the function's test condition.
template <typename Sequence1, typename Sequence2, typename BinaryPredicate>
container_algorithm_internal::ContainerIter<Sequence1> c_search(
Sequence1& sequence, Sequence2& subsequence, BinaryPredicate&& pred) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
container_algorithm_internal::ContainerIter<Sequence1>
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<Sequence1> c_search(
// 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) {
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 <typename Sequence1, typename Sequence2, typename BinaryPredicate>
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<BinaryPredicate>(pred)) !=
container_algorithm_internal::c_end(sequence);
......@@ -464,8 +490,9 @@ bool c_contains_subrange(Sequence1& sequence, Sequence2& subsequence,
// Container-based version of the <algorithm> `std::search_n()` function to
// search a container for the first sequence of N elements.
template <typename Sequence, typename Size, typename T>
container_algorithm_internal::ContainerIter<Sequence> c_search_n(
Sequence& sequence, Size count, T&& value) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
container_algorithm_internal::ContainerIter<Sequence>
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<T>(value));
......@@ -475,8 +502,10 @@ container_algorithm_internal::ContainerIter<Sequence> c_search_n(
// `==` as the function's test condition.
template <typename Sequence, typename Size, typename T,
typename BinaryPredicate>
container_algorithm_internal::ContainerIter<Sequence> c_search_n(
Sequence& sequence, Size count, T&& value, BinaryPredicate&& pred) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
container_algorithm_internal::ContainerIter<Sequence>
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<T>(value),
......
......@@ -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<int, 3>()) == 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<int, 3> 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<int, 3> 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<int, 3> 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<int, 3> 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<int, 3> kArray = [] {
std::array<int, 3> 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<int, 3> 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<int, 3> 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<int, 3> 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<int, 3> 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<int, 5> kHaystack = {1, 2, 3, 2, 3};
static constexpr std::array<int, 2> kNeedle = {2, 3};
static_assert(absl::c_find_end(kHaystack, kNeedle) == kHaystack.begin() + 3);
}
TEST(ConstexprTest, FindFirstOf) {
static constexpr std::array<int, 3> kArray = {1, 2, 3};
static_assert(absl::c_find_first_of(kArray, kArray) == kArray.begin());
}
TEST(ConstexprTest, AdjacentFind) {
static constexpr std::array<int, 4> kArray = {1, 2, 2, 3};
static_assert(absl::c_adjacent_find(kArray) == kArray.begin() + 1);
}
TEST(ConstexprTest, AdjacentFindWithPredicate) {
static constexpr std::array<int, 3> kArray = {1, 2, 3};
static_assert(absl::c_adjacent_find(kArray, std::less<int>()) ==
kArray.begin());
}
TEST(ConstexprTest, Count) {
static constexpr std::array<int, 3> 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<int, 3> 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<int, 3> kArray1 = {1, 2, 3};
static constexpr std::array<int, 3> kArray2 = {1, 2, 3};
static constexpr std::array<int, 3> 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<int, 3> kArray1 = {1, 2, 3};
static constexpr std::array<int, 3> kArray2 = {1, 2, 3};
static constexpr std::array<int, 3> kArray3 = {2, 3, 4};
static_assert(absl::c_mismatch(kArray1, kArray2, std::not_equal_to<int>()) ==
std::pair{kArray1.begin(), kArray2.begin()});
static_assert(absl::c_mismatch(kArray1, kArray3, std::not_equal_to<int>()) ==
std::pair{kArray1.end(), kArray3.end()});
}
TEST(ConstexprTest, Equal) {
static constexpr std::array<int, 3> kArray1 = {1, 2, 3};
static constexpr std::array<int, 3> kArray2 = {1, 2, 3};
static constexpr std::array<int, 3> 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<int, 3> kArray1 = {1, 2, 3};
static constexpr std::array<int, 3> kArray2 = {1, 2, 3};
static constexpr std::array<int, 3> kArray3 = {2, 3, 4};
static_assert(!absl::c_equal(kArray1, kArray2, std::not_equal_to<int>()));
static_assert(absl::c_equal(kArray1, kArray3, std::not_equal_to<int>()));
}
TEST(ConstexprTest, IsPermutation) {
static constexpr std::array<int, 3> kArray1 = {1, 2, 3};
static constexpr std::array<int, 3> kArray2 = {3, 2, 1};
static constexpr std::array<int, 3> 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<int, 3> kArray1 = {1, 2, 3};
static constexpr std::array<int, 3> kArray2 = {3, 2, 1};
static constexpr std::array<int, 3> kArray3 = {2, 3, 4};
static_assert(absl::c_is_permutation(kArray1, kArray2, std::equal_to<int>()));
static_assert(
!absl::c_is_permutation(kArray1, kArray3, std::equal_to<int>()));
}
TEST(ConstexprTest, Search) {
static constexpr std::array<int, 3> kArray1 = {1, 2, 3};
static constexpr std::array<int, 3> kArray2 = {1, 2, 3};
static constexpr std::array<int, 3> 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<int, 3> kArray1 = {1, 2, 3};
static constexpr std::array<int, 3> kArray2 = {1, 2, 3};
static constexpr std::array<int, 3> kArray3 = {2, 3, 4};
static_assert(absl::c_search(kArray1, kArray2, std::not_equal_to<int>()) ==
kArray1.end());
static_assert(absl::c_search(kArray1, kArray3, std::not_equal_to<int>()) ==
kArray1.begin());
}
TEST(ConstexprTest, ContainsSubrange) {
static constexpr std::array<int, 3> kArray1 = {1, 2, 3};
static constexpr std::array<int, 3> kArray2 = {1, 2, 3};
static constexpr std::array<int, 3> 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<int, 3> kArray1 = {1, 2, 3};
static constexpr std::array<int, 3> kArray2 = {1, 2, 3};
static constexpr std::array<int, 3> 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<int, 4> 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<int, 4> kArray = {1, 2, 2, 3};
static_assert(absl::c_search_n(kArray, 1, 1, std::not_equal_to<int>()) ==
kArray.begin() + 1);
static_assert(absl::c_search_n(kArray, 2, 2, std::not_equal_to<int>()) ==
kArray.end());
static_assert(absl::c_search_n(kArray, 1, 4, std::not_equal_to<int>()) ==
kArray.begin());
}
#endif // defined(ABSL_INTERNAL_CPLUSPLUS_LANG) &&
// ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
} // namespace
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment