16d528ed9Sopenharmony_ci// Copyright 2017 The Chromium Authors. All rights reserved. 26d528ed9Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 36d528ed9Sopenharmony_ci// found in the LICENSE file. 46d528ed9Sopenharmony_ci 56d528ed9Sopenharmony_ci#ifndef BASE_CONTAINERS_FLAT_TREE_H_ 66d528ed9Sopenharmony_ci#define BASE_CONTAINERS_FLAT_TREE_H_ 76d528ed9Sopenharmony_ci 86d528ed9Sopenharmony_ci#include <algorithm> 96d528ed9Sopenharmony_ci#include <iterator> 106d528ed9Sopenharmony_ci#include <type_traits> 116d528ed9Sopenharmony_ci#include <vector> 126d528ed9Sopenharmony_ci 136d528ed9Sopenharmony_ci#include "base/template_util.h" 146d528ed9Sopenharmony_ci 156d528ed9Sopenharmony_cinamespace base { 166d528ed9Sopenharmony_ci 176d528ed9Sopenharmony_cienum FlatContainerDupes { 186d528ed9Sopenharmony_ci KEEP_FIRST_OF_DUPES, 196d528ed9Sopenharmony_ci KEEP_LAST_OF_DUPES, 206d528ed9Sopenharmony_ci}; 216d528ed9Sopenharmony_ci 226d528ed9Sopenharmony_cinamespace internal { 236d528ed9Sopenharmony_ci 246d528ed9Sopenharmony_ci// This is a convenience method returning true if Iterator is at least a 256d528ed9Sopenharmony_ci// ForwardIterator and thus supports multiple passes over a range. 266d528ed9Sopenharmony_citemplate <class Iterator> 276d528ed9Sopenharmony_ciconstexpr bool is_multipass() { 286d528ed9Sopenharmony_ci return std::is_base_of< 296d528ed9Sopenharmony_ci std::forward_iterator_tag, 306d528ed9Sopenharmony_ci typename std::iterator_traits<Iterator>::iterator_category>::value; 316d528ed9Sopenharmony_ci} 326d528ed9Sopenharmony_ci 336d528ed9Sopenharmony_ci// This algorithm is like unique() from the standard library except it 346d528ed9Sopenharmony_ci// selects only the last of consecutive values instead of the first. 356d528ed9Sopenharmony_citemplate <class Iterator, class BinaryPredicate> 366d528ed9Sopenharmony_ciIterator LastUnique(Iterator first, Iterator last, BinaryPredicate compare) { 376d528ed9Sopenharmony_ci Iterator replacable = std::adjacent_find(first, last, compare); 386d528ed9Sopenharmony_ci 396d528ed9Sopenharmony_ci // No duplicate elements found. 406d528ed9Sopenharmony_ci if (replacable == last) 416d528ed9Sopenharmony_ci return last; 426d528ed9Sopenharmony_ci 436d528ed9Sopenharmony_ci first = std::next(replacable); 446d528ed9Sopenharmony_ci 456d528ed9Sopenharmony_ci // Last element is a duplicate but all others are unique. 466d528ed9Sopenharmony_ci if (first == last) 476d528ed9Sopenharmony_ci return replacable; 486d528ed9Sopenharmony_ci 496d528ed9Sopenharmony_ci // This loop is based on std::adjacent_find but std::adjacent_find doesn't 506d528ed9Sopenharmony_ci // quite cut it. 516d528ed9Sopenharmony_ci for (Iterator next = std::next(first); next != last; ++next, ++first) { 526d528ed9Sopenharmony_ci if (!compare(*first, *next)) 536d528ed9Sopenharmony_ci *replacable++ = std::move(*first); 546d528ed9Sopenharmony_ci } 556d528ed9Sopenharmony_ci 566d528ed9Sopenharmony_ci // Last element should be copied unconditionally. 576d528ed9Sopenharmony_ci *replacable++ = std::move(*first); 586d528ed9Sopenharmony_ci return replacable; 596d528ed9Sopenharmony_ci} 606d528ed9Sopenharmony_ci 616d528ed9Sopenharmony_ci// Uses SFINAE to detect whether type has is_transparent member. 626d528ed9Sopenharmony_citemplate <typename T, typename = void> 636d528ed9Sopenharmony_cistruct IsTransparentCompare : std::false_type {}; 646d528ed9Sopenharmony_citemplate <typename T> 656d528ed9Sopenharmony_cistruct IsTransparentCompare<T, std::void_t<typename T::is_transparent>> 666d528ed9Sopenharmony_ci : std::true_type {}; 676d528ed9Sopenharmony_ci 686d528ed9Sopenharmony_ci// Implementation ------------------------------------------------------------- 696d528ed9Sopenharmony_ci 706d528ed9Sopenharmony_ci// Implementation of a sorted vector for backing flat_set and flat_map. Do not 716d528ed9Sopenharmony_ci// use directly. 726d528ed9Sopenharmony_ci// 736d528ed9Sopenharmony_ci// The use of "value" in this is like std::map uses, meaning it's the thing 746d528ed9Sopenharmony_ci// contained (in the case of map it's a <Kay, Mapped> pair). The Key is how 756d528ed9Sopenharmony_ci// things are looked up. In the case of a set, Key == Value. In the case of 766d528ed9Sopenharmony_ci// a map, the Key is a component of a Value. 776d528ed9Sopenharmony_ci// 786d528ed9Sopenharmony_ci// The helper class GetKeyFromValue provides the means to extract a key from a 796d528ed9Sopenharmony_ci// value for comparison purposes. It should implement: 806d528ed9Sopenharmony_ci// const Key& operator()(const Value&). 816d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 826d528ed9Sopenharmony_ciclass flat_tree { 836d528ed9Sopenharmony_ci private: 846d528ed9Sopenharmony_ci using underlying_type = std::vector<Value>; 856d528ed9Sopenharmony_ci 866d528ed9Sopenharmony_ci public: 876d528ed9Sopenharmony_ci // -------------------------------------------------------------------------- 886d528ed9Sopenharmony_ci // Types. 896d528ed9Sopenharmony_ci // 906d528ed9Sopenharmony_ci using key_type = Key; 916d528ed9Sopenharmony_ci using key_compare = KeyCompare; 926d528ed9Sopenharmony_ci using value_type = Value; 936d528ed9Sopenharmony_ci 946d528ed9Sopenharmony_ci // Wraps the templated key comparison to compare values. 956d528ed9Sopenharmony_ci class value_compare : public key_compare { 966d528ed9Sopenharmony_ci public: 976d528ed9Sopenharmony_ci value_compare() = default; 986d528ed9Sopenharmony_ci 996d528ed9Sopenharmony_ci template <class Cmp> 1006d528ed9Sopenharmony_ci explicit value_compare(Cmp&& compare_arg) 1016d528ed9Sopenharmony_ci : KeyCompare(std::forward<Cmp>(compare_arg)) {} 1026d528ed9Sopenharmony_ci 1036d528ed9Sopenharmony_ci bool operator()(const value_type& left, const value_type& right) const { 1046d528ed9Sopenharmony_ci GetKeyFromValue extractor; 1056d528ed9Sopenharmony_ci return key_compare::operator()(extractor(left), extractor(right)); 1066d528ed9Sopenharmony_ci } 1076d528ed9Sopenharmony_ci }; 1086d528ed9Sopenharmony_ci 1096d528ed9Sopenharmony_ci using pointer = typename underlying_type::pointer; 1106d528ed9Sopenharmony_ci using const_pointer = typename underlying_type::const_pointer; 1116d528ed9Sopenharmony_ci using reference = typename underlying_type::reference; 1126d528ed9Sopenharmony_ci using const_reference = typename underlying_type::const_reference; 1136d528ed9Sopenharmony_ci using size_type = typename underlying_type::size_type; 1146d528ed9Sopenharmony_ci using difference_type = typename underlying_type::difference_type; 1156d528ed9Sopenharmony_ci using iterator = typename underlying_type::iterator; 1166d528ed9Sopenharmony_ci using const_iterator = typename underlying_type::const_iterator; 1176d528ed9Sopenharmony_ci using reverse_iterator = typename underlying_type::reverse_iterator; 1186d528ed9Sopenharmony_ci using const_reverse_iterator = 1196d528ed9Sopenharmony_ci typename underlying_type::const_reverse_iterator; 1206d528ed9Sopenharmony_ci 1216d528ed9Sopenharmony_ci // -------------------------------------------------------------------------- 1226d528ed9Sopenharmony_ci // Lifetime. 1236d528ed9Sopenharmony_ci // 1246d528ed9Sopenharmony_ci // Constructors that take range guarantee O(N * log^2(N)) + O(N) complexity 1256d528ed9Sopenharmony_ci // and take O(N * log(N)) + O(N) if extra memory is available (N is a range 1266d528ed9Sopenharmony_ci // length). 1276d528ed9Sopenharmony_ci // 1286d528ed9Sopenharmony_ci // Assume that move constructors invalidate iterators and references. 1296d528ed9Sopenharmony_ci // 1306d528ed9Sopenharmony_ci // The constructors that take ranges, lists, and vectors do not require that 1316d528ed9Sopenharmony_ci // the input be sorted. 1326d528ed9Sopenharmony_ci 1336d528ed9Sopenharmony_ci flat_tree(); 1346d528ed9Sopenharmony_ci explicit flat_tree(const key_compare& comp); 1356d528ed9Sopenharmony_ci 1366d528ed9Sopenharmony_ci template <class InputIterator> 1376d528ed9Sopenharmony_ci flat_tree(InputIterator first, 1386d528ed9Sopenharmony_ci InputIterator last, 1396d528ed9Sopenharmony_ci FlatContainerDupes dupe_handling = KEEP_FIRST_OF_DUPES, 1406d528ed9Sopenharmony_ci const key_compare& comp = key_compare()); 1416d528ed9Sopenharmony_ci 1426d528ed9Sopenharmony_ci flat_tree(const flat_tree&); 1436d528ed9Sopenharmony_ci flat_tree(flat_tree&&) noexcept = default; 1446d528ed9Sopenharmony_ci 1456d528ed9Sopenharmony_ci flat_tree(std::vector<value_type> items, 1466d528ed9Sopenharmony_ci FlatContainerDupes dupe_handling = KEEP_FIRST_OF_DUPES, 1476d528ed9Sopenharmony_ci const key_compare& comp = key_compare()); 1486d528ed9Sopenharmony_ci 1496d528ed9Sopenharmony_ci flat_tree(std::initializer_list<value_type> ilist, 1506d528ed9Sopenharmony_ci FlatContainerDupes dupe_handling = KEEP_FIRST_OF_DUPES, 1516d528ed9Sopenharmony_ci const key_compare& comp = key_compare()); 1526d528ed9Sopenharmony_ci 1536d528ed9Sopenharmony_ci ~flat_tree(); 1546d528ed9Sopenharmony_ci 1556d528ed9Sopenharmony_ci // -------------------------------------------------------------------------- 1566d528ed9Sopenharmony_ci // Assignments. 1576d528ed9Sopenharmony_ci // 1586d528ed9Sopenharmony_ci // Assume that move assignment invalidates iterators and references. 1596d528ed9Sopenharmony_ci 1606d528ed9Sopenharmony_ci flat_tree& operator=(const flat_tree&); 1616d528ed9Sopenharmony_ci flat_tree& operator=(flat_tree&&); 1626d528ed9Sopenharmony_ci // Takes the first if there are duplicates in the initializer list. 1636d528ed9Sopenharmony_ci flat_tree& operator=(std::initializer_list<value_type> ilist); 1646d528ed9Sopenharmony_ci 1656d528ed9Sopenharmony_ci // -------------------------------------------------------------------------- 1666d528ed9Sopenharmony_ci // Memory management. 1676d528ed9Sopenharmony_ci // 1686d528ed9Sopenharmony_ci // Beware that shrink_to_fit() simply forwards the request to the 1696d528ed9Sopenharmony_ci // underlying_type and its implementation is free to optimize otherwise and 1706d528ed9Sopenharmony_ci // leave capacity() to be greater that its size. 1716d528ed9Sopenharmony_ci // 1726d528ed9Sopenharmony_ci // reserve() and shrink_to_fit() invalidate iterators and references. 1736d528ed9Sopenharmony_ci 1746d528ed9Sopenharmony_ci void reserve(size_type new_capacity); 1756d528ed9Sopenharmony_ci size_type capacity() const; 1766d528ed9Sopenharmony_ci void shrink_to_fit(); 1776d528ed9Sopenharmony_ci 1786d528ed9Sopenharmony_ci // -------------------------------------------------------------------------- 1796d528ed9Sopenharmony_ci // Size management. 1806d528ed9Sopenharmony_ci // 1816d528ed9Sopenharmony_ci // clear() leaves the capacity() of the flat_tree unchanged. 1826d528ed9Sopenharmony_ci 1836d528ed9Sopenharmony_ci void clear(); 1846d528ed9Sopenharmony_ci 1856d528ed9Sopenharmony_ci size_type size() const; 1866d528ed9Sopenharmony_ci size_type max_size() const; 1876d528ed9Sopenharmony_ci bool empty() const; 1886d528ed9Sopenharmony_ci 1896d528ed9Sopenharmony_ci // -------------------------------------------------------------------------- 1906d528ed9Sopenharmony_ci // Iterators. 1916d528ed9Sopenharmony_ci 1926d528ed9Sopenharmony_ci iterator begin(); 1936d528ed9Sopenharmony_ci const_iterator begin() const; 1946d528ed9Sopenharmony_ci const_iterator cbegin() const; 1956d528ed9Sopenharmony_ci 1966d528ed9Sopenharmony_ci iterator end(); 1976d528ed9Sopenharmony_ci const_iterator end() const; 1986d528ed9Sopenharmony_ci const_iterator cend() const; 1996d528ed9Sopenharmony_ci 2006d528ed9Sopenharmony_ci reverse_iterator rbegin(); 2016d528ed9Sopenharmony_ci const_reverse_iterator rbegin() const; 2026d528ed9Sopenharmony_ci const_reverse_iterator crbegin() const; 2036d528ed9Sopenharmony_ci 2046d528ed9Sopenharmony_ci reverse_iterator rend(); 2056d528ed9Sopenharmony_ci const_reverse_iterator rend() const; 2066d528ed9Sopenharmony_ci const_reverse_iterator crend() const; 2076d528ed9Sopenharmony_ci 2086d528ed9Sopenharmony_ci // -------------------------------------------------------------------------- 2096d528ed9Sopenharmony_ci // Insert operations. 2106d528ed9Sopenharmony_ci // 2116d528ed9Sopenharmony_ci // Assume that every operation invalidates iterators and references. 2126d528ed9Sopenharmony_ci // Insertion of one element can take O(size). Capacity of flat_tree grows in 2136d528ed9Sopenharmony_ci // an implementation-defined manner. 2146d528ed9Sopenharmony_ci // 2156d528ed9Sopenharmony_ci // NOTE: Prefer to build a new flat_tree from a std::vector (or similar) 2166d528ed9Sopenharmony_ci // instead of calling insert() repeatedly. 2176d528ed9Sopenharmony_ci 2186d528ed9Sopenharmony_ci std::pair<iterator, bool> insert(const value_type& val); 2196d528ed9Sopenharmony_ci std::pair<iterator, bool> insert(value_type&& val); 2206d528ed9Sopenharmony_ci 2216d528ed9Sopenharmony_ci iterator insert(const_iterator position_hint, const value_type& x); 2226d528ed9Sopenharmony_ci iterator insert(const_iterator position_hint, value_type&& x); 2236d528ed9Sopenharmony_ci 2246d528ed9Sopenharmony_ci // This method inserts the values from the range [first, last) into the 2256d528ed9Sopenharmony_ci // current tree. In case of KEEP_LAST_OF_DUPES newly added elements can 2266d528ed9Sopenharmony_ci // overwrite existing values. 2276d528ed9Sopenharmony_ci template <class InputIterator> 2286d528ed9Sopenharmony_ci void insert(InputIterator first, 2296d528ed9Sopenharmony_ci InputIterator last, 2306d528ed9Sopenharmony_ci FlatContainerDupes dupes = KEEP_FIRST_OF_DUPES); 2316d528ed9Sopenharmony_ci 2326d528ed9Sopenharmony_ci template <class... Args> 2336d528ed9Sopenharmony_ci std::pair<iterator, bool> emplace(Args&&... args); 2346d528ed9Sopenharmony_ci 2356d528ed9Sopenharmony_ci template <class... Args> 2366d528ed9Sopenharmony_ci iterator emplace_hint(const_iterator position_hint, Args&&... args); 2376d528ed9Sopenharmony_ci 2386d528ed9Sopenharmony_ci // -------------------------------------------------------------------------- 2396d528ed9Sopenharmony_ci // Erase operations. 2406d528ed9Sopenharmony_ci // 2416d528ed9Sopenharmony_ci // Assume that every operation invalidates iterators and references. 2426d528ed9Sopenharmony_ci // 2436d528ed9Sopenharmony_ci // erase(position), erase(first, last) can take O(size). 2446d528ed9Sopenharmony_ci // erase(key) may take O(size) + O(log(size)). 2456d528ed9Sopenharmony_ci // 2466d528ed9Sopenharmony_ci // Prefer base::EraseIf() or some other variation on erase(remove(), end()) 2476d528ed9Sopenharmony_ci // idiom when deleting multiple non-consecutive elements. 2486d528ed9Sopenharmony_ci 2496d528ed9Sopenharmony_ci iterator erase(iterator position); 2506d528ed9Sopenharmony_ci iterator erase(const_iterator position); 2516d528ed9Sopenharmony_ci iterator erase(const_iterator first, const_iterator last); 2526d528ed9Sopenharmony_ci template <typename K> 2536d528ed9Sopenharmony_ci size_type erase(const K& key); 2546d528ed9Sopenharmony_ci 2556d528ed9Sopenharmony_ci // -------------------------------------------------------------------------- 2566d528ed9Sopenharmony_ci // Comparators. 2576d528ed9Sopenharmony_ci 2586d528ed9Sopenharmony_ci key_compare key_comp() const; 2596d528ed9Sopenharmony_ci value_compare value_comp() const; 2606d528ed9Sopenharmony_ci 2616d528ed9Sopenharmony_ci // -------------------------------------------------------------------------- 2626d528ed9Sopenharmony_ci // Search operations. 2636d528ed9Sopenharmony_ci // 2646d528ed9Sopenharmony_ci // Search operations have O(log(size)) complexity. 2656d528ed9Sopenharmony_ci 2666d528ed9Sopenharmony_ci template <typename K> 2676d528ed9Sopenharmony_ci size_type count(const K& key) const; 2686d528ed9Sopenharmony_ci 2696d528ed9Sopenharmony_ci template <typename K> 2706d528ed9Sopenharmony_ci iterator find(const K& key); 2716d528ed9Sopenharmony_ci 2726d528ed9Sopenharmony_ci template <typename K> 2736d528ed9Sopenharmony_ci const_iterator find(const K& key) const; 2746d528ed9Sopenharmony_ci 2756d528ed9Sopenharmony_ci template <typename K> 2766d528ed9Sopenharmony_ci std::pair<iterator, iterator> equal_range(const K& key); 2776d528ed9Sopenharmony_ci 2786d528ed9Sopenharmony_ci template <typename K> 2796d528ed9Sopenharmony_ci std::pair<const_iterator, const_iterator> equal_range(const K& key) const; 2806d528ed9Sopenharmony_ci 2816d528ed9Sopenharmony_ci template <typename K> 2826d528ed9Sopenharmony_ci iterator lower_bound(const K& key); 2836d528ed9Sopenharmony_ci 2846d528ed9Sopenharmony_ci template <typename K> 2856d528ed9Sopenharmony_ci const_iterator lower_bound(const K& key) const; 2866d528ed9Sopenharmony_ci 2876d528ed9Sopenharmony_ci template <typename K> 2886d528ed9Sopenharmony_ci iterator upper_bound(const K& key); 2896d528ed9Sopenharmony_ci 2906d528ed9Sopenharmony_ci template <typename K> 2916d528ed9Sopenharmony_ci const_iterator upper_bound(const K& key) const; 2926d528ed9Sopenharmony_ci 2936d528ed9Sopenharmony_ci // -------------------------------------------------------------------------- 2946d528ed9Sopenharmony_ci // General operations. 2956d528ed9Sopenharmony_ci // 2966d528ed9Sopenharmony_ci // Assume that swap invalidates iterators and references. 2976d528ed9Sopenharmony_ci // 2986d528ed9Sopenharmony_ci // Implementation note: currently we use operator==() and operator<() on 2996d528ed9Sopenharmony_ci // std::vector, because they have the same contract we need, so we use them 3006d528ed9Sopenharmony_ci // directly for brevity and in case it is more optimal than calling equal() 3016d528ed9Sopenharmony_ci // and lexicograhpical_compare(). If the underlying container type is changed, 3026d528ed9Sopenharmony_ci // this code may need to be modified. 3036d528ed9Sopenharmony_ci 3046d528ed9Sopenharmony_ci void swap(flat_tree& other) noexcept; 3056d528ed9Sopenharmony_ci 3066d528ed9Sopenharmony_ci friend bool operator==(const flat_tree& lhs, const flat_tree& rhs) { 3076d528ed9Sopenharmony_ci return lhs.impl_.body_ == rhs.impl_.body_; 3086d528ed9Sopenharmony_ci } 3096d528ed9Sopenharmony_ci 3106d528ed9Sopenharmony_ci friend bool operator!=(const flat_tree& lhs, const flat_tree& rhs) { 3116d528ed9Sopenharmony_ci return !(lhs == rhs); 3126d528ed9Sopenharmony_ci } 3136d528ed9Sopenharmony_ci 3146d528ed9Sopenharmony_ci friend bool operator<(const flat_tree& lhs, const flat_tree& rhs) { 3156d528ed9Sopenharmony_ci return lhs.impl_.body_ < rhs.impl_.body_; 3166d528ed9Sopenharmony_ci } 3176d528ed9Sopenharmony_ci 3186d528ed9Sopenharmony_ci friend bool operator>(const flat_tree& lhs, const flat_tree& rhs) { 3196d528ed9Sopenharmony_ci return rhs < lhs; 3206d528ed9Sopenharmony_ci } 3216d528ed9Sopenharmony_ci 3226d528ed9Sopenharmony_ci friend bool operator>=(const flat_tree& lhs, const flat_tree& rhs) { 3236d528ed9Sopenharmony_ci return !(lhs < rhs); 3246d528ed9Sopenharmony_ci } 3256d528ed9Sopenharmony_ci 3266d528ed9Sopenharmony_ci friend bool operator<=(const flat_tree& lhs, const flat_tree& rhs) { 3276d528ed9Sopenharmony_ci return !(lhs > rhs); 3286d528ed9Sopenharmony_ci } 3296d528ed9Sopenharmony_ci 3306d528ed9Sopenharmony_ci friend void swap(flat_tree& lhs, flat_tree& rhs) noexcept { lhs.swap(rhs); } 3316d528ed9Sopenharmony_ci 3326d528ed9Sopenharmony_ci protected: 3336d528ed9Sopenharmony_ci // Emplaces a new item into the tree that is known not to be in it. This 3346d528ed9Sopenharmony_ci // is for implementing map operator[]. 3356d528ed9Sopenharmony_ci template <class... Args> 3366d528ed9Sopenharmony_ci iterator unsafe_emplace(const_iterator position, Args&&... args); 3376d528ed9Sopenharmony_ci 3386d528ed9Sopenharmony_ci // Attempts to emplace a new element with key |key|. Only if |key| is not yet 3396d528ed9Sopenharmony_ci // present, construct value_type from |args| and insert it. Returns an 3406d528ed9Sopenharmony_ci // iterator to the element with key |key| and a bool indicating whether an 3416d528ed9Sopenharmony_ci // insertion happened. 3426d528ed9Sopenharmony_ci template <class K, class... Args> 3436d528ed9Sopenharmony_ci std::pair<iterator, bool> emplace_key_args(const K& key, Args&&... args); 3446d528ed9Sopenharmony_ci 3456d528ed9Sopenharmony_ci // Similar to |emplace_key_args|, but checks |hint| first as a possible 3466d528ed9Sopenharmony_ci // insertion position. 3476d528ed9Sopenharmony_ci template <class K, class... Args> 3486d528ed9Sopenharmony_ci std::pair<iterator, bool> emplace_hint_key_args(const_iterator hint, 3496d528ed9Sopenharmony_ci const K& key, 3506d528ed9Sopenharmony_ci Args&&... args); 3516d528ed9Sopenharmony_ci 3526d528ed9Sopenharmony_ci private: 3536d528ed9Sopenharmony_ci // Helper class for e.g. lower_bound that can compare a value on the left 3546d528ed9Sopenharmony_ci // to a key on the right. 3556d528ed9Sopenharmony_ci struct KeyValueCompare { 3566d528ed9Sopenharmony_ci // The key comparison object must outlive this class. 3576d528ed9Sopenharmony_ci explicit KeyValueCompare(const key_compare& key_comp) 3586d528ed9Sopenharmony_ci : key_comp_(key_comp) {} 3596d528ed9Sopenharmony_ci 3606d528ed9Sopenharmony_ci template <typename T, typename U> 3616d528ed9Sopenharmony_ci bool operator()(const T& lhs, const U& rhs) const { 3626d528ed9Sopenharmony_ci return key_comp_(extract_if_value_type(lhs), extract_if_value_type(rhs)); 3636d528ed9Sopenharmony_ci } 3646d528ed9Sopenharmony_ci 3656d528ed9Sopenharmony_ci private: 3666d528ed9Sopenharmony_ci const key_type& extract_if_value_type(const value_type& v) const { 3676d528ed9Sopenharmony_ci GetKeyFromValue extractor; 3686d528ed9Sopenharmony_ci return extractor(v); 3696d528ed9Sopenharmony_ci } 3706d528ed9Sopenharmony_ci 3716d528ed9Sopenharmony_ci template <typename K> 3726d528ed9Sopenharmony_ci const K& extract_if_value_type(const K& k) const { 3736d528ed9Sopenharmony_ci return k; 3746d528ed9Sopenharmony_ci } 3756d528ed9Sopenharmony_ci 3766d528ed9Sopenharmony_ci const key_compare& key_comp_; 3776d528ed9Sopenharmony_ci }; 3786d528ed9Sopenharmony_ci 3796d528ed9Sopenharmony_ci const flat_tree& as_const() { return *this; } 3806d528ed9Sopenharmony_ci 3816d528ed9Sopenharmony_ci iterator const_cast_it(const_iterator c_it) { 3826d528ed9Sopenharmony_ci auto distance = std::distance(cbegin(), c_it); 3836d528ed9Sopenharmony_ci return std::next(begin(), distance); 3846d528ed9Sopenharmony_ci } 3856d528ed9Sopenharmony_ci 3866d528ed9Sopenharmony_ci // This method is inspired by both std::map::insert(P&&) and 3876d528ed9Sopenharmony_ci // std::map::insert_or_assign(const K&, V&&). It inserts val if an equivalent 3886d528ed9Sopenharmony_ci // element is not present yet, otherwise it overwrites. It returns an iterator 3896d528ed9Sopenharmony_ci // to the modified element and a flag indicating whether insertion or 3906d528ed9Sopenharmony_ci // assignment happened. 3916d528ed9Sopenharmony_ci template <class V> 3926d528ed9Sopenharmony_ci std::pair<iterator, bool> insert_or_assign(V&& val) { 3936d528ed9Sopenharmony_ci auto position = lower_bound(GetKeyFromValue()(val)); 3946d528ed9Sopenharmony_ci 3956d528ed9Sopenharmony_ci if (position == end() || value_comp()(val, *position)) 3966d528ed9Sopenharmony_ci return {impl_.body_.emplace(position, std::forward<V>(val)), true}; 3976d528ed9Sopenharmony_ci 3986d528ed9Sopenharmony_ci *position = std::forward<V>(val); 3996d528ed9Sopenharmony_ci return {position, false}; 4006d528ed9Sopenharmony_ci } 4016d528ed9Sopenharmony_ci 4026d528ed9Sopenharmony_ci // This method is similar to insert_or_assign, with the following differences: 4036d528ed9Sopenharmony_ci // - Instead of searching [begin(), end()) it only searches [first, last). 4046d528ed9Sopenharmony_ci // - In case no equivalent element is found, val is appended to the end of the 4056d528ed9Sopenharmony_ci // underlying body and an iterator to the next bigger element in [first, 4066d528ed9Sopenharmony_ci // last) is returned. 4076d528ed9Sopenharmony_ci template <class V> 4086d528ed9Sopenharmony_ci std::pair<iterator, bool> append_or_assign(iterator first, 4096d528ed9Sopenharmony_ci iterator last, 4106d528ed9Sopenharmony_ci V&& val) { 4116d528ed9Sopenharmony_ci auto position = std::lower_bound(first, last, val, value_comp()); 4126d528ed9Sopenharmony_ci 4136d528ed9Sopenharmony_ci if (position == last || value_comp()(val, *position)) { 4146d528ed9Sopenharmony_ci // emplace_back might invalidate position, which is why distance needs to 4156d528ed9Sopenharmony_ci // be cached. 4166d528ed9Sopenharmony_ci const difference_type distance = std::distance(begin(), position); 4176d528ed9Sopenharmony_ci impl_.body_.emplace_back(std::forward<V>(val)); 4186d528ed9Sopenharmony_ci return {std::next(begin(), distance), true}; 4196d528ed9Sopenharmony_ci } 4206d528ed9Sopenharmony_ci 4216d528ed9Sopenharmony_ci *position = std::forward<V>(val); 4226d528ed9Sopenharmony_ci return {position, false}; 4236d528ed9Sopenharmony_ci } 4246d528ed9Sopenharmony_ci 4256d528ed9Sopenharmony_ci // This method is similar to insert, with the following differences: 4266d528ed9Sopenharmony_ci // - Instead of searching [begin(), end()) it only searches [first, last). 4276d528ed9Sopenharmony_ci // - In case no equivalent element is found, val is appended to the end of the 4286d528ed9Sopenharmony_ci // underlying body and an iterator to the next bigger element in [first, 4296d528ed9Sopenharmony_ci // last) is returned. 4306d528ed9Sopenharmony_ci template <class V> 4316d528ed9Sopenharmony_ci std::pair<iterator, bool> append_unique(iterator first, 4326d528ed9Sopenharmony_ci iterator last, 4336d528ed9Sopenharmony_ci V&& val) { 4346d528ed9Sopenharmony_ci auto position = std::lower_bound(first, last, val, value_comp()); 4356d528ed9Sopenharmony_ci 4366d528ed9Sopenharmony_ci if (position == last || value_comp()(val, *position)) { 4376d528ed9Sopenharmony_ci // emplace_back might invalidate position, which is why distance needs to 4386d528ed9Sopenharmony_ci // be cached. 4396d528ed9Sopenharmony_ci const difference_type distance = std::distance(begin(), position); 4406d528ed9Sopenharmony_ci impl_.body_.emplace_back(std::forward<V>(val)); 4416d528ed9Sopenharmony_ci return {std::next(begin(), distance), true}; 4426d528ed9Sopenharmony_ci } 4436d528ed9Sopenharmony_ci 4446d528ed9Sopenharmony_ci return {position, false}; 4456d528ed9Sopenharmony_ci } 4466d528ed9Sopenharmony_ci 4476d528ed9Sopenharmony_ci void sort_and_unique(iterator first, 4486d528ed9Sopenharmony_ci iterator last, 4496d528ed9Sopenharmony_ci FlatContainerDupes dupes) { 4506d528ed9Sopenharmony_ci // Preserve stability for the unique code below. 4516d528ed9Sopenharmony_ci std::stable_sort(first, last, impl_.get_value_comp()); 4526d528ed9Sopenharmony_ci 4536d528ed9Sopenharmony_ci auto comparator = [this](const value_type& lhs, const value_type& rhs) { 4546d528ed9Sopenharmony_ci // lhs is already <= rhs due to sort, therefore 4556d528ed9Sopenharmony_ci // !(lhs < rhs) <=> lhs == rhs. 4566d528ed9Sopenharmony_ci return !impl_.get_value_comp()(lhs, rhs); 4576d528ed9Sopenharmony_ci }; 4586d528ed9Sopenharmony_ci 4596d528ed9Sopenharmony_ci iterator erase_after; 4606d528ed9Sopenharmony_ci switch (dupes) { 4616d528ed9Sopenharmony_ci case KEEP_FIRST_OF_DUPES: 4626d528ed9Sopenharmony_ci erase_after = std::unique(first, last, comparator); 4636d528ed9Sopenharmony_ci break; 4646d528ed9Sopenharmony_ci case KEEP_LAST_OF_DUPES: 4656d528ed9Sopenharmony_ci erase_after = LastUnique(first, last, comparator); 4666d528ed9Sopenharmony_ci break; 4676d528ed9Sopenharmony_ci } 4686d528ed9Sopenharmony_ci erase(erase_after, last); 4696d528ed9Sopenharmony_ci } 4706d528ed9Sopenharmony_ci 4716d528ed9Sopenharmony_ci // To support comparators that may not be possible to default-construct, we 4726d528ed9Sopenharmony_ci // have to store an instance of Compare. Using this to store all internal 4736d528ed9Sopenharmony_ci // state of flat_tree and using private inheritance to store compare lets us 4746d528ed9Sopenharmony_ci // take advantage of an empty base class optimization to avoid extra space in 4756d528ed9Sopenharmony_ci // the common case when Compare has no state. 4766d528ed9Sopenharmony_ci struct Impl : private value_compare { 4776d528ed9Sopenharmony_ci Impl() = default; 4786d528ed9Sopenharmony_ci 4796d528ed9Sopenharmony_ci template <class Cmp, class... Body> 4806d528ed9Sopenharmony_ci explicit Impl(Cmp&& compare_arg, Body&&... underlying_type_args) 4816d528ed9Sopenharmony_ci : value_compare(std::forward<Cmp>(compare_arg)), 4826d528ed9Sopenharmony_ci body_(std::forward<Body>(underlying_type_args)...) {} 4836d528ed9Sopenharmony_ci 4846d528ed9Sopenharmony_ci const value_compare& get_value_comp() const { return *this; } 4856d528ed9Sopenharmony_ci const key_compare& get_key_comp() const { return *this; } 4866d528ed9Sopenharmony_ci 4876d528ed9Sopenharmony_ci underlying_type body_; 4886d528ed9Sopenharmony_ci } impl_; 4896d528ed9Sopenharmony_ci 4906d528ed9Sopenharmony_ci // If the compare is not transparent we want to construct key_type once. 4916d528ed9Sopenharmony_ci template <typename K> 4926d528ed9Sopenharmony_ci using KeyTypeOrK = typename std:: 4936d528ed9Sopenharmony_ci conditional<IsTransparentCompare<key_compare>::value, K, key_type>::type; 4946d528ed9Sopenharmony_ci}; 4956d528ed9Sopenharmony_ci 4966d528ed9Sopenharmony_ci// ---------------------------------------------------------------------------- 4976d528ed9Sopenharmony_ci// Lifetime. 4986d528ed9Sopenharmony_ci 4996d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 5006d528ed9Sopenharmony_ciflat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree() = default; 5016d528ed9Sopenharmony_ci 5026d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 5036d528ed9Sopenharmony_ciflat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree( 5046d528ed9Sopenharmony_ci const KeyCompare& comp) 5056d528ed9Sopenharmony_ci : impl_(comp) {} 5066d528ed9Sopenharmony_ci 5076d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 5086d528ed9Sopenharmony_citemplate <class InputIterator> 5096d528ed9Sopenharmony_ciflat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree( 5106d528ed9Sopenharmony_ci InputIterator first, 5116d528ed9Sopenharmony_ci InputIterator last, 5126d528ed9Sopenharmony_ci FlatContainerDupes dupe_handling, 5136d528ed9Sopenharmony_ci const KeyCompare& comp) 5146d528ed9Sopenharmony_ci : impl_(comp, first, last) { 5156d528ed9Sopenharmony_ci sort_and_unique(begin(), end(), dupe_handling); 5166d528ed9Sopenharmony_ci} 5176d528ed9Sopenharmony_ci 5186d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 5196d528ed9Sopenharmony_ciflat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree( 5206d528ed9Sopenharmony_ci const flat_tree&) = default; 5216d528ed9Sopenharmony_ci 5226d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 5236d528ed9Sopenharmony_ciflat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree( 5246d528ed9Sopenharmony_ci std::vector<value_type> items, 5256d528ed9Sopenharmony_ci FlatContainerDupes dupe_handling, 5266d528ed9Sopenharmony_ci const KeyCompare& comp) 5276d528ed9Sopenharmony_ci : impl_(comp, std::move(items)) { 5286d528ed9Sopenharmony_ci sort_and_unique(begin(), end(), dupe_handling); 5296d528ed9Sopenharmony_ci} 5306d528ed9Sopenharmony_ci 5316d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 5326d528ed9Sopenharmony_ciflat_tree<Key, Value, GetKeyFromValue, KeyCompare>::flat_tree( 5336d528ed9Sopenharmony_ci std::initializer_list<value_type> ilist, 5346d528ed9Sopenharmony_ci FlatContainerDupes dupe_handling, 5356d528ed9Sopenharmony_ci const KeyCompare& comp) 5366d528ed9Sopenharmony_ci : flat_tree(std::begin(ilist), std::end(ilist), dupe_handling, comp) {} 5376d528ed9Sopenharmony_ci 5386d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 5396d528ed9Sopenharmony_ciflat_tree<Key, Value, GetKeyFromValue, KeyCompare>::~flat_tree() = default; 5406d528ed9Sopenharmony_ci 5416d528ed9Sopenharmony_ci// ---------------------------------------------------------------------------- 5426d528ed9Sopenharmony_ci// Assignments. 5436d528ed9Sopenharmony_ci 5446d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 5456d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::operator=( 5466d528ed9Sopenharmony_ci const flat_tree&) -> flat_tree& = default; 5476d528ed9Sopenharmony_ci 5486d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 5496d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::operator=(flat_tree&&) 5506d528ed9Sopenharmony_ci -> flat_tree& = default; 5516d528ed9Sopenharmony_ci 5526d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 5536d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::operator=( 5546d528ed9Sopenharmony_ci std::initializer_list<value_type> ilist) -> flat_tree& { 5556d528ed9Sopenharmony_ci impl_.body_ = ilist; 5566d528ed9Sopenharmony_ci sort_and_unique(begin(), end(), KEEP_FIRST_OF_DUPES); 5576d528ed9Sopenharmony_ci return *this; 5586d528ed9Sopenharmony_ci} 5596d528ed9Sopenharmony_ci 5606d528ed9Sopenharmony_ci// ---------------------------------------------------------------------------- 5616d528ed9Sopenharmony_ci// Memory management. 5626d528ed9Sopenharmony_ci 5636d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 5646d528ed9Sopenharmony_civoid flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::reserve( 5656d528ed9Sopenharmony_ci size_type new_capacity) { 5666d528ed9Sopenharmony_ci impl_.body_.reserve(new_capacity); 5676d528ed9Sopenharmony_ci} 5686d528ed9Sopenharmony_ci 5696d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 5706d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::capacity() const 5716d528ed9Sopenharmony_ci -> size_type { 5726d528ed9Sopenharmony_ci return impl_.body_.capacity(); 5736d528ed9Sopenharmony_ci} 5746d528ed9Sopenharmony_ci 5756d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 5766d528ed9Sopenharmony_civoid flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::shrink_to_fit() { 5776d528ed9Sopenharmony_ci impl_.body_.shrink_to_fit(); 5786d528ed9Sopenharmony_ci} 5796d528ed9Sopenharmony_ci 5806d528ed9Sopenharmony_ci// ---------------------------------------------------------------------------- 5816d528ed9Sopenharmony_ci// Size management. 5826d528ed9Sopenharmony_ci 5836d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 5846d528ed9Sopenharmony_civoid flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::clear() { 5856d528ed9Sopenharmony_ci impl_.body_.clear(); 5866d528ed9Sopenharmony_ci} 5876d528ed9Sopenharmony_ci 5886d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 5896d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::size() const 5906d528ed9Sopenharmony_ci -> size_type { 5916d528ed9Sopenharmony_ci return impl_.body_.size(); 5926d528ed9Sopenharmony_ci} 5936d528ed9Sopenharmony_ci 5946d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 5956d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::max_size() const 5966d528ed9Sopenharmony_ci -> size_type { 5976d528ed9Sopenharmony_ci return impl_.body_.max_size(); 5986d528ed9Sopenharmony_ci} 5996d528ed9Sopenharmony_ci 6006d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 6016d528ed9Sopenharmony_cibool flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::empty() const { 6026d528ed9Sopenharmony_ci return impl_.body_.empty(); 6036d528ed9Sopenharmony_ci} 6046d528ed9Sopenharmony_ci 6056d528ed9Sopenharmony_ci// ---------------------------------------------------------------------------- 6066d528ed9Sopenharmony_ci// Iterators. 6076d528ed9Sopenharmony_ci 6086d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 6096d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::begin() -> iterator { 6106d528ed9Sopenharmony_ci return impl_.body_.begin(); 6116d528ed9Sopenharmony_ci} 6126d528ed9Sopenharmony_ci 6136d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 6146d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::begin() const 6156d528ed9Sopenharmony_ci -> const_iterator { 6166d528ed9Sopenharmony_ci return impl_.body_.begin(); 6176d528ed9Sopenharmony_ci} 6186d528ed9Sopenharmony_ci 6196d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 6206d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::cbegin() const 6216d528ed9Sopenharmony_ci -> const_iterator { 6226d528ed9Sopenharmony_ci return impl_.body_.cbegin(); 6236d528ed9Sopenharmony_ci} 6246d528ed9Sopenharmony_ci 6256d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 6266d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::end() -> iterator { 6276d528ed9Sopenharmony_ci return impl_.body_.end(); 6286d528ed9Sopenharmony_ci} 6296d528ed9Sopenharmony_ci 6306d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 6316d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::end() const 6326d528ed9Sopenharmony_ci -> const_iterator { 6336d528ed9Sopenharmony_ci return impl_.body_.end(); 6346d528ed9Sopenharmony_ci} 6356d528ed9Sopenharmony_ci 6366d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 6376d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::cend() const 6386d528ed9Sopenharmony_ci -> const_iterator { 6396d528ed9Sopenharmony_ci return impl_.body_.cend(); 6406d528ed9Sopenharmony_ci} 6416d528ed9Sopenharmony_ci 6426d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 6436d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::rbegin() 6446d528ed9Sopenharmony_ci -> reverse_iterator { 6456d528ed9Sopenharmony_ci return impl_.body_.rbegin(); 6466d528ed9Sopenharmony_ci} 6476d528ed9Sopenharmony_ci 6486d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 6496d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::rbegin() const 6506d528ed9Sopenharmony_ci -> const_reverse_iterator { 6516d528ed9Sopenharmony_ci return impl_.body_.rbegin(); 6526d528ed9Sopenharmony_ci} 6536d528ed9Sopenharmony_ci 6546d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 6556d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::crbegin() const 6566d528ed9Sopenharmony_ci -> const_reverse_iterator { 6576d528ed9Sopenharmony_ci return impl_.body_.crbegin(); 6586d528ed9Sopenharmony_ci} 6596d528ed9Sopenharmony_ci 6606d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 6616d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::rend() 6626d528ed9Sopenharmony_ci -> reverse_iterator { 6636d528ed9Sopenharmony_ci return impl_.body_.rend(); 6646d528ed9Sopenharmony_ci} 6656d528ed9Sopenharmony_ci 6666d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 6676d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::rend() const 6686d528ed9Sopenharmony_ci -> const_reverse_iterator { 6696d528ed9Sopenharmony_ci return impl_.body_.rend(); 6706d528ed9Sopenharmony_ci} 6716d528ed9Sopenharmony_ci 6726d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 6736d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::crend() const 6746d528ed9Sopenharmony_ci -> const_reverse_iterator { 6756d528ed9Sopenharmony_ci return impl_.body_.crend(); 6766d528ed9Sopenharmony_ci} 6776d528ed9Sopenharmony_ci 6786d528ed9Sopenharmony_ci// ---------------------------------------------------------------------------- 6796d528ed9Sopenharmony_ci// Insert operations. 6806d528ed9Sopenharmony_ci// 6816d528ed9Sopenharmony_ci// Currently we use position_hint the same way as eastl or boost: 6826d528ed9Sopenharmony_ci// https://github.com/electronicarts/EASTL/blob/master/include/EASTL/vector_set.h#L493 6836d528ed9Sopenharmony_ci 6846d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 6856d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::insert( 6866d528ed9Sopenharmony_ci const value_type& val) -> std::pair<iterator, bool> { 6876d528ed9Sopenharmony_ci return emplace_key_args(GetKeyFromValue()(val), val); 6886d528ed9Sopenharmony_ci} 6896d528ed9Sopenharmony_ci 6906d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 6916d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::insert( 6926d528ed9Sopenharmony_ci value_type&& val) -> std::pair<iterator, bool> { 6936d528ed9Sopenharmony_ci return emplace_key_args(GetKeyFromValue()(val), std::move(val)); 6946d528ed9Sopenharmony_ci} 6956d528ed9Sopenharmony_ci 6966d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 6976d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::insert( 6986d528ed9Sopenharmony_ci const_iterator position_hint, 6996d528ed9Sopenharmony_ci const value_type& val) -> iterator { 7006d528ed9Sopenharmony_ci return emplace_hint_key_args(position_hint, GetKeyFromValue()(val), val) 7016d528ed9Sopenharmony_ci .first; 7026d528ed9Sopenharmony_ci} 7036d528ed9Sopenharmony_ci 7046d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 7056d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::insert( 7066d528ed9Sopenharmony_ci const_iterator position_hint, 7076d528ed9Sopenharmony_ci value_type&& val) -> iterator { 7086d528ed9Sopenharmony_ci return emplace_hint_key_args(position_hint, GetKeyFromValue()(val), 7096d528ed9Sopenharmony_ci std::move(val)) 7106d528ed9Sopenharmony_ci .first; 7116d528ed9Sopenharmony_ci} 7126d528ed9Sopenharmony_ci 7136d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 7146d528ed9Sopenharmony_citemplate <class InputIterator> 7156d528ed9Sopenharmony_civoid flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::insert( 7166d528ed9Sopenharmony_ci InputIterator first, 7176d528ed9Sopenharmony_ci InputIterator last, 7186d528ed9Sopenharmony_ci FlatContainerDupes dupes) { 7196d528ed9Sopenharmony_ci if (first == last) 7206d528ed9Sopenharmony_ci return; 7216d528ed9Sopenharmony_ci 7226d528ed9Sopenharmony_ci // Cache results whether existing elements should be overwritten and whether 7236d528ed9Sopenharmony_ci // inserting new elements happens immediately or will be done in a batch. 7246d528ed9Sopenharmony_ci const bool overwrite_existing = dupes == KEEP_LAST_OF_DUPES; 7256d528ed9Sopenharmony_ci const bool insert_inplace = 7266d528ed9Sopenharmony_ci is_multipass<InputIterator>() && std::next(first) == last; 7276d528ed9Sopenharmony_ci 7286d528ed9Sopenharmony_ci if (insert_inplace) { 7296d528ed9Sopenharmony_ci if (overwrite_existing) { 7306d528ed9Sopenharmony_ci for (; first != last; ++first) 7316d528ed9Sopenharmony_ci insert_or_assign(*first); 7326d528ed9Sopenharmony_ci } else 7336d528ed9Sopenharmony_ci std::copy(first, last, std::inserter(*this, end())); 7346d528ed9Sopenharmony_ci return; 7356d528ed9Sopenharmony_ci } 7366d528ed9Sopenharmony_ci 7376d528ed9Sopenharmony_ci // Provide a convenience lambda to obtain an iterator pointing past the last 7386d528ed9Sopenharmony_ci // old element. This needs to be dymanic due to possible re-allocations. 7396d528ed9Sopenharmony_ci const size_type original_size = size(); 7406d528ed9Sopenharmony_ci auto middle = [this, original_size]() { 7416d528ed9Sopenharmony_ci return std::next(begin(), original_size); 7426d528ed9Sopenharmony_ci }; 7436d528ed9Sopenharmony_ci 7446d528ed9Sopenharmony_ci // For batch updates initialize the first insertion point. 7456d528ed9Sopenharmony_ci difference_type pos_first_new = original_size; 7466d528ed9Sopenharmony_ci 7476d528ed9Sopenharmony_ci // Loop over the input range while appending new values and overwriting 7486d528ed9Sopenharmony_ci // existing ones, if applicable. Keep track of the first insertion point. 7496d528ed9Sopenharmony_ci if (overwrite_existing) { 7506d528ed9Sopenharmony_ci for (; first != last; ++first) { 7516d528ed9Sopenharmony_ci std::pair<iterator, bool> result = 7526d528ed9Sopenharmony_ci append_or_assign(begin(), middle(), *first); 7536d528ed9Sopenharmony_ci if (result.second) { 7546d528ed9Sopenharmony_ci pos_first_new = 7556d528ed9Sopenharmony_ci std::min(pos_first_new, std::distance(begin(), result.first)); 7566d528ed9Sopenharmony_ci } 7576d528ed9Sopenharmony_ci } 7586d528ed9Sopenharmony_ci } else { 7596d528ed9Sopenharmony_ci for (; first != last; ++first) { 7606d528ed9Sopenharmony_ci std::pair<iterator, bool> result = 7616d528ed9Sopenharmony_ci append_unique(begin(), middle(), *first); 7626d528ed9Sopenharmony_ci if (result.second) { 7636d528ed9Sopenharmony_ci pos_first_new = 7646d528ed9Sopenharmony_ci std::min(pos_first_new, std::distance(begin(), result.first)); 7656d528ed9Sopenharmony_ci } 7666d528ed9Sopenharmony_ci } 7676d528ed9Sopenharmony_ci } 7686d528ed9Sopenharmony_ci 7696d528ed9Sopenharmony_ci // The new elements might be unordered and contain duplicates, so post-process 7706d528ed9Sopenharmony_ci // the just inserted elements and merge them with the rest, inserting them at 7716d528ed9Sopenharmony_ci // the previously found spot. 7726d528ed9Sopenharmony_ci sort_and_unique(middle(), end(), dupes); 7736d528ed9Sopenharmony_ci std::inplace_merge(std::next(begin(), pos_first_new), middle(), end(), 7746d528ed9Sopenharmony_ci value_comp()); 7756d528ed9Sopenharmony_ci} 7766d528ed9Sopenharmony_ci 7776d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 7786d528ed9Sopenharmony_citemplate <class... Args> 7796d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::emplace(Args&&... args) 7806d528ed9Sopenharmony_ci -> std::pair<iterator, bool> { 7816d528ed9Sopenharmony_ci return insert(value_type(std::forward<Args>(args)...)); 7826d528ed9Sopenharmony_ci} 7836d528ed9Sopenharmony_ci 7846d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 7856d528ed9Sopenharmony_citemplate <class... Args> 7866d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::emplace_hint( 7876d528ed9Sopenharmony_ci const_iterator position_hint, 7886d528ed9Sopenharmony_ci Args&&... args) -> iterator { 7896d528ed9Sopenharmony_ci return insert(position_hint, value_type(std::forward<Args>(args)...)); 7906d528ed9Sopenharmony_ci} 7916d528ed9Sopenharmony_ci 7926d528ed9Sopenharmony_ci// ---------------------------------------------------------------------------- 7936d528ed9Sopenharmony_ci// Erase operations. 7946d528ed9Sopenharmony_ci 7956d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 7966d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::erase( 7976d528ed9Sopenharmony_ci iterator position) -> iterator { 7986d528ed9Sopenharmony_ci return impl_.body_.erase(position); 7996d528ed9Sopenharmony_ci} 8006d528ed9Sopenharmony_ci 8016d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 8026d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::erase( 8036d528ed9Sopenharmony_ci const_iterator position) -> iterator { 8046d528ed9Sopenharmony_ci return impl_.body_.erase(position); 8056d528ed9Sopenharmony_ci} 8066d528ed9Sopenharmony_ci 8076d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 8086d528ed9Sopenharmony_citemplate <typename K> 8096d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::erase(const K& val) 8106d528ed9Sopenharmony_ci -> size_type { 8116d528ed9Sopenharmony_ci auto eq_range = equal_range(val); 8126d528ed9Sopenharmony_ci auto res = std::distance(eq_range.first, eq_range.second); 8136d528ed9Sopenharmony_ci erase(eq_range.first, eq_range.second); 8146d528ed9Sopenharmony_ci return res; 8156d528ed9Sopenharmony_ci} 8166d528ed9Sopenharmony_ci 8176d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 8186d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::erase( 8196d528ed9Sopenharmony_ci const_iterator first, 8206d528ed9Sopenharmony_ci const_iterator last) -> iterator { 8216d528ed9Sopenharmony_ci return impl_.body_.erase(first, last); 8226d528ed9Sopenharmony_ci} 8236d528ed9Sopenharmony_ci 8246d528ed9Sopenharmony_ci// ---------------------------------------------------------------------------- 8256d528ed9Sopenharmony_ci// Comparators. 8266d528ed9Sopenharmony_ci 8276d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 8286d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::key_comp() const 8296d528ed9Sopenharmony_ci -> key_compare { 8306d528ed9Sopenharmony_ci return impl_.get_key_comp(); 8316d528ed9Sopenharmony_ci} 8326d528ed9Sopenharmony_ci 8336d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 8346d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::value_comp() const 8356d528ed9Sopenharmony_ci -> value_compare { 8366d528ed9Sopenharmony_ci return impl_.get_value_comp(); 8376d528ed9Sopenharmony_ci} 8386d528ed9Sopenharmony_ci 8396d528ed9Sopenharmony_ci// ---------------------------------------------------------------------------- 8406d528ed9Sopenharmony_ci// Search operations. 8416d528ed9Sopenharmony_ci 8426d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 8436d528ed9Sopenharmony_citemplate <typename K> 8446d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::count( 8456d528ed9Sopenharmony_ci const K& key) const -> size_type { 8466d528ed9Sopenharmony_ci auto eq_range = equal_range(key); 8476d528ed9Sopenharmony_ci return std::distance(eq_range.first, eq_range.second); 8486d528ed9Sopenharmony_ci} 8496d528ed9Sopenharmony_ci 8506d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 8516d528ed9Sopenharmony_citemplate <typename K> 8526d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::find(const K& key) 8536d528ed9Sopenharmony_ci -> iterator { 8546d528ed9Sopenharmony_ci return const_cast_it(as_const().find(key)); 8556d528ed9Sopenharmony_ci} 8566d528ed9Sopenharmony_ci 8576d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 8586d528ed9Sopenharmony_citemplate <typename K> 8596d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::find( 8606d528ed9Sopenharmony_ci const K& key) const -> const_iterator { 8616d528ed9Sopenharmony_ci auto eq_range = equal_range(key); 8626d528ed9Sopenharmony_ci return (eq_range.first == eq_range.second) ? end() : eq_range.first; 8636d528ed9Sopenharmony_ci} 8646d528ed9Sopenharmony_ci 8656d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 8666d528ed9Sopenharmony_citemplate <typename K> 8676d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::equal_range( 8686d528ed9Sopenharmony_ci const K& key) -> std::pair<iterator, iterator> { 8696d528ed9Sopenharmony_ci auto res = as_const().equal_range(key); 8706d528ed9Sopenharmony_ci return {const_cast_it(res.first), const_cast_it(res.second)}; 8716d528ed9Sopenharmony_ci} 8726d528ed9Sopenharmony_ci 8736d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 8746d528ed9Sopenharmony_citemplate <typename K> 8756d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::equal_range( 8766d528ed9Sopenharmony_ci const K& key) const -> std::pair<const_iterator, const_iterator> { 8776d528ed9Sopenharmony_ci auto lower = lower_bound(key); 8786d528ed9Sopenharmony_ci 8796d528ed9Sopenharmony_ci GetKeyFromValue extractor; 8806d528ed9Sopenharmony_ci if (lower == end() || impl_.get_key_comp()(key, extractor(*lower))) 8816d528ed9Sopenharmony_ci return {lower, lower}; 8826d528ed9Sopenharmony_ci 8836d528ed9Sopenharmony_ci return {lower, std::next(lower)}; 8846d528ed9Sopenharmony_ci} 8856d528ed9Sopenharmony_ci 8866d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 8876d528ed9Sopenharmony_citemplate <typename K> 8886d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::lower_bound( 8896d528ed9Sopenharmony_ci const K& key) -> iterator { 8906d528ed9Sopenharmony_ci return const_cast_it(as_const().lower_bound(key)); 8916d528ed9Sopenharmony_ci} 8926d528ed9Sopenharmony_ci 8936d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 8946d528ed9Sopenharmony_citemplate <typename K> 8956d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::lower_bound( 8966d528ed9Sopenharmony_ci const K& key) const -> const_iterator { 8976d528ed9Sopenharmony_ci static_assert(std::is_convertible<const KeyTypeOrK<K>&, const K&>::value, 8986d528ed9Sopenharmony_ci "Requested type cannot be bound to the container's key_type " 8996d528ed9Sopenharmony_ci "which is required for a non-transparent compare."); 9006d528ed9Sopenharmony_ci 9016d528ed9Sopenharmony_ci const KeyTypeOrK<K>& key_ref = key; 9026d528ed9Sopenharmony_ci 9036d528ed9Sopenharmony_ci KeyValueCompare key_value(impl_.get_key_comp()); 9046d528ed9Sopenharmony_ci return std::lower_bound(begin(), end(), key_ref, key_value); 9056d528ed9Sopenharmony_ci} 9066d528ed9Sopenharmony_ci 9076d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 9086d528ed9Sopenharmony_citemplate <typename K> 9096d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::upper_bound( 9106d528ed9Sopenharmony_ci const K& key) -> iterator { 9116d528ed9Sopenharmony_ci return const_cast_it(as_const().upper_bound(key)); 9126d528ed9Sopenharmony_ci} 9136d528ed9Sopenharmony_ci 9146d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 9156d528ed9Sopenharmony_citemplate <typename K> 9166d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::upper_bound( 9176d528ed9Sopenharmony_ci const K& key) const -> const_iterator { 9186d528ed9Sopenharmony_ci static_assert(std::is_convertible<const KeyTypeOrK<K>&, const K&>::value, 9196d528ed9Sopenharmony_ci "Requested type cannot be bound to the container's key_type " 9206d528ed9Sopenharmony_ci "which is required for a non-transparent compare."); 9216d528ed9Sopenharmony_ci 9226d528ed9Sopenharmony_ci const KeyTypeOrK<K>& key_ref = key; 9236d528ed9Sopenharmony_ci 9246d528ed9Sopenharmony_ci KeyValueCompare key_value(impl_.get_key_comp()); 9256d528ed9Sopenharmony_ci return std::upper_bound(begin(), end(), key_ref, key_value); 9266d528ed9Sopenharmony_ci} 9276d528ed9Sopenharmony_ci 9286d528ed9Sopenharmony_ci// ---------------------------------------------------------------------------- 9296d528ed9Sopenharmony_ci// General operations. 9306d528ed9Sopenharmony_ci 9316d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 9326d528ed9Sopenharmony_civoid flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::swap( 9336d528ed9Sopenharmony_ci flat_tree& other) noexcept { 9346d528ed9Sopenharmony_ci std::swap(impl_, other.impl_); 9356d528ed9Sopenharmony_ci} 9366d528ed9Sopenharmony_ci 9376d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 9386d528ed9Sopenharmony_citemplate <class... Args> 9396d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::unsafe_emplace( 9406d528ed9Sopenharmony_ci const_iterator position, 9416d528ed9Sopenharmony_ci Args&&... args) -> iterator { 9426d528ed9Sopenharmony_ci return impl_.body_.emplace(position, std::forward<Args>(args)...); 9436d528ed9Sopenharmony_ci} 9446d528ed9Sopenharmony_ci 9456d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 9466d528ed9Sopenharmony_citemplate <class K, class... Args> 9476d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::emplace_key_args( 9486d528ed9Sopenharmony_ci const K& key, 9496d528ed9Sopenharmony_ci Args&&... args) -> std::pair<iterator, bool> { 9506d528ed9Sopenharmony_ci auto lower = lower_bound(key); 9516d528ed9Sopenharmony_ci if (lower == end() || key_comp()(key, GetKeyFromValue()(*lower))) 9526d528ed9Sopenharmony_ci return {unsafe_emplace(lower, std::forward<Args>(args)...), true}; 9536d528ed9Sopenharmony_ci return {lower, false}; 9546d528ed9Sopenharmony_ci} 9556d528ed9Sopenharmony_ci 9566d528ed9Sopenharmony_citemplate <class Key, class Value, class GetKeyFromValue, class KeyCompare> 9576d528ed9Sopenharmony_citemplate <class K, class... Args> 9586d528ed9Sopenharmony_ciauto flat_tree<Key, Value, GetKeyFromValue, KeyCompare>::emplace_hint_key_args( 9596d528ed9Sopenharmony_ci const_iterator hint, 9606d528ed9Sopenharmony_ci const K& key, 9616d528ed9Sopenharmony_ci Args&&... args) -> std::pair<iterator, bool> { 9626d528ed9Sopenharmony_ci GetKeyFromValue extractor; 9636d528ed9Sopenharmony_ci if ((hint == begin() || key_comp()(extractor(*std::prev(hint)), key))) { 9646d528ed9Sopenharmony_ci if (hint == end() || key_comp()(key, extractor(*hint))) { 9656d528ed9Sopenharmony_ci // *(hint - 1) < key < *hint => key did not exist and hint is correct. 9666d528ed9Sopenharmony_ci return {unsafe_emplace(hint, std::forward<Args>(args)...), true}; 9676d528ed9Sopenharmony_ci } 9686d528ed9Sopenharmony_ci if (!key_comp()(extractor(*hint), key)) { 9696d528ed9Sopenharmony_ci // key == *hint => no-op, return correct hint. 9706d528ed9Sopenharmony_ci return {const_cast_it(hint), false}; 9716d528ed9Sopenharmony_ci } 9726d528ed9Sopenharmony_ci } 9736d528ed9Sopenharmony_ci // hint was not helpful, dispatch to hintless version. 9746d528ed9Sopenharmony_ci return emplace_key_args(key, std::forward<Args>(args)...); 9756d528ed9Sopenharmony_ci} 9766d528ed9Sopenharmony_ci 9776d528ed9Sopenharmony_ci// For containers like sets, the key is the same as the value. This implements 9786d528ed9Sopenharmony_ci// the GetKeyFromValue template parameter to flat_tree for this case. 9796d528ed9Sopenharmony_citemplate <class Key> 9806d528ed9Sopenharmony_cistruct GetKeyFromValueIdentity { 9816d528ed9Sopenharmony_ci const Key& operator()(const Key& k) const { return k; } 9826d528ed9Sopenharmony_ci}; 9836d528ed9Sopenharmony_ci 9846d528ed9Sopenharmony_ci} // namespace internal 9856d528ed9Sopenharmony_ci 9866d528ed9Sopenharmony_ci// ---------------------------------------------------------------------------- 9876d528ed9Sopenharmony_ci// Free functions. 9886d528ed9Sopenharmony_ci 9896d528ed9Sopenharmony_ci// Erases all elements that match predicate. It has O(size) complexity. 9906d528ed9Sopenharmony_citemplate <class Key, 9916d528ed9Sopenharmony_ci class Value, 9926d528ed9Sopenharmony_ci class GetKeyFromValue, 9936d528ed9Sopenharmony_ci class KeyCompare, 9946d528ed9Sopenharmony_ci typename Predicate> 9956d528ed9Sopenharmony_civoid EraseIf(base::internal::flat_tree<Key, Value, GetKeyFromValue, KeyCompare>& 9966d528ed9Sopenharmony_ci container, 9976d528ed9Sopenharmony_ci Predicate pred) { 9986d528ed9Sopenharmony_ci container.erase(std::remove_if(container.begin(), container.end(), pred), 9996d528ed9Sopenharmony_ci container.end()); 10006d528ed9Sopenharmony_ci} 10016d528ed9Sopenharmony_ci 10026d528ed9Sopenharmony_ci} // namespace base 10036d528ed9Sopenharmony_ci 10046d528ed9Sopenharmony_ci#endif // BASE_CONTAINERS_FLAT_TREE_H_ 1005