FTL: Add clear() to containers

Bug: 185536303
Test: ftl_test
Change-Id: Icc13d1dcfdc006fd26a418e4904e5d2ce12724dd
diff --git a/include/ftl/small_map.h b/include/ftl/small_map.h
index bcaba82..988431a 100644
--- a/include/ftl/small_map.h
+++ b/include/ftl/small_map.h
@@ -237,6 +237,12 @@
   //
   bool erase(const key_type& key) { return erase(key, begin()); }
 
+  // Removes all mappings.
+  //
+  // All iterators are invalidated.
+  //
+  void clear() { map_.clear(); }
+
  private:
   iterator find(const key_type& key, iterator first) {
     return std::find_if(first, end(), [&key](const auto& pair) { return pair.first == key; });
diff --git a/include/ftl/small_vector.h b/include/ftl/small_vector.h
index 0341435..65a9536 100644
--- a/include/ftl/small_vector.h
+++ b/include/ftl/small_vector.h
@@ -151,8 +151,6 @@
   DISPATCH(reference, back, noexcept)
   DISPATCH(const_reference, back, const)
 
-#undef DISPATCH
-
   reference operator[](size_type i) {
     return dynamic() ? std::get<Dynamic>(vector_)[i] : std::get<Static>(vector_)[i];
   }
@@ -214,13 +212,15 @@
   //
   // The last() and end() iterators are invalidated.
   //
-  void pop_back() {
-    if (dynamic()) {
-      std::get<Dynamic>(vector_).pop_back();
-    } else {
-      std::get<Static>(vector_).pop_back();
-    }
-  }
+  DISPATCH(void, pop_back, noexcept)
+
+  // Removes all elements.
+  //
+  // All iterators are invalidated.
+  //
+  DISPATCH(void, clear, noexcept)
+
+#undef DISPATCH
 
   // Erases an element, but does not preserve order. Rather than shifting subsequent elements,
   // this moves the last element to the slot of the erased element.
@@ -345,6 +345,7 @@
     return true;
   }
 
+  using Impl::clear;
   using Impl::pop_back;
 
   void unstable_erase(iterator it) {
diff --git a/include/ftl/static_vector.h b/include/ftl/static_vector.h
index 96a1ae8..cd7b92a 100644
--- a/include/ftl/static_vector.h
+++ b/include/ftl/static_vector.h
@@ -189,8 +189,7 @@
   }
 
   StaticVector& operator=(StaticVector&& other) {
-    std::destroy(begin(), end());
-    size_ = 0;
+    clear();
     swap<true>(other);
     return *this;
   }
@@ -280,6 +279,15 @@
   //
   void pop_back() { unstable_erase(last()); }
 
+  // Removes all elements.
+  //
+  // All iterators are invalidated.
+  //
+  void clear() {
+    std::destroy(begin(), end());
+    size_ = 0;
+  }
+
   // Erases an element, but does not preserve order. Rather than shifting subsequent elements,
   // this moves the last element to the slot of the erased element.
   //
diff --git a/libs/ftl/small_map_test.cpp b/libs/ftl/small_map_test.cpp
index 2e81022..c292108 100644
--- a/libs/ftl/small_map_test.cpp
+++ b/libs/ftl/small_map_test.cpp
@@ -345,4 +345,21 @@
   }
 }
 
+TEST(SmallMap, Clear) {
+  SmallMap map = ftl::init::map(1, '1')(2, '2')(3, '3');
+
+  map.clear();
+
+  EXPECT_TRUE(map.empty());
+  EXPECT_FALSE(map.dynamic());
+
+  map = ftl::init::map(1, '1')(2, '2')(3, '3');
+  map.try_emplace(4, '4');
+
+  map.clear();
+
+  EXPECT_TRUE(map.empty());
+  EXPECT_TRUE(map.dynamic());
+}
+
 }  // namespace android::test
diff --git a/libs/ftl/small_vector_test.cpp b/libs/ftl/small_vector_test.cpp
index 3a03e69..4237496 100644
--- a/libs/ftl/small_vector_test.cpp
+++ b/libs/ftl/small_vector_test.cpp
@@ -460,4 +460,34 @@
   EXPECT_EQ(0, dead);
 }
 
+TEST(SmallVector, Clear) {
+  int live = 0;
+  int dead = 0;
+
+  SmallVector<DestroyCounts, 2> counts;
+  counts.emplace_back(live, dead);
+  counts.emplace_back(live, dead);
+
+  counts.clear();
+
+  EXPECT_TRUE(counts.empty());
+  EXPECT_FALSE(counts.dynamic());
+
+  EXPECT_EQ(2, live);
+  EXPECT_EQ(0, dead);
+
+  live = 0;
+  counts.emplace_back(live, dead);
+  counts.emplace_back(live, dead);
+  counts.emplace_back(live, dead);
+
+  counts.clear();
+
+  EXPECT_TRUE(counts.empty());
+  EXPECT_TRUE(counts.dynamic());
+
+  EXPECT_EQ(3, live);
+  EXPECT_EQ(2, dead);
+}
+
 }  // namespace android::test
diff --git a/libs/ftl/static_vector_test.cpp b/libs/ftl/static_vector_test.cpp
index cbe8dff..2de3ad2 100644
--- a/libs/ftl/static_vector_test.cpp
+++ b/libs/ftl/static_vector_test.cpp
@@ -396,4 +396,19 @@
   EXPECT_EQ(0, dead);
 }
 
+TEST(StaticVector, Clear) {
+  int live = 0;
+  int dead = 0;
+
+  StaticVector<DestroyCounts, 5> counts;
+  counts.emplace_back(live, dead);
+  counts.emplace_back(live, dead);
+
+  counts.clear();
+
+  EXPECT_TRUE(counts.empty());
+  EXPECT_EQ(2, live);
+  EXPECT_EQ(0, dead);
+}
+
 }  // namespace android::test