Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2365)

Unified Diff: base/stl_util.h

Issue 2723853002: Implementing erase/erase_if functions from library fundamentals ts: (Closed)
Patch Set: Review, round 1. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: base/stl_util.h
diff --git a/base/stl_util.h b/base/stl_util.h
index 016bb156450692415d9814f6a011446cf68ca591..0edbec4f53875267833052edde98022cd5547213 100644
--- a/base/stl_util.h
+++ b/base/stl_util.h
@@ -8,9 +8,16 @@
#define BASE_STL_UTIL_H_
#include <algorithm>
+#include <deque>
+#include <forward_list>
#include <functional>
#include <iterator>
+#include <list>
+#include <map>
+#include <set>
#include <string>
+#include <unordered_map>
+#include <unordered_set>
#include <vector>
#include "base/logging.h"
@@ -126,6 +133,163 @@ bool STLIncludes(const Arg1& a1, const Arg2& a2) {
a2.begin(), a2.end());
}
+// STLErase/STLEraseIf are based on library fundamentals ts v2 erase/erase_if
+// http://en.cppreference.com/w/cpp/experimental/lib_extensions_2
+// They provide a generic way to erase elements from a container.
+// The functions here implement these for the standard containers until those
+// functions are available in the C++ standard.
+// For Chromium containers overloads should be defined in their own headers
+// (like standard containers).
+
+// Not container specific erasure functions -----------------------------------
+// Most of container specific functions are implemented in terms of
+// STLEraseRemove, STLEraseRemoveIf, STLEraseByOneIf, STLEraseMember,
+// STLEraseMemberIf - you can use them directly if the necessary
+// overload is not available or if you need non-default behavior, for example
+// erase(std::remove) for lists.
+
+// Uses erase(std::remove) idiom.
+template <typename Container, typename Value>
+void STLEraseRemove(Container& container, const Value& value) {
danakj 2017/03/03 20:11:49 These should be in the base::internal namespace, b
dyaroshev 2017/03/03 23:16:54 Done.
+ container.erase(
+ std::remove(std::begin(container), std::end(container), value),
+ std::end(container));
+}
+
+// Uses erase(std::remove) idiom.
+template <typename Container, typename Predicate>
+void STLEraseRemoveIf(Container& container, Predicate pred) {
+ container.erase(
+ std::remove_if(std::begin(container), std::end(container), pred),
+ std::end(container));
+}
+
+// Calls erase on iterators of matching elements.
+template <typename Container, typename Predicate>
+void STLEraseByOneIf(Container& container, Predicate pred) {
danakj 2017/03/03 20:11:49 This maybe justifies a helper method in the intern
dyaroshev 2017/03/03 23:16:54 Done.
+ for (auto it = std::begin(container); it != std::end(container);) {
+ if (pred(*it))
+ it = container.erase(it);
+ else
+ ++it;
+ }
+}
+
+// Calls container's remove_if method.
+template <typename Container, typename Predicate>
+void STLEraseMemberIf(Container& container, Predicate pred) {
+ container.remove_if(pred);
danakj 2017/03/03 20:11:49 can't see why the caller wouldn't just call contai
dyaroshev 2017/03/03 23:16:54 Done.
+}
+
+// Calls container's remove_if method.
+template <typename Container, typename Value>
+void STLEraseMember(Container& container, const Value& value) {
+ // Unlike std::*list::remove, this function template accepts heterogeneous
+ // types and does not force a conversion to the container's value type before
+ // invoking the == operator.
+ STLEraseMemberIf(container, [&](const typename Container::value_type& cur) {
+ return cur == value;
+ });
+}
+
+// STLErase/STLEraseIf overloaded for standard containers ----------------------
+// Note: there is no std::erase for standard associative containers so we don't
+// have it either.
+
+template <typename CharT, typename Traits, typename Allocator, typename Value>
+void STLErase(std::basic_string<CharT, Traits, Allocator>& container,
danakj 2017/03/03 20:11:49 I'm not sure where the whole STL prefix thing star
dyaroshev 2017/03/03 23:16:54 Done.
+ const Value& value) {
+ STLEraseRemove(container, value);
+}
+
+template <typename CharT, typename Traits, typename Allocator, class Predicate>
+void STLEraseIf(std::basic_string<CharT, Traits, Allocator>& container,
+ Predicate pred) {
+ STLEraseRemoveIf(container, pred);
+}
+
+template <class T, class Allocator, class Value>
+void STLErase(std::deque<T, Allocator>& container, const Value& value) {
+ STLEraseRemove(container, value);
+}
+
+template <class T, class Allocator, class Predicate>
+void STLEraseIf(std::deque<T, Allocator>& container, Predicate pred) {
+ STLEraseRemoveIf(container, pred);
+}
+
+template <class T, class Allocator, class Value>
+void STLErase(std::vector<T, Allocator>& container, const Value& value) {
+ STLEraseRemove(container, value);
+}
+
+template <class T, class Allocator, class Predicate>
+void STLEraseIf(std::vector<T, Allocator>& container, Predicate pred) {
+ STLEraseRemoveIf(container, pred);
+}
+
+template <class T, class Allocator, class Value>
+void STLErase(std::forward_list<T, Allocator>& container, const Value& value) {
+ STLEraseMember(container, value);
+}
+
+template <class T, class Allocator, class Predicate>
+void STLEraseIf(std::forward_list<T, Allocator>& container, Predicate pred) {
+ STLEraseMemberIf(container, pred);
+}
+
+template <class T, class Allocator, class Value>
+void STLErase(std::list<T, Allocator>& container, const Value& value) {
+ STLEraseMember(container, value);
+}
+
+template <class T, class Allocator, class Predicate>
+void STLEraseIf(std::list<T, Allocator>& container, Predicate pred) {
+ STLEraseMemberIf(container, pred);
+}
+
+template <class T, class Allocator, class Predicate>
+void STLEraseIf(std::map<T, Allocator>& container, Predicate pred) {
+ STLEraseByOneIf(container, pred);
+}
+
+template <class T, class Allocator, class Predicate>
+void STLEraseIf(std::multimap<T, Allocator>& container, Predicate pred) {
+ STLEraseByOneIf(container, pred);
+}
+
+template <class T, class Allocator, class Predicate>
+void STLEraseIf(std::set<T, Allocator>& container, Predicate pred) {
+ STLEraseByOneIf(container, pred);
+}
+
+template <class T, class Allocator, class Predicate>
+void STLEraseIf(std::multiset<T, Allocator>& container, Predicate pred) {
+ STLEraseByOneIf(container, pred);
+}
+
+template <class T, class Allocator, class Predicate>
+void STLEraseIf(std::unordered_map<T, Allocator>& container, Predicate pred) {
+ STLEraseByOneIf(container, pred);
+}
+
+template <class T, class Allocator, class Predicate>
+void STLEraseIf(std::unordered_multimap<T, Allocator>& container,
+ Predicate pred) {
+ STLEraseByOneIf(container, pred);
+}
+
+template <class T, class Allocator, class Predicate>
+void STLEraseIf(std::unordered_set<T, Allocator>& container, Predicate pred) {
+ STLEraseByOneIf(container, pred);
+}
+
+template <class T, class Allocator, class Predicate>
+void STLEraseIf(std::unordered_multiset<T, Allocator>& container,
+ Predicate pred) {
+ STLEraseByOneIf(container, pred);
+}
+
} // namespace base
#endif // BASE_STL_UTIL_H_

Powered by Google App Engine
This is Rietveld 408576698