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

Unified Diff: base/containers/flat_tree.h

Issue 2944523002: Improving flat containers interface. (Closed)
Patch Set: Other platforms compilation 2. Created 3 years, 5 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
« no previous file with comments | « base/containers/flat_set_unittest.cc ('k') | base/containers/flat_tree_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/containers/flat_tree.h
diff --git a/base/containers/flat_tree.h b/base/containers/flat_tree.h
index 8bbd3007739aff77bc184f1aa9c97294dbd1039c..37c5de9584846204737ec440c4bcdb6291afadfb 100644
--- a/base/containers/flat_tree.h
+++ b/base/containers/flat_tree.h
@@ -7,8 +7,11 @@
#include <algorithm>
#include <iterator>
+#include <type_traits>
#include <vector>
+#include "base/template_util.h"
+
namespace base {
enum FlatContainerDupes {
@@ -55,6 +58,15 @@ Iterator LastUnique(Iterator first, Iterator last, BinaryPredicate compare) {
return replacable;
}
+// Uses SFINAE to detect whether type has is_transparent member.
+template <typename T, typename = void>
+struct IsTransparentCompare : std::false_type {};
+template <typename T>
+struct IsTransparentCompare<T, void_t<typename T::is_transparent>>
+ : std::true_type {};
+
+// Implementation -------------------------------------------------------------
+
// Implementation of a sorted vector for backing flat_set and flat_map. Do not
// use directly.
//
@@ -234,9 +246,11 @@ class flat_tree {
// Prefer base::EraseIf() or some other variation on erase(remove(), end())
// idiom when deleting multiple non-consecutive elements.
+ iterator erase(iterator position);
iterator erase(const_iterator position);
iterator erase(const_iterator first, const_iterator last);
- size_type erase(const key_type& key);
+ template <typename K>
+ size_type erase(const K& key);
// --------------------------------------------------------------------------
// Comparators.
@@ -249,20 +263,32 @@ class flat_tree {
//
// Search operations have O(log(size)) complexity.
- size_type count(const key_type& key) const;
+ template <typename K>
+ size_type count(const K& key) const;
+
+ template <typename K>
+ iterator find(const K& key);
+
+ template <typename K>
+ const_iterator find(const K& key) const;
+
+ template <typename K>
+ std::pair<iterator, iterator> equal_range(const K& key);
+
+ template <typename K>
+ std::pair<const_iterator, const_iterator> equal_range(const K& key) const;
- iterator find(const key_type& key);
- const_iterator find(const key_type& key) const;
+ template <typename K>
+ iterator lower_bound(const K& key);
- std::pair<iterator, iterator> equal_range(const key_type& ket);
- std::pair<const_iterator, const_iterator> equal_range(
- const key_type& key) const;
+ template <typename K>
+ const_iterator lower_bound(const K& key) const;
- iterator lower_bound(const key_type& key);
- const_iterator lower_bound(const key_type& key) const;
+ template <typename K>
+ iterator upper_bound(const K& key);
- iterator upper_bound(const key_type& key);
- const_iterator upper_bound(const key_type& key) const;
+ template <typename K>
+ const_iterator upper_bound(const K& key) const;
// --------------------------------------------------------------------------
// General operations.
@@ -317,12 +343,22 @@ class flat_tree {
explicit KeyValueCompare(const key_compare& key_comp)
: key_comp_(key_comp) {}
- bool operator()(const value_type& left, const key_type& right) const {
- GetKeyFromValue extractor;
- return key_comp_(extractor(left), right);
+ template <typename T, typename U>
+ bool operator()(const T& lhs, const U& rhs) const {
+ return key_comp_(extract_if_value_type(lhs), extract_if_value_type(rhs));
}
private:
+ const key_type& extract_if_value_type(const value_type& v) const {
+ GetKeyFromValue extractor;
+ return extractor(v);
+ }
+
+ template <typename K>
+ const K& extract_if_value_type(const K& k) const {
+ return k;
+ }
+
const key_compare& key_comp_;
};
@@ -436,6 +472,11 @@ class flat_tree {
underlying_type body_;
} impl_;
+
+ // If the compare is not transparent we want to construct key_type once.
+ template <typename K>
+ using KeyTypeOrK = typename std::
+ conditional<IsTransparentCompare<key_compare>::value, K, key_type>::type;
};
// ----------------------------------------------------------------------------
@@ -767,14 +808,21 @@ auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::emplace_hint(
template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::erase(
+ iterator position) -> iterator {
+ return impl_.body_.erase(position);
+}
+
+template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
+auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::erase(
const_iterator position) -> iterator {
// We have to cast away const because of crbug.com/677044.
- return impl_.body_.erase(const_cast_it(position));
+ return erase(const_cast_it(position));
}
template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
-auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::erase(
- const key_type& val) -> size_type {
+template <typename K>
+auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::erase(const K& val)
+ -> size_type {
auto eq_range = equal_range(val);
auto res = std::distance(eq_range.first, eq_range.second);
// We have to cast away const because of crbug.com/677044.
@@ -809,35 +857,40 @@ auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::value_comp() const
// Search operations.
template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
+template <typename K>
auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::count(
- const key_type& key) const -> size_type {
+ const K& key) const -> size_type {
auto eq_range = equal_range(key);
return std::distance(eq_range.first, eq_range.second);
}
template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
-auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::find(
- const key_type& key) -> iterator {
+template <typename K>
+auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::find(const K& key)
+ -> iterator {
return const_cast_it(as_const().find(key));
}
template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
+template <typename K>
auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::find(
- const key_type& key) const -> const_iterator {
+ const K& key) const -> const_iterator {
auto eq_range = equal_range(key);
return (eq_range.first == eq_range.second) ? end() : eq_range.first;
}
template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
+template <typename K>
auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::equal_range(
- const key_type& key) -> std::pair<iterator, iterator> {
+ const K& key) -> std::pair<iterator, iterator> {
auto res = as_const().equal_range(key);
return {const_cast_it(res.first), const_cast_it(res.second)};
}
template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
+template <typename K>
auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::equal_range(
- const key_type& key) const -> std::pair<const_iterator, const_iterator> {
+ const K& key) const -> std::pair<const_iterator, const_iterator> {
auto lower = lower_bound(key);
GetKeyFromValue extractor;
@@ -848,29 +901,45 @@ auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::equal_range(
}
template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
+template <typename K>
auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::lower_bound(
- const key_type& key) -> iterator {
+ const K& key) -> iterator {
return const_cast_it(as_const().lower_bound(key));
}
template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
+template <typename K>
auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::lower_bound(
- const key_type& key) const -> const_iterator {
+ const K& key) const -> const_iterator {
+ static_assert(std::is_convertible<const KeyTypeOrK<K>&, const K&>::value,
+ "Requested type cannot be bound to the container's key_type "
+ "which is required for a non-transparent compare.");
+
+ const KeyTypeOrK<K>& key_ref = key;
+
KeyValueCompare key_value(impl_.get_key_comp());
- return std::lower_bound(begin(), end(), key, key_value);
+ return std::lower_bound(begin(), end(), key_ref, key_value);
}
template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
+template <typename K>
auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::upper_bound(
- const key_type& key) -> iterator {
+ const K& key) -> iterator {
return const_cast_it(as_const().upper_bound(key));
}
template <class Key, class Value, class GetKeyFromValue, class KeyCompare>
+template <typename K>
auto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::upper_bound(
- const key_type& key) const -> const_iterator {
+ const K& key) const -> const_iterator {
+ static_assert(std::is_convertible<const KeyTypeOrK<K>&, const K&>::value,
+ "Requested type cannot be bound to the container's key_type "
+ "which is required for a non-transparent compare.");
+
+ const KeyTypeOrK<K>& key_ref = key;
+
KeyValueCompare key_value(impl_.get_key_comp());
- return std::upper_bound(begin(), end(), key, key_value);
+ return std::upper_bound(begin(), end(), key_ref, key_value);
}
// ----------------------------------------------------------------------------
« no previous file with comments | « base/containers/flat_set_unittest.cc ('k') | base/containers/flat_tree_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698