[libc++][P1115][C++20] Improving the Return Value of Erase-Like Algorithms II: Free erase/erase if.

Summary:
This patch adds return type to std::erase and std::erase_if functions.

Also:
* Update __cpp_lib_erase_if to 202002L.
* Fix synopsis in unordered_map.
* Fix generate_feature_test_macro_components.py script.

Reviewers: EricWF, mclow.lists, ldionne, #libc

Reviewed By: ldionne, #libc

Subscribers: broadwaylamb, zoecarver, dexonsmith, ldionne, libcxx-commits

Tags: #libc

Differential Revision: https://reviews.llvm.org/D75905

Cr-Mirrored-From: https://chromium.googlesource.com/external/github.com/llvm/llvm-project
Cr-Mirrored-Commit: 3e895085de0afdd85574b35de48a1bcc6544f2ec
diff --git a/include/deque b/include/deque
index 115b1b6..c2ea5f2 100644
--- a/include/deque
+++ b/include/deque
@@ -150,9 +150,11 @@
          noexcept(noexcept(x.swap(y)));
 
 template <class T, class Allocator, class U>
-    void erase(deque<T, Allocator>& c, const U& value);       // C++20
+    typename deque<T, Allocator>::size_type
+    erase(deque<T, Allocator>& c, const U& value);       // C++20
 template <class T, class Allocator, class Predicate>
-    void erase_if(deque<T, Allocator>& c, Predicate pred);    // C++20
+    typename deque<T, Allocator>::size_type
+    erase_if(deque<T, Allocator>& c, Predicate pred);    // C++20
 
 }  // std
 
@@ -3021,14 +3023,20 @@
 
 #if _LIBCPP_STD_VER > 17
 template <class _Tp, class _Allocator, class _Up>
-inline _LIBCPP_INLINE_VISIBILITY
-void erase(deque<_Tp, _Allocator>& __c, const _Up& __v)
-{ __c.erase(_VSTD::remove(__c.begin(), __c.end(), __v), __c.end()); }
+inline _LIBCPP_INLINE_VISIBILITY typename deque<_Tp, _Allocator>::size_type
+erase(deque<_Tp, _Allocator>& __c, const _Up& __v) {
+  auto __old_size = __c.size();
+  __c.erase(_VSTD::remove(__c.begin(), __c.end(), __v), __c.end());
+  return __old_size - __c.size();
+}
 
 template <class _Tp, class _Allocator, class _Predicate>
-inline _LIBCPP_INLINE_VISIBILITY
-void erase_if(deque<_Tp, _Allocator>& __c, _Predicate __pred)
-{ __c.erase(_VSTD::remove_if(__c.begin(), __c.end(), __pred), __c.end()); }
+inline _LIBCPP_INLINE_VISIBILITY typename deque<_Tp, _Allocator>::size_type
+erase_if(deque<_Tp, _Allocator>& __c, _Predicate __pred) {
+  auto __old_size = __c.size();
+  __c.erase(_VSTD::remove_if(__c.begin(), __c.end(), __pred), __c.end());
+  return __old_size - __c.size();
+}
 #endif
 
 
diff --git a/include/forward_list b/include/forward_list
index 3905745..3bd8db8 100644
--- a/include/forward_list
+++ b/include/forward_list
@@ -169,9 +169,11 @@
          noexcept(noexcept(x.swap(y)));
 
 template <class T, class Allocator, class U>
-    void erase(forward_list<T, Allocator>& c, const U& value);       // C++20
+    typename forward_list<T, Allocator>::size_type
+    erase(forward_list<T, Allocator>& c, const U& value);       // C++20
 template <class T, class Allocator, class Predicate>
-    void erase_if(forward_list<T, Allocator>& c, Predicate pred);    // C++20
+    typename forward_list<T, Allocator>::size_type
+    erase_if(forward_list<T, Allocator>& c, Predicate pred);    // C++20
 
 }  // std
 
