`UnorderedElementsAre()`: Allow matching containers where `end` is a [sentinel](https://en.cppreference.com/cpp/iterator/sentinel_for). `ElementsAre` already supports that.

PiperOrigin-RevId: 971869110
Change-Id: I1316463fbd0b532bdf5d636d47165aace84b3801
This commit is contained in:
Abseil Team 2026-08-27 04:13:04 -07:00 committed by Copybara-Service
parent 938220d0f6
commit 36ba75f0ad
2 changed files with 62 additions and 2 deletions

View File

@ -3971,8 +3971,8 @@ class [[nodiscard]] UnorderedElementsAreMatcherImpl
}
private:
template <typename ElementIter>
MatchMatrix AnalyzeElements(ElementIter elem_first, ElementIter elem_last,
template <typename ElementIter, typename ElementIterEnd>
MatchMatrix AnalyzeElements(ElementIter elem_first, ElementIterEnd elem_last,
::std::vector<std::string>* element_printouts,
MatchResultListener* listener) const {
element_printouts->clear();

View File

@ -78,6 +78,52 @@ TEST(ContainsTest, WorksWithMoveOnly) {
INSTANTIATE_GTEST_MATCHER_TEST_P(ElementsAreTest);
// A range of decreasing, positive integers.
class DecreasingIntRange {
public:
explicit DecreasingIntRange(int start) : v_(start) {}
struct Sentinel {};
class Iterator {
public:
using difference_type = std::ptrdiff_t;
using value_type = int;
using iterator_category = std::input_iterator_tag;
using pointer = void;
using reference = int;
explicit Iterator(int v) : v_(v) {}
int operator*() const { return v_; }
Iterator& operator++() {
--v_;
return *this;
}
Iterator operator++(int) {
auto tmp = *this;
++*this;
return tmp;
}
bool operator==(const Iterator& other) const { return v_ == other.v_; }
bool operator!=(const Iterator& other) const { return v_ != other.v_; }
bool operator==(const Sentinel&) const { return v_ < 0; }
bool operator!=(const Sentinel&) const { return v_ >= 0; }
private:
int v_;
};
Iterator begin() const { return Iterator(v_); }
Sentinel end() const { return Sentinel{}; }
private:
int v_;
};
// Tests the variadic version of the ElementsAreMatcher
TEST(ElementsAreTest, HugeMatcher) {
vector<int> test_vector{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
@ -87,6 +133,13 @@ TEST(ElementsAreTest, HugeMatcher) {
Eq(8), Eq(9), Eq(10), Gt(1), Eq(12)));
}
// Tests ElementsAreMatcher with a range that uses a sentinel.
TEST(ElementsAreTest, HugeMatcherSentinel) {
DecreasingIntRange range(3);
EXPECT_THAT(range, ElementsAre(Eq(3), Eq(2), Eq(1), Eq(0)));
}
// Tests the variadic version of the UnorderedElementsAreMatcher
TEST(ElementsAreTest, HugeMatcherStr) {
vector<std::string> test_vector{
@ -105,6 +158,13 @@ TEST(ElementsAreTest, HugeMatcherUnordered) {
Eq(3), Eq(9), Eq(12), Eq(11), Ne(122)));
}
// Tests the UnorderedElementsAreMatcher with a range that uses a sentinel.
TEST(ElementsAreTest, HugeMatcherUnorderedSentinel) {
DecreasingIntRange range(3);
EXPECT_THAT(range, UnorderedElementsAre(Eq(2), Eq(1), Eq(3), Eq(0)));
}
// Tests that ASSERT_THAT() and EXPECT_THAT() work when the value
// matches the matcher.
TEST(MatcherAssertionTest, WorksWhenMatcherIsSatisfied) {