[ADT] Make SmallSet::insert(const T &) return const_iterator

This patch makes `SmallSet::insert(const T &)` return
`std::pair<const_iterator, bool>` instead of
`std::pair<NoneType, bool>`. This will exactly match std::set's behavior
and make deduplicating items with SmallSet easier.

Reviewed By: dblaikie, lattner

Differential Revision: https://reviews.llvm.org/D131549
This commit is contained in:
Zijia Zhu 2022-08-15 13:43:59 +08:00
parent d797c2ffdb
commit 8719faafdb
2 changed files with 33 additions and 19 deletions

View File

@ -141,6 +141,7 @@ class SmallSet {
std::set<T, C> Set; std::set<T, C> Set;
using VIterator = typename SmallVector<T, N>::const_iterator; using VIterator = typename SmallVector<T, N>::const_iterator;
using SIterator = typename std::set<T, C>::const_iterator;
using mutable_iterator = typename SmallVector<T, N>::iterator; using mutable_iterator = typename SmallVector<T, N>::iterator;
// In small mode SmallPtrSet uses linear search for the elements, so it is // In small mode SmallPtrSet uses linear search for the elements, so it is
@ -171,22 +172,21 @@ public:
} }
/// insert - Insert an element into the set if it isn't already there. /// insert - Insert an element into the set if it isn't already there.
/// Returns true if the element is inserted (it was not in the set before). /// Returns a pair. The first value of it is an iterator to the inserted
/// The first value of the returned pair is unused and provided for /// element or the existing element in the set. The second value is true
/// partial compatibility with the standard library self-associative container /// if the element is inserted (it was not in the set before).
/// concept. std::pair<const_iterator, bool> insert(const T &V) {
// FIXME: Add iterators that abstract over the small and large form, and then if (!isSmall()) {
// return those here. auto [I, Inserted] = Set.insert(V);
std::pair<NoneType, bool> insert(const T &V) { return std::make_pair(const_iterator(I), Inserted);
if (!isSmall()) }
return std::make_pair(None, Set.insert(V).second);
VIterator I = vfind(V); VIterator I = vfind(V);
if (I != Vector.end()) // Don't reinsert if it already exists. if (I != Vector.end()) // Don't reinsert if it already exists.
return std::make_pair(None, false); return std::make_pair(const_iterator(I), false);
if (Vector.size() < N) { if (Vector.size() < N) {
Vector.push_back(V); Vector.push_back(V);
return std::make_pair(None, true); return std::make_pair(const_iterator(std::prev(Vector.end())), true);
} }
// Otherwise, grow from vector to set. // Otherwise, grow from vector to set.
@ -194,8 +194,7 @@ public:
Set.insert(Vector.back()); Set.insert(Vector.back());
Vector.pop_back(); Vector.pop_back();
} }
Set.insert(V); return std::make_pair(const_iterator(Set.insert(V).first), true);
return std::make_pair(None, true);
} }
template <typename IterT> template <typename IterT>

View File

@ -21,11 +21,17 @@ TEST(SmallSetTest, Insert) {
SmallSet<int, 4> s1; SmallSet<int, 4> s1;
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++) {
s1.insert(i); auto InsertResult = s1.insert(i);
EXPECT_EQ(*InsertResult.first, i);
EXPECT_EQ(InsertResult.second, true);
}
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++) {
s1.insert(i); auto InsertResult = s1.insert(i);
EXPECT_EQ(*InsertResult.first, i);
EXPECT_EQ(InsertResult.second, false);
}
EXPECT_EQ(4u, s1.size()); EXPECT_EQ(4u, s1.size());
@ -38,8 +44,17 @@ TEST(SmallSetTest, Insert) {
TEST(SmallSetTest, Grow) { TEST(SmallSetTest, Grow) {
SmallSet<int, 4> s1; SmallSet<int, 4> s1;
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++) {
s1.insert(i); auto InsertResult = s1.insert(i);
EXPECT_EQ(*InsertResult.first, i);
EXPECT_EQ(InsertResult.second, true);
}
for (int i = 0; i < 8; i++) {
auto InsertResult = s1.insert(i);
EXPECT_EQ(*InsertResult.first, i);
EXPECT_EQ(InsertResult.second, false);
}
EXPECT_EQ(8u, s1.size()); EXPECT_EQ(8u, s1.size());