@@ -1765,13 +1767,17 @@
 #if _LIBCPP_STD_VER > 17
 template <class _Tp, class _Allocator, class _Predicate>
 inline _LIBCPP_INLINE_VISIBILITY
-void erase_if(forward_list<_Tp, _Allocator>& __c, _Predicate __pred)
-{ __c.remove_if(__pred); }
+    typename forward_list<_Tp, _Allocator>::size_type
+    erase_if(forward_list<_Tp, _Allocator>& __c, _Predicate __pred) {
+  return __c.remove_if(__pred);
+}
 
 template <class _Tp, class _Allocator, class _Up>
 inline _LIBCPP_INLINE_VISIBILITY
-void erase(forward_list<_Tp, _Allocator>& __c, const _Up& __v)
-{ _VSTD::erase_if(__c, [&](auto& __elem) { return __elem == __v; }); }
+    typename forward_list<_Tp, _Allocator>::size_type
+    erase(forward_list<_Tp, _Allocator>& __c, const _Up& __v) {
+  return _VSTD::erase_if(__c, [&](auto& __elem) { return __elem == __v; });
+}
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/include/functional b/include/functional
index 62b7d09..67be9ee 100644
--- a/include/functional
+++ b/include/functional
@@ -3163,15 +3163,19 @@
 #endif // > C++17
 
 template <class _Container, class _Predicate>
-inline void __libcpp_erase_if_container( _Container& __c, _Predicate __pred)
-{
-	for (typename _Container::iterator __iter = __c.begin(), __last = __c.end(); __iter != __last;)
-	{
-		if (__pred(*__iter))
-			__iter = __c.erase(__iter);
-		else
-			++__iter;
-	}
+inline typename _Container::size_type
+__libcpp_erase_if_container(_Container& __c, _Predicate __pred) {
+  typename _Container::size_type __old_size = __c.size();
+
+  const typename _Container::iterator __last = __c.end();
+  for (typename _Container::iterator __iter = __c.begin(); __iter != __last;) {
+    if (__pred(*__iter))
+      __iter = __c.erase(__iter);
+    else
+      ++__iter;
+  }
+
+  return __old_size - __c.size();
 }
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/include/list b/include/list
index ae318ea..55b45f1 100644
--- a/include/list
+++ b/include/list
@@ -170,9 +170,11 @@
          noexcept(noexcept(x.swap(y)));
 
 template <class T, class Allocator, class U>
-    void erase(list<T, Allocator>& c, const U& value);       // C++20
+    typename list<T, Allocator>::size_type
+    erase(list<T, Allocator>& c, const U& value);       // C++20
 template <class T, class Allocator, class Predicate>
-    void erase_if(list<T, Allocator>& c, Predicate pred);    // C++20
+    typename list<T, Allocator>::size_type
+    erase_if(list<T, Allocator>& c, Predicate pred);    // C++20
 
 }  // std
 
@@ -2471,14 +2473,16 @@
 
 #if _LIBCPP_STD_VER > 17
 template <class _Tp, class _Allocator, class _Predicate>
-inline _LIBCPP_INLINE_VISIBILITY
-void erase_if(list<_Tp, _Allocator>& __c, _Predicate __pred)
-{ __c.remove_if(__pred); }
+inline _LIBCPP_INLINE_VISIBILITY typename list<_Tp, _Allocator>::size_type
+erase_if(list<_Tp, _Allocator>& __c, _Predicate __pred) {
+  return __c.remove_if(__pred);
+}
 
 template <class _Tp, class _Allocator, class _Up>
-inline _LIBCPP_INLINE_VISIBILITY
-void erase(list<_Tp, _Allocator>& __c, const _Up& __v)
-{ _VSTD::erase_if(__c, [&](auto& __elem) { return __elem == __v; }); }
+inline _LIBCPP_INLINE_VISIBILITY typename list<_Tp, _Allocator>::size_type
+erase(list<_Tp, _Allocator>& __c, const _Up& __v) {
+  return _VSTD::erase_if(__c, [&](auto& __elem) { return __elem == __v; });
+}
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/include/map b/include/map
index b6f89bf..d2b8259 100644
--- a/include/map
+++ b/include/map
@@ -254,7 +254,8 @@
     noexcept(noexcept(x.swap(y)));
 
 template <class Key, class T, class Compare, class Allocator, class Predicate>
