Chromium Code Reviews| Index: base/stl_util.h |
| diff --git a/base/stl_util.h b/base/stl_util.h |
| index 016bb156450692415d9814f6a011446cf68ca591..6831bc60e4da3ae11fe1e0cda1012c7bc4c27504 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,195 @@ 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. |
| +// Here we provide overloads for standard containers and general tools to |
| +// implement this functions for arbitrary containers. |
|
dyaroshev
2017/02/28 23:28:33
Three times the word provide.
Peter Kasting
2017/03/01 03:20:10
Nit: I would make this sentence "The functions her
dyaroshev
2017/03/01 20:05:37
Done.
|
| +// Chromium containers should provide overloads 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, |
|
Peter Kasting
2017/03/01 03:20:11
Nit: Space after comma
dyaroshev
2017/03/01 20:05:37
Done.
|
| +// STLEraseMemberIf - you can use them directly if the necessary |
| +// overload is not provided here or if you need not default behavior like |
|
Peter Kasting
2017/03/01 03:20:10
Nit: not default -> non-default
dyaroshev
2017/03/01 20:05:37
Done.
|
| +// erase(std::remove) for lists. |
| +// Note: because there is no std::erase for associative containers, we don't |
| +// provide STLEraseByOne either. |
|
Peter Kasting
2017/03/01 03:20:11
Nit: I think this note is unnecessary given the si
dyaroshev
2017/03/01 20:05:37
Done.
|
| + |
| +// erase(std::remove) idiom. |
| +template <typename Container, typename Value> |
| +// Requires Container is a ForwardContainer, |
| +// Requires ValueType<Container> is Movable. |
| +// ValueType<Container> is equality comparable with Value. |
|
dyaroshev
2017/02/28 23:28:33
@pkasting - I know you don't like describing conce
Peter Kasting
2017/03/01 03:20:11
With respect to the folks writing the C++ Core Gui
dyaroshev
2017/03/01 20:05:37
Done.
|
| +void STLEraseRemove(Container& container, const Value& value) { |
| + container.erase( |
| + std::remove(std::begin(container), std::end(container), value), |
| + std::end(container)); |
| +} |
| + |
| +// erase(std::remove) idiom. |
| +template <typename Container, typename Predicate> |
| +// Requires Container is a ForwardContainer, |
| +// ValueType<Container> is Movable |
| +// Predicate is an UnaryPredicate on ValueType<Container>. |
| +void STLEraseRemoveIf(Container& container, Predicate pred) { |
| + container.erase( |
| + std::remove_if(std::begin(container), std::end(container), pred), |
| + std::end(container)); |
| +} |
| + |
| +// erasing by one element. |
|
Peter Kasting
2017/03/01 03:20:10
Nit: Capitalize start of comment sentences (multip
dyaroshev
2017/03/01 20:05:37
Done.
|
| +template <typename Container, typename Predicate> |
| +// Requires Predicate is an UnaryPredicate on ValueType<Container>. |
| +void STLEraseByOneIf(Container& container, Predicate pred) { |
| + for (auto it = std::begin(container); it != std::end(container);) { |
| + if (pred(*it)) { |
|
Peter Kasting
2017/03/01 03:20:11
Nit: No {}
dyaroshev
2017/03/01 20:05:37
Done.
|
| + it = container.erase(it); |
| + } else { |
| + ++it; |
| + } |
| + } |
| +} |
| + |
| +// calls container's remove_if method. |
| +template <typename Container, typename Predicate> |
| +// Requires Container implements remove_if member function, |
| +// Predicate is an UnaryPredicate on ValueType<Container>. |
| +void STLEraseMemberIf(Container& container, Predicate pred) { |
| + container.remove_if(pred); |
| +} |
| + |
| +// calls container's remove_if method. |
| +template <typename Container, typename Value> |
| +// Requires Container implements remove_if member function, |
| +// ValueType<Container> is equality comparable with Value. |
| +void STLEraseMember(Container& container, const Value& value) { |
| + // Unlike std::*list::remove, this function template accepts heterogenous |
| + // 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. |
| + |
| +// http://en.cppreference.com/w/cpp/experimental/basic_string/erase |
|
Peter Kasting
2017/03/01 03:20:11
Nit: I might (not sure) remove all these comments
dyaroshev
2017/03/01 20:05:37
I removed the comments. I don't know about the bla
|
| +template <typename CharT, typename Traits, typename Allocator, typename Value> |
| +void STLErase(std::basic_string<CharT, Traits, Allocator>& container, |
| + const Value& value) { |
| + STLEraseRemove(container, value); |
| +} |
| + |
| +// http://en.cppreference.com/w/cpp/experimental/basic_string/erase_if |
| +template <typename CharT, typename Traits, typename Allocator, class Predicate> |
| +void STLEraseIf(std::basic_string<CharT, Traits, Allocator>& container, |
| + Predicate pred) { |
| + STLEraseRemoveIf(container, pred); |
| +} |
| + |
| +// http://en.cppreference.com/w/cpp/experimental/deque/erase |
| +template <class T, class Allocator, class Value> |
| +void STLErase(std::deque<T, Allocator>& container, const Value& value) { |
| + STLEraseRemove(container, value); |
| +} |
| + |
| +// http://en.cppreference.com/w/cpp/experimental/deque/erase_if |
| +template <class T, class Allocator, class Predicate> |
| +void STLEraseIf(std::deque<T, Allocator>& container, Predicate pred) { |
| + STLEraseRemoveIf(container, pred); |
| +} |
| + |
| +// http://en.cppreference.com/w/cpp/experimental/vector/erase |
| +template <class T, class Allocator, class Value> |
| +void STLErase(std::vector<T, Allocator>& container, const Value& value) { |
| + STLEraseRemove(container, value); |
| +} |
| + |
| +// http://en.cppreference.com/w/cpp/experimental/vector/erase_if |
| +template <class T, class Allocator, class Predicate> |
| +void STLEraseIf(std::vector<T, Allocator>& container, Predicate pred) { |
| + STLEraseRemoveIf(container, pred); |
| +} |
| + |
| +// http://en.cppreference.com/w/cpp/experimental/forward_list/erase |
| +template <class T, class Allocator, class Value> |
| +void STLErase(std::forward_list<T, Allocator>& container, const Value& value) { |
| + STLEraseMember(container, value); |
| +} |
| + |
| +// http://en.cppreference.com/w/cpp/experimental/forward_list/erase_if |
| +template <class T, class Allocator, class Predicate> |
| +void STLEraseIf(std::forward_list<T, Allocator>& container, Predicate pred) { |
| + STLEraseMemberIf(container, pred); |
| +} |
| + |
| +// http://en.cppreference.com/w/cpp/experimental/list/erase |
| +template <class T, class Allocator, class Value> |
| +void STLErase(std::list<T, Allocator>& container, const Value& value) { |
| + STLEraseMember(container, value); |
| +} |
| + |
| +// http://en.cppreference.com/w/cpp/experimental/list/erase_if |
| +template <class T, class Allocator, class Predicate> |
| +void STLEraseIf(std::list<T, Allocator>& container, Predicate pred) { |
| + STLEraseMemberIf(container, pred); |
| +} |
| + |
| +// http://en.cppreference.com/w/cpp/experimental/map/erase_if |
| +template <class T, class Allocator, class Predicate> |
| +void STLEraseIf(std::map<T, Allocator>& container, Predicate pred) { |
| + STLEraseByOneIf(container, pred); |
| +} |
| + |
| +// http://en.cppreference.com/w/cpp/experimental/multimap/erase_if |
| +template <class T, class Allocator, class Predicate> |
| +void STLEraseIf(std::multimap<T, Allocator>& container, Predicate pred) { |
| + STLEraseByOneIf(container, pred); |
| +} |
| + |
| +// http://en.cppreference.com/w/cpp/experimental/set/erase_if |
| +template <class T, class Allocator, class Predicate> |
| +void STLEraseIf(std::set<T, Allocator>& container, Predicate pred) { |
| + STLEraseByOneIf(container, pred); |
| +} |
| + |
| +// http://en.cppreference.com/w/cpp/experimental/multiset/erase_if |
| +template <class T, class Allocator, class Predicate> |
| +void STLEraseIf(std::multiset<T, Allocator>& container, Predicate pred) { |
| + STLEraseByOneIf(container, pred); |
| +} |
| + |
| +// http://en.cppreference.com/w/cpp/experimental/unordered_map/erase_if |
| +template <class T, class Allocator, class Predicate> |
| +void STLEraseIf(std::unordered_map<T, Allocator>& container, Predicate pred) { |
| + STLEraseByOneIf(container, pred); |
| +} |
| + |
| +// http://en.cppreference.com/w/cpp/experimental/unordered_multimap/erase_if |
| +template <class T, class Allocator, class Predicate> |
| +void STLEraseIf(std::unordered_multimap<T, Allocator>& container, |
| + Predicate pred) { |
| + STLEraseByOneIf(container, pred); |
| +} |
| + |
| +// http://en.cppreference.com/w/cpp/experimental/unordered_set/erase_if |
| +template <class T, class Allocator, class Predicate> |
| +void STLEraseIf(std::unordered_set<T, Allocator>& container, Predicate pred) { |
| + STLEraseByOneIf(container, pred); |
| +} |
| + |
| +// http://en.cppreference.com/w/cpp/experimental/unordered_multiset/erase_if |
| +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_ |