mirror of
https://github.com/abseil/abseil-cpp.git
synced 2026-06-04 12:07:05 +08:00
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
This commit is contained in:
committed by
Copybara-Service
parent
809e5de7b9
commit
00478de3e9
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user