-  void erase_if(map<Key, T, Compare, Allocator>& c, Predicate pred);  // C++20
+typename map<Key, T, Compare, Allocator>::size_type
+erase_if(map<Key, T, Compare, Allocator>& c, Predicate pred);  // C++20
 
 
 template <class Key, class T, class Compare = less<Key>,
@@ -469,7 +470,8 @@
     noexcept(noexcept(x.swap(y)));
 
 template <class Key, class T, class Compare, class Allocator, class Predicate>
-  void erase_if(multimap<Key, T, Compare, Allocator>& c, Predicate pred);  // C++20
+typename multimap<Key, T, Compare, Allocator>::size_type
+erase_if(multimap<Key, T, Compare, Allocator>& c, Predicate pred);  // C++20
 
 }  // std
 
@@ -1653,10 +1655,13 @@
 }
 
 #if _LIBCPP_STD_VER > 17
-template <class _Key, class _Tp, class _Compare, class _Allocator, class _Predicate>
+template <class _Key, class _Tp, class _Compare, class _Allocator,
+          class _Predicate>
 inline _LIBCPP_INLINE_VISIBILITY
-void erase_if(map<_Key, _Tp, _Compare, _Allocator>& __c, _Predicate __pred)
-{ __libcpp_erase_if_container(__c, __pred); }
+    typename map<_Key, _Tp, _Compare, _Allocator>::size_type
+    erase_if(map<_Key, _Tp, _Compare, _Allocator>& __c, _Predicate __pred) {
+  return __libcpp_erase_if_container(__c, __pred);
+}
 #endif
 
 
@@ -2235,10 +2240,14 @@
 }
 
 #if _LIBCPP_STD_VER > 17
-template <class _Key, class _Tp, class _Compare, class _Allocator, class _Predicate>
+template <class _Key, class _Tp, class _Compare, class _Allocator,
+          class _Predicate>
 inline _LIBCPP_INLINE_VISIBILITY
-void erase_if(multimap<_Key, _Tp, _Compare, _Allocator>& __c, _Predicate __pred)
-{ __libcpp_erase_if_container(__c, __pred); }
+    typename multimap<_Key, _Tp, _Compare, _Allocator>::size_type
+    erase_if(multimap<_Key, _Tp, _Compare, _Allocator>& __c,
+             _Predicate __pred) {
+  return __libcpp_erase_if_container(__c, __pred);
+}
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/include/set b/include/set
index ac3fbbe..d58455b 100644
--- a/include/set
+++ b/include/set
@@ -216,7 +216,8 @@
     noexcept(noexcept(x.swap(y)));
 
 template <class Key, class Compare, class Allocator, class Predicate>
-  void erase_if(set<Key, Compare, Allocator>& c, Predicate pred);  // C++20
+typename set<Key, Compare, Allocator>::size_type
+erase_if(set<Key, Compare, Allocator>& c, Predicate pred);  // C++20
 
 template <class Key, class Compare = less<Key>,
           class Allocator = allocator<Key>>
@@ -417,7 +418,8 @@
     noexcept(noexcept(x.swap(y)));
 
 template <class Key, class Compare, class Allocator, class Predicate>
-  void erase_if(multiset<Key, Compare, Allocator>& c, Predicate pred);  // C++20
+typename multiset<Key, Compare, Allocator>::size_type
+erase_if(multiset<Key, Compare, Allocator>& c, Predicate pred);  // C++20
 
 }  // std
 
@@ -960,8 +962,10 @@
 #if _LIBCPP_STD_VER > 17
 template <class _Key, class _Compare, class _Allocator, class _Predicate>
 inline _LIBCPP_INLINE_VISIBILITY
