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

Unified Diff: base/stl_util.h

Issue 2723853002: Implementing erase/erase_if functions from library fundamentals ts: (Closed)
Patch Set: Review, round 2. 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..77ef6c9c3082eb7b817213372c5a161cc6608f9f 100644
--- a/base/stl_util.h
+++ b/base/stl_util.h
@@ -8,15 +8,37 @@
#define BASE_STL_UTIL_H_
#include <algorithm>
+#include <deque>
danakj 2017/03/03 23:51:22 What is including all of these headers together so
dyaroshev 2017/03/04 00:32:49 Good point. I will do the measurements and come ba
dyaroshev 2017/03/05 10:49:59 Doesn't seem to affect build times. Checked on mac
+#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"
namespace base {
+namespace internal {
+
+// Calls erase on iterators of matching elements.
+template <typename Container, typename Predicate>
+void IterateAndEraseIf(Container& container, Predicate pred) {
+ for (auto it = std::begin(container); it != std::end(container);) {
danakj 2017/03/03 23:51:22 you could use container.begin()/end() here too rig
dyaroshev 2017/03/04 00:32:49 Done.
+ if (pred(*it))
+ it = container.erase(it);
+ else
+ ++it;
+ }
+}
+
+} // namespace internal
+
// Clears internal memory of an STL object.
// STL clear()/reserve(0) does not always free internal memory allocated
// This function uses swap/destructor to ensure the internal memory is freed.
@@ -126,6 +148,126 @@ bool STLIncludes(const Arg1& a1, const Arg2& a2) {
a2.begin(), a2.end());
}
+// Erase/EraseIf 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).
+// 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 Erase(std::basic_string<CharT, Traits, Allocator>& container,
+ const Value& value) {
+ container.erase(
+ std::remove(std::begin(container), std::end(container), value),
danakj 2017/03/03 23:51:22 same for these, you don't need std::begin/end righ
dyaroshev 2017/03/04 00:32:49 Done.
+ std::end(container));
+}
+
+template <typename CharT, typename Traits, typename Allocator, class Predicate>
+void EraseIf(std::basic_string<CharT, Traits, Allocator>& container,
+ Predicate pred) {
+ container.erase(
+ std::remove_if(std::begin(container), std::end(container), pred),
+ std::end(container));
+}
+
+template <class T, class Allocator, class Value>
+void Erase(std::deque<T, Allocator>& container, const Value& value) {
+ container.erase(
+ std::remove(std::begin(container), std::end(container), value),
+ std::end(container));
+}
+
+template <class T, class Allocator, class Predicate>
+void EraseIf(std::deque<T, Allocator>& container, Predicate pred) {
+ container.erase(
+ std::remove_if(std::begin(container), std::end(container), pred),
+ std::end(container));
+}
+
+template <class T, class Allocator, class Value>
+void Erase(std::vector<T, Allocator>& container, const Value& value) {
+ container.erase(
+ std::remove(std::begin(container), std::end(container), value),
+ std::end(container));
+}
+
+template <class T, class Allocator, class Predicate>
+void EraseIf(std::vector<T, Allocator>& container, Predicate pred) {
+ container.erase(
+ std::remove_if(std::begin(container), std::end(container), pred),
+ std::end(container));
+}
+
+template <class T, class Allocator, class Value>
+void Erase(std::forward_list<T, Allocator>& container, const Value& value) {
+ // Unlike std::forward_list::remove, this function template accepts
+ // heterogeneous types and does not force a conversion to the container's
+ // value type before invoking the == operator.
+ container.remove_if([&](const T& cur) { return cur == value; });
+}
+
+template <class T, class Allocator, class Predicate>
+void EraseIf(std::forward_list<T, Allocator>& container, Predicate pred) {
+ container.remove_if(pred);
+}
+
+template <class T, class Allocator, class Value>
+void Erase(std::list<T, Allocator>& 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.
+ container.remove_if([&](const T& cur) { return cur == value; });
+}
+
+template <class T, class Allocator, class Predicate>
+void EraseIf(std::list<T, Allocator>& container, Predicate pred) {
+ container.remove_if(pred);
+}
+
+template <class T, class Allocator, class Predicate>
+void EraseIf(std::map<T, Allocator>& container, Predicate pred) {
+ internal::IterateAndEraseIf(container, pred);
+}
+
+template <class T, class Allocator, class Predicate>
+void EraseIf(std::multimap<T, Allocator>& container, Predicate pred) {
+ internal::IterateAndEraseIf(container, pred);
+}
+
+template <class T, class Allocator, class Predicate>
+void EraseIf(std::set<T, Allocator>& container, Predicate pred) {
+ internal::IterateAndEraseIf(container, pred);
+}
+
+template <class T, class Allocator, class Predicate>
+void EraseIf(std::multiset<T, Allocator>& container, Predicate pred) {
+ internal::IterateAndEraseIf(container, pred);
+}
+
+template <class T, class Allocator, class Predicate>
+void EraseIf(std::unordered_map<T, Allocator>& container, Predicate pred) {
+ internal::IterateAndEraseIf(container, pred);
+}
+
+template <class T, class Allocator, class Predicate>
+void EraseIf(std::unordered_multimap<T, Allocator>& container, Predicate pred) {
+ internal::IterateAndEraseIf(container, pred);
+}
+
+template <class T, class Allocator, class Predicate>
+void EraseIf(std::unordered_set<T, Allocator>& container, Predicate pred) {
+ internal::IterateAndEraseIf(container, pred);
+}
+
+template <class T, class Allocator, class Predicate>
+void EraseIf(std::unordered_multiset<T, Allocator>& container, Predicate pred) {
+ internal::IterateAndEraseIf(container, pred);
+}
+
} // namespace base
#endif // BASE_STL_UTIL_H_

Powered by Google App Engine
This is Rietveld 408576698