Skip to content

Commit

Permalink
[ADT] Use adl_begin/end in enumerate
Browse files Browse the repository at this point in the history
This allows `enumerate` to work with range types that expose custom
`begin`/`end` functions.

This is a cleanup in preparation for future changes in
https://reviews.llvm.org/D144503.

Reviewed By: zero9178

Differential Revision: https://reviews.llvm.org/D145026
  • Loading branch information
kuhar committed Mar 1, 2023
1 parent 613c9b9 commit 1527a1b
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 32 deletions.
10 changes: 4 additions & 6 deletions llvm/include/llvm/ADT/STLExtras.h
Expand Up @@ -2271,17 +2271,15 @@ template <typename R> class enumerator {
explicit enumerator(R &&Range) : TheRange(std::forward<R>(Range)) {}

enumerator_iter<R> begin() {
return enumerator_iter<R>(0, std::begin(TheRange));
return enumerator_iter<R>(0, adl_begin(TheRange));
}
enumerator_iter<R> begin() const {
return enumerator_iter<R>(0, std::begin(TheRange));
return enumerator_iter<R>(0, adl_begin(TheRange));
}

enumerator_iter<R> end() {
return enumerator_iter<R>(std::end(TheRange));
}
enumerator_iter<R> end() { return enumerator_iter<R>(adl_end(TheRange)); }
enumerator_iter<R> end() const {
return enumerator_iter<R>(std::end(TheRange));
return enumerator_iter<R>(adl_end(TheRange));
}

private:
Expand Down
66 changes: 40 additions & 26 deletions llvm/unittests/ADT/STLExtrasTest.cpp
Expand Up @@ -260,6 +260,46 @@ TEST(STLExtrasTest, EnumerateLifetimeSemanticsLValue) {
EXPECT_EQ(1, Destructors);
}

namespace some_namespace {
struct some_struct {
std::vector<int> data;
std::string swap_val;
};

std::vector<int>::const_iterator begin(const some_struct &s) {
return s.data.begin();
}

std::vector<int>::const_iterator end(const some_struct &s) {
return s.data.end();
}

void swap(some_struct &lhs, some_struct &rhs) {
// make swap visible as non-adl swap would even seem to
// work with std::swap which defaults to moving
lhs.swap_val = "lhs";
rhs.swap_val = "rhs";
}

struct requires_move {};
int *begin(requires_move &&) { return nullptr; }
int *end(requires_move &&) { return nullptr; }
} // namespace some_namespace

TEST(STLExtrasTest, EnumerateCustomBeginEnd) {
// Check that `enumerate` uses ADL to find `begin`/`end` iterators
// of the enumerated type.
some_namespace::some_struct X{};
X.data = {1, 2, 3};

unsigned Iters = 0;
for (auto [Idx, Val] : enumerate(X)) {
EXPECT_EQ(Val, X.data[Idx]);
++Iters;
}
EXPECT_EQ(Iters, 3u);
}

TEST(STLExtrasTest, CountAdaptor) {
std::vector<int> v;

Expand Down Expand Up @@ -375,32 +415,6 @@ TEST(STLExtrasTest, AppendRange) {
EXPECT_THAT(Str, ElementsAre('a', 'b', 'c', '\0', 'd', 'e', 'f', '\0'));
}

namespace some_namespace {
struct some_struct {
std::vector<int> data;
std::string swap_val;
};

std::vector<int>::const_iterator begin(const some_struct &s) {
return s.data.begin();
}

std::vector<int>::const_iterator end(const some_struct &s) {
return s.data.end();
}

void swap(some_struct &lhs, some_struct &rhs) {
// make swap visible as non-adl swap would even seem to
// work with std::swap which defaults to moving
lhs.swap_val = "lhs";
rhs.swap_val = "rhs";
}

struct requires_move {};
int *begin(requires_move &&) { return nullptr; }
int *end(requires_move &&) { return nullptr; }
} // namespace some_namespace

TEST(STLExtrasTest, ADLTest) {
some_namespace::some_struct s{{1, 2, 3, 4, 5}, ""};
some_namespace::some_struct s2{{2, 4, 6, 8, 10}, ""};
Expand Down

0 comments on commit 1527a1b

Please sign in to comment.