-void erase_if(set<_Key, _Compare, _Allocator>& __c, _Predicate __pred)
-{ __libcpp_erase_if_container(__c, __pred); }
+    typename set<_Key, _Compare, _Allocator>::size_type
+    erase_if(set<_Key, _Compare, _Allocator>& __c, _Predicate __pred) {
+  return __libcpp_erase_if_container(__c, __pred);
+}
 #endif
 
 template <class _Key, class _Compare = less<_Key>,
@@ -1484,8 +1488,10 @@
 #if _LIBCPP_STD_VER > 17
 template <class _Key, class _Compare, class _Allocator, class _Predicate>
 inline _LIBCPP_INLINE_VISIBILITY
-void erase_if(multiset<_Key, _Compare, _Allocator>& __c, _Predicate __pred)
-{ __libcpp_erase_if_container(__c, __pred); }
+    typename multiset<_Key, _Compare, _Allocator>::size_type
+    erase_if(multiset<_Key, _Compare, _Allocator>& __c, _Predicate __pred) {
+  return __libcpp_erase_if_container(__c, __pred);
+}
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/include/string b/include/string
index 6938ee4..179080d 100644
--- a/include/string
+++ b/include/string
@@ -437,9 +437,11 @@
 getline(basic_istream<charT, traits>& is, basic_string<charT, traits, Allocator>& str);
 
 template<class charT, class traits, class Allocator, class U>
-void erase(basic_string<charT, traits, Allocator>& c, const U& value); // C++20
+typename basic_string<charT, traits, Allocator>::size_type
+erase(basic_string<charT, traits, Allocator>& c, const U& value);    // C++20
 template<class charT, class traits, class Allocator, class Predicate>
-void erase_if(basic_string<charT, traits, Allocator>& c, Predicate pred); // C++20
+typename basic_string<charT, traits, Allocator>::size_type
+erase_if(basic_string<charT, traits, Allocator>& c, Predicate pred); // C++20
 
 typedef basic_string<char>    string;
 typedef basic_string<wchar_t> wstring;
@@ -4379,15 +4381,25 @@
 #endif  // _LIBCPP_CXX03_LANG
 
 #if _LIBCPP_STD_VER > 17
-template<class _CharT, class _Traits, class _Allocator, class _Up>
+template <class _CharT, class _Traits, class _Allocator, class _Up>
 inline _LIBCPP_INLINE_VISIBILITY
-void erase(basic_string<_CharT, _Traits, _Allocator>& __str, const _Up& __v)
-{ __str.erase(_VSTD::remove(__str.begin(), __str.end(), __v), __str.end()); }
+    typename basic_string<_CharT, _Traits, _Allocator>::size_type
+    erase(basic_string<_CharT, _Traits, _Allocator>& __str, const _Up& __v) {
+  auto __old_size = __str.size();
+  __str.erase(_VSTD::remove(__str.begin(), __str.end(), __v), __str.end());
+  return __old_size - __str.size();
+}
 
-template<class _CharT, class _Traits, class _Allocator, class _Predicate>
+template <class _CharT, class _Traits, class _Allocator, class _Predicate>
 inline _LIBCPP_INLINE_VISIBILITY
-void erase_if(basic_string<_CharT, _Traits, _Allocator>& __str, _Predicate __pred)
-{ __str.erase(_VSTD::remove_if(__str.begin(), __str.end(), __pred), __str.end()); }
+    typename basic_string<_CharT, _Traits, _Allocator>::size_type
+    erase_if(basic_string<_CharT, _Traits, _Allocator>& __str,
+             _Predicate __pred) {
+  auto __old_size = __str.size();
+  __str.erase(_VSTD::remove_if(__str.begin(), __str.end(), __pred),
+              __str.end());
+  return __old_size - __str.size();
+}
 #endif
 
 #if _LIBCPP_DEBUG_LEVEL >= 2
diff --git a/include/unordered_map b/include/unordered_map
index ad17f77..6156cfd 100644
--- a/include/unordered_map
+++ b/include/unordered_map
@@ -386,10 +386,12 @@
               noexcept(noexcept(x.swap(y)));
 
 template <class K, class T, class H, class P, class A, class Predicate>
