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