Warning, file /include/absl/container/internal/btree.h was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 
0002 
0003 
0004 
0005 
0006 
0007 
0008 
0009 
0010 
0011 
0012 
0013 
0014 
0015 
0016 
0017 
0018 
0019 
0020 
0021 
0022 
0023 
0024 
0025 
0026 
0027 
0028 
0029 
0030 
0031 
0032 
0033 
0034 
0035 
0036 
0037 
0038 
0039 
0040 
0041 
0042 
0043 
0044 
0045 #ifndef ABSL_CONTAINER_INTERNAL_BTREE_H_
0046 #define ABSL_CONTAINER_INTERNAL_BTREE_H_
0047 
0048 #include <algorithm>
0049 #include <cassert>
0050 #include <cstddef>
0051 #include <cstdint>
0052 #include <cstring>
0053 #include <functional>
0054 #include <iterator>
0055 #include <limits>
0056 #include <string>
0057 #include <type_traits>
0058 #include <utility>
0059 
0060 #include "absl/base/config.h"
0061 #include "absl/base/internal/raw_logging.h"
0062 #include "absl/base/macros.h"
0063 #include "absl/container/internal/common.h"
0064 #include "absl/container/internal/common_policy_traits.h"
0065 #include "absl/container/internal/compressed_tuple.h"
0066 #include "absl/container/internal/container_memory.h"
0067 #include "absl/container/internal/layout.h"
0068 #include "absl/memory/memory.h"
0069 #include "absl/meta/type_traits.h"
0070 #include "absl/strings/cord.h"
0071 #include "absl/strings/string_view.h"
0072 #include "absl/types/compare.h"
0073 
0074 namespace absl {
0075 ABSL_NAMESPACE_BEGIN
0076 namespace container_internal {
0077 
0078 #ifdef ABSL_BTREE_ENABLE_GENERATIONS
0079 #error ABSL_BTREE_ENABLE_GENERATIONS cannot be directly set
0080 #elif (defined(ABSL_HAVE_ADDRESS_SANITIZER) ||   \
0081        defined(ABSL_HAVE_HWADDRESS_SANITIZER) || \
0082        defined(ABSL_HAVE_MEMORY_SANITIZER)) &&   \
0083     !defined(NDEBUG_SANITIZER)  
0084 
0085 
0086 
0087 #define ABSL_BTREE_ENABLE_GENERATIONS
0088 #endif
0089 
0090 #ifdef ABSL_BTREE_ENABLE_GENERATIONS
0091 constexpr bool BtreeGenerationsEnabled() { return true; }
0092 #else
0093 constexpr bool BtreeGenerationsEnabled() { return false; }
0094 #endif
0095 
0096 template <typename Compare, typename T, typename U>
0097 using compare_result_t = absl::result_of_t<const Compare(const T &, const U &)>;
0098 
0099 
0100 
0101 template <typename Compare, typename T>
0102 using btree_is_key_compare_to =
0103     std::is_convertible<compare_result_t<Compare, T, T>, absl::weak_ordering>;
0104 
0105 struct StringBtreeDefaultLess {
0106   using is_transparent = void;
0107 
0108   StringBtreeDefaultLess() = default;
0109 
0110   
0111   StringBtreeDefaultLess(std::less<std::string>) {}        
0112   StringBtreeDefaultLess(std::less<absl::string_view>) {}  
0113 
0114   
0115   explicit operator std::less<std::string>() const { return {}; }
0116   explicit operator std::less<absl::string_view>() const { return {}; }
0117   explicit operator std::less<absl::Cord>() const { return {}; }
0118 
0119   absl::weak_ordering operator()(absl::string_view lhs,
0120                                  absl::string_view rhs) const {
0121     return compare_internal::compare_result_as_ordering(lhs.compare(rhs));
0122   }
0123   StringBtreeDefaultLess(std::less<absl::Cord>) {}  
0124   absl::weak_ordering operator()(const absl::Cord &lhs,
0125                                  const absl::Cord &rhs) const {
0126     return compare_internal::compare_result_as_ordering(lhs.Compare(rhs));
0127   }
0128   absl::weak_ordering operator()(const absl::Cord &lhs,
0129                                  absl::string_view rhs) const {
0130     return compare_internal::compare_result_as_ordering(lhs.Compare(rhs));
0131   }
0132   absl::weak_ordering operator()(absl::string_view lhs,
0133                                  const absl::Cord &rhs) const {
0134     return compare_internal::compare_result_as_ordering(-rhs.Compare(lhs));
0135   }
0136 };
0137 
0138 struct StringBtreeDefaultGreater {
0139   using is_transparent = void;
0140 
0141   StringBtreeDefaultGreater() = default;
0142 
0143   StringBtreeDefaultGreater(std::greater<std::string>) {}        
0144   StringBtreeDefaultGreater(std::greater<absl::string_view>) {}  
0145 
0146   
0147   explicit operator std::greater<std::string>() const { return {}; }
0148   explicit operator std::greater<absl::string_view>() const { return {}; }
0149   explicit operator std::greater<absl::Cord>() const { return {}; }
0150 
0151   absl::weak_ordering operator()(absl::string_view lhs,
0152                                  absl::string_view rhs) const {
0153     return compare_internal::compare_result_as_ordering(rhs.compare(lhs));
0154   }
0155   StringBtreeDefaultGreater(std::greater<absl::Cord>) {}  
0156   absl::weak_ordering operator()(const absl::Cord &lhs,
0157                                  const absl::Cord &rhs) const {
0158     return compare_internal::compare_result_as_ordering(rhs.Compare(lhs));
0159   }
0160   absl::weak_ordering operator()(const absl::Cord &lhs,
0161                                  absl::string_view rhs) const {
0162     return compare_internal::compare_result_as_ordering(-lhs.Compare(rhs));
0163   }
0164   absl::weak_ordering operator()(absl::string_view lhs,
0165                                  const absl::Cord &rhs) const {
0166     return compare_internal::compare_result_as_ordering(rhs.Compare(lhs));
0167   }
0168 };
0169 
0170 
0171 template <typename Compare, bool is_class = std::is_class<Compare>::value>
0172 struct checked_compare_base : Compare {
0173   using Compare::Compare;
0174   explicit checked_compare_base(Compare c) : Compare(std::move(c)) {}
0175   const Compare &comp() const { return *this; }
0176 };
0177 template <typename Compare>
0178 struct checked_compare_base<Compare, false> {
0179   explicit checked_compare_base(Compare c) : compare(std::move(c)) {}
0180   const Compare &comp() const { return compare; }
0181   Compare compare;
0182 };
0183 
0184 
0185 struct BtreeTestOnlyCheckedCompareOptOutBase {};
0186 
0187 
0188 
0189 
0190 
0191 
0192 
0193 
0194 
0195 
0196 
0197 template <typename Compare, typename Key>
0198 struct key_compare_adapter {
0199   
0200   
0201   
0202   
0203   
0204   
0205   
0206   struct checked_compare : checked_compare_base<Compare> {
0207    private:
0208     using Base = typename checked_compare::checked_compare_base;
0209     using Base::comp;
0210 
0211     
0212     
0213     
0214     
0215     bool is_self_equivalent(const Key &k) const {
0216       
0217       return comp()(k, k) == 0;
0218     }
0219     
0220     template <typename T>
0221     bool is_self_equivalent(const T &) const {
0222       return true;
0223     }
0224 
0225    public:
0226     using Base::Base;
0227     checked_compare(Compare comp) : Base(std::move(comp)) {}  
0228 
0229     
0230     explicit operator Compare() const { return comp(); }
0231 
0232     template <typename T, typename U,
0233               absl::enable_if_t<
0234                   std::is_same<bool, compare_result_t<Compare, T, U>>::value,
0235                   int> = 0>
0236     bool operator()(const T &lhs, const U &rhs) const {
0237       
0238       
0239       
0240       assert(is_self_equivalent(lhs));
0241       assert(is_self_equivalent(rhs));
0242       const bool lhs_comp_rhs = comp()(lhs, rhs);
0243       assert(!lhs_comp_rhs || !comp()(rhs, lhs));
0244       return lhs_comp_rhs;
0245     }
0246 
0247     template <
0248         typename T, typename U,
0249         absl::enable_if_t<std::is_convertible<compare_result_t<Compare, T, U>,
0250                                               absl::weak_ordering>::value,
0251                           int> = 0>
0252     absl::weak_ordering operator()(const T &lhs, const U &rhs) const {
0253       
0254       
0255       
0256       assert(is_self_equivalent(lhs));
0257       assert(is_self_equivalent(rhs));
0258       const absl::weak_ordering lhs_comp_rhs = comp()(lhs, rhs);
0259 #ifndef NDEBUG
0260       const absl::weak_ordering rhs_comp_lhs = comp()(rhs, lhs);
0261       if (lhs_comp_rhs > 0) {
0262         assert(rhs_comp_lhs < 0 && "lhs_comp_rhs > 0 -> rhs_comp_lhs < 0");
0263       } else if (lhs_comp_rhs == 0) {
0264         assert(rhs_comp_lhs == 0 && "lhs_comp_rhs == 0 -> rhs_comp_lhs == 0");
0265       } else {
0266         assert(rhs_comp_lhs > 0 && "lhs_comp_rhs < 0 -> rhs_comp_lhs > 0");
0267       }
0268 #endif
0269       return lhs_comp_rhs;
0270     }
0271   };
0272   using type = absl::conditional_t<
0273       std::is_base_of<BtreeTestOnlyCheckedCompareOptOutBase, Compare>::value,
0274       Compare, checked_compare>;
0275 };
0276 
0277 template <>
0278 struct key_compare_adapter<std::less<std::string>, std::string> {
0279   using type = StringBtreeDefaultLess;
0280 };
0281 
0282 template <>
0283 struct key_compare_adapter<std::greater<std::string>, std::string> {
0284   using type = StringBtreeDefaultGreater;
0285 };
0286 
0287 template <>
0288 struct key_compare_adapter<std::less<absl::string_view>, absl::string_view> {
0289   using type = StringBtreeDefaultLess;
0290 };
0291 
0292 template <>
0293 struct key_compare_adapter<std::greater<absl::string_view>, absl::string_view> {
0294   using type = StringBtreeDefaultGreater;
0295 };
0296 
0297 template <>
0298 struct key_compare_adapter<std::less<absl::Cord>, absl::Cord> {
0299   using type = StringBtreeDefaultLess;
0300 };
0301 
0302 template <>
0303 struct key_compare_adapter<std::greater<absl::Cord>, absl::Cord> {
0304   using type = StringBtreeDefaultGreater;
0305 };
0306 
0307 
0308 
0309 
0310 
0311 
0312 
0313 
0314 
0315 
0316 
0317 
0318 
0319 
0320 
0321 
0322 
0323 
0324 
0325 
0326 template <typename T, typename = void>
0327 struct has_linear_node_search_preference : std::false_type {};
0328 template <typename T, typename = void>
0329 struct prefers_linear_node_search : std::false_type {};
0330 template <typename T>
0331 struct has_linear_node_search_preference<
0332     T, absl::void_t<typename T::absl_btree_prefer_linear_node_search>>
0333     : std::true_type {};
0334 template <typename T>
0335 struct prefers_linear_node_search<
0336     T, absl::void_t<typename T::absl_btree_prefer_linear_node_search>>
0337     : T::absl_btree_prefer_linear_node_search {};
0338 
0339 template <typename Compare, typename Key>
0340 constexpr bool compare_has_valid_result_type() {
0341   using compare_result_type = compare_result_t<Compare, Key, Key>;
0342   return std::is_same<compare_result_type, bool>::value ||
0343          std::is_convertible<compare_result_type, absl::weak_ordering>::value;
0344 }
0345 
0346 template <typename original_key_compare, typename value_type>
0347 class map_value_compare {
0348   template <typename Params>
0349   friend class btree;
0350 
0351   
0352   
0353  protected:
0354   explicit map_value_compare(original_key_compare c) : comp(std::move(c)) {}
0355 
0356   original_key_compare comp;  
0357 
0358  public:
0359   auto operator()(const value_type &lhs, const value_type &rhs) const
0360       -> decltype(comp(lhs.first, rhs.first)) {
0361     return comp(lhs.first, rhs.first);
0362   }
0363 };
0364 
0365 template <typename Key, typename Compare, typename Alloc, int TargetNodeSize,
0366           bool IsMulti, bool IsMap, typename SlotPolicy>
0367 struct common_params : common_policy_traits<SlotPolicy> {
0368   using original_key_compare = Compare;
0369 
0370   
0371   
0372   
0373   
0374   
0375   
0376   
0377   
0378   using key_compare =
0379       absl::conditional_t<!compare_has_valid_result_type<Compare, Key>(),
0380                           Compare,
0381                           typename key_compare_adapter<Compare, Key>::type>;
0382 
0383   static constexpr bool kIsKeyCompareStringAdapted =
0384       std::is_same<key_compare, StringBtreeDefaultLess>::value ||
0385       std::is_same<key_compare, StringBtreeDefaultGreater>::value;
0386   static constexpr bool kIsKeyCompareTransparent =
0387       IsTransparent<original_key_compare>::value || kIsKeyCompareStringAdapted;
0388 
0389   
0390   
0391   using is_key_compare_to = btree_is_key_compare_to<key_compare, Key>;
0392 
0393   using allocator_type = Alloc;
0394   using key_type = Key;
0395   using size_type = size_t;
0396   using difference_type = ptrdiff_t;
0397 
0398   using slot_policy = SlotPolicy;
0399   using slot_type = typename slot_policy::slot_type;
0400   using value_type = typename slot_policy::value_type;
0401   using init_type = typename slot_policy::mutable_value_type;
0402   using pointer = value_type *;
0403   using const_pointer = const value_type *;
0404   using reference = value_type &;
0405   using const_reference = const value_type &;
0406 
0407   using value_compare =
0408       absl::conditional_t<IsMap,
0409                           map_value_compare<original_key_compare, value_type>,
0410                           original_key_compare>;
0411   using is_map_container = std::integral_constant<bool, IsMap>;
0412 
0413   
0414   
0415   
0416   
0417   
0418   
0419   
0420   
0421   template <typename LookupKey>
0422   constexpr static bool can_have_multiple_equivalent_keys() {
0423     return IsMulti || (IsTransparent<key_compare>::value &&
0424                        !std::is_same<LookupKey, Key>::value &&
0425                        !kIsKeyCompareStringAdapted);
0426   }
0427 
0428   enum {
0429     kTargetNodeSize = TargetNodeSize,
0430 
0431     
0432     
0433     
0434     kNodeSlotSpace = TargetNodeSize - (sizeof(void *) + 4),
0435   };
0436 
0437   
0438   
0439   using node_count_type =
0440       absl::conditional_t<(kNodeSlotSpace / sizeof(slot_type) >
0441                            (std::numeric_limits<uint8_t>::max)()),
0442                           uint16_t, uint8_t>;  
0443 };
0444 
0445 
0446 
0447 
0448 
0449 template <typename Compare>
0450 struct upper_bound_adapter {
0451   explicit upper_bound_adapter(const Compare &c) : comp(c) {}
0452   template <typename K1, typename K2>
0453   bool operator()(const K1 &a, const K2 &b) const {
0454     
0455     return !compare_internal::compare_result_as_less_than(comp(b, a));
0456   }
0457 
0458  private:
0459   Compare comp;
0460 };
0461 
0462 enum class MatchKind : uint8_t { kEq, kNe };
0463 
0464 template <typename V, bool IsCompareTo>
0465 struct SearchResult {
0466   V value;
0467   MatchKind match;
0468 
0469   static constexpr bool HasMatch() { return true; }
0470   bool IsEq() const { return match == MatchKind::kEq; }
0471 };
0472 
0473 
0474 
0475 
0476 template <typename V>
0477 struct SearchResult<V, false> {
0478   SearchResult() = default;
0479   explicit SearchResult(V v) : value(v) {}
0480   SearchResult(V v, MatchKind ) : value(v) {}
0481 
0482   V value;
0483 
0484   static constexpr bool HasMatch() { return false; }
0485   static constexpr bool IsEq() { return false; }
0486 };
0487 
0488 
0489 
0490 
0491 template <typename Params>
0492 class btree_node {
0493   using is_key_compare_to = typename Params::is_key_compare_to;
0494   using field_type = typename Params::node_count_type;
0495   using allocator_type = typename Params::allocator_type;
0496   using slot_type = typename Params::slot_type;
0497   using original_key_compare = typename Params::original_key_compare;
0498 
0499  public:
0500   using params_type = Params;
0501   using key_type = typename Params::key_type;
0502   using value_type = typename Params::value_type;
0503   using pointer = typename Params::pointer;
0504   using const_pointer = typename Params::const_pointer;
0505   using reference = typename Params::reference;
0506   using const_reference = typename Params::const_reference;
0507   using key_compare = typename Params::key_compare;
0508   using size_type = typename Params::size_type;
0509   using difference_type = typename Params::difference_type;
0510 
0511   
0512   
0513   
0514   
0515   
0516   
0517   
0518   using use_linear_search = std::integral_constant<
0519       bool, has_linear_node_search_preference<original_key_compare>::value
0520                 ? prefers_linear_node_search<original_key_compare>::value
0521             : has_linear_node_search_preference<key_type>::value
0522                 ? prefers_linear_node_search<key_type>::value
0523                 : std::is_arithmetic<key_type>::value &&
0524                       (std::is_same<std::less<key_type>,
0525                                     original_key_compare>::value ||
0526                        std::is_same<std::greater<key_type>,
0527                                     original_key_compare>::value)>;
0528 
0529   
0530   
0531   
0532   
0533   
0534   
0535   
0536   
0537   
0538   
0539   
0540   
0541   
0542   
0543   
0544   
0545   
0546   
0547   
0548   
0549   
0550   
0551   
0552   
0553   
0554   
0555   
0556   
0557   
0558   
0559   
0560   
0561   
0562   
0563   
0564   
0565   
0566   
0567   
0568   
0569   
0570   
0571   
0572   ~btree_node() = default;
0573   btree_node(btree_node const &) = delete;
0574   btree_node &operator=(btree_node const &) = delete;
0575 
0576  protected:
0577   btree_node() = default;
0578 
0579  private:
0580   using layout_type =
0581       absl::container_internal::Layout<btree_node *, uint32_t, field_type,
0582                                        slot_type, btree_node *>;
0583   using leaf_layout_type = typename layout_type::template WithStaticSizes<
0584        1,
0585        BtreeGenerationsEnabled() ? 1 : 0,
0586        4>;
0587   constexpr static size_type SizeWithNSlots(size_type n) {
0588     return leaf_layout_type( n,  0).AllocSize();
0589   }
0590   
0591   constexpr static size_type MinimumOverhead() {
0592     return SizeWithNSlots(1) - sizeof(slot_type);
0593   }
0594 
0595   
0596   
0597   constexpr static size_type NodeTargetSlots(const size_type begin,
0598                                              const size_type end) {
0599     return begin == end ? begin
0600            : SizeWithNSlots((begin + end) / 2 + 1) >
0601                    params_type::kTargetNodeSize
0602                ? NodeTargetSlots(begin, (begin + end) / 2)
0603                : NodeTargetSlots((begin + end) / 2 + 1, end);
0604   }
0605 
0606   constexpr static size_type kTargetNodeSize = params_type::kTargetNodeSize;
0607   constexpr static size_type kNodeTargetSlots =
0608       NodeTargetSlots(0, kTargetNodeSize);
0609 
0610   
0611   
0612   
0613   
0614   
0615   constexpr static size_type kMinNodeSlots = 4;
0616 
0617   constexpr static size_type kNodeSlots =
0618       kNodeTargetSlots >= kMinNodeSlots ? kNodeTargetSlots : kMinNodeSlots;
0619 
0620   using internal_layout_type = typename layout_type::template WithStaticSizes<
0621        1,
0622        BtreeGenerationsEnabled() ? 1 : 0,
0623        4,  kNodeSlots,
0624        kNodeSlots + 1>;
0625 
0626   
0627   
0628   constexpr static field_type kInternalNodeMaxCount = 0;
0629 
0630   
0631   constexpr static leaf_layout_type LeafLayout(
0632       const size_type slot_count = kNodeSlots) {
0633     return leaf_layout_type(slot_count, 0);
0634   }
0635   constexpr static auto InternalLayout() { return internal_layout_type(); }
0636   constexpr static size_type LeafSize(const size_type slot_count = kNodeSlots) {
0637     return LeafLayout(slot_count).AllocSize();
0638   }
0639   constexpr static size_type InternalSize() {
0640     return InternalLayout().AllocSize();
0641   }
0642 
0643   constexpr static size_type Alignment() {
0644     static_assert(LeafLayout(1).Alignment() == InternalLayout().Alignment(),
0645                   "Alignment of all nodes must be equal.");
0646     return InternalLayout().Alignment();
0647   }
0648 
0649   
0650   
0651   template <size_type N>
0652   inline typename layout_type::template ElementType<N> *GetField() {
0653     
0654     assert(N < 4 || is_internal());
0655     return InternalLayout().template Pointer<N>(reinterpret_cast<char *>(this));
0656   }
0657   template <size_type N>
0658   inline const typename layout_type::template ElementType<N> *GetField() const {
0659     assert(N < 4 || is_internal());
0660     return InternalLayout().template Pointer<N>(
0661         reinterpret_cast<const char *>(this));
0662   }
0663   void set_parent(btree_node *p) { *GetField<0>() = p; }
0664   field_type &mutable_finish() { return GetField<2>()[2]; }
0665   slot_type *slot(size_type i) { return &GetField<3>()[i]; }
0666   slot_type *start_slot() { return slot(start()); }
0667   slot_type *finish_slot() { return slot(finish()); }
0668   const slot_type *slot(size_type i) const { return &GetField<3>()[i]; }
0669   void set_position(field_type v) { GetField<2>()[0] = v; }
0670   void set_start(field_type v) { GetField<2>()[1] = v; }
0671   void set_finish(field_type v) { GetField<2>()[2] = v; }
0672   
0673   void set_max_count(field_type v) { GetField<2>()[3] = v; }
0674 
0675  public:
0676   
0677   
0678   bool is_leaf() const { return GetField<2>()[3] != kInternalNodeMaxCount; }
0679   
0680   
0681   bool is_internal() const { return !is_leaf(); }
0682 
0683   
0684   field_type position() const { return GetField<2>()[0]; }
0685 
0686   
0687   field_type start() const {
0688     
0689     assert(GetField<2>()[1] == 0);
0690     return 0;
0691   }
0692 
0693   
0694   field_type finish() const { return GetField<2>()[2]; }
0695 
0696   
0697   field_type count() const {
0698     assert(finish() >= start());
0699     return finish() - start();
0700   }
0701   field_type max_count() const {
0702     
0703     
0704     const field_type max_count = GetField<2>()[3];
0705     return max_count == field_type{kInternalNodeMaxCount}
0706                ? field_type{kNodeSlots}
0707                : max_count;
0708   }
0709 
0710   
0711   btree_node *parent() const { return *GetField<0>(); }
0712   
0713   
0714   
0715   bool is_root() const { return parent()->is_leaf(); }
0716   void make_root() {
0717     assert(parent()->is_root());
0718     set_generation(parent()->generation());
0719     set_parent(parent()->parent());
0720   }
0721 
0722   
0723   uint32_t *get_root_generation() const {
0724     assert(BtreeGenerationsEnabled());
0725     const btree_node *curr = this;
0726     for (; !curr->is_root(); curr = curr->parent()) continue;
0727     return const_cast<uint32_t *>(&curr->GetField<1>()[0]);
0728   }
0729 
0730   
0731   uint32_t generation() const {
0732     return BtreeGenerationsEnabled() ? *get_root_generation() : 0;
0733   }
0734   
0735   
0736   void set_generation(uint32_t generation) {
0737     if (BtreeGenerationsEnabled()) GetField<1>()[0] = generation;
0738   }
0739   
0740   void next_generation() {
0741     if (BtreeGenerationsEnabled()) ++*get_root_generation();
0742   }
0743 
0744   
0745   const key_type &key(size_type i) const { return params_type::key(slot(i)); }
0746   reference value(size_type i) { return params_type::element(slot(i)); }
0747   const_reference value(size_type i) const {
0748     return params_type::element(slot(i));
0749   }
0750 
0751   
0752   btree_node *child(field_type i) const { return GetField<4>()[i]; }
0753   btree_node *start_child() const { return child(start()); }
0754   btree_node *&mutable_child(field_type i) { return GetField<4>()[i]; }
0755   void clear_child(field_type i) {
0756     absl::container_internal::SanitizerPoisonObject(&mutable_child(i));
0757   }
0758   void set_child_noupdate_position(field_type i, btree_node *c) {
0759     absl::container_internal::SanitizerUnpoisonObject(&mutable_child(i));
0760     mutable_child(i) = c;
0761   }
0762   void set_child(field_type i, btree_node *c) {
0763     set_child_noupdate_position(i, c);
0764     c->set_position(i);
0765   }
0766   void init_child(field_type i, btree_node *c) {
0767     set_child(i, c);
0768     c->set_parent(this);
0769   }
0770 
0771   
0772   template <typename K>
0773   SearchResult<size_type, is_key_compare_to::value> lower_bound(
0774       const K &k, const key_compare &comp) const {
0775     return use_linear_search::value ? linear_search(k, comp)
0776                                     : binary_search(k, comp);
0777   }
0778   
0779   template <typename K>
0780   size_type upper_bound(const K &k, const key_compare &comp) const {
0781     auto upper_compare = upper_bound_adapter<key_compare>(comp);
0782     return use_linear_search::value ? linear_search(k, upper_compare).value
0783                                     : binary_search(k, upper_compare).value;
0784   }
0785 
0786   template <typename K, typename Compare>
0787   SearchResult<size_type, btree_is_key_compare_to<Compare, key_type>::value>
0788   linear_search(const K &k, const Compare &comp) const {
0789     return linear_search_impl(k, start(), finish(), comp,
0790                               btree_is_key_compare_to<Compare, key_type>());
0791   }
0792 
0793   template <typename K, typename Compare>
0794   SearchResult<size_type, btree_is_key_compare_to<Compare, key_type>::value>
0795   binary_search(const K &k, const Compare &comp) const {
0796     return binary_search_impl(k, start(), finish(), comp,
0797                               btree_is_key_compare_to<Compare, key_type>());
0798   }
0799 
0800   
0801   
0802   template <typename K, typename Compare>
0803   SearchResult<size_type, false> linear_search_impl(
0804       const K &k, size_type s, const size_type e, const Compare &comp,
0805       std::false_type ) const {
0806     while (s < e) {
0807       if (!comp(key(s), k)) {
0808         break;
0809       }
0810       ++s;
0811     }
0812     return SearchResult<size_type, false>{s};
0813   }
0814 
0815   
0816   
0817   template <typename K, typename Compare>
0818   SearchResult<size_type, true> linear_search_impl(
0819       const K &k, size_type s, const size_type e, const Compare &comp,
0820       std::true_type ) const {
0821     while (s < e) {
0822       const absl::weak_ordering c = comp(key(s), k);
0823       if (c == 0) {
0824         return {s, MatchKind::kEq};
0825       } else if (c > 0) {
0826         break;
0827       }
0828       ++s;
0829     }
0830     return {s, MatchKind::kNe};
0831   }
0832 
0833   
0834   
0835   template <typename K, typename Compare>
0836   SearchResult<size_type, false> binary_search_impl(
0837       const K &k, size_type s, size_type e, const Compare &comp,
0838       std::false_type ) const {
0839     while (s != e) {
0840       const size_type mid = (s + e) >> 1;
0841       if (comp(key(mid), k)) {
0842         s = mid + 1;
0843       } else {
0844         e = mid;
0845       }
0846     }
0847     return SearchResult<size_type, false>{s};
0848   }
0849 
0850   
0851   
0852   template <typename K, typename CompareTo>
0853   SearchResult<size_type, true> binary_search_impl(
0854       const K &k, size_type s, size_type e, const CompareTo &comp,
0855       std::true_type ) const {
0856     if (params_type::template can_have_multiple_equivalent_keys<K>()) {
0857       MatchKind exact_match = MatchKind::kNe;
0858       while (s != e) {
0859         const size_type mid = (s + e) >> 1;
0860         const absl::weak_ordering c = comp(key(mid), k);
0861         if (c < 0) {
0862           s = mid + 1;
0863         } else {
0864           e = mid;
0865           if (c == 0) {
0866             
0867             
0868             
0869             exact_match = MatchKind::kEq;
0870           }
0871         }
0872       }
0873       return {s, exact_match};
0874     } else {  
0875       while (s != e) {
0876         const size_type mid = (s + e) >> 1;
0877         const absl::weak_ordering c = comp(key(mid), k);
0878         if (c < 0) {
0879           s = mid + 1;
0880         } else if (c > 0) {
0881           e = mid;
0882         } else {
0883           return {mid, MatchKind::kEq};
0884         }
0885       }
0886       return {s, MatchKind::kNe};
0887     }
0888   }
0889 
0890   
0891   
0892   
0893   
0894   template <typename Compare>
0895   bool is_ordered_correctly(field_type i, const Compare &comp) const {
0896     if (std::is_base_of<BtreeTestOnlyCheckedCompareOptOutBase,
0897                         Compare>::value ||
0898         params_type::kIsKeyCompareStringAdapted) {
0899       return true;
0900     }
0901 
0902     const auto compare = [&](field_type a, field_type b) {
0903       const absl::weak_ordering cmp =
0904           compare_internal::do_three_way_comparison(comp, key(a), key(b));
0905       return cmp < 0 ? -1 : cmp > 0 ? 1 : 0;
0906     };
0907     int cmp = -1;
0908     constexpr bool kCanHaveEquivKeys =
0909         params_type::template can_have_multiple_equivalent_keys<key_type>();
0910     for (field_type j = start(); j < finish(); ++j) {
0911       if (j == i) {
0912         if (cmp > 0) return false;
0913         continue;
0914       }
0915       int new_cmp = compare(j, i);
0916       if (new_cmp < cmp || (!kCanHaveEquivKeys && new_cmp == 0)) return false;
0917       cmp = new_cmp;
0918     }
0919     return true;
0920   }
0921 
0922   
0923   
0924   template <typename... Args>
0925   void emplace_value(field_type i, allocator_type *alloc, Args &&...args);
0926 
0927   
0928   
0929   
0930   void remove_values(field_type i, field_type to_erase, allocator_type *alloc);
0931 
0932   
0933   void rebalance_right_to_left(field_type to_move, btree_node *right,
0934                                allocator_type *alloc);
0935   void rebalance_left_to_right(field_type to_move, btree_node *right,
0936                                allocator_type *alloc);
0937 
0938   
0939   void split(int insert_position, btree_node *dest, allocator_type *alloc);
0940 
0941   
0942   
0943   void merge(btree_node *src, allocator_type *alloc);
0944 
0945   
0946   void init_leaf(field_type position, field_type max_count,
0947                  btree_node *parent) {
0948     set_generation(0);
0949     set_parent(parent);
0950     set_position(position);
0951     set_start(0);
0952     set_finish(0);
0953     set_max_count(max_count);
0954     absl::container_internal::SanitizerPoisonMemoryRegion(
0955         start_slot(), max_count * sizeof(slot_type));
0956   }
0957   void init_internal(field_type position, btree_node *parent) {
0958     init_leaf(position, kNodeSlots, parent);
0959     
0960     
0961     set_max_count(kInternalNodeMaxCount);
0962     absl::container_internal::SanitizerPoisonMemoryRegion(
0963         &mutable_child(start()), (kNodeSlots + 1) * sizeof(btree_node *));
0964   }
0965 
0966   static void deallocate(const size_type size, btree_node *node,
0967                          allocator_type *alloc) {
0968     absl::container_internal::SanitizerUnpoisonMemoryRegion(node, size);
0969     absl::container_internal::Deallocate<Alignment()>(alloc, node, size);
0970   }
0971 
0972   
0973   static void clear_and_delete(btree_node *node, allocator_type *alloc);
0974 
0975  private:
0976   template <typename... Args>
0977   void value_init(const field_type i, allocator_type *alloc, Args &&...args) {
0978     next_generation();
0979     absl::container_internal::SanitizerUnpoisonObject(slot(i));
0980     params_type::construct(alloc, slot(i), std::forward<Args>(args)...);
0981   }
0982   void value_destroy(const field_type i, allocator_type *alloc) {
0983     next_generation();
0984     params_type::destroy(alloc, slot(i));
0985     absl::container_internal::SanitizerPoisonObject(slot(i));
0986   }
0987   void value_destroy_n(const field_type i, const field_type n,
0988                        allocator_type *alloc) {
0989     next_generation();
0990     for (slot_type *s = slot(i), *end = slot(i + n); s != end; ++s) {
0991       params_type::destroy(alloc, s);
0992       absl::container_internal::SanitizerPoisonObject(s);
0993     }
0994   }
0995 
0996   static void transfer(slot_type *dest, slot_type *src, allocator_type *alloc) {
0997     absl::container_internal::SanitizerUnpoisonObject(dest);
0998     params_type::transfer(alloc, dest, src);
0999     absl::container_internal::SanitizerPoisonObject(src);
1000   }
1001 
1002   
1003   void transfer(const size_type dest_i, const size_type src_i,
1004                 btree_node *src_node, allocator_type *alloc) {
1005     next_generation();
1006     transfer(slot(dest_i), src_node->slot(src_i), alloc);
1007   }
1008 
1009   
1010   
1011   void transfer_n(const size_type n, const size_type dest_i,
1012                   const size_type src_i, btree_node *src_node,
1013                   allocator_type *alloc) {
1014     next_generation();
1015     for (slot_type *src = src_node->slot(src_i), *end = src + n,
1016                    *dest = slot(dest_i);
1017          src != end; ++src, ++dest) {
1018       transfer(dest, src, alloc);
1019     }
1020   }
1021 
1022   
1023   
1024   void transfer_n_backward(const size_type n, const size_type dest_i,
1025                            const size_type src_i, btree_node *src_node,
1026                            allocator_type *alloc) {
1027     next_generation();
1028     for (slot_type *src = src_node->slot(src_i + n), *end = src - n,
1029                    *dest = slot(dest_i + n);
1030          src != end; --src, --dest) {
1031       
1032       
1033       
1034       
1035       
1036       transfer(dest - 1, src - 1, alloc);
1037     }
1038   }
1039 
1040   template <typename P>
1041   friend class btree;
1042   template <typename N, typename R, typename P>
1043   friend class btree_iterator;
1044   friend class BtreeNodePeer;
1045   friend struct btree_access;
1046 };
1047 
1048 template <typename Node>
1049 bool AreNodesFromSameContainer(const Node *node_a, const Node *node_b) {
1050   
1051   
1052   
1053   if (node_a == nullptr || node_b == nullptr) return true;
1054   while (!node_a->is_root()) node_a = node_a->parent();
1055   while (!node_b->is_root()) node_b = node_b->parent();
1056   return node_a == node_b;
1057 }
1058 
1059 class btree_iterator_generation_info_enabled {
1060  public:
1061   explicit btree_iterator_generation_info_enabled(uint32_t g)
1062       : generation_(g) {}
1063 
1064   
1065   
1066   template <typename Node>
1067   void update_generation(const Node *node) {
1068     if (node != nullptr) generation_ = node->generation();
1069   }
1070   uint32_t generation() const { return generation_; }
1071 
1072   template <typename Node>
1073   void assert_valid_generation(const Node *node) const {
1074     if (node != nullptr && node->generation() != generation_) {
1075       ABSL_INTERNAL_LOG(
1076           FATAL,
1077           "Attempting to use an invalidated iterator. The corresponding b-tree "
1078           "container has been mutated since this iterator was constructed.");
1079     }
1080   }
1081 
1082  private:
1083   
1084   uint32_t generation_;
1085 };
1086 
1087 class btree_iterator_generation_info_disabled {
1088  public:
1089   explicit btree_iterator_generation_info_disabled(uint32_t) {}
1090   static void update_generation(const void *) {}
1091   static uint32_t generation() { return 0; }
1092   static void assert_valid_generation(const void *) {}
1093 };
1094 
1095 #ifdef ABSL_BTREE_ENABLE_GENERATIONS
1096 using btree_iterator_generation_info = btree_iterator_generation_info_enabled;
1097 #else
1098 using btree_iterator_generation_info = btree_iterator_generation_info_disabled;
1099 #endif
1100 
1101 template <typename Node, typename Reference, typename Pointer>
1102 class btree_iterator : private btree_iterator_generation_info {
1103   using field_type = typename Node::field_type;
1104   using key_type = typename Node::key_type;
1105   using size_type = typename Node::size_type;
1106   using params_type = typename Node::params_type;
1107   using is_map_container = typename params_type::is_map_container;
1108 
1109   using node_type = Node;
1110   using normal_node = typename std::remove_const<Node>::type;
1111   using const_node = const Node;
1112   using normal_pointer = typename params_type::pointer;
1113   using normal_reference = typename params_type::reference;
1114   using const_pointer = typename params_type::const_pointer;
1115   using const_reference = typename params_type::const_reference;
1116   using slot_type = typename params_type::slot_type;
1117 
1118   
1119   using iterator = absl::conditional_t<
1120       is_map_container::value,
1121       btree_iterator<normal_node, normal_reference, normal_pointer>,
1122       btree_iterator<normal_node, const_reference, const_pointer>>;
1123   using const_iterator =
1124       btree_iterator<const_node, const_reference, const_pointer>;
1125 
1126  public:
1127   
1128   using difference_type = typename Node::difference_type;
1129   using value_type = typename params_type::value_type;
1130   using pointer = Pointer;
1131   using reference = Reference;
1132   using iterator_category = std::bidirectional_iterator_tag;
1133 
1134   btree_iterator() : btree_iterator(nullptr, -1) {}
1135   explicit btree_iterator(Node *n) : btree_iterator(n, n->start()) {}
1136   btree_iterator(Node *n, int p)
1137       : btree_iterator_generation_info(n != nullptr ? n->generation()
1138                                                     : ~uint32_t{}),
1139         node_(n),
1140         position_(p) {}
1141 
1142   
1143   
1144   
1145   template <typename N, typename R, typename P,
1146             absl::enable_if_t<
1147                 std::is_same<btree_iterator<N, R, P>, iterator>::value &&
1148                     std::is_same<btree_iterator, const_iterator>::value,
1149                 int> = 0>
1150   btree_iterator(const btree_iterator<N, R, P> other)  
1151       : btree_iterator_generation_info(other),
1152         node_(other.node_),
1153         position_(other.position_) {}
1154 
1155   bool operator==(const iterator &other) const {
1156     return Equals(other);
1157   }
1158   bool operator==(const const_iterator &other) const {
1159     return Equals(other);
1160   }
1161   bool operator!=(const iterator &other) const {
1162     return !Equals(other);
1163   }
1164   bool operator!=(const const_iterator &other) const {
1165     return !Equals(other);
1166   }
1167 
1168   
1169   
1170   difference_type operator-(const_iterator other) const {
1171     if (node_ == other.node_) {
1172       if (node_->is_leaf()) return position_ - other.position_;
1173       if (position_ == other.position_) return 0;
1174     }
1175     return distance_slow(other);
1176   }
1177 
1178   
1179   reference operator*() const {
1180     ABSL_HARDENING_ASSERT(node_ != nullptr);
1181     assert_valid_generation(node_);
1182     ABSL_HARDENING_ASSERT(position_ >= node_->start());
1183     if (position_ >= node_->finish()) {
1184       ABSL_HARDENING_ASSERT(!IsEndIterator() && "Dereferencing end() iterator");
1185       ABSL_HARDENING_ASSERT(position_ < node_->finish());
1186     }
1187     return node_->value(static_cast<field_type>(position_));
1188   }
1189   pointer operator->() const { return &operator*(); }
1190 
1191   btree_iterator &operator++() {
1192     increment();
1193     return *this;
1194   }
1195   btree_iterator &operator--() {
1196     decrement();
1197     return *this;
1198   }
1199   btree_iterator operator++(int) {
1200     btree_iterator tmp = *this;
1201     ++*this;
1202     return tmp;
1203   }
1204   btree_iterator operator--(int) {
1205     btree_iterator tmp = *this;
1206     --*this;
1207     return tmp;
1208   }
1209 
1210  private:
1211   friend iterator;
1212   friend const_iterator;
1213   template <typename Params>
1214   friend class btree;
1215   template <typename Tree>
1216   friend class btree_container;
1217   template <typename Tree>
1218   friend class btree_set_container;
1219   template <typename Tree>
1220   friend class btree_map_container;
1221   template <typename Tree>
1222   friend class btree_multiset_container;
1223   template <typename TreeType, typename CheckerType>
1224   friend class base_checker;
1225   friend struct btree_access;
1226 
1227   
1228   
1229   
1230   
1231   template <typename N, typename R, typename P,
1232             absl::enable_if_t<
1233                 std::is_same<btree_iterator<N, R, P>, const_iterator>::value &&
1234                     std::is_same<btree_iterator, iterator>::value,
1235                 int> = 0>
1236   explicit btree_iterator(const btree_iterator<N, R, P> other)
1237       : btree_iterator_generation_info(other.generation()),
1238         node_(const_cast<node_type *>(other.node_)),
1239         position_(other.position_) {}
1240 
1241   bool Equals(const const_iterator other) const {
1242     ABSL_HARDENING_ASSERT(((node_ == nullptr && other.node_ == nullptr) ||
1243                            (node_ != nullptr && other.node_ != nullptr)) &&
1244                           "Comparing default-constructed iterator with "
1245                           "non-default-constructed iterator.");
1246     
1247     
1248     
1249     assert(AreNodesFromSameContainer(node_, other.node_) &&
1250            "Comparing iterators from different containers.");
1251     assert_valid_generation(node_);
1252     other.assert_valid_generation(other.node_);
1253     return node_ == other.node_ && position_ == other.position_;
1254   }
1255 
1256   bool IsEndIterator() const {
1257     if (position_ != node_->finish()) return false;
1258     node_type *node = node_;
1259     while (!node->is_root()) {
1260       if (node->position() != node->parent()->finish()) return false;
1261       node = node->parent();
1262     }
1263     return true;
1264   }
1265 
1266   
1267   
1268   
1269   difference_type distance_slow(const_iterator other) const;
1270 
1271   
1272   void increment() {
1273     assert_valid_generation(node_);
1274     if (node_->is_leaf() && ++position_ < node_->finish()) {
1275       return;
1276     }
1277     increment_slow();
1278   }
1279   void increment_slow();
1280 
1281   void decrement() {
1282     assert_valid_generation(node_);
1283     if (node_->is_leaf() && --position_ >= node_->start()) {
1284       return;
1285     }
1286     decrement_slow();
1287   }
1288   void decrement_slow();
1289 
1290   const key_type &key() const {
1291     return node_->key(static_cast<size_type>(position_));
1292   }
1293   decltype(std::declval<Node *>()->slot(0)) slot() {
1294     return node_->slot(static_cast<size_type>(position_));
1295   }
1296 
1297   void update_generation() {
1298     btree_iterator_generation_info::update_generation(node_);
1299   }
1300 
1301   
1302   Node *node_;
1303   
1304   
1305   
1306   int position_;
1307 };
1308 
1309 template <typename Params>
1310 class btree {
1311   using node_type = btree_node<Params>;
1312   using is_key_compare_to = typename Params::is_key_compare_to;
1313   using field_type = typename node_type::field_type;
1314 
1315   
1316   
1317   struct EmptyNodeType : node_type {
1318     using field_type = typename node_type::field_type;
1319     node_type *parent;
1320 #ifdef ABSL_BTREE_ENABLE_GENERATIONS
1321     uint32_t generation = 0;
1322 #endif
1323     field_type position = 0;
1324     field_type start = 0;
1325     field_type finish = 0;
1326     
1327     
1328     field_type max_count = node_type::kInternalNodeMaxCount + 1;
1329 
1330     constexpr EmptyNodeType() : parent(this) {}
1331   };
1332 
1333   static node_type *EmptyNode() {
1334     alignas(node_type::Alignment()) static constexpr EmptyNodeType empty_node;
1335     return const_cast<EmptyNodeType *>(&empty_node);
1336   }
1337 
1338   enum : uint32_t {
1339     kNodeSlots = node_type::kNodeSlots,
1340     kMinNodeValues = kNodeSlots / 2,
1341   };
1342 
1343   struct node_stats {
1344     using size_type = typename Params::size_type;
1345 
1346     node_stats(size_type l, size_type i) : leaf_nodes(l), internal_nodes(i) {}
1347 
1348     node_stats &operator+=(const node_stats &other) {
1349       leaf_nodes += other.leaf_nodes;
1350       internal_nodes += other.internal_nodes;
1351       return *this;
1352     }
1353 
1354     size_type leaf_nodes;
1355     size_type internal_nodes;
1356   };
1357 
1358  public:
1359   using key_type = typename Params::key_type;
1360   using value_type = typename Params::value_type;
1361   using size_type = typename Params::size_type;
1362   using difference_type = typename Params::difference_type;
1363   using key_compare = typename Params::key_compare;
1364   using original_key_compare = typename Params::original_key_compare;
1365   using value_compare = typename Params::value_compare;
1366   using allocator_type = typename Params::allocator_type;
1367   using reference = typename Params::reference;
1368   using const_reference = typename Params::const_reference;
1369   using pointer = typename Params::pointer;
1370   using const_pointer = typename Params::const_pointer;
1371   using iterator =
1372       typename btree_iterator<node_type, reference, pointer>::iterator;
1373   using const_iterator = typename iterator::const_iterator;
1374   using reverse_iterator = std::reverse_iterator<iterator>;
1375   using const_reverse_iterator = std::reverse_iterator<const_iterator>;
1376   using node_handle_type = node_handle<Params, Params, allocator_type>;
1377 
1378   
1379   using params_type = Params;
1380   using slot_type = typename Params::slot_type;
1381 
1382  private:
1383   
1384   
1385   
1386   
1387   template <typename Btree>
1388   void copy_or_move_values_in_order(Btree &other);
1389 
1390   
1391   constexpr static bool static_assert_validation();
1392 
1393  public:
1394   btree(const key_compare &comp, const allocator_type &alloc)
1395       : root_(EmptyNode()), rightmost_(comp, alloc, EmptyNode()), size_(0) {}
1396 
1397   btree(const btree &other) : btree(other, other.allocator()) {}
1398   btree(const btree &other, const allocator_type &alloc)
1399       : btree(other.key_comp(), alloc) {
1400     copy_or_move_values_in_order(other);
1401   }
1402   btree(btree &&other) noexcept
1403       : root_(std::exchange(other.root_, EmptyNode())),
1404         rightmost_(std::move(other.rightmost_)),
1405         size_(std::exchange(other.size_, 0u)) {
1406     other.mutable_rightmost() = EmptyNode();
1407   }
1408   btree(btree &&other, const allocator_type &alloc)
1409       : btree(other.key_comp(), alloc) {
1410     if (alloc == other.allocator()) {
1411       swap(other);
1412     } else {
1413       
1414       copy_or_move_values_in_order(other);
1415     }
1416   }
1417 
1418   ~btree() {
1419     
1420     
1421     static_assert(static_assert_validation(), "This call must be elided.");
1422     clear();
1423   }
1424 
1425   
1426   btree &operator=(const btree &other);
1427   btree &operator=(btree &&other) noexcept;
1428 
1429   iterator begin() { return iterator(leftmost()); }
1430   const_iterator begin() const { return const_iterator(leftmost()); }
1431   iterator end() { return iterator(rightmost(), rightmost()->finish()); }
1432   const_iterator end() const {
1433     return const_iterator(rightmost(), rightmost()->finish());
1434   }
1435   reverse_iterator rbegin() { return reverse_iterator(end()); }
1436   const_reverse_iterator rbegin() const {
1437     return const_reverse_iterator(end());
1438   }
1439   reverse_iterator rend() { return reverse_iterator(begin()); }
1440   const_reverse_iterator rend() const {
1441     return const_reverse_iterator(begin());
1442   }
1443 
1444   
1445   template <typename K>
1446   iterator lower_bound(const K &key) {
1447     return internal_end(internal_lower_bound(key).value);
1448   }
1449   template <typename K>
1450   const_iterator lower_bound(const K &key) const {
1451     return internal_end(internal_lower_bound(key).value);
1452   }
1453 
1454   
1455   
1456   template <typename K>
1457   std::pair<iterator, bool> lower_bound_equal(const K &key) const;
1458 
1459   
1460   template <typename K>
1461   iterator upper_bound(const K &key) {
1462     return internal_end(internal_upper_bound(key));
1463   }
1464   template <typename K>
1465   const_iterator upper_bound(const K &key) const {
1466     return internal_end(internal_upper_bound(key));
1467   }
1468 
1469   
1470   
1471   
1472   template <typename K>
1473   std::pair<iterator, iterator> equal_range(const K &key);
1474   template <typename K>
1475   std::pair<const_iterator, const_iterator> equal_range(const K &key) const {
1476     return const_cast<btree *>(this)->equal_range(key);
1477   }
1478 
1479   
1480   
1481   
1482   
1483   template <typename K, typename... Args>
1484   std::pair<iterator, bool> insert_unique(const K &key, Args &&...args);
1485 
1486   
1487   
1488   
1489   
1490   
1491   
1492   template <typename K, typename... Args>
1493   std::pair<iterator, bool> insert_hint_unique(iterator position, const K &key,
1494                                                Args &&...args);
1495 
1496   
1497   
1498   
1499   template <typename InputIterator,
1500             typename = decltype(std::declval<const key_compare &>()(
1501                 params_type::key(*std::declval<InputIterator>()),
1502                 std::declval<const key_type &>()))>
1503   void insert_iterator_unique(InputIterator b, InputIterator e, int);
1504   
1505   
1506   template <typename InputIterator>
1507   void insert_iterator_unique(InputIterator b, InputIterator e, char);
1508 
1509   
1510   template <typename ValueType>
1511   iterator insert_multi(const key_type &key, ValueType &&v);
1512 
1513   
1514   template <typename ValueType>
1515   iterator insert_multi(ValueType &&v) {
1516     return insert_multi(params_type::key(v), std::forward<ValueType>(v));
1517   }
1518 
1519   
1520   
1521   
1522   
1523   template <typename ValueType>
1524   iterator insert_hint_multi(iterator position, ValueType &&v);
1525 
1526   
1527   template <typename InputIterator>
1528   void insert_iterator_multi(InputIterator b,
1529                              InputIterator e);
1530 
1531   
1532   
1533   
1534   
1535   iterator erase(iterator iter);
1536 
1537   
1538   
1539   std::pair<size_type, iterator> erase_range(iterator begin, iterator end);
1540 
1541   
1542   
1543   template <typename K>
1544   iterator find(const K &key) {
1545     return internal_end(internal_find(key));
1546   }
1547   template <typename K>
1548   const_iterator find(const K &key) const {
1549     return internal_end(internal_find(key));
1550   }
1551 
1552   
1553   void clear();
1554 
1555   
1556   void swap(btree &other);
1557 
1558   const key_compare &key_comp() const noexcept {
1559     return rightmost_.template get<0>();
1560   }
1561   template <typename K1, typename K2>
1562   bool compare_keys(const K1 &a, const K2 &b) const {
1563     return compare_internal::compare_result_as_less_than(key_comp()(a, b));
1564   }
1565 
1566   value_compare value_comp() const {
1567     return value_compare(original_key_compare(key_comp()));
1568   }
1569 
1570   
1571   void verify() const;
1572 
1573   
1574   size_type size() const { return size_; }
1575   size_type max_size() const { return (std::numeric_limits<size_type>::max)(); }
1576   bool empty() const { return size_ == 0; }
1577 
1578   
1579   size_type height() const {
1580     size_type h = 0;
1581     if (!empty()) {
1582       
1583       
1584       
1585       
1586       const node_type *n = root();
1587       do {
1588         ++h;
1589         n = n->parent();
1590       } while (n != root());
1591     }
1592     return h;
1593   }
1594 
1595   
1596   size_type leaf_nodes() const { return internal_stats(root()).leaf_nodes; }
1597   size_type internal_nodes() const {
1598     return internal_stats(root()).internal_nodes;
1599   }
1600   size_type nodes() const {
1601     node_stats stats = internal_stats(root());
1602     return stats.leaf_nodes + stats.internal_nodes;
1603   }
1604 
1605   
1606   
1607   size_type bytes_used() const {
1608     node_stats stats = internal_stats(root());
1609     if (stats.leaf_nodes == 1 && stats.internal_nodes == 0) {
1610       return sizeof(*this) + node_type::LeafSize(root()->max_count());
1611     } else {
1612       return sizeof(*this) + stats.leaf_nodes * node_type::LeafSize() +
1613              stats.internal_nodes * node_type::InternalSize();
1614     }
1615   }
1616 
1617   
1618   
1619   static double average_bytes_per_value() {
1620     
1621     
1622     const double expected_values_per_node = (kNodeSlots + kMinNodeValues) / 2.0;
1623     return node_type::LeafSize() / expected_values_per_node;
1624   }
1625 
1626   
1627   
1628   
1629   
1630   
1631   double fullness() const {
1632     if (empty()) return 0.0;
1633     return static_cast<double>(size()) / (nodes() * kNodeSlots);
1634   }
1635   
1636   
1637   
1638   
1639   double overhead() const {
1640     if (empty()) return 0.0;
1641     return (bytes_used() - size() * sizeof(value_type)) /
1642            static_cast<double>(size());
1643   }
1644 
1645   
1646   allocator_type get_allocator() const { return allocator(); }
1647 
1648  private:
1649   friend struct btree_access;
1650 
1651   
1652   node_type *root() { return root_; }
1653   const node_type *root() const { return root_; }
1654   node_type *&mutable_root() noexcept { return root_; }
1655   node_type *rightmost() { return rightmost_.template get<2>(); }
1656   const node_type *rightmost() const { return rightmost_.template get<2>(); }
1657   node_type *&mutable_rightmost() noexcept {
1658     return rightmost_.template get<2>();
1659   }
1660   key_compare *mutable_key_comp() noexcept {
1661     return &rightmost_.template get<0>();
1662   }
1663 
1664   
1665   node_type *leftmost() { return root()->parent(); }
1666   const node_type *leftmost() const { return root()->parent(); }
1667 
1668   
1669   allocator_type *mutable_allocator() noexcept {
1670     return &rightmost_.template get<1>();
1671   }
1672   const allocator_type &allocator() const noexcept {
1673     return rightmost_.template get<1>();
1674   }
1675 
1676   
1677   
1678   node_type *allocate(size_type size) {
1679     return reinterpret_cast<node_type *>(
1680         absl::container_internal::Allocate<node_type::Alignment()>(
1681             mutable_allocator(), size));
1682   }
1683 
1684   
1685   node_type *new_internal_node(field_type position, node_type *parent) {
1686     node_type *n = allocate(node_type::InternalSize());
1687     n->init_internal(position, parent);
1688     return n;
1689   }
1690   node_type *new_leaf_node(field_type position, node_type *parent) {
1691     node_type *n = allocate(node_type::LeafSize());
1692     n->init_leaf(position, kNodeSlots, parent);
1693     return n;
1694   }
1695   node_type *new_leaf_root_node(field_type max_count) {
1696     node_type *n = allocate(node_type::LeafSize(max_count));
1697     n->init_leaf(0, max_count, n);
1698     return n;
1699   }
1700 
1701   
1702   iterator rebalance_after_delete(iterator iter);
1703 
1704   
1705   void rebalance_or_split(iterator *iter);
1706 
1707   
1708   
1709   void merge_nodes(node_type *left, node_type *right);
1710 
1711   
1712   
1713   
1714   
1715   bool try_merge_or_rebalance(iterator *iter);
1716 
1717   
1718   void try_shrink();
1719 
1720   iterator internal_end(iterator iter) {
1721     return iter.node_ != nullptr ? iter : end();
1722   }
1723   const_iterator internal_end(const_iterator iter) const {
1724     return iter.node_ != nullptr ? iter : end();
1725   }
1726 
1727   
1728   
1729   template <typename... Args>
1730   iterator internal_emplace(iterator iter, Args &&...args);
1731 
1732   
1733   
1734   
1735   
1736   template <typename IterType>
1737   static IterType internal_last(IterType iter);
1738 
1739   
1740   
1741   
1742   
1743   
1744   
1745   template <typename K>
1746   SearchResult<iterator, is_key_compare_to::value> internal_locate(
1747       const K &key) const;
1748 
1749   
1750   template <typename K>
1751   SearchResult<iterator, is_key_compare_to::value> internal_lower_bound(
1752       const K &key) const;
1753 
1754   
1755   template <typename K>
1756   iterator internal_upper_bound(const K &key) const;
1757 
1758   
1759   template <typename K>
1760   iterator internal_find(const K &key) const;
1761 
1762   
1763   size_type internal_verify(const node_type *node, const key_type *lo,
1764                             const key_type *hi) const;
1765 
1766   node_stats internal_stats(const node_type *node) const {
1767     
1768     if (node == nullptr || (node == root() && empty())) {
1769       return node_stats(0, 0);
1770     }
1771     if (node->is_leaf()) {
1772       return node_stats(1, 0);
1773     }
1774     node_stats res(0, 1);
1775     for (int i = node->start(); i <= node->finish(); ++i) {
1776       res += internal_stats(node->child(i));
1777     }
1778     return res;
1779   }
1780 
1781   node_type *root_;
1782 
1783   
1784   
1785   
1786   absl::container_internal::CompressedTuple<key_compare, allocator_type,
1787                                             node_type *>
1788       rightmost_;
1789 
1790   
1791   size_type size_;
1792 };
1793 
1794 
1795 
1796 template <typename P>
1797 template <typename... Args>
1798 inline void btree_node<P>::emplace_value(const field_type i,
1799                                          allocator_type *alloc,
1800                                          Args &&...args) {
1801   assert(i >= start());
1802   assert(i <= finish());
1803   
1804   
1805   if (i < finish()) {
1806     transfer_n_backward(finish() - i, i + 1, i, this,
1807                         alloc);
1808   }
1809   value_init(static_cast<field_type>(i), alloc, std::forward<Args>(args)...);
1810   set_finish(finish() + 1);
1811 
1812   if (is_internal() && finish() > i + 1) {
1813     for (field_type j = finish(); j > i + 1; --j) {
1814       set_child(j, child(j - 1));
1815     }
1816     clear_child(i + 1);
1817   }
1818 }
1819 
1820 template <typename P>
1821 inline void btree_node<P>::remove_values(const field_type i,
1822                                          const field_type to_erase,
1823                                          allocator_type *alloc) {
1824   
1825   value_destroy_n(i, to_erase, alloc);
1826   const field_type orig_finish = finish();
1827   const field_type src_i = i + to_erase;
1828   transfer_n(orig_finish - src_i, i, src_i, this, alloc);
1829 
1830   if (is_internal()) {
1831     
1832     for (field_type j = 0; j < to_erase; ++j) {
1833       clear_and_delete(child(i + j + 1), alloc);
1834     }
1835     
1836     for (field_type j = i + to_erase + 1; j <= orig_finish; ++j) {
1837       set_child(j - to_erase, child(j));
1838       clear_child(j);
1839     }
1840   }
1841   set_finish(orig_finish - to_erase);
1842 }
1843 
1844 template <typename P>
1845 void btree_node<P>::rebalance_right_to_left(field_type to_move,
1846                                             btree_node *right,
1847                                             allocator_type *alloc) {
1848   assert(parent() == right->parent());
1849   assert(position() + 1 == right->position());
1850   assert(right->count() >= count());
1851   assert(to_move >= 1);
1852   assert(to_move <= right->count());
1853 
1854   
1855   transfer(finish(), position(), parent(), alloc);
1856 
1857   
1858   transfer_n(to_move - 1, finish() + 1, right->start(), right, alloc);
1859 
1860   
1861   parent()->transfer(position(), right->start() + to_move - 1, right, alloc);
1862 
1863   
1864   right->transfer_n(right->count() - to_move, right->start(),
1865                     right->start() + to_move, right, alloc);
1866 
1867   if (is_internal()) {
1868     
1869     for (field_type i = 0; i < to_move; ++i) {
1870       init_child(finish() + i + 1, right->child(i));
1871     }
1872     for (field_type i = right->start(); i <= right->finish() - to_move; ++i) {
1873       assert(i + to_move <= right->max_count());
1874       right->init_child(i, right->child(i + to_move));
1875       right->clear_child(i + to_move);
1876     }
1877   }
1878 
1879   
1880   set_finish(finish() + to_move);
1881   right->set_finish(right->finish() - to_move);
1882 }
1883 
1884 template <typename P>
1885 void btree_node<P>::rebalance_left_to_right(field_type to_move,
1886                                             btree_node *right,
1887                                             allocator_type *alloc) {
1888   assert(parent() == right->parent());
1889   assert(position() + 1 == right->position());
1890   assert(count() >= right->count());
1891   assert(to_move >= 1);
1892   assert(to_move <= count());
1893 
1894   
1895   
1896   
1897   
1898   
1899 
1900   
1901   right->transfer_n_backward(right->count(), right->start() + to_move,
1902                              right->start(), right, alloc);
1903 
1904   
1905   right->transfer(right->start() + to_move - 1, position(), parent(), alloc);
1906 
1907   
1908   right->transfer_n(to_move - 1, right->start(), finish() - (to_move - 1), this,
1909                     alloc);
1910 
1911   
1912   parent()->transfer(position(), finish() - to_move, this, alloc);
1913 
1914   if (is_internal()) {
1915     
1916     for (field_type i = right->finish() + 1; i > right->start(); --i) {
1917       right->init_child(i - 1 + to_move, right->child(i - 1));
1918       right->clear_child(i - 1);
1919     }
1920     for (field_type i = 1; i <= to_move; ++i) {
1921       right->init_child(i - 1, child(finish() - to_move + i));
1922       clear_child(finish() - to_move + i);
1923     }
1924   }
1925 
1926   
1927   set_finish(finish() - to_move);
1928   right->set_finish(right->finish() + to_move);
1929 }
1930 
1931 template <typename P>
1932 void btree_node<P>::split(const int insert_position, btree_node *dest,
1933                           allocator_type *alloc) {
1934   assert(dest->count() == 0);
1935   assert(max_count() == kNodeSlots);
1936   assert(position() + 1 == dest->position());
1937   assert(parent() == dest->parent());
1938 
1939   
1940   
1941   
1942   
1943   if (insert_position == start()) {
1944     dest->set_finish(dest->start() + finish() - 1);
1945   } else if (insert_position == kNodeSlots) {
1946     dest->set_finish(dest->start());
1947   } else {
1948     dest->set_finish(dest->start() + count() / 2);
1949   }
1950   set_finish(finish() - dest->count());
1951   assert(count() >= 1);
1952 
1953   
1954   dest->transfer_n(dest->count(), dest->start(), finish(), this, alloc);
1955 
1956   
1957   --mutable_finish();
1958   parent()->emplace_value(position(), alloc, finish_slot());
1959   value_destroy(finish(), alloc);
1960   parent()->set_child_noupdate_position(position() + 1, dest);
1961 
1962   if (is_internal()) {
1963     for (field_type i = dest->start(), j = finish() + 1; i <= dest->finish();
1964          ++i, ++j) {
1965       assert(child(j) != nullptr);
1966       dest->init_child(i, child(j));
1967       clear_child(j);
1968     }
1969   }
1970 }
1971 
1972 template <typename P>
1973 void btree_node<P>::merge(btree_node *src, allocator_type *alloc) {
1974   assert(parent() == src->parent());
1975   assert(position() + 1 == src->position());
1976 
1977   
1978   value_init(finish(), alloc, parent()->slot(position()));
1979 
1980   
1981   transfer_n(src->count(), finish() + 1, src->start(), src, alloc);
1982 
1983   if (is_internal()) {
1984     
1985     for (field_type i = src->start(), j = finish() + 1; i <= src->finish();
1986          ++i, ++j) {
1987       init_child(j, src->child(i));
1988       src->clear_child(i);
1989     }
1990   }
1991 
1992   
1993   set_finish(start() + 1 + count() + src->count());
1994   src->set_finish(src->start());
1995 
1996   
1997   parent()->remove_values(position(), 1, alloc);
1998 }
1999 
2000 template <typename P>
2001 void btree_node<P>::clear_and_delete(btree_node *node, allocator_type *alloc) {
2002   if (node->is_leaf()) {
2003     node->value_destroy_n(node->start(), node->count(), alloc);
2004     deallocate(LeafSize(node->max_count()), node, alloc);
2005     return;
2006   }
2007   if (node->count() == 0) {
2008     deallocate(InternalSize(), node, alloc);
2009     return;
2010   }
2011 
2012   
2013   btree_node *delete_root_parent = node->parent();
2014 
2015   
2016   while (node->is_internal()) node = node->start_child();
2017 #ifdef ABSL_BTREE_ENABLE_GENERATIONS
2018   
2019   
2020   
2021   
2022   
2023   btree_node *leftmost_leaf = node;
2024 #endif
2025   
2026   
2027   size_type pos = node->position();
2028   btree_node *parent = node->parent();
2029   for (;;) {
2030     
2031     assert(pos <= parent->finish());
2032     do {
2033       node = parent->child(static_cast<field_type>(pos));
2034       if (node->is_internal()) {
2035         
2036         while (node->is_internal()) node = node->start_child();
2037         pos = node->position();
2038         parent = node->parent();
2039       }
2040       node->value_destroy_n(node->start(), node->count(), alloc);
2041 #ifdef ABSL_BTREE_ENABLE_GENERATIONS
2042       if (leftmost_leaf != node)
2043 #endif
2044         deallocate(LeafSize(node->max_count()), node, alloc);
2045       ++pos;
2046     } while (pos <= parent->finish());
2047 
2048     
2049     assert(pos > parent->finish());
2050     do {
2051       node = parent;
2052       pos = node->position();
2053       parent = node->parent();
2054       node->value_destroy_n(node->start(), node->count(), alloc);
2055       deallocate(InternalSize(), node, alloc);
2056       if (parent == delete_root_parent) {
2057 #ifdef ABSL_BTREE_ENABLE_GENERATIONS
2058         deallocate(LeafSize(leftmost_leaf->max_count()), leftmost_leaf, alloc);
2059 #endif
2060         return;
2061       }
2062       ++pos;
2063     } while (pos > parent->finish());
2064   }
2065 }
2066 
2067 
2068 
2069 
2070 
2071 template <typename N, typename R, typename P>
2072 auto btree_iterator<N, R, P>::distance_slow(const_iterator other) const
2073     -> difference_type {
2074   const_iterator begin = other;
2075   const_iterator end = *this;
2076   assert(begin.node_ != end.node_ || !begin.node_->is_leaf() ||
2077          begin.position_ != end.position_);
2078 
2079   const node_type *node = begin.node_;
2080   
2081   difference_type count = node->is_leaf() ? -begin.position_ : 0;
2082 
2083   
2084   if (node->is_internal()) {
2085     ++count;
2086     node = node->child(begin.position_ + 1);
2087   }
2088   while (node->is_internal()) node = node->start_child();
2089 
2090   
2091   
2092   size_type pos = node->position();
2093   const node_type *parent = node->parent();
2094   for (;;) {
2095     
2096     assert(pos <= parent->finish());
2097     do {
2098       node = parent->child(static_cast<field_type>(pos));
2099       if (node->is_internal()) {
2100         
2101         while (node->is_internal()) node = node->start_child();
2102         pos = node->position();
2103         parent = node->parent();
2104       }
2105       if (node == end.node_) return count + end.position_;
2106       if (parent == end.node_ && pos == static_cast<size_type>(end.position_))
2107         return count + node->count();
2108       
2109       count += node->count() + 1;
2110       ++pos;
2111     } while (pos <= parent->finish());
2112 
2113     
2114     assert(pos > parent->finish());
2115     do {
2116       node = parent;
2117       pos = node->position();
2118       parent = node->parent();
2119       
2120       if (parent == end.node_ && pos == static_cast<size_type>(end.position_))
2121         return count - 1;
2122       ++pos;
2123     } while (pos > parent->finish());
2124   }
2125 }
2126 
2127 template <typename N, typename R, typename P>
2128 void btree_iterator<N, R, P>::increment_slow() {
2129   if (node_->is_leaf()) {
2130     assert(position_ >= node_->finish());
2131     btree_iterator save(*this);
2132     while (position_ == node_->finish() && !node_->is_root()) {
2133       assert(node_->parent()->child(node_->position()) == node_);
2134       position_ = node_->position();
2135       node_ = node_->parent();
2136     }
2137     
2138     if (position_ == node_->finish()) {
2139       *this = save;
2140     }
2141   } else {
2142     assert(position_ < node_->finish());
2143     node_ = node_->child(static_cast<field_type>(position_ + 1));
2144     while (node_->is_internal()) {
2145       node_ = node_->start_child();
2146     }
2147     position_ = node_->start();
2148   }
2149 }
2150 
2151 template <typename N, typename R, typename P>
2152 void btree_iterator<N, R, P>::decrement_slow() {
2153   if (node_->is_leaf()) {
2154     assert(position_ <= -1);
2155     btree_iterator save(*this);
2156     while (position_ < node_->start() && !node_->is_root()) {
2157       assert(node_->parent()->child(node_->position()) == node_);
2158       position_ = node_->position() - 1;
2159       node_ = node_->parent();
2160     }
2161     
2162     if (position_ < node_->start()) {
2163       *this = save;
2164     }
2165   } else {
2166     assert(position_ >= node_->start());
2167     node_ = node_->child(static_cast<field_type>(position_));
2168     while (node_->is_internal()) {
2169       node_ = node_->child(node_->finish());
2170     }
2171     position_ = node_->finish() - 1;
2172   }
2173 }
2174 
2175 
2176 
2177 template <typename P>
2178 template <typename Btree>
2179 void btree<P>::copy_or_move_values_in_order(Btree &other) {
2180   static_assert(std::is_same<btree, Btree>::value ||
2181                     std::is_same<const btree, Btree>::value,
2182                 "Btree type must be same or const.");
2183   assert(empty());
2184 
2185   
2186   
2187   auto iter = other.begin();
2188   if (iter == other.end()) return;
2189   insert_multi(iter.slot());
2190   ++iter;
2191   for (; iter != other.end(); ++iter) {
2192     
2193     
2194     internal_emplace(end(), iter.slot());
2195   }
2196 }
2197 
2198 template <typename P>
2199 constexpr bool btree<P>::static_assert_validation() {
2200   static_assert(std::is_nothrow_copy_constructible<key_compare>::value,
2201                 "Key comparison must be nothrow copy constructible");
2202   static_assert(std::is_nothrow_copy_constructible<allocator_type>::value,
2203                 "Allocator must be nothrow copy constructible");
2204   static_assert(std::is_trivially_copyable<iterator>::value,
2205                 "iterator not trivially copyable.");
2206 
2207   
2208   
2209   static_assert(
2210       kNodeSlots < (1 << (8 * sizeof(typename node_type::field_type))),
2211       "target node size too large");
2212 
2213   
2214   static_assert(
2215       compare_has_valid_result_type<key_compare, key_type>(),
2216       "key comparison function must return absl::{weak,strong}_ordering or "
2217       "bool.");
2218 
2219   
2220   static_assert(node_type::MinimumOverhead() >= sizeof(void *) + 4,
2221                 "node space assumption incorrect");
2222 
2223   return true;
2224 }
2225 
2226 template <typename P>
2227 template <typename K>
2228 auto btree<P>::lower_bound_equal(const K &key) const
2229     -> std::pair<iterator, bool> {
2230   const SearchResult<iterator, is_key_compare_to::value> res =
2231       internal_lower_bound(key);
2232   const iterator lower = iterator(internal_end(res.value));
2233   const bool equal = res.HasMatch()
2234                          ? res.IsEq()
2235                          : lower != end() && !compare_keys(key, lower.key());
2236   return {lower, equal};
2237 }
2238 
2239 template <typename P>
2240 template <typename K>
2241 auto btree<P>::equal_range(const K &key) -> std::pair<iterator, iterator> {
2242   const std::pair<iterator, bool> lower_and_equal = lower_bound_equal(key);
2243   const iterator lower = lower_and_equal.first;
2244   if (!lower_and_equal.second) {
2245     return {lower, lower};
2246   }
2247 
2248   const iterator next = std::next(lower);
2249   if (!params_type::template can_have_multiple_equivalent_keys<K>()) {
2250     
2251     
2252     
2253     
2254     assert(next == end() || compare_keys(key, next.key()));
2255     return {lower, next};
2256   }
2257   
2258   
2259   
2260   
2261   if (next == end() || compare_keys(key, next.key())) return {lower, next};
2262 
2263   
2264   
2265   return {lower, upper_bound(key)};
2266 }
2267 
2268 template <typename P>
2269 template <typename K, typename... Args>
2270 auto btree<P>::insert_unique(const K &key, Args &&...args)
2271     -> std::pair<iterator, bool> {
2272   if (empty()) {
2273     mutable_root() = mutable_rightmost() = new_leaf_root_node(1);
2274   }
2275 
2276   SearchResult<iterator, is_key_compare_to::value> res = internal_locate(key);
2277   iterator iter = res.value;
2278 
2279   if (res.HasMatch()) {
2280     if (res.IsEq()) {
2281       
2282       return {iter, false};
2283     }
2284   } else {
2285     iterator last = internal_last(iter);
2286     if (last.node_ && !compare_keys(key, last.key())) {
2287       
2288       return {last, false};
2289     }
2290   }
2291   return {internal_emplace(iter, std::forward<Args>(args)...), true};
2292 }
2293 
2294 template <typename P>
2295 template <typename K, typename... Args>
2296 inline auto btree<P>::insert_hint_unique(iterator position, const K &key,
2297                                          Args &&...args)
2298     -> std::pair<iterator, bool> {
2299   if (!empty()) {
2300     if (position == end() || compare_keys(key, position.key())) {
2301       if (position == begin() || compare_keys(std::prev(position).key(), key)) {
2302         
2303         return {internal_emplace(position, std::forward<Args>(args)...), true};
2304       }
2305     } else if (compare_keys(position.key(), key)) {
2306       ++position;
2307       if (position == end() || compare_keys(key, position.key())) {
2308         
2309         return {internal_emplace(position, std::forward<Args>(args)...), true};
2310       }
2311     } else {
2312       
2313       return {position, false};
2314     }
2315   }
2316   return insert_unique(key, std::forward<Args>(args)...);
2317 }
2318 
2319 template <typename P>
2320 template <typename InputIterator, typename>
2321 void btree<P>::insert_iterator_unique(InputIterator b, InputIterator e, int) {
2322   for (; b != e; ++b) {
2323     insert_hint_unique(end(), params_type::key(*b), *b);
2324   }
2325 }
2326 
2327 template <typename P>
2328 template <typename InputIterator>
2329 void btree<P>::insert_iterator_unique(InputIterator b, InputIterator e, char) {
2330   for (; b != e; ++b) {
2331     
2332     auto node_handle =
2333         CommonAccess::Construct<node_handle_type>(get_allocator(), *b);
2334     slot_type *slot = CommonAccess::GetSlot(node_handle);
2335     insert_hint_unique(end(), params_type::key(slot), slot);
2336   }
2337 }
2338 
2339 template <typename P>
2340 template <typename ValueType>
2341 auto btree<P>::insert_multi(const key_type &key, ValueType &&v) -> iterator {
2342   if (empty()) {
2343     mutable_root() = mutable_rightmost() = new_leaf_root_node(1);
2344   }
2345 
2346   iterator iter = internal_upper_bound(key);
2347   if (iter.node_ == nullptr) {
2348     iter = end();
2349   }
2350   return internal_emplace(iter, std::forward<ValueType>(v));
2351 }
2352 
2353 template <typename P>
2354 template <typename ValueType>
2355 auto btree<P>::insert_hint_multi(iterator position, ValueType &&v) -> iterator {
2356   if (!empty()) {
2357     const key_type &key = params_type::key(v);
2358     if (position == end() || !compare_keys(position.key(), key)) {
2359       if (position == begin() ||
2360           !compare_keys(key, std::prev(position).key())) {
2361         
2362         return internal_emplace(position, std::forward<ValueType>(v));
2363       }
2364     } else {
2365       ++position;
2366       if (position == end() || !compare_keys(position.key(), key)) {
2367         
2368         return internal_emplace(position, std::forward<ValueType>(v));
2369       }
2370     }
2371   }
2372   return insert_multi(std::forward<ValueType>(v));
2373 }
2374 
2375 template <typename P>
2376 template <typename InputIterator>
2377 void btree<P>::insert_iterator_multi(InputIterator b, InputIterator e) {
2378   for (; b != e; ++b) {
2379     insert_hint_multi(end(), *b);
2380   }
2381 }
2382 
2383 template <typename P>
2384 auto btree<P>::operator=(const btree &other) -> btree & {
2385   if (this != &other) {
2386     clear();
2387 
2388     *mutable_key_comp() = other.key_comp();
2389     if (absl::allocator_traits<
2390             allocator_type>::propagate_on_container_copy_assignment::value) {
2391       *mutable_allocator() = other.allocator();
2392     }
2393 
2394     copy_or_move_values_in_order(other);
2395   }
2396   return *this;
2397 }
2398 
2399 template <typename P>
2400 auto btree<P>::operator=(btree &&other) noexcept -> btree & {
2401   if (this != &other) {
2402     clear();
2403 
2404     using std::swap;
2405     if (absl::allocator_traits<
2406             allocator_type>::propagate_on_container_move_assignment::value) {
2407       swap(root_, other.root_);
2408       
2409       swap(rightmost_, other.rightmost_);
2410       swap(size_, other.size_);
2411     } else {
2412       if (allocator() == other.allocator()) {
2413         swap(mutable_root(), other.mutable_root());
2414         swap(*mutable_key_comp(), *other.mutable_key_comp());
2415         swap(mutable_rightmost(), other.mutable_rightmost());
2416         swap(size_, other.size_);
2417       } else {
2418         
2419         
2420         
2421         
2422         
2423         *mutable_key_comp() = other.key_comp();
2424         copy_or_move_values_in_order(other);
2425       }
2426     }
2427   }
2428   return *this;
2429 }
2430 
2431 template <typename P>
2432 auto btree<P>::erase(iterator iter) -> iterator {
2433   iter.node_->value_destroy(static_cast<field_type>(iter.position_),
2434                             mutable_allocator());
2435   iter.update_generation();
2436 
2437   const bool internal_delete = iter.node_->is_internal();
2438   if (internal_delete) {
2439     
2440     
2441     
2442     iterator internal_iter(iter);
2443     --iter;
2444     assert(iter.node_->is_leaf());
2445     internal_iter.node_->transfer(
2446         static_cast<size_type>(internal_iter.position_),
2447         static_cast<size_type>(iter.position_), iter.node_,
2448         mutable_allocator());
2449   } else {
2450     
2451     
2452     const field_type transfer_from =
2453         static_cast<field_type>(iter.position_ + 1);
2454     const field_type num_to_transfer = iter.node_->finish() - transfer_from;
2455     iter.node_->transfer_n(num_to_transfer,
2456                            static_cast<size_type>(iter.position_),
2457                            transfer_from, iter.node_, mutable_allocator());
2458   }
2459   
2460   iter.node_->set_finish(iter.node_->finish() - 1);
2461   --size_;
2462 
2463   
2464   
2465   
2466   
2467   
2468   
2469 
2470   iterator res = rebalance_after_delete(iter);
2471 
2472   
2473   if (internal_delete) {
2474     ++res;
2475   }
2476   return res;
2477 }
2478 
2479 template <typename P>
2480 auto btree<P>::rebalance_after_delete(iterator iter) -> iterator {
2481   
2482   iterator res(iter);
2483   bool first_iteration = true;
2484   for (;;) {
2485     if (iter.node_ == root()) {
2486       try_shrink();
2487       if (empty()) {
2488         return end();
2489       }
2490       break;
2491     }
2492     if (iter.node_->count() >= kMinNodeValues) {
2493       break;
2494     }
2495     bool merged = try_merge_or_rebalance(&iter);
2496     
2497     
2498     if (first_iteration) {
2499       res = iter;
2500       first_iteration = false;
2501     }
2502     if (!merged) {
2503       break;
2504     }
2505     iter.position_ = iter.node_->position();
2506     iter.node_ = iter.node_->parent();
2507   }
2508   res.update_generation();
2509 
2510   
2511   
2512   if (res.position_ == res.node_->finish()) {
2513     res.position_ = res.node_->finish() - 1;
2514     ++res;
2515   }
2516 
2517   return res;
2518 }
2519 
2520 
2521 
2522 
2523 
2524 template <typename P>
2525 auto btree<P>::erase_range(iterator begin, iterator end)
2526     -> std::pair<size_type, iterator> {
2527   size_type count = static_cast<size_type>(end - begin);
2528   assert(count >= 0);
2529 
2530   if (count == 0) {
2531     return {0, begin};
2532   }
2533 
2534   if (static_cast<size_type>(count) == size_) {
2535     clear();
2536     return {count, this->end()};
2537   }
2538 
2539   if (begin.node_ == end.node_) {
2540     assert(end.position_ > begin.position_);
2541     begin.node_->remove_values(
2542         static_cast<field_type>(begin.position_),
2543         static_cast<field_type>(end.position_ - begin.position_),
2544         mutable_allocator());
2545     size_ -= count;
2546     return {count, rebalance_after_delete(begin)};
2547   }
2548 
2549   const size_type target_size = size_ - count;
2550   while (size_ > target_size) {
2551     if (begin.node_->is_leaf()) {
2552       const size_type remaining_to_erase = size_ - target_size;
2553       const size_type remaining_in_node =
2554           static_cast<size_type>(begin.node_->finish() - begin.position_);
2555       const field_type to_erase = static_cast<field_type>(
2556           (std::min)(remaining_to_erase, remaining_in_node));
2557       begin.node_->remove_values(static_cast<field_type>(begin.position_),
2558                                  to_erase, mutable_allocator());
2559       size_ -= to_erase;
2560       begin = rebalance_after_delete(begin);
2561     } else {
2562       begin = erase(begin);
2563     }
2564   }
2565   begin.update_generation();
2566   return {count, begin};
2567 }
2568 
2569 template <typename P>
2570 void btree<P>::clear() {
2571   if (!empty()) {
2572     node_type::clear_and_delete(root(), mutable_allocator());
2573   }
2574   mutable_root() = mutable_rightmost() = EmptyNode();
2575   size_ = 0;
2576 }
2577 
2578 template <typename P>
2579 void btree<P>::swap(btree &other) {
2580   using std::swap;
2581   if (absl::allocator_traits<
2582           allocator_type>::propagate_on_container_swap::value) {
2583     
2584     swap(rightmost_, other.rightmost_);
2585   } else {
2586     
2587     assert(allocator() == other.allocator());
2588     swap(mutable_rightmost(), other.mutable_rightmost());
2589     swap(*mutable_key_comp(), *other.mutable_key_comp());
2590   }
2591   swap(mutable_root(), other.mutable_root());
2592   swap(size_, other.size_);
2593 }
2594 
2595 template <typename P>
2596 void btree<P>::verify() const {
2597   assert(root() != nullptr);
2598   assert(leftmost() != nullptr);
2599   assert(rightmost() != nullptr);
2600   assert(empty() || size() == internal_verify(root(), nullptr, nullptr));
2601   assert(leftmost() == (++const_iterator(root(), -1)).node_);
2602   assert(rightmost() == (--const_iterator(root(), root()->finish())).node_);
2603   assert(leftmost()->is_leaf());
2604   assert(rightmost()->is_leaf());
2605 }
2606 
2607 template <typename P>
2608 void btree<P>::rebalance_or_split(iterator *iter) {
2609   node_type *&node = iter->node_;
2610   int &insert_position = iter->position_;
2611   assert(node->count() == node->max_count());
2612   assert(kNodeSlots == node->max_count());
2613 
2614   
2615   node_type *parent = node->parent();
2616   if (node != root()) {
2617     if (node->position() > parent->start()) {
2618       
2619       node_type *left = parent->child(node->position() - 1);
2620       assert(left->max_count() == kNodeSlots);
2621       if (left->count() < kNodeSlots) {
2622         
2623         
2624         
2625         field_type to_move =
2626             (kNodeSlots - left->count()) /
2627             (1 + (static_cast<field_type>(insert_position) < kNodeSlots));
2628         to_move = (std::max)(field_type{1}, to_move);
2629 
2630         if (static_cast<field_type>(insert_position) - to_move >=
2631                 node->start() ||
2632             left->count() + to_move < kNodeSlots) {
2633           left->rebalance_right_to_left(to_move, node, mutable_allocator());
2634 
2635           assert(node->max_count() - node->count() == to_move);
2636           insert_position = static_cast<int>(
2637               static_cast<field_type>(insert_position) - to_move);
2638           if (insert_position < node->start()) {
2639             insert_position = insert_position + left->count() + 1;
2640             node = left;
2641           }
2642 
2643           assert(node->count() < node->max_count());
2644           return;
2645         }
2646       }
2647     }
2648 
2649     if (node->position() < parent->finish()) {
2650       
2651       node_type *right = parent->child(node->position() + 1);
2652       assert(right->max_count() == kNodeSlots);
2653       if (right->count() < kNodeSlots) {
2654         
2655         
2656         
2657         field_type to_move = (kNodeSlots - right->count()) /
2658                              (1 + (insert_position > node->start()));
2659         to_move = (std::max)(field_type{1}, to_move);
2660 
2661         if (static_cast<field_type>(insert_position) <=
2662                 node->finish() - to_move ||
2663             right->count() + to_move < kNodeSlots) {
2664           node->rebalance_left_to_right(to_move, right, mutable_allocator());
2665 
2666           if (insert_position > node->finish()) {
2667             insert_position = insert_position - node->count() - 1;
2668             node = right;
2669           }
2670 
2671           assert(node->count() < node->max_count());
2672           return;
2673         }
2674       }
2675     }
2676 
2677     
2678     
2679     assert(parent->max_count() == kNodeSlots);
2680     if (parent->count() == kNodeSlots) {
2681       iterator parent_iter(parent, node->position());
2682       rebalance_or_split(&parent_iter);
2683       parent = node->parent();
2684     }
2685   } else {
2686     
2687     
2688     
2689     parent = new_internal_node(0, parent);
2690     parent->set_generation(root()->generation());
2691     parent->init_child(parent->start(), node);
2692     mutable_root() = parent;
2693     
2694     assert(parent->start_child()->is_internal() ||
2695            parent->start_child() == rightmost());
2696   }
2697 
2698   
2699   node_type *split_node;
2700   if (node->is_leaf()) {
2701     split_node = new_leaf_node(node->position() + 1, parent);
2702     node->split(insert_position, split_node, mutable_allocator());
2703     if (rightmost() == node) mutable_rightmost() = split_node;
2704   } else {
2705     split_node = new_internal_node(node->position() + 1, parent);
2706     node->split(insert_position, split_node, mutable_allocator());
2707   }
2708 
2709   if (insert_position > node->finish()) {
2710     insert_position = insert_position - node->count() - 1;
2711     node = split_node;
2712   }
2713 }
2714 
2715 template <typename P>
2716 void btree<P>::merge_nodes(node_type *left, node_type *right) {
2717   left->merge(right, mutable_allocator());
2718   if (rightmost() == right) mutable_rightmost() = left;
2719 }
2720 
2721 template <typename P>
2722 bool btree<P>::try_merge_or_rebalance(iterator *iter) {
2723   node_type *parent = iter->node_->parent();
2724   if (iter->node_->position() > parent->start()) {
2725     
2726     node_type *left = parent->child(iter->node_->position() - 1);
2727     assert(left->max_count() == kNodeSlots);
2728     if (1U + left->count() + iter->node_->count() <= kNodeSlots) {
2729       iter->position_ += 1 + left->count();
2730       merge_nodes(left, iter->node_);
2731       iter->node_ = left;
2732       return true;
2733     }
2734   }
2735   if (iter->node_->position() < parent->finish()) {
2736     
2737     node_type *right = parent->child(iter->node_->position() + 1);
2738     assert(right->max_count() == kNodeSlots);
2739     if (1U + iter->node_->count() + right->count() <= kNodeSlots) {
2740       merge_nodes(iter->node_, right);
2741       return true;
2742     }
2743     
2744     
2745     
2746     
2747     if (right->count() > kMinNodeValues &&
2748         (iter->node_->count() == 0 || iter->position_ > iter->node_->start())) {
2749       field_type to_move = (right->count() - iter->node_->count()) / 2;
2750       to_move =
2751           (std::min)(to_move, static_cast<field_type>(right->count() - 1));
2752       iter->node_->rebalance_right_to_left(to_move, right, mutable_allocator());
2753       return false;
2754     }
2755   }
2756   if (iter->node_->position() > parent->start()) {
2757     
2758     
2759     
2760     
2761     node_type *left = parent->child(iter->node_->position() - 1);
2762     if (left->count() > kMinNodeValues &&
2763         (iter->node_->count() == 0 ||
2764          iter->position_ < iter->node_->finish())) {
2765       field_type to_move = (left->count() - iter->node_->count()) / 2;
2766       to_move = (std::min)(to_move, static_cast<field_type>(left->count() - 1));
2767       left->rebalance_left_to_right(to_move, iter->node_, mutable_allocator());
2768       iter->position_ += to_move;
2769       return false;
2770     }
2771   }
2772   return false;
2773 }
2774 
2775 template <typename P>
2776 void btree<P>::try_shrink() {
2777   node_type *orig_root = root();
2778   if (orig_root->count() > 0) {
2779     return;
2780   }
2781   
2782   if (orig_root->is_leaf()) {
2783     assert(size() == 0);
2784     mutable_root() = mutable_rightmost() = EmptyNode();
2785   } else {
2786     node_type *child = orig_root->start_child();
2787     child->make_root();
2788     mutable_root() = child;
2789   }
2790   node_type::clear_and_delete(orig_root, mutable_allocator());
2791 }
2792 
2793 template <typename P>
2794 template <typename IterType>
2795 inline IterType btree<P>::internal_last(IterType iter) {
2796   assert(iter.node_ != nullptr);
2797   while (iter.position_ == iter.node_->finish()) {
2798     iter.position_ = iter.node_->position();
2799     iter.node_ = iter.node_->parent();
2800     if (iter.node_->is_leaf()) {
2801       iter.node_ = nullptr;
2802       break;
2803     }
2804   }
2805   iter.update_generation();
2806   return iter;
2807 }
2808 
2809 template <typename P>
2810 template <typename... Args>
2811 inline auto btree<P>::internal_emplace(iterator iter, Args &&...args)
2812     -> iterator {
2813   if (iter.node_->is_internal()) {
2814     
2815     
2816     --iter;
2817     ++iter.position_;
2818   }
2819   const field_type max_count = iter.node_->max_count();
2820   allocator_type *alloc = mutable_allocator();
2821 
2822   const auto transfer_and_delete = [&](node_type *old_node,
2823                                        node_type *new_node) {
2824     new_node->transfer_n(old_node->count(), new_node->start(),
2825                          old_node->start(), old_node, alloc);
2826     new_node->set_finish(old_node->finish());
2827     old_node->set_finish(old_node->start());
2828     new_node->set_generation(old_node->generation());
2829     node_type::clear_and_delete(old_node, alloc);
2830   };
2831   const auto replace_leaf_root_node = [&](field_type new_node_size) {
2832     assert(iter.node_ == root());
2833     node_type *old_root = iter.node_;
2834     node_type *new_root = iter.node_ = new_leaf_root_node(new_node_size);
2835     transfer_and_delete(old_root, new_root);
2836     mutable_root() = mutable_rightmost() = new_root;
2837   };
2838 
2839   bool replaced_node = false;
2840   if (iter.node_->count() == max_count) {
2841     
2842     if (max_count < kNodeSlots) {
2843       
2844       
2845       replace_leaf_root_node(static_cast<field_type>(
2846           (std::min)(static_cast<int>(kNodeSlots), 2 * max_count)));
2847       replaced_node = true;
2848     } else {
2849       rebalance_or_split(&iter);
2850     }
2851   }
2852   (void)replaced_node;
2853 #if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \
2854     defined(ABSL_HAVE_HWADDRESS_SANITIZER)
2855   if (!replaced_node) {
2856     assert(iter.node_->is_leaf());
2857     if (iter.node_->is_root()) {
2858       replace_leaf_root_node(max_count);
2859     } else {
2860       node_type *old_node = iter.node_;
2861       const bool was_rightmost = rightmost() == old_node;
2862       const bool was_leftmost = leftmost() == old_node;
2863       node_type *parent = old_node->parent();
2864       const field_type position = old_node->position();
2865       node_type *new_node = iter.node_ = new_leaf_node(position, parent);
2866       parent->set_child_noupdate_position(position, new_node);
2867       transfer_and_delete(old_node, new_node);
2868       if (was_rightmost) mutable_rightmost() = new_node;
2869       
2870       if (was_leftmost) root()->set_parent(new_node);
2871     }
2872   }
2873 #endif
2874   iter.node_->emplace_value(static_cast<field_type>(iter.position_), alloc,
2875                             std::forward<Args>(args)...);
2876   assert(
2877       iter.node_->is_ordered_correctly(static_cast<field_type>(iter.position_),
2878                                        original_key_compare(key_comp())) &&
2879       "If this assert fails, then either (1) the comparator may violate "
2880       "transitivity, i.e. comp(a,b) && comp(b,c) -> comp(a,c) (see "
2881       "https://en.cppreference.com/w/cpp/named_req/Compare), or (2) a "
2882       "key may have been mutated after it was inserted into the tree.");
2883   ++size_;
2884   iter.update_generation();
2885   return iter;
2886 }
2887 
2888 template <typename P>
2889 template <typename K>
2890 inline auto btree<P>::internal_locate(const K &key) const
2891     -> SearchResult<iterator, is_key_compare_to::value> {
2892   iterator iter(const_cast<node_type *>(root()));
2893   for (;;) {
2894     SearchResult<size_type, is_key_compare_to::value> res =
2895         iter.node_->lower_bound(key, key_comp());
2896     iter.position_ = static_cast<int>(res.value);
2897     if (res.IsEq()) {
2898       return {iter, MatchKind::kEq};
2899     }
2900     
2901     
2902     
2903     
2904     if (iter.node_->is_leaf()) {
2905       break;
2906     }
2907     iter.node_ = iter.node_->child(static_cast<field_type>(iter.position_));
2908   }
2909   
2910   
2911   return {iter, MatchKind::kNe};
2912 }
2913 
2914 template <typename P>
2915 template <typename K>
2916 auto btree<P>::internal_lower_bound(const K &key) const
2917     -> SearchResult<iterator, is_key_compare_to::value> {
2918   if (!params_type::template can_have_multiple_equivalent_keys<K>()) {
2919     SearchResult<iterator, is_key_compare_to::value> ret = internal_locate(key);
2920     ret.value = internal_last(ret.value);
2921     return ret;
2922   }
2923   iterator iter(const_cast<node_type *>(root()));
2924   SearchResult<size_type, is_key_compare_to::value> res;
2925   bool seen_eq = false;
2926   for (;;) {
2927     res = iter.node_->lower_bound(key, key_comp());
2928     iter.position_ = static_cast<int>(res.value);
2929     if (iter.node_->is_leaf()) {
2930       break;
2931     }
2932     seen_eq = seen_eq || res.IsEq();
2933     iter.node_ = iter.node_->child(static_cast<field_type>(iter.position_));
2934   }
2935   if (res.IsEq()) return {iter, MatchKind::kEq};
2936   return {internal_last(iter), seen_eq ? MatchKind::kEq : MatchKind::kNe};
2937 }
2938 
2939 template <typename P>
2940 template <typename K>
2941 auto btree<P>::internal_upper_bound(const K &key) const -> iterator {
2942   iterator iter(const_cast<node_type *>(root()));
2943   for (;;) {
2944     iter.position_ = static_cast<int>(iter.node_->upper_bound(key, key_comp()));
2945     if (iter.node_->is_leaf()) {
2946       break;
2947     }
2948     iter.node_ = iter.node_->child(static_cast<field_type>(iter.position_));
2949   }
2950   return internal_last(iter);
2951 }
2952 
2953 template <typename P>
2954 template <typename K>
2955 auto btree<P>::internal_find(const K &key) const -> iterator {
2956   SearchResult<iterator, is_key_compare_to::value> res = internal_locate(key);
2957   if (res.HasMatch()) {
2958     if (res.IsEq()) {
2959       return res.value;
2960     }
2961   } else {
2962     const iterator iter = internal_last(res.value);
2963     if (iter.node_ != nullptr && !compare_keys(key, iter.key())) {
2964       return iter;
2965     }
2966   }
2967   return {nullptr, 0};
2968 }
2969 
2970 template <typename P>
2971 typename btree<P>::size_type btree<P>::internal_verify(
2972     const node_type *node, const key_type *lo, const key_type *hi) const {
2973   assert(node->count() > 0);
2974   assert(node->count() <= node->max_count());
2975   if (lo) {
2976     assert(!compare_keys(node->key(node->start()), *lo));
2977   }
2978   if (hi) {
2979     assert(!compare_keys(*hi, node->key(node->finish() - 1)));
2980   }
2981   for (int i = node->start() + 1; i < node->finish(); ++i) {
2982     assert(!compare_keys(node->key(i), node->key(i - 1)));
2983   }
2984   size_type count = node->count();
2985   if (node->is_internal()) {
2986     for (field_type i = node->start(); i <= node->finish(); ++i) {
2987       assert(node->child(i) != nullptr);
2988       assert(node->child(i)->parent() == node);
2989       assert(node->child(i)->position() == i);
2990       count += internal_verify(node->child(i),
2991                                i == node->start() ? lo : &node->key(i - 1),
2992                                i == node->finish() ? hi : &node->key(i));
2993     }
2994   }
2995   return count;
2996 }
2997 
2998 struct btree_access {
2999   template <typename BtreeContainer, typename Pred>
3000   static auto erase_if(BtreeContainer &container, Pred pred) ->
3001       typename BtreeContainer::size_type {
3002     const auto initial_size = container.size();
3003     auto &tree = container.tree_;
3004     auto *alloc = tree.mutable_allocator();
3005     for (auto it = container.begin(); it != container.end();) {
3006       if (!pred(*it)) {
3007         ++it;
3008         continue;
3009       }
3010       auto *node = it.node_;
3011       if (node->is_internal()) {
3012         
3013         it = container.erase(it);
3014         continue;
3015       }
3016       
3017       
3018 
3019       
3020       int to_pos = it.position_;
3021       node->value_destroy(it.position_, alloc);
3022       while (++it.position_ < node->finish()) {
3023         it.update_generation();
3024         if (pred(*it)) {
3025           node->value_destroy(it.position_, alloc);
3026         } else {
3027           node->transfer(node->slot(to_pos++), node->slot(it.position_), alloc);
3028         }
3029       }
3030       const int num_deleted = node->finish() - to_pos;
3031       tree.size_ -= num_deleted;
3032       node->set_finish(to_pos);
3033       it.position_ = to_pos;
3034       it = tree.rebalance_after_delete(it);
3035     }
3036     return initial_size - container.size();
3037   }
3038 };
3039 
3040 #undef ABSL_BTREE_ENABLE_GENERATIONS
3041 
3042 }  
3043 ABSL_NAMESPACE_END
3044 }  
3045 
3046 #endif