-    void erase_if(unordered_set<K, T, H, P, A>& c, Predicate pred);       // C++20
+    typename unordered_map<K, T, H, P, A>::size_type
+    erase_if(unordered_map<K, T, H, P, A>& c, Predicate pred);       // C++20
 
 template <class K, class T, class H, class P, class A, class Predicate>
-    void erase_if(unordered_multiset<K, T, H, P, A>& c, Predicate pred);  // C++20
+    typename unordered_multimap<K, T, H, P, A>::size_type
+    erase_if(unordered_multimap<K, T, H, P, A>& c, Predicate pred);  // C++20
 
 template <class Key, class T, class Hash, class Pred, class Alloc>
     bool
@@ -1704,10 +1706,14 @@
 }
 
 #if _LIBCPP_STD_VER > 17
-template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc, class _Predicate>
+template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc,
+          class _Predicate>
 inline _LIBCPP_INLINE_VISIBILITY
-void erase_if(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __c, _Predicate __pred)
-{ __libcpp_erase_if_container(__c, __pred); }
+    typename unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::size_type
+    erase_if(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __c,
+             _Predicate __pred) {
+  return __libcpp_erase_if_container(__c, __pred);
+}
 #endif
 
 template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
@@ -2402,10 +2408,14 @@
 }
 
 #if _LIBCPP_STD_VER > 17
-template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc, class _Predicate>
+template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc,
+          class _Predicate>
 inline _LIBCPP_INLINE_VISIBILITY
-void erase_if(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __c, _Predicate __pred)
-{ __libcpp_erase_if_container(__c, __pred); }
+    typename unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>::size_type
+    erase_if(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __c,
+             _Predicate __pred) {
+  return __libcpp_erase_if_container(__c, __pred);
+}
 #endif
 
 template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
diff --git a/include/unordered_set b/include/unordered_set
index 68f777a..6c4ad93 100644
--- a/include/unordered_set
+++ b/include/unordered_set
@@ -341,10 +341,12 @@
               noexcept(noexcept(x.swap(y)));
 
 template <class K, class T, class H, class P, class A, class Predicate>
-    void erase_if(unordered_set<K, T, H, P, A>& c, Predicate pred);       // C++20
+    typename unordered_set<K, T, H, P, A>::size_type
+    erase_if(unordered_set<K, T, H, P, A>& c, Predicate pred);       // C++20
 
 template <class K, class T, class H, class P, class A, class Predicate>
-    void erase_if(unordered_multiset<K, T, H, P, A>& c, Predicate pred);  // C++20
+    typename unordered_multiset<K, T, H, P, A>::size_type
+    erase_if(unordered_multiset<K, T, H, P, A>& c, Predicate pred);  // C++20
 
 
 template <class Value, class Hash, class Pred, class Alloc>
@@ -1006,10 +1008,14 @@
 }
 
 #if _LIBCPP_STD_VER > 17
-template <class _Value, class _Hash, class _Pred, class _Alloc, class _Predicate>
+template <class _Value, class _Hash, class _Pred, class _Alloc,
+          class _Predicate>
 inline _LIBCPP_INLINE_VISIBILITY
-void erase_if(unordered_set<_Value, _Hash, _Pred, _Alloc>& __c, _Predicate __pred)
-{ __libcpp_erase_if_container(__c, __pred); }
+    typename unordered_set<_Value, _Hash, _Pred, _Alloc>::size_type
+    erase_if(unordered_set<_Value, _Hash, _Pred, _Alloc>& __c,
+             _Predicate __pred) {
+  return __libcpp_erase_if_container(__c, __pred);
+}
 #endif
 
 template <class _Value, class _Hash, class _Pred, class _Alloc>
@@ -1637,10 +1643,14 @@
 }
 
 #if _LIBCPP_STD_VER > 17
