diff options
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/docs/ProgrammersManual.rst | 6 | ||||
| -rw-r--r-- | llvm/include/llvm/ADT/MapVector.h | 28 | ||||
| -rw-r--r-- | llvm/unittests/ADT/MapVectorTest.cpp | 21 |
3 files changed, 53 insertions, 2 deletions
diff --git a/llvm/docs/ProgrammersManual.rst b/llvm/docs/ProgrammersManual.rst index e828e6bf501..40eabbe442d 100644 --- a/llvm/docs/ProgrammersManual.rst +++ b/llvm/docs/ProgrammersManual.rst @@ -1441,8 +1441,10 @@ order, making it an easy (but somewhat expensive) solution for non-deterministic iteration over maps of pointers. It is implemented by mapping from key to an index in a vector of key,value -pairs. This provides fast lookup and iteration, but has two main drawbacks: The -key is stored twice and removing elements takes linear time. +pairs. This provides fast lookup and iteration, but has two main drawbacks: +the key is stored twice and removing elements takes linear time. If it is +necessary to remove elements, it's best to remove them in bulk using +``remove_if()``. .. _dss_inteqclasses: diff --git a/llvm/include/llvm/ADT/MapVector.h b/llvm/include/llvm/ADT/MapVector.h index 0fa68245ff4..4e1fc152727 100644 --- a/llvm/include/llvm/ADT/MapVector.h +++ b/llvm/include/llvm/ADT/MapVector.h @@ -146,8 +146,36 @@ public: } return Next; } + + /// \brief Remove the elements that match the predicate. + /// + /// Erase all elements that match \c Pred in a single pass. Takes linear + /// time. + template <class Predicate> void remove_if(Predicate Pred); }; +template <typename KeyT, typename ValueT, typename MapType, typename VectorType> +template <class Function> +void MapVector<KeyT, ValueT, MapType, VectorType>::remove_if(Function Pred) { + auto O = Vector.begin(); + for (auto I = O, E = Vector.end(); I != E; ++I) { + if (Pred(*I)) { + // Erase from the map. + Map.erase(I->first); + continue; + } + + if (I != O) { + // Move the value and update the index in the map. + *O = std::move(*I); + Map[O->first] = O - Vector.begin(); + } + ++O; + } + // Erase trailing entries in the vector. + Vector.erase(O, Vector.end()); +} + } // end namespace llvm #endif diff --git a/llvm/unittests/ADT/MapVectorTest.cpp b/llvm/unittests/ADT/MapVectorTest.cpp index dd84e7ebd13..92f0dc41910 100644 --- a/llvm/unittests/ADT/MapVectorTest.cpp +++ b/llvm/unittests/ADT/MapVectorTest.cpp @@ -68,3 +68,24 @@ TEST(MapVectorTest, erase) { ASSERT_EQ(MV[3], 4); ASSERT_EQ(MV[5], 6); } + +TEST(MapVectorTest, remove_if) { + MapVector<int, int> MV; + + MV.insert(std::make_pair(1, 11)); + MV.insert(std::make_pair(2, 12)); + MV.insert(std::make_pair(3, 13)); + MV.insert(std::make_pair(4, 14)); + MV.insert(std::make_pair(5, 15)); + MV.insert(std::make_pair(6, 16)); + ASSERT_EQ(MV.size(), 6u); + + MV.remove_if([](const std::pair<int, int> &Val) { return Val.second % 2; }); + ASSERT_EQ(MV.size(), 3u); + ASSERT_EQ(MV.find(1), MV.end()); + ASSERT_EQ(MV.find(3), MV.end()); + ASSERT_EQ(MV.find(5), MV.end()); + ASSERT_EQ(MV[2], 12); + ASSERT_EQ(MV[4], 14); + ASSERT_EQ(MV[6], 16); +} |

