Chromium Code Reviews| 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_ |