-template <class _Value, class _Hash, class _Pred, class _Alloc, class _Predicate>
+template <class _Value, class _Hash, class _Pred, class _Alloc,
+          class _Predicate>
 inline _LIBCPP_INLINE_VISIBILITY
-void erase_if(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __c, _Predicate __pred)
-{ __libcpp_erase_if_container(__c, __pred); }
+    typename unordered_multiset<_Value, _Hash, _Pred, _Alloc>::size_type
+    erase_if(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __c,
+             _Predicate __pred) {
+  return __libcpp_erase_if_container(__c, __pred);
+}
 #endif
 
 template <class _Value, class _Hash, class _Pred, class _Alloc>
diff --git a/include/vector b/include/vector
index af96bff..7d0fec8 100644
--- a/include/vector
+++ b/include/vector
@@ -261,9 +261,11 @@
     noexcept(noexcept(x.swap(y)));
 
 template <class T, class Allocator, class U>
-    void erase(vector<T, Allocator>& c, const U& value);       // C++20
+typename vector<T, Allocator>::size_type
+erase(vector<T, Allocator>& c, const U& value);       // C++20
 template <class T, class Allocator, class Predicate>
-    void erase_if(vector<T, Allocator>& c, Predicate pred);    // C++20
+typename vector<T, Allocator>::size_type
+erase_if(vector<T, Allocator>& c, Predicate pred);    // C++20
 
 }  // std
 
@@ -3389,14 +3391,20 @@
 
 #if _LIBCPP_STD_VER > 17
 template <class _Tp, class _Allocator, class _Up>
-inline _LIBCPP_INLINE_VISIBILITY
-void erase(vector<_Tp, _Allocator>& __c, const _Up& __v)
-{ __c.erase(_VSTD::remove(__c.begin(), __c.end(), __v), __c.end()); }
+inline _LIBCPP_INLINE_VISIBILITY typename vector<_Tp, _Allocator>::size_type
+erase(vector<_Tp, _Allocator>& __c, const _Up& __v) {
+  auto __old_size = __c.size();
+  __c.erase(_VSTD::remove(__c.begin(), __c.end(), __v), __c.end());
+  return __old_size - __c.size();
+}
 
 template <class _Tp, class _Allocator, class _Predicate>
-inline _LIBCPP_INLINE_VISIBILITY
-void erase_if(vector<_Tp, _Allocator>& __c, _Predicate __pred)
-{ __c.erase(_VSTD::remove_if(__c.begin(), __c.end(), __pred), __c.end()); }
+inline _LIBCPP_INLINE_VISIBILITY typename vector<_Tp, _Allocator>::size_type
+erase_if(vector<_Tp, _Allocator>& __c, _Predicate __pred) {
+  auto __old_size = __c.size();
+  __c.erase(_VSTD::remove_if(__c.begin(), __c.end(), __pred), __c.end());
+  return __old_size - __c.size();
+}
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/include/version b/include/version
index ab62a85..c2e99cc 100644
--- a/include/version
+++ b/include/version
@@ -44,7 +44,7 @@
 __cpp_lib_destroying_delete                             201806L <new>
 __cpp_lib_enable_shared_from_this                       201603L <memory>
 __cpp_lib_endian                                        201907L <bit>
-__cpp_lib_erase_if                                      201811L <string> <deque> <forward_list>
+__cpp_lib_erase_if                                      202002L <string> <deque> <forward_list>
                                                                 <list> <vector> <map>
                                                                 <set> <unordered_map> <unordered_set>
 __cpp_lib_exchange_function                             201304L <utility>
@@ -226,7 +226,7 @@
 #   define __cpp_lib_destroying_delete                  201806L
 # endif
 # define __cpp_lib_endian                               201907L
-# define __cpp_lib_erase_if                             201811L
+# define __cpp_lib_erase_if                             202002L
 // # define __cpp_lib_generic_unordered_lookup             201811L
 # define __cpp_lib_interpolate                          201902L
 # if !defined(_LIBCPP_HAS_NO_BUILTIN_IS_CONSTANT_EVALUATED)