NIM 跨平台 C++ SDK
载入中...
搜索中...
未找到
btree.h
浏览该文件的文档.
1// ---------------------------------------------------------------------------
2// Copyright (c) 2019, Gregory Popovitch - greg7mdp@gmail.com
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// https://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16// Includes work from abseil-cpp (https://github.com/abseil/abseil-cpp)
17// with modifications.
18//
19// Copyright 2018 The Abseil Authors.
20//
21// Licensed under the Apache License, Version 2.0 (the "License");
22// you may not use this file except in compliance with the License.
23// You may obtain a copy of the License at
24//
25// https://www.apache.org/licenses/LICENSE-2.0
26//
27// Unless required by applicable law or agreed to in writing, software
28// distributed under the License is distributed on an "AS IS" BASIS,
29// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
30// See the License for the specific language governing permissions and
31// limitations under the License.
32// ---------------------------------------------------------------------------
33
34#ifndef PHMAP_BTREE_BTREE_CONTAINER_H_
35#define PHMAP_BTREE_BTREE_CONTAINER_H_
36
37#ifdef _MSC_VER
38 #pragma warning(push)
39
40 #pragma warning(disable : 4127) // conditional expression is constant
41 #pragma warning(disable : 4324) // structure was padded due to alignment specifier
42 #pragma warning(disable : 4355) // 'this': used in base member initializer list
43 #pragma warning(disable : 4365) // conversion from 'int' to 'const unsigned __int64', signed/unsigned mismatch
44 #pragma warning(disable : 4514) // unreferenced inline function has been removed
45 #pragma warning(disable : 4623) // default constructor was implicitly defined as deleted
46 #pragma warning(disable : 4625) // copy constructor was implicitly defined as deleted
47 #pragma warning(disable : 4626) // assignment operator was implicitly defined as deleted
48 #pragma warning(disable : 4710) // function not inlined
49 #pragma warning(disable : 4711) // selected for automatic inline expansion
50 #pragma warning(disable : 4820) // '6' bytes padding added after data member
51 #pragma warning(disable : 4868) // compiler may not enforce left-to-right evaluation order in braced initializer list
52 #pragma warning(disable : 5026) // move constructor was implicitly defined as deleted
53 #pragma warning(disable : 5027) // move assignment operator was implicitly defined as deleted
54 #pragma warning(disable : 5045) // Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified
55#endif
56
57
58#include <cstdint>
59#include <cstdlib>
60#include <cstring>
61#include <limits>
62#include <new>
63
64#include "phmap_fwd_decl.h"
65#include "phmap_base.h"
66
67#if PHMAP_HAVE_STD_STRING_VIEW
68 #include <string_view>
69#endif
70
71// MSVC constructibility traits do not detect destructor properties and so our
72// implementations should not use them as a source-of-truth.
73#if defined(_MSC_VER) && !defined(__clang__) && !defined(__GNUC__)
74 #define PHMAP_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION 1
75#endif
76
77namespace phmap {
78
79 // Defined and documented later on in this file.
80 template <typename T>
82
83 // Defined and documented later on in this file.
84 template <typename T>
86
87 namespace type_traits_internal {
88
89 // Silence MSVC warnings about the destructor being defined as deleted.
90#if defined(_MSC_VER) && !defined(__GNUC__)
91 #pragma warning(push)
92 #pragma warning(disable : 4624)
93#endif // defined(_MSC_VER) && !defined(__GNUC__)
94
95 template <class T>
97 T t;
98 };
99
100 // Restore the state of the destructor warning that was silenced above.
101#if defined(_MSC_VER) && !defined(__GNUC__)
102 #pragma warning(pop)
103#endif // defined(_MSC_VER) && !defined(__GNUC__)
104
105 template <class T>
107 : std::integral_constant<
108 bool, std::is_move_constructible<
109 type_traits_internal::SingleMemberUnion<T>>::value &&
110 phmap::is_trivially_destructible<T>::value> {};
111
112 template <class T>
114 : std::integral_constant<
115 bool, std::is_copy_constructible<
116 type_traits_internal::SingleMemberUnion<T>>::value &&
117 phmap::is_trivially_destructible<T>::value> {};
118
119 template <class T>
120 struct IsTriviallyMoveAssignableReference : std::false_type {};
121
122 template <class T>
125
126 template <class T>
129
130 } // namespace type_traits_internal
131
132
133 template <typename... Ts>
134 using void_t = typename type_traits_internal::VoidTImpl<Ts...>::type;
135
136
137 template <typename T>
139 : std::integral_constant<
140 bool, !(std::is_reference<T>::value ||
141 std::is_const<typename std::add_const<T>::type>::value)> {};
142
143
144 namespace type_traits_internal {
145
146 template <typename T>
148 using ExtentsRemoved = typename std::remove_all_extents<T>::type;
149 static constexpr bool kIsCopyOrMoveConstructible =
150 std::is_copy_constructible<ExtentsRemoved>::value ||
151 std::is_move_constructible<ExtentsRemoved>::value;
152 static constexpr bool kIsCopyOrMoveAssignable =
155
156 public:
157 static constexpr bool kValue =
158 (__has_trivial_copy(ExtentsRemoved) || !kIsCopyOrMoveConstructible) &&
159 (__has_trivial_assign(ExtentsRemoved) || !kIsCopyOrMoveAssignable) &&
162 // We need to check for this explicitly because otherwise we'll say
163 // references are trivial copyable when compiled by MSVC.
164 !std::is_reference<ExtentsRemoved>::value;
165 };
166
167 template <typename T>
169 : std::integral_constant<
170 bool, type_traits_internal::is_trivially_copyable_impl<T>::kValue> {};
171 } // namespace type_traits_internal
172
173 namespace swap_internal {
174
175 // Necessary for the traits.
176 using std::swap;
177
178 // This declaration prevents global `swap` and `phmap::swap` overloads from being
179 // considered unless ADL picks them up.
180 void swap();
181
182 template <class T>
183 using IsSwappableImpl = decltype(swap(std::declval<T&>(), std::declval<T&>()));
184
185 // NOTE: This dance with the default template parameter is for MSVC.
186 template <class T,
187 class IsNoexcept = std::integral_constant<
188 bool, noexcept(swap(std::declval<T&>(), std::declval<T&>()))>>
189 using IsNothrowSwappableImpl = typename std::enable_if<IsNoexcept::value>::type;
190
191 template <class T>
194
195 template <class T>
198
199 template <class T, phmap::enable_if_t<IsSwappable<T>::value, int> = 0>
200 void Swap(T& lhs, T& rhs) noexcept(IsNothrowSwappable<T>::value) {
201 swap(lhs, rhs);
202 }
203
205
206 } // namespace swap_internal
207
208 namespace type_traits_internal {
209
210 // Make the swap-related traits/function accessible from this namespace.
215
216 } // namespace type_traits_internal
217
218 namespace compare_internal {
219
220 using value_type = int8_t;
221
222 template <typename T>
223 struct Fail {
224 static_assert(sizeof(T) < 0, "Only literal `0` is allowed.");
225 };
226
227 template <typename NullPtrT = std::nullptr_t>
229 constexpr OnlyLiteralZero(NullPtrT) noexcept {} // NOLINT
230
231 template <
232 typename T,
233 typename = typename std::enable_if<
234 std::is_same<T, std::nullptr_t>::value ||
235 (std::is_integral<T>::value && !std::is_same<T, int>::value)>::type,
236 typename = typename Fail<T>::type>
237 OnlyLiteralZero(T); // NOLINT
238 };
239
240 enum class eq : value_type {
241 equal = 0,
243 nonequal = 1,
245 };
246
247 enum class ord : value_type { less = -1, greater = 1 };
248
249 enum class ncmp : value_type { unordered = -127 };
250
251#if defined(__cpp_inline_variables) && !defined(_MSC_VER)
252
253#define PHMAP_COMPARE_INLINE_BASECLASS_DECL(name)
254
255#define PHMAP_COMPARE_INLINE_SUBCLASS_DECL(type, name) \
256 static const type name;
257
258#define PHMAP_COMPARE_INLINE_INIT(type, name, init) \
259 inline constexpr type type::name(init)
260
261#else // __cpp_inline_variables
262
263#define PHMAP_COMPARE_INLINE_BASECLASS_DECL(name) \
264 static const T name;
265
266#define PHMAP_COMPARE_INLINE_SUBCLASS_DECL(type, name)
267
268#define PHMAP_COMPARE_INLINE_INIT(type, name, init) \
269 template <typename T> \
270 const T compare_internal::type##_base<T>::name(init)
271
272#endif // __cpp_inline_variables
273
274 // These template base classes allow for defining the values of the constants
275 // in the header file (for performance) without using inline variables (which
276 // aren't available in C++11).
277 template <typename T>
281 };
282
283 template <typename T>
289 };
290
291 template <typename T>
297 };
298
299 template <typename T>
304 };
305
306 template <typename T>
312 };
313
314 } // namespace compare_internal
315
318 explicit constexpr weak_equality(compare_internal::eq v) noexcept
319 : value_(static_cast<compare_internal::value_type>(v)) {}
321
322 public:
325
326 // Comparisons
327 friend constexpr bool operator==(
328 weak_equality v, compare_internal::OnlyLiteralZero<>) noexcept {
329 return v.value_ == 0;
330 }
331 friend constexpr bool operator!=(
333 return v.value_ != 0;
334 }
336 weak_equality v) noexcept {
337 return 0 == v.value_;
338 }
340 weak_equality v) noexcept {
341 return 0 != v.value_;
342 }
343
344 private:
346 };
351
354 explicit constexpr strong_equality(compare_internal::eq v) noexcept
355 : value_(static_cast<compare_internal::value_type>(v)) {}
357
358 public:
363
364 // Conversion
365 constexpr operator weak_equality() const noexcept { // NOLINT
366 return value_ == 0 ? weak_equality::equivalent
367 : weak_equality::nonequivalent;
368 }
369 // Comparisons
370 friend constexpr bool operator==(
372 return v.value_ == 0;
373 }
374 friend constexpr bool operator!=(
376 return v.value_ != 0;
377 }
379 strong_equality v) noexcept {
380 return 0 == v.value_;
381 }
383 strong_equality v) noexcept {
384 return 0 != v.value_;
385 }
386
387 private:
389 };
390
398
401 explicit constexpr partial_ordering(compare_internal::eq v) noexcept
402 : value_(static_cast<compare_internal::value_type>(v)) {}
403 explicit constexpr partial_ordering(compare_internal::ord v) noexcept
404 : value_(static_cast<compare_internal::value_type>(v)) {}
405 explicit constexpr partial_ordering(compare_internal::ncmp v) noexcept
406 : value_(static_cast<compare_internal::value_type>(v)) {}
408
409 constexpr bool is_ordered() const noexcept {
410 return value_ !=
412 }
413
414 public:
419
420 // Conversion
421 constexpr operator weak_equality() const noexcept { // NOLINT
422 return value_ == 0 ? weak_equality::equivalent
423 : weak_equality::nonequivalent;
424 }
425 // Comparisons
426 friend constexpr bool operator==(
428 return v.is_ordered() && v.value_ == 0;
429 }
430 friend constexpr bool operator!=(
432 return !v.is_ordered() || v.value_ != 0;
433 }
434 friend constexpr bool operator<(
436 return v.is_ordered() && v.value_ < 0;
437 }
438 friend constexpr bool operator<=(
440 return v.is_ordered() && v.value_ <= 0;
441 }
442 friend constexpr bool operator>(
444 return v.is_ordered() && v.value_ > 0;
445 }
446 friend constexpr bool operator>=(
448 return v.is_ordered() && v.value_ >= 0;
449 }
451 partial_ordering v) noexcept {
452 return v.is_ordered() && 0 == v.value_;
453 }
455 partial_ordering v) noexcept {
456 return !v.is_ordered() || 0 != v.value_;
457 }
459 partial_ordering v) noexcept {
460 return v.is_ordered() && 0 < v.value_;
461 }
463 partial_ordering v) noexcept {
464 return v.is_ordered() && 0 <= v.value_;
465 }
467 partial_ordering v) noexcept {
468 return v.is_ordered() && 0 > v.value_;
469 }
471 partial_ordering v) noexcept {
472 return v.is_ordered() && 0 >= v.value_;
473 }
474
475 private:
477 };
478
486
488 : public compare_internal::weak_ordering_base<weak_ordering> {
489 explicit constexpr weak_ordering(compare_internal::eq v) noexcept
490 : value_(static_cast<compare_internal::value_type>(v)) {}
491 explicit constexpr weak_ordering(compare_internal::ord v) noexcept
492 : value_(static_cast<compare_internal::value_type>(v)) {}
494
495 public:
499
500 // Conversions
501 constexpr operator weak_equality() const noexcept { // NOLINT
502 return value_ == 0 ? weak_equality::equivalent
503 : weak_equality::nonequivalent;
504 }
505 constexpr operator partial_ordering() const noexcept { // NOLINT
506 return value_ == 0 ? partial_ordering::equivalent
507 : (value_ < 0 ? partial_ordering::less
508 : partial_ordering::greater);
509 }
510 // Comparisons
511 friend constexpr bool operator==(
513 return v.value_ == 0;
514 }
515 friend constexpr bool operator!=(
517 return v.value_ != 0;
518 }
519 friend constexpr bool operator<(
521 return v.value_ < 0;
522 }
523 friend constexpr bool operator<=(
525 return v.value_ <= 0;
526 }
527 friend constexpr bool operator>(
529 return v.value_ > 0;
530 }
531 friend constexpr bool operator>=(
533 return v.value_ >= 0;
534 }
536 weak_ordering v) noexcept {
537 return 0 == v.value_;
538 }
540 weak_ordering v) noexcept {
541 return 0 != v.value_;
542 }
544 weak_ordering v) noexcept {
545 return 0 < v.value_;
546 }
548 weak_ordering v) noexcept {
549 return 0 <= v.value_;
550 }
552 weak_ordering v) noexcept {
553 return 0 > v.value_;
554 }
556 weak_ordering v) noexcept {
557 return 0 >= v.value_;
558 }
559
560 private:
562 };
563
569
571 : public compare_internal::strong_ordering_base<strong_ordering> {
572 explicit constexpr strong_ordering(compare_internal::eq v) noexcept
573 : value_(static_cast<compare_internal::value_type>(v)) {}
574 explicit constexpr strong_ordering(compare_internal::ord v) noexcept
575 : value_(static_cast<compare_internal::value_type>(v)) {}
577
578 public:
583
584 // Conversions
585 constexpr operator weak_equality() const noexcept { // NOLINT
586 return value_ == 0 ? weak_equality::equivalent
587 : weak_equality::nonequivalent;
588 }
589 constexpr operator strong_equality() const noexcept { // NOLINT
590 return value_ == 0 ? strong_equality::equal : strong_equality::nonequal;
591 }
592 constexpr operator partial_ordering() const noexcept { // NOLINT
593 return value_ == 0 ? partial_ordering::equivalent
594 : (value_ < 0 ? partial_ordering::less
595 : partial_ordering::greater);
596 }
597 constexpr operator weak_ordering() const noexcept { // NOLINT
598 return value_ == 0
599 ? weak_ordering::equivalent
600 : (value_ < 0 ? weak_ordering::less : weak_ordering::greater);
601 }
602 // Comparisons
603 friend constexpr bool operator==(
605 return v.value_ == 0;
606 }
607 friend constexpr bool operator!=(
609 return v.value_ != 0;
610 }
611 friend constexpr bool operator<(
613 return v.value_ < 0;
614 }
615 friend constexpr bool operator<=(
617 return v.value_ <= 0;
618 }
619 friend constexpr bool operator>(
621 return v.value_ > 0;
622 }
623 friend constexpr bool operator>=(
625 return v.value_ >= 0;
626 }
628 strong_ordering v) noexcept {
629 return 0 == v.value_;
630 }
632 strong_ordering v) noexcept {
633 return 0 != v.value_;
634 }
636 strong_ordering v) noexcept {
637 return 0 < v.value_;
638 }
640 strong_ordering v) noexcept {
641 return 0 <= v.value_;
642 }
644 strong_ordering v) noexcept {
645 return 0 > v.value_;
646 }
648 strong_ordering v) noexcept {
649 return 0 >= v.value_;
650 }
651
652 private:
654 };
661
662#undef PHMAP_COMPARE_INLINE_BASECLASS_DECL
663#undef PHMAP_COMPARE_INLINE_SUBCLASS_DECL
664#undef PHMAP_COMPARE_INLINE_INIT
665
666 namespace compare_internal {
667 // We also provide these comparator adapter functions for internal phmap use.
668
669 // Helper functions to do a boolean comparison of two keys given a boolean
670 // or three-way comparator.
671 // SFINAE prevents implicit conversions to bool (such as from int).
672 template <typename BoolType,
674 constexpr bool compare_result_as_less_than(const BoolType r) { return r; }
676 return r < 0;
677 }
678
679 template <typename Compare, typename K, typename LK>
680 constexpr bool do_less_than_comparison(const Compare &compare, const K &x,
681 const LK &y) {
682 return compare_result_as_less_than(compare(x, y));
683 }
684
685 // Helper functions to do a three-way comparison of two keys given a boolean or
686 // three-way comparator.
687 // SFINAE prevents implicit conversions to int (such as from bool).
688 template <typename Int,
691 return c < 0 ? phmap::weak_ordering::less
692 : c == 0 ? phmap::weak_ordering::equivalent
693 : phmap::weak_ordering::greater;
694 }
696 const phmap::weak_ordering c) {
697 return c;
698 }
699
700 template <
701 typename Compare, typename K, typename LK,
703 Compare, const K &, const LK &>>::value,
704 int> = 0>
705 constexpr phmap::weak_ordering do_three_way_comparison(const Compare &compare,
706 const K &x, const LK &y) {
707 return compare_result_as_ordering(compare(x, y));
708 }
709 template <
710 typename Compare, typename K, typename LK,
711 phmap::enable_if_t<std::is_same<bool, phmap::invoke_result_t<Compare,
712 const K &, const LK &>>::value,
713 int> = 0>
714 constexpr phmap::weak_ordering do_three_way_comparison(const Compare &compare,
715 const K &x, const LK &y) {
716 return compare(x, y) ? phmap::weak_ordering::less
717 : compare(y, x) ? phmap::weak_ordering::greater
718 : phmap::weak_ordering::equivalent;
719 }
720
721 } // namespace compare_internal
722}
723
724
725namespace phmap {
726
727namespace priv {
728
729 // A helper class that indicates if the Compare parameter is a key-compare-to
730 // comparator.
731 template <typename Compare, typename T>
733 std::is_convertible<phmap::invoke_result_t<Compare, const T &, const T &>,
735
737 using is_transparent = void;
738
740
741 // Compatibility constructor.
742 StringBtreeDefaultLess(std::less<std::string>) {} // NOLINT
743#if PHMAP_HAVE_STD_STRING_VIEW
744 StringBtreeDefaultLess(std::less<std::string_view>) {} // NOLINT
746
747 phmap::weak_ordering operator()(std::string_view lhs,
748 std::string_view rhs) const {
749 return compare_internal::compare_result_as_ordering(lhs.compare(rhs));
750 }
751#else
753 std::string rhs) const {
754 return compare_internal::compare_result_as_ordering(lhs.compare(rhs));
755 }
756#endif
757 };
758
760 using is_transparent = void;
761
763
764 StringBtreeDefaultGreater(std::greater<std::string>) {} // NOLINT
765#if PHMAP_HAVE_STD_STRING_VIEW
766 StringBtreeDefaultGreater(std::greater<std::string_view>) {} // NOLINT
767
768 phmap::weak_ordering operator()(std::string_view lhs,
769 std::string_view rhs) const {
770 return compare_internal::compare_result_as_ordering(rhs.compare(lhs));
771 }
772#else
774 std::string rhs) const {
775 return compare_internal::compare_result_as_ordering(rhs.compare(lhs));
776 }
777#endif
778 };
779
780 // A helper class to convert a boolean comparison into a three-way "compare-to"
781 // comparison that returns a negative value to indicate less-than, zero to
782 // indicate equality and a positive value to indicate greater-than. This helper
783 // class is specialized for less<std::string>, greater<std::string>,
784 // less<std::string_view>, and greater<std::string_view>.
785 //
786 // key_compare_to_adapter is provided so that btree users
787 // automatically get the more efficient compare-to code when using common
788 // google string types with common comparison functors.
789 // These string-like specializations also turn on heterogeneous lookup by
790 // default.
791 template <typename Compare>
793 using type = Compare;
794 };
795
796 template <>
797 struct key_compare_to_adapter<std::less<std::string>> {
799 };
800
801 template <>
802 struct key_compare_to_adapter<phmap::Less<std::string>> {
804 };
805
806 template <>
807 struct key_compare_to_adapter<std::greater<std::string>> {
809 };
810
811#if PHMAP_HAVE_STD_STRING_VIEW
812 template <>
813 struct key_compare_to_adapter<std::less<std::string_view>> {
815 };
816
817 template <>
818 struct key_compare_to_adapter<phmap::Less<std::string_view>> {
819 using type = StringBtreeDefaultLess;
820 };
821
822 template <>
823 struct key_compare_to_adapter<std::greater<std::string_view>> {
824 using type = StringBtreeDefaultGreater;
825 };
826#endif
827
828 template <typename Key, typename Compare, typename Alloc, int TargetNodeSize,
829 bool Multi, typename SlotPolicy>
831 // If Compare is a common comparator for a std::string-like type, then we adapt it
832 // to use heterogeneous lookup and to be a key-compare-to comparator.
834 // A type which indicates if we have a key-compare-to functor or a plain old
835 // key-compare functor.
837
838 using allocator_type = Alloc;
839 using key_type = Key;
840 using size_type = std::size_t ;
841 using difference_type = ptrdiff_t;
842
843 // True if this is a multiset or multimap.
844 using is_multi_container = std::integral_constant<bool, Multi>;
845
846 using slot_policy = SlotPolicy;
847 using slot_type = typename slot_policy::slot_type;
848 using value_type = typename slot_policy::value_type;
849 using init_type = typename slot_policy::mutable_value_type;
851 using const_pointer = const value_type *;
854
855 enum {
856 kTargetNodeSize = TargetNodeSize,
857
858 // Upper bound for the available space for values. This is largest for leaf
859 // nodes, which have overhead of at least a pointer + 4 bytes (for storing
860 // 3 field_types and an enum).
862 TargetNodeSize - /*minimum overhead=*/(sizeof(void *) + 4),
863 };
864
865 // This is an integral type large enough to hold as many
866 // ValueSize-values as will fit a node of TargetNodeSize bytes.
869 (std::numeric_limits<uint8_t>::max)()),
870 uint16_t, uint8_t>; // NOLINT
871
872 // The following methods are necessary for passing this struct as PolicyTraits
873 // for node_handle and/or are used within btree.
874 static value_type &element(slot_type *slot) {
875 return slot_policy::element(slot);
876 }
877 static const value_type &element(const slot_type *slot) {
878 return slot_policy::element(slot);
879 }
880 template <class... Args>
881 static void construct(Alloc *alloc, slot_type *slot, Args &&... args) {
882 slot_policy::construct(alloc, slot, std::forward<Args>(args)...);
883 }
884 static void construct(Alloc *alloc, slot_type *slot, slot_type *other) {
885 slot_policy::construct(alloc, slot, other);
886 }
887 static void destroy(Alloc *alloc, slot_type *slot) {
888 slot_policy::destroy(alloc, slot);
889 }
890 static void transfer(Alloc *alloc, slot_type *new_slot, slot_type *old_slot) {
891 construct(alloc, new_slot, old_slot);
892 destroy(alloc, old_slot);
893 }
894 static void swap(Alloc *alloc, slot_type *a, slot_type *b) {
895 slot_policy::swap(alloc, a, b);
896 }
897 static void move(Alloc *alloc, slot_type *src, slot_type *dest) {
898 slot_policy::move(alloc, src, dest);
899 }
900 static void move(Alloc *alloc, slot_type *first, slot_type *last,
901 slot_type *result) {
902 slot_policy::move(alloc, first, last, result);
903 }
904 };
905
906 // A parameters structure for holding the type parameters for a btree_map.
907 // Compare and Alloc should be nothrow copy-constructible.
908 template <typename Key, typename Data, typename Compare, typename Alloc,
909 int TargetNodeSize, bool Multi>
910 struct map_params : common_params<Key, Compare, Alloc, TargetNodeSize, Multi,
911 phmap::priv::map_slot_policy<Key, Data>> {
912 using super_type = typename map_params::common_params;
913 using mapped_type = Data;
914 // This type allows us to move keys when it is safe to do so. It is safe
915 // for maps in which value_type and mutable_value_type are layout compatible.
916 using slot_policy = typename super_type::slot_policy;
917 using slot_type = typename super_type::slot_type;
918 using value_type = typename super_type::value_type;
919 using init_type = typename super_type::init_type;
920
921 using key_compare = typename super_type::key_compare;
922 // Inherit from key_compare for empty base class optimization.
923 struct value_compare : private key_compare {
924 value_compare() = default;
925 explicit value_compare(const key_compare &cmp) : key_compare(cmp) {}
926
927 template <typename T, typename U>
928 auto operator()(const T &left, const U &right) const
929 -> decltype(std::declval<key_compare>()(left.first, right.first)) {
930 return key_compare::operator()(left.first, right.first);
931 }
932 };
933 using is_map_container = std::true_type;
934
935 static const Key &key(const value_type &x) { return x.first; }
936 static const Key &key(const init_type &x) { return x.first; }
937 static const Key &key(const slot_type *x) { return slot_policy::key(x); }
938 static mapped_type &value(value_type *value) { return value->second; }
939 };
940
941 // This type implements the necessary functions from the
942 // btree::priv::slot_type interface.
943 template <typename Key>
945 using slot_type = Key;
946 using value_type = Key;
948
949 static value_type &element(slot_type *slot) { return *slot; }
950 static const value_type &element(const slot_type *slot) { return *slot; }
951
952 template <typename Alloc, class... Args>
953 static void construct(Alloc *alloc, slot_type *slot, Args &&... args) {
955 std::forward<Args>(args)...);
956 }
957
958 template <typename Alloc>
959 static void construct(Alloc *alloc, slot_type *slot, slot_type *other) {
960 phmap::allocator_traits<Alloc>::construct(*alloc, slot, std::move(*other));
961 }
962
963 template <typename Alloc>
964 static void destroy(Alloc *alloc, slot_type *slot) {
966 }
967
968 template <typename Alloc>
969 static void swap(Alloc * /*alloc*/, slot_type *a, slot_type *b) {
970 using std::swap;
971 swap(*a, *b);
972 }
973
974 template <typename Alloc>
975 static void move(Alloc * /*alloc*/, slot_type *src, slot_type *dest) {
976 *dest = std::move(*src);
977 }
978
979 template <typename Alloc>
980 static void move(Alloc *alloc, slot_type *first, slot_type *last,
981 slot_type *result) {
982 for (slot_type *src = first, *dest = result; src != last; ++src, ++dest)
983 move(alloc, src, dest);
984 }
985 };
986
987 // A parameters structure for holding the type parameters for a btree_set.
988 // Compare and Alloc should be nothrow copy-constructible.
989 template <typename Key, typename Compare, typename Alloc, int TargetNodeSize,
990 bool Multi>
991 struct set_params : common_params<Key, Compare, Alloc, TargetNodeSize, Multi,
992 set_slot_policy<Key>> {
993 using value_type = Key;
994 using slot_type = typename set_params::common_params::slot_type;
995 using value_compare = typename set_params::common_params::key_compare;
996 using is_map_container = std::false_type;
997
998 static const Key &key(const value_type &x) { return x; }
999 static const Key &key(const slot_type *x) { return *x; }
1000 };
1001
1002 // An adapter class that converts a lower-bound compare into an upper-bound
1003 // compare. Note: there is no need to make a version of this adapter specialized
1004 // for key-compare-to functors because the upper-bound (the first value greater
1005 // than the input) is never an exact match.
1006 template <typename Compare>
1008 explicit upper_bound_adapter(const Compare &c) : comp(c) {}
1009 template <typename K, typename LK>
1010 bool operator()(const K &a, const LK &b) const {
1011 // Returns true when a is not greater than b.
1013 }
1014
1015 private:
1016 Compare comp;
1017 };
1018
1019 enum class MatchKind : uint8_t { kEq, kNe };
1020
1021 template <typename V, bool IsCompareTo>
1025
1026 static constexpr bool HasMatch() { return true; }
1027 bool IsEq() const { return match == MatchKind::kEq; }
1028 };
1029
1030 // When we don't use CompareTo, `match` is not present.
1031 // This ensures that callers can't use it accidentally when it provides no
1032 // useful information.
1033 template <typename V>
1034 struct SearchResult<V, false> {
1036
1037 static constexpr bool HasMatch() { return false; }
1038 static constexpr bool IsEq() { return false; }
1039 };
1040
1041 // A node in the btree holding. The same node type is used for both internal
1042 // and leaf nodes in the btree, though the nodes are allocated in such a way
1043 // that the children array is only valid in internal nodes.
1044 template <typename Params>
1046 using is_key_compare_to = typename Params::is_key_compare_to;
1047 using is_multi_container = typename Params::is_multi_container;
1048 using field_type = typename Params::node_count_type;
1049 using allocator_type = typename Params::allocator_type;
1050 using slot_type = typename Params::slot_type;
1051
1052 public:
1053 using params_type = Params;
1054 using key_type = typename Params::key_type;
1055 using value_type = typename Params::value_type;
1056 using pointer = typename Params::pointer;
1057 using const_pointer = typename Params::const_pointer;
1058 using reference = typename Params::reference;
1059 using const_reference = typename Params::const_reference;
1060 using key_compare = typename Params::key_compare;
1061 using size_type = typename Params::size_type;
1062 using difference_type = typename Params::difference_type;
1063
1064 // Btree decides whether to use linear node search as follows:
1065 // - If the key is arithmetic and the comparator is std::less or
1066 // std::greater, choose linear.
1067 // - Otherwise, choose binary.
1068 // TODO(ezb): Might make sense to add condition(s) based on node-size.
1069 using use_linear_search = std::integral_constant<
1070 bool,
1071 std::is_arithmetic<key_type>::value &&
1072 (std::is_same<phmap::Less<key_type>, key_compare>::value ||
1073 std::is_same<std::less<key_type>, key_compare>::value ||
1074 std::is_same<std::greater<key_type>, key_compare>::value)>;
1075
1076
1077 ~btree_node() = default;
1078 btree_node(btree_node const &) = delete;
1079 btree_node &operator=(btree_node const &) = delete;
1080
1081 // Public for EmptyNodeType.
1082 constexpr static size_type Alignment() {
1083 static_assert(LeafLayout(1).Alignment() == InternalLayout().Alignment(),
1084 "Alignment of all nodes must be equal.");
1085 return (size_type)InternalLayout().Alignment();
1086 }
1087
1088 protected:
1089 btree_node() = default;
1090
1091 private:
1095 return (size_type)layout_type(/*parent*/ 1,
1096 /*position, start, count, max_count*/ 4,
1097 /*values*/ (size_t)n,
1098 /*children*/ 0)
1099 .AllocSize();
1100 }
1101 // A lower bound for the overhead of fields other than values in a leaf node.
1102 constexpr static size_type MinimumOverhead() {
1103 return (size_type)(SizeWithNValues(1) - sizeof(value_type));
1104 }
1105
1106 // Compute how many values we can fit onto a leaf node taking into account
1107 // padding.
1108 constexpr static size_type NodeTargetValues(const int begin, const int end) {
1109 return begin == end ? begin
1110 : SizeWithNValues((begin + end) / 2 + 1) >
1111 params_type::kTargetNodeSize
1112 ? NodeTargetValues(begin, (begin + end) / 2)
1113 : NodeTargetValues((begin + end) / 2 + 1, end);
1114 }
1115
1116 enum {
1117 kTargetNodeSize = params_type::kTargetNodeSize,
1118 kNodeTargetValues = NodeTargetValues(0, params_type::kTargetNodeSize),
1119
1120 // We need a minimum of 3 values per internal node in order to perform
1121 // splitting (1 value for the two nodes involved in the split and 1 value
1122 // propagated to the parent as the delimiter for the split).
1123 kNodeValues = kNodeTargetValues >= 3 ? kNodeTargetValues : 3,
1124
1125 // The node is internal (i.e. is not a leaf node) if and only if `max_count`
1126 // has this value.
1127 kInternalNodeMaxCount = 0,
1128 };
1129
1130 // Leaves can have less than kNodeValues values.
1131 constexpr static layout_type LeafLayout(const int max_values = kNodeValues) {
1132 return layout_type(/*parent*/ 1,
1133 /*position, start, count, max_count*/ 4,
1134 /*values*/ (size_t)max_values,
1135 /*children*/ 0);
1136 }
1137 constexpr static layout_type InternalLayout() {
1138 return layout_type(/*parent*/ 1,
1139 /*position, start, count, max_count*/ 4,
1140 /*values*/ kNodeValues,
1141 /*children*/ kNodeValues + 1);
1142 }
1143 constexpr static size_type LeafSize(const int max_values = kNodeValues) {
1144 return (size_type)LeafLayout(max_values).AllocSize();
1145 }
1146 constexpr static size_type InternalSize() {
1147 return (size_type)InternalLayout().AllocSize();
1148 }
1149
1150 // N is the index of the type in the Layout definition.
1151 // ElementType<N> is the Nth type in the Layout definition.
1152 template <size_type N>
1153 inline typename layout_type::template ElementType<N> *GetField() {
1154 // We assert that we don't read from values that aren't there.
1155 assert(N < 3 || !leaf());
1156 return InternalLayout().template Pointer<N>(reinterpret_cast<char *>(this));
1157 }
1158
1159 template <size_type N>
1160 inline const typename layout_type::template ElementType<N> *GetField() const {
1161 assert(N < 3 || !leaf());
1162 return InternalLayout().template Pointer<N>(
1163 reinterpret_cast<const char *>(this));
1164 }
1165
1166 void set_parent(btree_node *p) { *GetField<0>() = p; }
1167 field_type &mutable_count() { return GetField<1>()[2]; }
1168 slot_type *slot(size_type i) { return &GetField<2>()[i]; }
1169 const slot_type *slot(size_type i) const { return &GetField<2>()[i]; }
1170 void set_position(field_type v) { GetField<1>()[0] = v; }
1171 void set_start(field_type v) { GetField<1>()[1] = v; }
1172 void set_count(field_type v) { GetField<1>()[2] = v; }
1173 void set_max_count(field_type v) { GetField<1>()[3] = v; }
1174
1175 public:
1176 // Whether this is a leaf node or not. This value doesn't change after the
1177 // node is created.
1178 bool leaf() const { return GetField<1>()[3] != kInternalNodeMaxCount; }
1179
1180 // Getter for the position of this node in its parent.
1181 field_type position() const { return GetField<1>()[0]; }
1182
1183 // Getter for the offset of the first value in the `values` array.
1184 field_type start() const { return GetField<1>()[1]; }
1185
1186 // Getters for the number of values stored in this node.
1187 field_type count() const { return GetField<1>()[2]; }
1189 // Internal nodes have max_count==kInternalNodeMaxCount.
1190 // Leaf nodes have max_count in [1, kNodeValues].
1191 const field_type max_cnt = GetField<1>()[3];
1192 return max_cnt == field_type{kInternalNodeMaxCount}
1193 ? field_type{kNodeValues}
1194 : max_cnt;
1195 }
1196
1197 // Getter for the parent of this node.
1198 btree_node *parent() const { return *GetField<0>(); }
1199 // Getter for whether the node is the root of the tree. The parent of the
1200 // root of the tree is the leftmost node in the tree which is guaranteed to
1201 // be a leaf.
1202 bool is_root() const { return parent()->leaf(); }
1203 void make_root() {
1204 assert(parent()->is_root());
1205 set_parent(parent()->parent());
1206 }
1207
1208 // Getters for the key/value at position i in the node.
1209 const key_type &key(size_type i) const { return params_type::key(slot(i)); }
1210 reference value(size_type i) { return params_type::element(slot(i)); }
1211 const_reference value(size_type i) const { return params_type::element(slot(i)); }
1212
1213#if defined(__GNUC__) || defined(__clang__)
1214#pragma GCC diagnostic push
1215#pragma GCC diagnostic ignored "-Warray-bounds"
1216#endif
1217 // Getters/setter for the child at position i in the node.
1218 btree_node *child(size_type i) const { return GetField<3>()[i]; }
1219 btree_node *&mutable_child(size_type i) { return GetField<3>()[i]; }
1222 }
1225 mutable_child(i) = c;
1226 c->set_position((field_type)i);
1227 }
1228#if defined(__GNUC__) || defined(__clang__)
1229#pragma GCC diagnostic pop
1230#endif
1231 void init_child(int i, btree_node *c) {
1232 set_child(i, c);
1233 c->set_parent(this);
1234 }
1235
1236 // Returns the position of the first value whose key is not less than k.
1237 template <typename K>
1239 const K &k, const key_compare &comp) const {
1240 return use_linear_search::value ? linear_search(k, comp)
1241 : binary_search(k, comp);
1242 }
1243 // Returns the position of the first value whose key is greater than k.
1244 template <typename K>
1245 int upper_bound(const K &k, const key_compare &comp) const {
1246 auto upper_compare = upper_bound_adapter<key_compare>(comp);
1247 return use_linear_search::value ? linear_search(k, upper_compare).value
1248 : binary_search(k, upper_compare).value;
1249 }
1250
1251 template <typename K, typename Compare>
1253 linear_search(const K &k, const Compare &comp) const {
1254 return linear_search_impl(k, 0, count(), comp,
1256 }
1257
1258 template <typename K, typename Compare>
1260 binary_search(const K &k, const Compare &comp) const {
1261 return binary_search_impl(k, 0, count(), comp,
1263 }
1264
1265 // Returns the position of the first value whose key is not less than k using
1266 // linear search performed using plain compare.
1267 template <typename K, typename Compare>
1269 const K &k, int s, const int e, const Compare &comp,
1270 std::false_type /* IsCompareTo */) const {
1271 while (s < e) {
1272 if (!comp(key(s), k)) {
1273 break;
1274 }
1275 ++s;
1276 }
1277 return {s};
1278 }
1279
1280 // Returns the position of the first value whose key is not less than k using
1281 // linear search performed using compare-to.
1282 template <typename K, typename Compare>
1284 const K &k, int s, const int e, const Compare &comp,
1285 std::true_type /* IsCompareTo */) const {
1286 while (s < e) {
1287 const phmap::weak_ordering c = comp(key(s), k);
1288 if (c == 0) {
1289 return {s, MatchKind::kEq};
1290 } else if (c > 0) {
1291 break;
1292 }
1293 ++s;
1294 }
1295 return {s, MatchKind::kNe};
1296 }
1297
1298 // Returns the position of the first value whose key is not less than k using
1299 // binary search performed using plain compare.
1300 template <typename K, typename Compare>
1302 const K &k, int s, int e, const Compare &comp,
1303 std::false_type /* IsCompareTo */) const {
1304 while (s != e) {
1305 const int mid = (s + e) >> 1;
1306 if (comp(key(mid), k)) {
1307 s = mid + 1;
1308 } else {
1309 e = mid;
1310 }
1311 }
1312 return {s};
1313 }
1314
1315 // Returns the position of the first value whose key is not less than k using
1316 // binary search performed using compare-to.
1317 template <typename K, typename CompareTo>
1319 const K &k, int s, int e, const CompareTo &comp,
1320 std::true_type /* IsCompareTo */) const {
1321 if (is_multi_container::value) {
1322 MatchKind exact_match = MatchKind::kNe;
1323 while (s != e) {
1324 const int mid = (s + e) >> 1;
1325 const phmap::weak_ordering c = comp(key(mid), k);
1326 if (c < 0) {
1327 s = mid + 1;
1328 } else {
1329 e = mid;
1330 if (c == 0) {
1331 // Need to return the first value whose key is not less than k,
1332 // which requires continuing the binary search if this is a
1333 // multi-container.
1334 exact_match = MatchKind::kEq;
1335 }
1336 }
1337 }
1338 return {s, exact_match};
1339 } else { // Not a multi-container.
1340 while (s != e) {
1341 const int mid = (s + e) >> 1;
1342 const phmap::weak_ordering c = comp(key(mid), k);
1343 if (c < 0) {
1344 s = mid + 1;
1345 } else if (c > 0) {
1346 e = mid;
1347 } else {
1348 return {mid, MatchKind::kEq};
1349 }
1350 }
1351 return {s, MatchKind::kNe};
1352 }
1353 }
1354
1355 // Emplaces a value at position i, shifting all existing values and
1356 // children at positions >= i to the right by 1.
1357 template <typename... Args>
1358 void emplace_value(size_type i, allocator_type *alloc, Args &&... args);
1359
1360 // Removes the value at position i, shifting all existing values and children
1361 // at positions > i to the left by 1.
1362 void remove_value(int i, allocator_type *alloc);
1363
1364 // Removes the values at positions [i, i + to_erase), shifting all values
1365 // after that range to the left by to_erase. Does not change children at all.
1366 void remove_values_ignore_children(int i, size_type to_erase,
1367 allocator_type *alloc);
1368
1369 // Rebalances a node with its right sibling.
1370 void rebalance_right_to_left(int to_move, btree_node *right,
1371 allocator_type *alloc);
1372 void rebalance_left_to_right(int to_move, btree_node *right,
1373 allocator_type *alloc);
1374
1375 // Splits a node, moving a portion of the node's values to its right sibling.
1376 void split(int insert_position, btree_node *dest, allocator_type *alloc);
1377
1378 // Merges a node with its right sibling, moving all of the values and the
1379 // delimiting key in the parent node onto itself.
1380 void merge(btree_node *sibling, allocator_type *alloc);
1381
1382 // Swap the contents of "this" and "src".
1383 void swap(btree_node *src, allocator_type *alloc);
1384
1385 // Node allocation/deletion routines.
1387 int max_cnt) {
1388 n->set_parent(parent);
1389 n->set_position(0);
1390 n->set_start(0);
1391 n->set_count(0);
1392 n->set_max_count((field_type)max_cnt);
1394 n->slot(0), max_cnt * sizeof(slot_type));
1395 return n;
1396 }
1398 init_leaf(n, parent, kNodeValues);
1399 // Set `max_count` to a sentinel value to indicate that this node is
1400 // internal.
1401 n->set_max_count(kInternalNodeMaxCount);
1403 &n->mutable_child(0), (kNodeValues + 1) * sizeof(btree_node *));
1404 return n;
1405 }
1407 for (int i = 0; i < count(); ++i) {
1408 value_destroy(i, alloc);
1409 }
1410 }
1411
1412 public:
1413 // Exposed only for tests.
1415 return use_linear_search::value;
1416 }
1417
1418 private:
1419 template <typename... Args>
1420 void value_init(const size_type i, allocator_type *alloc, Args &&... args) {
1422 params_type::construct(alloc, slot(i), std::forward<Args>(args)...);
1423 }
1425 params_type::destroy(alloc, slot(i));
1427 }
1428
1429 // Move n values starting at value i in this node into the values starting at
1430 // value j in node x.
1432 const size_type j, btree_node *x,
1433 allocator_type *alloc) {
1435 x->slot(j), n * sizeof(slot_type));
1436 for (slot_type *src = slot(i), *end = src + n, *dest = x->slot(j);
1437 src != end; ++src, ++dest) {
1438 params_type::construct(alloc, dest, src);
1439 }
1440 }
1441
1442 // Destroys a range of n values, starting at index i.
1443 void value_destroy_n(const size_type i, const size_type n,
1444 allocator_type *alloc) {
1445 for (size_type j = 0; j < n; ++j) {
1446 value_destroy(i + j, alloc);
1447 }
1448 }
1449
1450 template <typename P>
1451 friend class btree;
1452 template <typename N, typename R, typename P>
1453 friend struct btree_iterator;
1454 friend class BtreeNodePeer;
1455 };
1456
1457 template <typename Node, typename Reference, typename Pointer>
1459 private:
1460 using key_type = typename Node::key_type;
1461 using size_type = typename Node::size_type;
1462 using params_type = typename Node::params_type;
1463
1464 using node_type = Node;
1465 using normal_node = typename std::remove_const<Node>::type;
1466 using const_node = const Node;
1467 using normal_pointer = typename params_type::pointer;
1468 using normal_reference = typename params_type::reference;
1469 using const_pointer = typename params_type::const_pointer;
1470 using const_reference = typename params_type::const_reference;
1471 using slot_type = typename params_type::slot_type;
1472
1473 using iterator =
1477
1478 public:
1479 // These aliases are public for std::iterator_traits.
1480 using difference_type = typename Node::difference_type;
1481 using value_type = typename params_type::value_type;
1482 using pointer = Pointer;
1483 using reference = Reference;
1484 using iterator_category = std::bidirectional_iterator_tag;
1485
1486 btree_iterator() : node(nullptr), position(-1) {}
1487 btree_iterator(Node *n, int p) : node(n), position(p) {}
1488
1489 // NOTE: this SFINAE allows for implicit conversions from iterator to
1490 // const_iterator, but it specifically avoids defining copy constructors so
1491 // that btree_iterator can be trivially copyable. This is for performance and
1492 // binary size reasons.
1493 template <typename N, typename R, typename P,
1495 std::is_same<btree_iterator<N, R, P>, iterator>::value &&
1496 std::is_same<btree_iterator, const_iterator>::value,
1497 int> = 0>
1499 : node(x.node), position(x.position) {}
1500
1501 private:
1502 // This SFINAE allows explicit conversions from const_iterator to
1503 // iterator, but also avoids defining a copy constructor.
1504 // NOTE: the const_cast is safe because this constructor is only called by
1505 // non-const methods and the container owns the nodes.
1506 template <typename N, typename R, typename P,
1508 std::is_same<btree_iterator<N, R, P>, const_iterator>::value &&
1509 std::is_same<btree_iterator, iterator>::value,
1510 int> = 0>
1512 : node(const_cast<node_type *>(x.node)), position(x.position) {}
1513
1514 // Increment/decrement the iterator.
1515 void increment() {
1516 if (node->leaf() && ++position < node->count()) {
1517 return;
1518 }
1520 }
1521 void increment_slow();
1522
1523 void decrement() {
1524 if (node->leaf() && --position >= 0) {
1525 return;
1526 }
1528 }
1529 void decrement_slow();
1530
1531 public:
1532 bool operator==(const const_iterator &x) const {
1533 return node == x.node && position == x.position;
1534 }
1535 bool operator!=(const const_iterator &x) const {
1536 return node != x.node || position != x.position;
1537 }
1538 bool operator==(const iterator &x) const {
1539 return node == x.node && position == x.position;
1540 }
1541 bool operator!=(const iterator &x) const {
1542 return node != x.node || position != x.position;
1543 }
1544
1545 // Accessors for the key/value the iterator is pointing at.
1547 return node->value(position);
1548 }
1550 return &node->value(position);
1551 }
1552
1554 increment();
1555 return *this;
1556 }
1558 decrement();
1559 return *this;
1560 }
1562 btree_iterator tmp = *this;
1563 ++*this;
1564 return tmp;
1565 }
1567 btree_iterator tmp = *this;
1568 --*this;
1569 return tmp;
1570 }
1571
1572 private:
1573 template <typename Params>
1574 friend class btree;
1575 template <typename Tree>
1576 friend class btree_container;
1577 template <typename Tree>
1579 template <typename Tree>
1581 template <typename Tree>
1583 template <typename N, typename R, typename P>
1584 friend struct btree_iterator;
1585 template <typename TreeType, typename CheckerType>
1586 friend class base_checker;
1587
1588 const key_type &key() const { return node->key(position); }
1589 slot_type *slot() { return node->slot(position); }
1590
1591 // The node in the tree the iterator is pointing at.
1592 Node *node;
1593 // The position within the node of the tree the iterator is pointing at.
1594 // TODO(ezb): make this a field_type
1596 };
1597
1598 template <typename Params>
1599 class btree {
1601 using is_key_compare_to = typename Params::is_key_compare_to;
1602
1603 // We use a static empty node for the root/leftmost/rightmost of empty btrees
1604 // in order to avoid branching in begin()/end().
1605 struct alignas(node_type::Alignment()) EmptyNodeType : node_type {
1611 // max_count must be != kInternalNodeMaxCount (so that this node is regarded
1612 // as a leaf node). max_count() is never called when the tree is empty.
1613 field_type max_count = node_type::kInternalNodeMaxCount + 1;
1614
1615#ifdef _MSC_VER
1616 // MSVC has constexpr code generations bugs here.
1617 EmptyNodeType() : parent(this) {}
1618#else
1619 constexpr EmptyNodeType(node_type *p) : parent(p) {}
1620#endif
1621 };
1622
1624#ifdef _MSC_VER
1625 static EmptyNodeType empty_node;
1626 // This assert fails on some other construction methods.
1627 assert(empty_node.parent == &empty_node);
1628 return &empty_node;
1629#else
1630 static constexpr EmptyNodeType empty_node(
1631 const_cast<EmptyNodeType *>(&empty_node));
1632 return const_cast<EmptyNodeType *>(&empty_node);
1633#endif
1634 }
1635
1636 enum {
1637 kNodeValues = node_type::kNodeValues,
1639 };
1640
1641 struct node_stats {
1642 using size_type = typename Params::size_type;
1643
1645 : leaf_nodes(l),
1646 internal_nodes(i) {
1647 }
1648
1652 return *this;
1653 }
1654
1657 };
1658
1659 public:
1660 using key_type = typename Params::key_type;
1661 using value_type = typename Params::value_type;
1662 using size_type = typename Params::size_type;
1663 using difference_type = typename Params::difference_type;
1664 using key_compare = typename Params::key_compare;
1665 using value_compare = typename Params::value_compare;
1666 using allocator_type = typename Params::allocator_type;
1667 using reference = typename Params::reference;
1668 using const_reference = typename Params::const_reference;
1669 using pointer = typename Params::pointer;
1670 using const_pointer = typename Params::const_pointer;
1673 using reverse_iterator = std::reverse_iterator<iterator>;
1674 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
1676
1677 // Internal types made public for use by btree_container types.
1678 using params_type = Params;
1679 using slot_type = typename Params::slot_type;
1680
1681 private:
1682 // For use in copy_or_move_values_in_order.
1684 value_type &&maybe_move_from_iterator(iterator x) { return std::move(*x); }
1685
1686 // Copies or moves (depending on the template parameter) the values in
1687 // x into this btree in their order in x. This btree must be empty before this
1688 // method is called. This method is used in copy construction, copy
1689 // assignment, and move assignment.
1690 template <typename Btree>
1692
1693 // Validates that various assumptions/requirements are true at compile time.
1694 constexpr static bool static_assert_validation();
1695
1696 public:
1697 btree(const key_compare &comp, const allocator_type &alloc);
1698
1699 btree(const btree &x);
1700 btree(btree &&x) noexcept
1701 : root_(std::move(x.root_)),
1702 rightmost_(phmap::exchange(x.rightmost_, EmptyNode())),
1703 size_(phmap::exchange(x.size_, 0)) {
1704 x.mutable_root() = EmptyNode();
1705 }
1706
1708 // Put static_asserts in destructor to avoid triggering them before the type
1709 // is complete.
1710 static_assert(static_assert_validation(), "This call must be elided.");
1711 clear();
1712 }
1713
1714 // Assign the contents of x to *this.
1716 btree &operator=(btree &&x) noexcept;
1717
1719 return iterator(leftmost(), 0);
1720 }
1722 return const_iterator(leftmost(), 0);
1723 }
1727 }
1729 return reverse_iterator(end());
1730 }
1732 return const_reverse_iterator(end());
1733 }
1735 return reverse_iterator(begin());
1736 }
1738 return const_reverse_iterator(begin());
1739 }
1740
1741 // Finds the first element whose key is not less than key.
1742 template <typename K>
1743 iterator lower_bound(const K &key) {
1745 }
1746 template <typename K>
1747 const_iterator lower_bound(const K &key) const {
1749 }
1750
1751 // Finds the first element whose key is greater than key.
1752 template <typename K>
1753 iterator upper_bound(const K &key) {
1755 }
1756 template <typename K>
1757 const_iterator upper_bound(const K &key) const {
1759 }
1760
1761 // Finds the range of values which compare equal to key. The first member of
1762 // the returned pair is equal to lower_bound(key). The second member pair of
1763 // the pair is equal to upper_bound(key).
1764 template <typename K>
1765 std::pair<iterator, iterator> equal_range(const K &key) {
1766 return {lower_bound(key), upper_bound(key)};
1767 }
1768 template <typename K>
1769 std::pair<const_iterator, const_iterator> equal_range(const K &key) const {
1770 return {lower_bound(key), upper_bound(key)};
1771 }
1772
1773 // Inserts a value into the btree only if it does not already exist. The
1774 // boolean return value indicates whether insertion succeeded or failed.
1775 // Requirement: if `key` already exists in the btree, does not consume `args`.
1776 // Requirement: `key` is never referenced after consuming `args`.
1777 template <typename... Args>
1778 std::pair<iterator, bool> insert_unique(const key_type &key, Args &&... args);
1779
1780 // Inserts with hint. Checks to see if the value should be placed immediately
1781 // before `position` in the tree. If so, then the insertion will take
1782 // amortized constant time. If not, the insertion will take amortized
1783 // logarithmic time as if a call to insert_unique() were made.
1784 // Requirement: if `key` already exists in the btree, does not consume `args`.
1785 // Requirement: `key` is never referenced after consuming `args`.
1786 template <typename... Args>
1787 std::pair<iterator, bool> insert_hint_unique(iterator position,
1788 const key_type &key,
1789 Args &&... args);
1790
1791 // Insert a range of values into the btree.
1792 template <typename InputIterator>
1793 void insert_iterator_unique(InputIterator b, InputIterator e);
1794
1795 // Inserts a value into the btree.
1796 template <typename ValueType>
1797 iterator insert_multi(const key_type &key, ValueType &&v);
1798
1799 // Inserts a value into the btree.
1800 template <typename ValueType>
1801 iterator insert_multi(ValueType &&v) {
1802 return insert_multi(params_type::key(v), std::forward<ValueType>(v));
1803 }
1804
1805 // Insert with hint. Check to see if the value should be placed immediately
1806 // before position in the tree. If it does, then the insertion will take
1807 // amortized constant time. If not, the insertion will take amortized
1808 // logarithmic time as if a call to insert_multi(v) were made.
1809 template <typename ValueType>
1810 iterator insert_hint_multi(iterator position, ValueType &&v);
1811
1812 // Insert a range of values into the btree.
1813 template <typename InputIterator>
1814 void insert_iterator_multi(InputIterator b, InputIterator e);
1815
1816 // Erase the specified iterator from the btree. The iterator must be valid
1817 // (i.e. not equal to end()). Return an iterator pointing to the node after
1818 // the one that was erased (or end() if none exists).
1819 // Requirement: does not read the value at `*iter`.
1821
1822 // Erases range. Returns the number of keys erased and an iterator pointing
1823 // to the element after the last erased element.
1824 std::pair<size_type, iterator> erase(iterator begin, iterator end);
1825
1826 // Erases the specified key from the btree. Returns 1 if an element was
1827 // erased and 0 otherwise.
1828 template <typename K>
1830
1831 // Erases all of the entries matching the specified key from the
1832 // btree. Returns the number of elements erased.
1833 template <typename K>
1834 size_type erase_multi(const K &key);
1835
1836 // Finds the iterator corresponding to a key or returns end() if the key is
1837 // not present.
1838 template <typename K>
1839 iterator find(const K &key) {
1840 return internal_end(internal_find(key));
1841 }
1842 template <typename K>
1843 const_iterator find(const K &key) const {
1844 return internal_end(internal_find(key));
1845 }
1846
1847 // Returns a count of the number of times the key appears in the btree.
1848 template <typename K>
1849 size_type count_unique(const K &key) const {
1850 const iterator beg = internal_find(key);
1851 if (beg.node == nullptr) {
1852 // The key doesn't exist in the tree.
1853 return 0;
1854 }
1855 return 1;
1856 }
1857 // Returns a count of the number of times the key appears in the btree.
1858 template <typename K>
1859 size_type count_multi(const K &key) const {
1860 const auto range = equal_range(key);
1861 return std::distance(range.first, range.second);
1862 }
1863
1864 // Clear the btree, deleting all of the values it contains.
1865 void clear();
1866
1867 // Swap the contents of *this and x.
1868 void swap(btree &x);
1869
1870 const key_compare &key_comp() const noexcept {
1871 return root_.template get<0>();
1872 }
1873 template <typename K, typename LK>
1874 bool compare_keys(const K &x, const LK &y) const {
1876 }
1877
1879
1880 // Verifies the structure of the btree.
1881 void verify() const;
1882
1883 // Size routines.
1884 size_type size() const { return size_; }
1885 size_type max_size() const { return (std::numeric_limits<size_type>::max)(); }
1886 bool empty() const { return size_ == 0; }
1887
1888 // The height of the btree. An empty tree will have height 0.
1890 size_type h = 0;
1891 if (!empty()) {
1892 // Count the length of the chain from the leftmost node up to the
1893 // root. We actually count from the root back around to the level below
1894 // the root, but the calculation is the same because of the circularity
1895 // of that traversal.
1896 const node_type *n = root();
1897 do {
1898 ++h;
1899 n = n->parent();
1900 } while (n != root());
1901 }
1902 return h;
1903 }
1904
1905 // The number of internal, leaf and total nodes used by the btree.
1907 return internal_stats(root()).leaf_nodes;
1908 }
1911 }
1913 node_stats stats = internal_stats(root());
1914 return stats.leaf_nodes + stats.internal_nodes;
1915 }
1916
1917 // The total number of bytes used by the btree.
1919 node_stats stats = internal_stats(root());
1920 if (stats.leaf_nodes == 1 && stats.internal_nodes == 0) {
1921 return sizeof(*this) +
1922 node_type::LeafSize(root()->max_count());
1923 } else {
1924 return sizeof(*this) +
1927 }
1928 }
1929
1930 // The average number of bytes used per value stored in the btree.
1931 static double average_bytes_per_value() {
1932 // Returns the number of bytes per value on a leaf node that is 75%
1933 // full. Experimentally, this matches up nicely with the computed number of
1934 // bytes per value in trees that had their values inserted in random order.
1935 return node_type::LeafSize() / (kNodeValues * 0.75);
1936 }
1937
1938 // The fullness of the btree. Computed as the number of elements in the btree
1939 // divided by the maximum number of elements a tree with the current number
1940 // of nodes could hold. A value of 1 indicates perfect space
1941 // utilization. Smaller values indicate space wastage.
1942 // Returns 0 for empty trees.
1943 double fullness() const {
1944 if (empty()) return 0.0;
1945 return static_cast<double>(size()) / (nodes() * kNodeValues);
1946 }
1947 // The overhead of the btree structure in bytes per node. Computed as the
1948 // total number of bytes used by the btree minus the number of bytes used for
1949 // storing elements divided by the number of elements.
1950 // Returns 0 for empty trees.
1951 double overhead() const {
1952 if (empty()) return 0.0;
1953 return (bytes_used() - size() * sizeof(value_type)) /
1954 static_cast<double>(size());
1955 }
1956
1957 // The allocator used by the btree.
1959 return allocator();
1960 }
1961
1962 private:
1963 // Internal accessor routines.
1964 node_type *root() { return root_.template get<2>(); }
1965 const node_type *root() const { return root_.template get<2>(); }
1966 node_type *&mutable_root() noexcept { return root_.template get<2>(); }
1967 key_compare *mutable_key_comp() noexcept { return &root_.template get<0>(); }
1968
1969 // The leftmost node is stored as the parent of the root node.
1970 node_type *leftmost() { return root()->parent(); }
1971 const node_type *leftmost() const { return root()->parent(); }
1972
1973 // Allocator routines.
1975 return &root_.template get<1>();
1976 }
1977 const allocator_type &allocator() const noexcept {
1978 return root_.template get<1>();
1979 }
1980
1981 // Allocates a correctly aligned node of at least size bytes using the
1982 // allocator.
1984 return reinterpret_cast<node_type *>(
1985 phmap::priv::Allocate<node_type::Alignment()>(
1986 mutable_allocator(), (size_t)sz));
1987 }
1988
1989 // Node creation/deletion routines.
1992 return node_type::init_internal(p, parent);
1993 }
1996 return node_type::init_leaf(p, parent, kNodeValues);
1997 }
1998 node_type *new_leaf_root_node(const int max_count) {
1999 node_type *p = allocate(node_type::LeafSize(max_count));
2000 return node_type::init_leaf(p, p, max_count);
2001 }
2002
2003 // Deletion helper routines.
2007
2008 // Deallocates a node of a certain size in bytes using the allocator.
2009 void deallocate(const size_type sz, node_type *node) {
2010 phmap::priv::Deallocate<node_type::Alignment()>(
2011 mutable_allocator(), node, (size_t)sz);
2012 }
2013
2015 node->destroy(mutable_allocator());
2017 }
2019 node->destroy(mutable_allocator());
2021 }
2022
2023 // Rebalances or splits the node iter points to.
2025
2026 // Merges the values of left, right and the delimiting key on their parent
2027 // onto left, removing the delimiting key and deleting right.
2028 void merge_nodes(node_type *left, node_type *right);
2029
2030 // Tries to merge node with its left or right sibling, and failing that,
2031 // rebalance with its left or right sibling. Returns true if a merge
2032 // occurred, at which point it is no longer valid to access node. Returns
2033 // false if no merging took place.
2035
2036 // Tries to shrink the height of the tree by 1.
2038
2040 return iter.node != nullptr ? iter : end();
2041 }
2043 return iter.node != nullptr ? iter : end();
2044 }
2045
2046 // Emplaces a value into the btree immediately before iter. Requires that
2047 // key(v) <= iter.key() and (--iter).key() <= key(v).
2048 template <typename... Args>
2049 iterator internal_emplace(iterator iter, Args &&... args);
2050
2051 // Returns an iterator pointing to the first value >= the value "iter" is
2052 // pointing at. Note that "iter" might be pointing to an invalid location as
2053 // iter.position == iter.node->count(). This routine simply moves iter up in
2054 // the tree to a valid location.
2055 // Requires: iter.node is non-null.
2056 template <typename IterType>
2057 static IterType internal_last(IterType iter);
2058
2059 // Returns an iterator pointing to the leaf position at which key would
2060 // reside in the tree. We provide 2 versions of internal_locate. The first
2061 // version uses a less-than comparator and is incapable of distinguishing when
2062 // there is an exact match. The second version is for the key-compare-to
2063 // specialization and distinguishes exact matches. The key-compare-to
2064 // specialization allows the caller to avoid a subsequent comparison to
2065 // determine if an exact match was made, which is important for keys with
2066 // expensive comparison, such as strings.
2067 template <typename K>
2069 const K &key) const;
2070
2071 template <typename K>
2073 const K &key, std::false_type /* IsCompareTo */) const;
2074
2075 template <typename K>
2077 const K &key, std::true_type /* IsCompareTo */) const;
2078
2079 // Internal routine which implements lower_bound().
2080 template <typename K>
2081 iterator internal_lower_bound(const K &key) const;
2082
2083 // Internal routine which implements upper_bound().
2084 template <typename K>
2085 iterator internal_upper_bound(const K &key) const;
2086
2087 // Internal routine which implements find().
2088 template <typename K>
2089 iterator internal_find(const K &key) const;
2090
2091 // Deletes a node and all of its children.
2093
2094 // Verifies the tree structure of node.
2096 const key_type *lo, const key_type *hi) const;
2097
2099 // The root can be a static empty node.
2100 if (node == nullptr || (node == root() && empty())) {
2101 return node_stats(0, 0);
2102 }
2103 if (node->leaf()) {
2104 return node_stats(1, 0);
2105 }
2106 node_stats res(0, 1);
2107 for (int i = 0; i <= node->count(); ++i) {
2108 res += internal_stats(node->child(i));
2109 }
2110 return res;
2111 }
2112
2113 public:
2114 // Exposed only for tests.
2117 }
2118
2119 private:
2120 // We use compressed tuple in order to save space because key_compare and
2121 // allocator_type are usually empty.
2123 node_type *>
2125
2126 // A pointer to the rightmost node. Note that the leftmost node is stored as
2127 // the root's parent.
2129
2130 // Number of values.
2132 };
2133
2135 // btree_node methods
2136 template <typename P>
2137 template <typename... Args>
2139 allocator_type *alloc,
2140 Args &&... args) {
2141 assert(i <= count());
2142 // Shift old values to create space for new value and then construct it in
2143 // place.
2144 if (i < count()) {
2145 value_init(count(), alloc, slot(count() - 1));
2146 for (size_type j = count() - 1; j > i; --j)
2147 params_type::move(alloc, slot(j - 1), slot(j));
2148 value_destroy(i, alloc);
2149 }
2150 value_init(i, alloc, std::forward<Args>(args)...);
2151 set_count((field_type)(count() + 1));
2152
2153 if (!leaf() && count() > i + 1) {
2154 for (int j = count(); j > (int)(i + 1); --j) {
2155 set_child(j, child(j - 1));
2156 }
2157 clear_child(i + 1);
2158 }
2159 }
2160
2161 template <typename P>
2162 inline void btree_node<P>::remove_value(const int i, allocator_type *alloc) {
2163 if (!leaf() && count() > i + 1) {
2164 assert(child(i + 1)->count() == 0);
2165 for (size_type j = i + 1; j < count(); ++j) {
2166 set_child(j, child(j + 1));
2167 }
2168 clear_child(count());
2169 }
2170
2171 remove_values_ignore_children(i, /*to_erase=*/1, alloc);
2172 }
2173
2174 template <typename P>
2176 int i, size_type to_erase, allocator_type *alloc) {
2177 params_type::move(alloc, slot(i + to_erase), slot(count()), slot(i));
2178 value_destroy_n(count() - to_erase, to_erase, alloc);
2179 set_count((field_type)(count() - to_erase));
2180 }
2181
2182 template <typename P>
2184 btree_node *right,
2185 allocator_type *alloc) {
2186 assert(parent() == right->parent());
2187 assert(position() + 1 == right->position());
2188 assert(right->count() >= count());
2189 assert(to_move >= 1);
2190 assert(to_move <= right->count());
2191
2192 // 1) Move the delimiting value in the parent to the left node.
2193 value_init(count(), alloc, parent()->slot(position()));
2194
2195 // 2) Move the (to_move - 1) values from the right node to the left node.
2196 right->uninitialized_move_n(to_move - 1, 0, count() + 1, this, alloc);
2197
2198 // 3) Move the new delimiting value to the parent from the right node.
2199 params_type::move(alloc, right->slot(to_move - 1),
2200 parent()->slot(position()));
2201
2202 // 4) Shift the values in the right node to their correct position.
2203 params_type::move(alloc, right->slot(to_move), right->slot(right->count()),
2204 right->slot(0));
2205
2206 // 5) Destroy the now-empty to_move entries in the right node.
2207 right->value_destroy_n(right->count() - to_move, to_move, alloc);
2208
2209 if (!leaf()) {
2210 // Move the child pointers from the right to the left node.
2211 for (int i = 0; i < to_move; ++i) {
2212 init_child(count() + i + 1, right->child(i));
2213 }
2214 for (int i = 0; i <= right->count() - to_move; ++i) {
2215 assert(i + to_move <= right->max_count());
2216 right->init_child(i, right->child(i + to_move));
2217 right->clear_child(i + to_move);
2218 }
2219 }
2220
2221 // Fixup the counts on the left and right nodes.
2222 set_count((field_type)(count() + to_move));
2223 right->set_count((field_type)(right->count() - to_move));
2224 }
2225
2226 template <typename P>
2228 btree_node *right,
2229 allocator_type *alloc) {
2230 assert(parent() == right->parent());
2231 assert(position() + 1 == right->position());
2232 assert(count() >= right->count());
2233 assert(to_move >= 1);
2234 assert(to_move <= count());
2235
2236 // Values in the right node are shifted to the right to make room for the
2237 // new to_move values. Then, the delimiting value in the parent and the
2238 // other (to_move - 1) values in the left node are moved into the right node.
2239 // Lastly, a new delimiting value is moved from the left node into the
2240 // parent, and the remaining empty left node entries are destroyed.
2241
2242 if (right->count() >= to_move) {
2243 // The original location of the right->count() values are sufficient to hold
2244 // the new to_move entries from the parent and left node.
2245
2246 // 1) Shift existing values in the right node to their correct positions.
2247 right->uninitialized_move_n(to_move, right->count() - to_move,
2248 right->count(), right, alloc);
2249 if (right->count() > to_move) {
2250 for (slot_type *src = right->slot(right->count() - to_move - 1),
2251 *dest = right->slot(right->count() - 1),
2252 *end = right->slot(0);
2253 src >= end; --src, --dest) {
2254 params_type::move(alloc, src, dest);
2255 }
2256 }
2257
2258 // 2) Move the delimiting value in the parent to the right node.
2259 params_type::move(alloc, parent()->slot(position()),
2260 right->slot(to_move - 1));
2261
2262 // 3) Move the (to_move - 1) values from the left node to the right node.
2263 params_type::move(alloc, slot(count() - (to_move - 1)), slot(count()),
2264 right->slot(0));
2265 } else {
2266 // The right node does not have enough initialized space to hold the new
2267 // to_move entries, so part of them will move to uninitialized space.
2268
2269 // 1) Shift existing values in the right node to their correct positions.
2270 right->uninitialized_move_n(right->count(), 0, to_move, right, alloc);
2271
2272 // 2) Move the delimiting value in the parent to the right node.
2273 right->value_init(to_move - 1, alloc, parent()->slot(position()));
2274
2275 // 3) Move the (to_move - 1) values from the left node to the right node.
2276 const size_type uninitialized_remaining = to_move - right->count() - 1;
2277 uninitialized_move_n(uninitialized_remaining,
2278 count() - uninitialized_remaining, right->count(),
2279 right, alloc);
2280 params_type::move(alloc, slot(count() - (to_move - 1)),
2281 slot(count() - uninitialized_remaining), right->slot(0));
2282 }
2283
2284 // 4) Move the new delimiting value to the parent from the left node.
2285 params_type::move(alloc, slot(count() - to_move), parent()->slot(position()));
2286
2287 // 5) Destroy the now-empty to_move entries in the left node.
2288 value_destroy_n(count() - to_move, to_move, alloc);
2289
2290 if (!leaf()) {
2291 // Move the child pointers from the left to the right node.
2292 for (int i = right->count(); i >= 0; --i) {
2293 right->init_child(i + to_move, right->child(i));
2294 right->clear_child(i);
2295 }
2296 for (int i = 1; i <= to_move; ++i) {
2297 right->init_child(i - 1, child(count() - to_move + i));
2298 clear_child(count() - to_move + i);
2299 }
2300 }
2301
2302 // Fixup the counts on the left and right nodes.
2303 set_count((field_type)(count() - to_move));
2304 right->set_count((field_type)(right->count() + to_move));
2305 }
2306
2307 template <typename P>
2308 void btree_node<P>::split(const int insert_position, btree_node *dest,
2309 allocator_type *alloc) {
2310 assert(dest->count() == 0);
2311 assert(max_count() == kNodeValues);
2312
2313 // We bias the split based on the position being inserted. If we're
2314 // inserting at the beginning of the left node then bias the split to put
2315 // more values on the right node. If we're inserting at the end of the
2316 // right node then bias the split to put more values on the left node.
2317 if (insert_position == 0) {
2318 dest->set_count((field_type)(count() - 1));
2319 } else if (insert_position == kNodeValues) {
2320 dest->set_count(0);
2321 } else {
2322 dest->set_count((field_type)(count() / 2));
2323 }
2324 set_count((field_type)(count() - dest->count()));
2325 assert(count() >= 1);
2326
2327 // Move values from the left sibling to the right sibling.
2328 uninitialized_move_n(dest->count(), count(), 0, dest, alloc);
2329
2330 // Destroy the now-empty entries in the left node.
2331 value_destroy_n(count(), dest->count(), alloc);
2332
2333 // The split key is the largest value in the left sibling.
2334 set_count((field_type)(count() - 1));
2335 parent()->emplace_value(position(), alloc, slot(count()));
2336 value_destroy(count(), alloc);
2337 parent()->init_child(position() + 1, dest);
2338
2339 if (!leaf()) {
2340 for (int i = 0; i <= dest->count(); ++i) {
2341 assert(child(count() + i + 1) != nullptr);
2342 dest->init_child(i, child(count() + i + 1));
2343 clear_child(count() + i + 1);
2344 }
2345 }
2346 }
2347
2348 template <typename P>
2350 assert(parent() == src->parent());
2351 assert(position() + 1 == src->position());
2352
2353 // Move the delimiting value to the left node.
2354 value_init(count(), alloc, parent()->slot(position()));
2355
2356 // Move the values from the right to the left node.
2357 src->uninitialized_move_n(src->count(), 0, count() + 1, this, alloc);
2358
2359 // Destroy the now-empty entries in the right node.
2360 src->value_destroy_n(0, src->count(), alloc);
2361
2362 if (!leaf()) {
2363 // Move the child pointers from the right to the left node.
2364 for (int i = 0; i <= src->count(); ++i) {
2365 init_child(count() + i + 1, src->child(i));
2366 src->clear_child(i);
2367 }
2368 }
2369
2370 // Fixup the counts on the src and dest nodes.
2371 set_count((field_type)(1 + count() + src->count()));
2372 src->set_count(0);
2373
2374 // Remove the value on the parent node.
2375 parent()->remove_value(position(), alloc);
2376 }
2377
2378 template <typename P>
2380 using std::swap;
2381 assert(leaf() == x->leaf());
2382
2383 // Determine which is the smaller/larger node.
2384 btree_node *smaller = this, *larger = x;
2385 if (smaller->count() > larger->count()) {
2386 swap(smaller, larger);
2387 }
2388
2389 // Swap the values.
2390 for (slot_type *a = smaller->slot(0), *b = larger->slot(0),
2391 *end = a + smaller->count();
2392 a != end; ++a, ++b) {
2393 params_type::swap(alloc, a, b);
2394 }
2395
2396 // Move values that can't be swapped.
2397 const size_type to_move = larger->count() - smaller->count();
2398 larger->uninitialized_move_n(to_move, smaller->count(), smaller->count(),
2399 smaller, alloc);
2400 larger->value_destroy_n(smaller->count(), to_move, alloc);
2401
2402 if (!leaf()) {
2403 // Swap the child pointers.
2404 std::swap_ranges(&smaller->mutable_child(0),
2405 &smaller->mutable_child(smaller->count() + 1),
2406 &larger->mutable_child(0));
2407 // Update swapped children's parent pointers.
2408 int i = 0;
2409 for (; i <= smaller->count(); ++i) {
2410 smaller->child(i)->set_parent(smaller);
2411 larger->child(i)->set_parent(larger);
2412 }
2413 // Move the child pointers that couldn't be swapped.
2414 for (; i <= larger->count(); ++i) {
2415 smaller->init_child(i, larger->child(i));
2416 larger->clear_child(i);
2417 }
2418 }
2419
2420 // Swap the counts.
2421 swap(mutable_count(), x->mutable_count());
2422 }
2423
2425 // btree_iterator methods
2426 template <typename N, typename R, typename P>
2428 if (node->leaf()) {
2429 assert(position >= node->count());
2430 btree_iterator save(*this);
2431 while (position == node->count() && !node->is_root()) {
2432 assert(node->parent()->child(node->position()) == node);
2433 position = node->position();
2434 node = node->parent();
2435 }
2436 if (position == node->count()) {
2437 *this = save;
2438 }
2439 } else {
2440 assert(position < node->count());
2441 node = node->child(position + 1);
2442 while (!node->leaf()) {
2443 node = node->child(0);
2444 }
2445 position = 0;
2446 }
2447 }
2448
2449 template <typename N, typename R, typename P>
2451 if (node->leaf()) {
2452 assert(position <= -1);
2453 btree_iterator save(*this);
2454 while (position < 0 && !node->is_root()) {
2455 assert(node->parent()->child(node->position()) == node);
2456 position = node->position() - 1;
2457 node = node->parent();
2458 }
2459 if (position < 0) {
2460 *this = save;
2461 }
2462 } else {
2463 assert(position >= 0);
2464 node = node->child(position);
2465 while (!node->leaf()) {
2466 node = node->child(node->count());
2467 }
2468 position = node->count() - 1;
2469 }
2470 }
2471
2473 // btree methods
2474 template <typename P>
2475 template <typename Btree>
2477 static_assert(std::is_same<btree, Btree>::value ||
2478 std::is_same<const btree, Btree>::value,
2479 "Btree type must be same or const.");
2480 assert(empty());
2481
2482 // We can avoid key comparisons because we know the order of the
2483 // values is the same order we'll store them in.
2484 auto iter = x->begin();
2485 if (iter == x->end()) return;
2486 insert_multi(maybe_move_from_iterator(iter));
2487 ++iter;
2488 for (; iter != x->end(); ++iter) {
2489 // If the btree is not empty, we can just insert the new value at the end
2490 // of the tree.
2491 internal_emplace(end(), maybe_move_from_iterator(iter));
2492 }
2493 }
2494
2495 template <typename P>
2497 static_assert(std::is_nothrow_copy_constructible<key_compare>::value,
2498 "Key comparison must be nothrow copy constructible");
2499 static_assert(std::is_nothrow_copy_constructible<allocator_type>::value,
2500 "Allocator must be nothrow copy constructible");
2502 "iterator not trivially copyable.");
2503
2504 // Note: We assert that kTargetValues, which is computed from
2505 // Params::kTargetNodeSize, must fit the node_type::field_type.
2506 static_assert(
2507 kNodeValues < (1 << (8 * sizeof(typename node_type::field_type))),
2508 "target node size too large");
2509
2510 // Verify that key_compare returns an phmap::{weak,strong}_ordering or bool.
2511 using compare_result_type =
2513 static_assert(
2514 std::is_same<compare_result_type, bool>::value ||
2515 std::is_convertible<compare_result_type, phmap::weak_ordering>::value,
2516 "key comparison function must return phmap::{weak,strong}_ordering or "
2517 "bool.");
2518
2519 // Test the assumption made in setting kNodeSlotSpace.
2520 static_assert(node_type::MinimumOverhead() >= sizeof(void *) + 4,
2521 "node space assumption incorrect");
2522
2523 return true;
2524 }
2525
2526 template <typename P>
2527 btree<P>::btree(const key_compare &comp, const allocator_type &alloc)
2528 : root_(comp, alloc, EmptyNode()), rightmost_(EmptyNode()), size_(0) {}
2529
2530 template <typename P>
2531 btree<P>::btree(const btree &x) : btree(x.key_comp(), x.allocator()) {
2533 }
2534
2535 template <typename P>
2536 template <typename... Args>
2537 auto btree<P>::insert_unique(const key_type &key, Args &&... args)
2538 -> std::pair<iterator, bool> {
2539 if (empty()) {
2540 mutable_root() = rightmost_ = new_leaf_root_node(1);
2541 }
2542
2543 auto res = internal_locate(key);
2544 iterator &iter = res.value;
2545
2546 if (res.HasMatch()) {
2547 if (res.IsEq()) {
2548 // The key already exists in the tree, do nothing.
2549 return {iter, false};
2550 }
2551 } else {
2552 iterator last = internal_last(iter);
2553 if (last.node && !compare_keys(key, last.key())) {
2554 // The key already exists in the tree, do nothing.
2555 return {last, false};
2556 }
2557 }
2558 return {internal_emplace(iter, std::forward<Args>(args)...), true};
2559 }
2560
2561 template <typename P>
2562 template <typename... Args>
2563 inline auto btree<P>::insert_hint_unique(iterator position, const key_type &key,
2564 Args &&... args)
2565 -> std::pair<iterator, bool> {
2566 if (!empty()) {
2567 if (position == end() || compare_keys(key, position.key())) {
2568 iterator prev = position;
2569 if (position == begin() || compare_keys((--prev).key(), key)) {
2570 // prev.key() < key < position.key()
2571 return {internal_emplace(position, std::forward<Args>(args)...), true};
2572 }
2573 } else if (compare_keys(position.key(), key)) {
2574 ++position;
2575 if (position == end() || compare_keys(key, position.key())) {
2576 // {original `position`}.key() < key < {current `position`}.key()
2577 return {internal_emplace(position, std::forward<Args>(args)...), true};
2578 }
2579 } else {
2580 // position.key() == key
2581 return {position, false};
2582 }
2583 }
2584 return insert_unique(key, std::forward<Args>(args)...);
2585 }
2586
2587 template <typename P>
2588 template <typename InputIterator>
2589 void btree<P>::insert_iterator_unique(InputIterator b, InputIterator e) {
2590 for (; b != e; ++b) {
2591 insert_hint_unique(end(), params_type::key(*b), *b);
2592 }
2593 }
2594
2595 template <typename P>
2596 template <typename ValueType>
2597 auto btree<P>::insert_multi(const key_type &key, ValueType &&v) -> iterator {
2598 if (empty()) {
2599 mutable_root() = rightmost_ = new_leaf_root_node(1);
2600 }
2601
2602 iterator iter = internal_upper_bound(key);
2603 if (iter.node == nullptr) {
2604 iter = end();
2605 }
2606 return internal_emplace(iter, std::forward<ValueType>(v));
2607 }
2608
2609 template <typename P>
2610 template <typename ValueType>
2611 auto btree<P>::insert_hint_multi(iterator position, ValueType &&v) -> iterator {
2612 if (!empty()) {
2613 const key_type &key = params_type::key(v);
2614 if (position == end() || !compare_keys(position.key(), key)) {
2615 iterator prev = position;
2616 if (position == begin() || !compare_keys(key, (--prev).key())) {
2617 // prev.key() <= key <= position.key()
2618 return internal_emplace(position, std::forward<ValueType>(v));
2619 }
2620 } else {
2621 iterator next = position;
2622 ++next;
2623 if (next == end() || !compare_keys(next.key(), key)) {
2624 // position.key() < key <= next.key()
2625 return internal_emplace(next, std::forward<ValueType>(v));
2626 }
2627 }
2628 }
2629 return insert_multi(std::forward<ValueType>(v));
2630 }
2631
2632 template <typename P>
2633 template <typename InputIterator>
2634 void btree<P>::insert_iterator_multi(InputIterator b, InputIterator e) {
2635 for (; b != e; ++b) {
2636 insert_hint_multi(end(), *b);
2637 }
2638 }
2639
2640 template <typename P>
2641 auto btree<P>::operator=(const btree &x) -> btree & {
2642 if (this != &x) {
2643 clear();
2644
2645 *mutable_key_comp() = x.key_comp();
2647 allocator_type>::propagate_on_container_copy_assignment::value) {
2648 *mutable_allocator() = x.allocator();
2649 }
2650
2651 copy_or_move_values_in_order(&x);
2652 }
2653 return *this;
2654 }
2655
2656 template <typename P>
2657 auto btree<P>::operator=(btree &&x) noexcept -> btree & {
2658 if (this != &x) {
2659 clear();
2660
2661 using std::swap;
2663 allocator_type>::propagate_on_container_copy_assignment::value) {
2664 // Note: `root_` also contains the allocator and the key comparator.
2665 swap(root_, x.root_);
2666 swap(rightmost_, x.rightmost_);
2667 swap(size_, x.size_);
2668 } else {
2669 if (allocator() == x.allocator()) {
2670 swap(mutable_root(), x.mutable_root());
2671 swap(*mutable_key_comp(), *x.mutable_key_comp());
2672 swap(rightmost_, x.rightmost_);
2673 swap(size_, x.size_);
2674 } else {
2675 // We aren't allowed to propagate the allocator and the allocator is
2676 // different so we can't take over its memory. We must move each element
2677 // individually. We need both `x` and `this` to have `x`s key comparator
2678 // while moving the values so we can't swap the key comparators.
2679 *mutable_key_comp() = x.key_comp();
2680 copy_or_move_values_in_order(&x);
2681 }
2682 }
2683 }
2684 return *this;
2685 }
2686
2687 template <typename P>
2689 bool internal_delete = false;
2690 if (!iter.node->leaf()) {
2691 // Deletion of a value on an internal node. First, move the largest value
2692 // from our left child here, then delete that position (in remove_value()
2693 // below). We can get to the largest value from our left child by
2694 // decrementing iter.
2695 iterator internal_iter(iter);
2696 --iter;
2697 assert(iter.node->leaf());
2698 params_type::move(mutable_allocator(), iter.node->slot(iter.position),
2699 internal_iter.node->slot(internal_iter.position));
2700 internal_delete = true;
2701 }
2702
2703 // Delete the key from the leaf.
2704 iter.node->remove_value(iter.position, mutable_allocator());
2705 --size_;
2706
2707 // We want to return the next value after the one we just erased. If we
2708 // erased from an internal node (internal_delete == true), then the next
2709 // value is ++(++iter). If we erased from a leaf node (internal_delete ==
2710 // false) then the next value is ++iter. Note that ++iter may point to an
2711 // internal node and the value in the internal node may move to a leaf node
2712 // (iter.node) when rebalancing is performed at the leaf level.
2713
2714 iterator res = rebalance_after_delete(iter);
2715
2716 // If we erased from an internal node, advance the iterator.
2717 if (internal_delete) {
2718 ++res;
2719 }
2720 return res;
2721 }
2722
2723 template <typename P>
2725 // Merge/rebalance as we walk back up the tree.
2726 iterator res(iter);
2727 bool first_iteration = true;
2728 for (;;) {
2729 if (iter.node == root()) {
2730 try_shrink();
2731 if (empty()) {
2732 return end();
2733 }
2734 break;
2735 }
2736 if (iter.node->count() >= kMinNodeValues) {
2737 break;
2738 }
2739 bool merged = try_merge_or_rebalance(&iter);
2740 // On the first iteration, we should update `res` with `iter` because `res`
2741 // may have been invalidated.
2742 if (first_iteration) {
2743 res = iter;
2744 first_iteration = false;
2745 }
2746 if (!merged) {
2747 break;
2748 }
2749 iter.position = iter.node->position();
2750 iter.node = iter.node->parent();
2751 }
2752
2753 // Adjust our return value. If we're pointing at the end of a node, advance
2754 // the iterator.
2755 if (res.position == res.node->count()) {
2756 res.position = res.node->count() - 1;
2757 ++res;
2758 }
2759
2760 return res;
2761 }
2762
2763 template <typename P>
2765 -> std::pair<size_type, iterator> {
2766 difference_type count = std::distance(_begin, _end);
2767 assert(count >= 0);
2768
2769 if (count == 0) {
2770 return {0, _begin};
2771 }
2772
2773 if (count == (difference_type)size_) {
2774 clear();
2775 return {count, this->end()};
2776 }
2777
2778 if (_begin.node == _end.node) {
2779 erase_same_node(_begin, _end);
2780 size_ -= count;
2781 return {count, rebalance_after_delete(_begin)};
2782 }
2783
2784 const size_type target_size = size_ - count;
2785 while (size_ > target_size) {
2786 if (_begin.node->leaf()) {
2787 const size_type remaining_to_erase = size_ - target_size;
2788 const size_type remaining_in_node = _begin.node->count() - _begin.position;
2789 _begin = erase_from_leaf_node(
2790 _begin, (std::min)(remaining_to_erase, remaining_in_node));
2791 } else {
2792 _begin = erase(_begin);
2793 }
2794 }
2795 return {count, _begin};
2796 }
2797
2798 template <typename P>
2800 assert(_begin.node == _end.node);
2801 assert(_end.position > _begin.position);
2802
2803 node_type *node = _begin.node;
2804 size_type to_erase = _end.position - _begin.position;
2805 if (!node->leaf()) {
2806 // Delete all children between _begin and _end.
2807 for (size_type i = 0; i < to_erase; ++i) {
2808 internal_clear(node->child(_begin.position + i + 1));
2809 }
2810 // Rotate children after _end into new positions.
2811 for (size_type i = _begin.position + to_erase + 1; i <= node->count(); ++i) {
2812 node->set_child(i - to_erase, node->child(i));
2813 node->clear_child(i);
2814 }
2815 }
2816 node->remove_values_ignore_children(_begin.position, to_erase,
2817 mutable_allocator());
2818
2819 // Do not need to update rightmost_, because
2820 // * either _end == this->end(), and therefore node == rightmost_, and still
2821 // exists
2822 // * or _end != this->end(), and therefore rightmost_ hasn't been erased, since
2823 // it wasn't covered in [_begin, _end)
2824 }
2825
2826 template <typename P>
2828 -> iterator {
2829 node_type *node = _begin.node;
2830 assert(node->leaf());
2831 assert(node->count() > _begin.position);
2832 assert(_begin.position + to_erase <= node->count());
2833
2834 node->remove_values_ignore_children(_begin.position, to_erase,
2835 mutable_allocator());
2836
2837 size_ -= to_erase;
2838
2839 return rebalance_after_delete(_begin);
2840 }
2841
2842 template <typename P>
2843 template <typename K>
2844 auto btree<P>::erase_unique(const K &key) -> size_type {
2845 const iterator iter = internal_find(key);
2846 if (iter.node == nullptr) {
2847 // The key doesn't exist in the tree, return nothing done.
2848 return 0;
2849 }
2850 erase(iter);
2851 return 1;
2852 }
2853
2854 template <typename P>
2855 template <typename K>
2856 auto btree<P>::erase_multi(const K &key) -> size_type {
2857 const iterator _begin = internal_lower_bound(key);
2858 if (_begin.node == nullptr) {
2859 // The key doesn't exist in the tree, return nothing done.
2860 return 0;
2861 }
2862 // Delete all of the keys between _begin and upper_bound(key).
2863 const iterator _end = internal_end(internal_upper_bound(key));
2864 return erase(_begin, _end).first;
2865 }
2866
2867 template <typename P>
2869 if (!empty()) {
2870 internal_clear(root());
2871 }
2872 mutable_root() = EmptyNode();
2873 rightmost_ = EmptyNode();
2874 size_ = 0;
2875 }
2876
2877 template <typename P>
2879 using std::swap;
2881 allocator_type>::propagate_on_container_swap::value) {
2882 // Note: `root_` also contains the allocator and the key comparator.
2883 swap(root_, x.root_);
2884 } else {
2885 // It's undefined behavior if the allocators are unequal here.
2886 assert(allocator() == x.allocator());
2887 swap(mutable_root(), x.mutable_root());
2888 swap(*mutable_key_comp(), *x.mutable_key_comp());
2889 }
2890 swap(rightmost_, x.rightmost_);
2891 swap(size_, x.size_);
2892 }
2893
2894 template <typename P>
2895 void btree<P>::verify() const {
2896 assert(root() != nullptr);
2897 assert(leftmost() != nullptr);
2898 assert(rightmost_ != nullptr);
2899 assert(empty() || size() == internal_verify(root(), nullptr, nullptr));
2900 assert(leftmost() == (++const_iterator(root(), -1)).node);
2901 assert(rightmost_ == (--const_iterator(root(), root()->count())).node);
2902 assert(leftmost()->leaf());
2903 assert(rightmost_->leaf());
2904 }
2905
2906 template <typename P>
2908 node_type *&node = iter->node;
2909 int &insert_position = iter->position;
2910 assert(node->count() == node->max_count());
2911 assert(kNodeValues == node->max_count());
2912
2913 // First try to make room on the node by rebalancing.
2914 node_type *parent = node->parent();
2915 if (node != root()) {
2916 if (node->position() > 0) {
2917 // Try rebalancing with our left sibling.
2918 node_type *left = parent->child(node->position() - 1);
2919 assert(left->max_count() == kNodeValues);
2920 if (left->count() < kNodeValues) {
2921 // We bias rebalancing based on the position being inserted. If we're
2922 // inserting at the end of the right node then we bias rebalancing to
2923 // fill up the left node.
2924 int to_move = (kNodeValues - left->count()) /
2925 (1 + (insert_position < kNodeValues));
2926 to_move = (std::max)(1, to_move);
2927
2928 if (((insert_position - to_move) >= 0) ||
2929 ((left->count() + to_move) < kNodeValues)) {
2930 left->rebalance_right_to_left(to_move, node, mutable_allocator());
2931
2932 assert(node->max_count() - node->count() == to_move);
2933 insert_position = insert_position - to_move;
2934 if (insert_position < 0) {
2935 insert_position = insert_position + left->count() + 1;
2936 node = left;
2937 }
2938
2939 assert(node->count() < node->max_count());
2940 return;
2941 }
2942 }
2943 }
2944
2945 if (node->position() < parent->count()) {
2946 // Try rebalancing with our right sibling.
2947 node_type *right = parent->child(node->position() + 1);
2948 assert(right->max_count() == kNodeValues);
2949 if (right->count() < kNodeValues) {
2950 // We bias rebalancing based on the position being inserted. If we're
2951 // inserting at the _beginning of the left node then we bias rebalancing
2952 // to fill up the right node.
2953 int to_move =
2954 (kNodeValues - right->count()) / (1 + (insert_position > 0));
2955 to_move = (std::max)(1, to_move);
2956
2957 if ((insert_position <= (node->count() - to_move)) ||
2958 ((right->count() + to_move) < kNodeValues)) {
2959 node->rebalance_left_to_right(to_move, right, mutable_allocator());
2960
2961 if (insert_position > node->count()) {
2962 insert_position = insert_position - node->count() - 1;
2963 node = right;
2964 }
2965
2966 assert(node->count() < node->max_count());
2967 return;
2968 }
2969 }
2970 }
2971
2972 // Rebalancing failed, make sure there is room on the parent node for a new
2973 // value.
2974 assert(parent->max_count() == kNodeValues);
2975 if (parent->count() == kNodeValues) {
2976 iterator parent_iter(node->parent(), node->position());
2977 rebalance_or_split(&parent_iter);
2978 }
2979 } else {
2980 // Rebalancing not possible because this is the root node.
2981 // Create a new root node and set the current root node as the child of the
2982 // new root.
2983 parent = new_internal_node(parent);
2984 parent->init_child(0, root());
2985 mutable_root() = parent;
2986 // If the former root was a leaf node, then it's now the rightmost node.
2987 assert(!parent->child(0)->leaf() || parent->child(0) == rightmost_);
2988 }
2989
2990 // Split the node.
2991 node_type *split_node;
2992 if (node->leaf()) {
2993 split_node = new_leaf_node(parent);
2994 node->split(insert_position, split_node, mutable_allocator());
2995 if (rightmost_ == node) rightmost_ = split_node;
2996 } else {
2997 split_node = new_internal_node(parent);
2998 node->split(insert_position, split_node, mutable_allocator());
2999 }
3000
3001 if (insert_position > node->count()) {
3002 insert_position = insert_position - node->count() - 1;
3003 node = split_node;
3004 }
3005 }
3006
3007 template <typename P>
3009 left->merge(right, mutable_allocator());
3010 if (right->leaf()) {
3011 if (rightmost_ == right) rightmost_ = left;
3012 delete_leaf_node(right);
3013 } else {
3014 delete_internal_node(right);
3015 }
3016 }
3017
3018 template <typename P>
3020 node_type *parent = iter->node->parent();
3021 if (iter->node->position() > 0) {
3022 // Try merging with our left sibling.
3023 node_type *left = parent->child(iter->node->position() - 1);
3024 assert(left->max_count() == kNodeValues);
3025 if ((1 + left->count() + iter->node->count()) <= kNodeValues) {
3026 iter->position += 1 + left->count();
3027 merge_nodes(left, iter->node);
3028 iter->node = left;
3029 return true;
3030 }
3031 }
3032 if (iter->node->position() < parent->count()) {
3033 // Try merging with our right sibling.
3034 node_type *right = parent->child(iter->node->position() + 1);
3035 assert(right->max_count() == kNodeValues);
3036 if ((1 + iter->node->count() + right->count()) <= kNodeValues) {
3037 merge_nodes(iter->node, right);
3038 return true;
3039 }
3040 // Try rebalancing with our right sibling. We don't perform rebalancing if
3041 // we deleted the first element from iter->node and the node is not
3042 // empty. This is a small optimization for the common pattern of deleting
3043 // from the front of the tree.
3044 if ((right->count() > kMinNodeValues) &&
3045 ((iter->node->count() == 0) ||
3046 (iter->position > 0))) {
3047 int to_move = (right->count() - iter->node->count()) / 2;
3048 to_move = (std::min)(to_move, right->count() - 1);
3049 iter->node->rebalance_right_to_left(to_move, right, mutable_allocator());
3050 return false;
3051 }
3052 }
3053 if (iter->node->position() > 0) {
3054 // Try rebalancing with our left sibling. We don't perform rebalancing if
3055 // we deleted the last element from iter->node and the node is not
3056 // empty. This is a small optimization for the common pattern of deleting
3057 // from the back of the tree.
3058 node_type *left = parent->child(iter->node->position() - 1);
3059 if ((left->count() > kMinNodeValues) &&
3060 ((iter->node->count() == 0) ||
3061 (iter->position < iter->node->count()))) {
3062 int to_move = (left->count() - iter->node->count()) / 2;
3063 to_move = (std::min)(to_move, left->count() - 1);
3064 left->rebalance_left_to_right(to_move, iter->node, mutable_allocator());
3065 iter->position += to_move;
3066 return false;
3067 }
3068 }
3069 return false;
3070 }
3071
3072 template <typename P>
3074 if (root()->count() > 0) {
3075 return;
3076 }
3077 // Deleted the last item on the root node, shrink the height of the tree.
3078 if (root()->leaf()) {
3079 assert(size() == 0);
3080 delete_leaf_node(root());
3081 mutable_root() = EmptyNode();
3082 rightmost_ = EmptyNode();
3083 } else {
3084 node_type *child = root()->child(0);
3085 child->make_root();
3086 delete_internal_node(root());
3087 mutable_root() = child;
3088 }
3089 }
3090
3091 template <typename P>
3092 template <typename IterType>
3093 inline IterType btree<P>::internal_last(IterType iter) {
3094 assert(iter.node != nullptr);
3095 while (iter.position == iter.node->count()) {
3096 iter.position = iter.node->position();
3097 iter.node = iter.node->parent();
3098 if (iter.node->leaf()) {
3099 iter.node = nullptr;
3100 break;
3101 }
3102 }
3103 return iter;
3104 }
3105
3106 template <typename P>
3107 template <typename... Args>
3108 inline auto btree<P>::internal_emplace(iterator iter, Args &&... args)
3109 -> iterator {
3110 if (!iter.node->leaf()) {
3111 // We can't insert on an internal node. Instead, we'll insert after the
3112 // previous value which is guaranteed to be on a leaf node.
3113 --iter;
3114 ++iter.position;
3115 }
3116 const int max_count = iter.node->max_count();
3117 if (iter.node->count() == max_count) {
3118 // Make room in the leaf for the new item.
3119 if (max_count < kNodeValues) {
3120 // Insertion into the root where the root is smaller than the full node
3121 // size. Simply grow the size of the root node.
3122 assert(iter.node == root());
3123 iter.node =
3124 new_leaf_root_node((std::min<int>)(kNodeValues, 2 * max_count));
3125 iter.node->swap(root(), mutable_allocator());
3126 delete_leaf_node(root());
3127 mutable_root() = iter.node;
3128 rightmost_ = iter.node;
3129 } else {
3130 rebalance_or_split(&iter);
3131 }
3132 }
3133 iter.node->emplace_value(iter.position, mutable_allocator(),
3134 std::forward<Args>(args)...);
3135 ++size_;
3136 return iter;
3137 }
3138
3139 template <typename P>
3140 template <typename K>
3141 inline auto btree<P>::internal_locate(const K &key) const
3143 return internal_locate_impl(key, is_key_compare_to());
3144 }
3145
3146 template <typename P>
3147 template <typename K>
3149 const K &key, std::false_type /* IsCompareTo */) const
3151 iterator iter(const_cast<node_type *>(root()), 0);
3152 for (;;) {
3153 iter.position = iter.node->lower_bound(key, key_comp()).value;
3154 // NOTE: we don't need to walk all the way down the tree if the keys are
3155 // equal, but determining equality would require doing an extra comparison
3156 // on each node on the way down, and we will need to go all the way to the
3157 // leaf node in the expected case.
3158 if (iter.node->leaf()) {
3159 break;
3160 }
3161 iter.node = iter.node->child(iter.position);
3162 }
3163 return {iter};
3164 }
3165
3166 template <typename P>
3167 template <typename K>
3169 const K &key, std::true_type /* IsCompareTo */) const
3171 iterator iter(const_cast<node_type *>(root()), 0);
3172 for (;;) {
3173 SearchResult<int, true> res = iter.node->lower_bound(key, key_comp());
3174 iter.position = res.value;
3175 if (res.match == MatchKind::kEq) {
3176 return {iter, MatchKind::kEq};
3177 }
3178 if (iter.node->leaf()) {
3179 break;
3180 }
3181 iter.node = iter.node->child(iter.position);
3182 }
3183 return {iter, MatchKind::kNe};
3184 }
3185
3186 template <typename P>
3187 template <typename K>
3188 auto btree<P>::internal_lower_bound(const K &key) const -> iterator {
3189 iterator iter(const_cast<node_type *>(root()), 0);
3190 for (;;) {
3191 iter.position = iter.node->lower_bound(key, key_comp()).value;
3192 if (iter.node->leaf()) {
3193 break;
3194 }
3195 iter.node = iter.node->child(iter.position);
3196 }
3197 return internal_last(iter);
3198 }
3199
3200 template <typename P>
3201 template <typename K>
3202 auto btree<P>::internal_upper_bound(const K &key) const -> iterator {
3203 iterator iter(const_cast<node_type *>(root()), 0);
3204 for (;;) {
3205 iter.position = iter.node->upper_bound(key, key_comp());
3206 if (iter.node->leaf()) {
3207 break;
3208 }
3209 iter.node = iter.node->child(iter.position);
3210 }
3211 return internal_last(iter);
3212 }
3213
3214 template <typename P>
3215 template <typename K>
3216 auto btree<P>::internal_find(const K &key) const -> iterator {
3217 auto res = internal_locate(key);
3218 if (res.HasMatch()) {
3219 if (res.IsEq()) {
3220 return res.value;
3221 }
3222 } else {
3223 const iterator iter = internal_last(res.value);
3224 if (iter.node != nullptr && !compare_keys(key, iter.key())) {
3225 return iter;
3226 }
3227 }
3228 return {nullptr, 0};
3229 }
3230
3231 template <typename P>
3233 if (!node->leaf()) {
3234 for (int i = 0; i <= node->count(); ++i) {
3235 internal_clear(node->child(i));
3236 }
3237 delete_internal_node(node);
3238 } else {
3239 delete_leaf_node(node);
3240 }
3241 }
3242
3243 template <typename P>
3245 const node_type *node, const key_type *lo, const key_type *hi) const {
3246 assert(node->count() > 0);
3247 assert(node->count() <= node->max_count());
3248 if (lo) {
3249 assert(!compare_keys(node->key(0), *lo));
3250 }
3251 if (hi) {
3252 assert(!compare_keys(*hi, node->key(node->count() - 1)));
3253 }
3254 for (int i = 1; i < node->count(); ++i) {
3255 assert(!compare_keys(node->key(i), node->key(i - 1)));
3256 }
3257 size_type count = node->count();
3258 if (!node->leaf()) {
3259 for (int i = 0; i <= node->count(); ++i) {
3260 assert(node->child(i) != nullptr);
3261 assert(node->child(i)->parent() == node);
3262 assert(node->child(i)->position() == i);
3263 count += internal_verify(
3264 node->child(i),
3265 (i == 0) ? lo : &node->key(i - 1),
3266 (i == node->count()) ? hi : &node->key(i));
3267 }
3268 }
3269 return count;
3270 }
3271
3272 // A common base class for btree_set, btree_map, btree_multiset, and btree_multimap.
3273 // ---------------------------------------------------------------------------------
3274 template <typename Tree>
3276 using params_type = typename Tree::params_type;
3277
3278 protected:
3279 // Alias used for heterogeneous lookup functions.
3280 // `key_arg<K>` evaluates to `K` when the functors are transparent and to
3281 // `key_type` otherwise. It permits template argument deduction on `K` for the
3282 // transparent case.
3283 template <class K>
3284 using key_arg =
3286 template type<K, typename Tree::key_type>;
3287
3288 public:
3289 using key_type = typename Tree::key_type;
3290 using value_type = typename Tree::value_type;
3291 using size_type = typename Tree::size_type;
3292 using difference_type = typename Tree::difference_type;
3293 using key_compare = typename Tree::key_compare;
3294 using value_compare = typename Tree::value_compare;
3295 using allocator_type = typename Tree::allocator_type;
3296 using reference = typename Tree::reference;
3297 using const_reference = typename Tree::const_reference;
3298 using pointer = typename Tree::pointer;
3299 using const_pointer = typename Tree::const_pointer;
3300 using iterator = typename Tree::iterator;
3301 using const_iterator = typename Tree::const_iterator;
3302 using reverse_iterator = typename Tree::reverse_iterator;
3303 using const_reverse_iterator = typename Tree::const_reverse_iterator;
3304 using node_type = typename Tree::node_handle_type;
3305
3306 // Constructors/assignments.
3308 explicit btree_container(const key_compare &comp,
3309 const allocator_type &alloc = allocator_type())
3310 : tree_(comp, alloc) {}
3312 btree_container(btree_container &&x) noexcept = default;
3315 std::is_nothrow_move_assignable<Tree>::value) = default;
3316
3317 // Iterator routines.
3318 iterator begin() { return tree_.begin(); }
3319 const_iterator begin() const { return tree_.begin(); }
3320 const_iterator cbegin() const { return tree_.begin(); }
3321 iterator end() { return tree_.end(); }
3322 const_iterator end() const { return tree_.end(); }
3323 const_iterator cend() const { return tree_.end(); }
3324 reverse_iterator rbegin() { return tree_.rbegin(); }
3325 const_reverse_iterator rbegin() const { return tree_.rbegin(); }
3326 const_reverse_iterator crbegin() const { return tree_.rbegin(); }
3327 reverse_iterator rend() { return tree_.rend(); }
3328 const_reverse_iterator rend() const { return tree_.rend(); }
3329 const_reverse_iterator crend() const { return tree_.rend(); }
3330
3331 // Lookup routines.
3332 // ----------------
3333 template <typename K = key_type>
3334 size_type count(const key_arg<K> &key) const {
3335 auto equal_range = this->equal_range(key);
3336 return std::distance(equal_range.first, equal_range.second);
3337 }
3338 template <typename K = key_type>
3340 return tree_.find(key);
3341 }
3342 template <typename K = key_type>
3343 const_iterator find(const key_arg<K> &key) const { return tree_.find(key); }
3344
3345 template <typename K = key_type>
3346 bool contains(const key_arg<K> &key) const { return find(key) != end(); }
3347
3348 template <typename K = key_type>
3349 iterator lower_bound(const key_arg<K> &key) { return tree_.lower_bound(key); }
3350
3351 template <typename K = key_type>
3352 const_iterator lower_bound(const key_arg<K> &key) const { return tree_.lower_bound(key); }
3353
3354 template <typename K = key_type>
3355 iterator upper_bound(const key_arg<K> &key) { return tree_.upper_bound(key); }
3356
3357 template <typename K = key_type>
3358 const_iterator upper_bound(const key_arg<K> &key) const { return tree_.upper_bound(key); }
3359
3360 template <typename K = key_type>
3361 std::pair<iterator, iterator> equal_range(const key_arg<K> &key) { return tree_.equal_range(key); }
3362
3363 template <typename K = key_type>
3364 std::pair<const_iterator, const_iterator> equal_range(
3365 const key_arg<K> &key) const {
3366 return tree_.equal_range(key);
3367 }
3368
3369 iterator erase(const_iterator iter) { return tree_.erase(iterator(iter)); }
3370 iterator erase(iterator iter) { return tree_.erase(iter); }
3372 return tree_.erase(iterator(first), iterator(last)).second;
3373 }
3374 template <typename K = key_type>
3376 auto equal_range = this->equal_range(key);
3377 return tree_.erase_range(equal_range.first, equal_range.second).first;
3378 }
3380 // Use Move instead of Transfer, because the rebalancing code expects to
3381 // have a valid object to scribble metadata bits on top of.
3382 auto node = CommonAccess::Move<node_type>(get_allocator(), position.slot());
3383 erase(position);
3384 return node;
3385 }
3386
3388 return extract(iterator(position));
3389 }
3390
3391 public:
3392 void clear() { tree_.clear(); }
3393 void swap(btree_container &x) { tree_.swap(x.tree_); }
3394 void verify() const { tree_.verify(); }
3395
3396 size_type size() const { return tree_.size(); }
3397 size_type max_size() const { return tree_.max_size(); }
3398 bool empty() const { return tree_.empty(); }
3399
3400 friend bool operator==(const btree_container &x, const btree_container &y) {
3401 if (x.size() != y.size()) return false;
3402 return std::equal(x.begin(), x.end(), y.begin());
3403 }
3404
3405 friend bool operator!=(const btree_container &x, const btree_container &y) { return !(x == y); }
3406
3407 friend bool operator<(const btree_container &x, const btree_container &y) {
3408 return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
3409 }
3410
3411 friend bool operator>(const btree_container &x, const btree_container &y) { return y < x; }
3412
3413 friend bool operator<=(const btree_container &x, const btree_container &y) { return !(y < x); }
3414
3415 friend bool operator>=(const btree_container &x, const btree_container &y) { return !(x < y); }
3416
3417 // The allocator used by the btree.
3418 allocator_type get_allocator() const { return tree_.get_allocator(); }
3419
3420 // The key comparator used by the btree.
3421 key_compare key_comp() const { return tree_.key_comp(); }
3422 value_compare value_comp() const { return tree_.value_comp(); }
3423
3424 // Support absl::Hash.
3425 template <typename State>
3426 friend State AbslHashValue(State h, const btree_container &b) {
3427 for (const auto &v : b) {
3428 h = State::combine(std::move(h), v);
3429 }
3430 return State::combine(std::move(h), b.size());
3431 }
3432
3433 protected:
3434 Tree tree_;
3435 };
3436
3437 // A common base class for btree_set and btree_map.
3438 // -----------------------------------------------
3439 template <typename Tree>
3442 using params_type = typename Tree::params_type;
3443 using init_type = typename params_type::init_type;
3444 using is_key_compare_to = typename params_type::is_key_compare_to;
3445 friend class BtreeNodePeer;
3446
3447 protected:
3448 template <class K>
3449 using key_arg = typename super_type::template key_arg<K>;
3450
3451 public:
3452 using key_type = typename Tree::key_type;
3453 using value_type = typename Tree::value_type;
3454 using size_type = typename Tree::size_type;
3455 using key_compare = typename Tree::key_compare;
3456 using allocator_type = typename Tree::allocator_type;
3457 using iterator = typename Tree::iterator;
3458 using const_iterator = typename Tree::const_iterator;
3461 using super_type::super_type;
3463
3464 template <class InputIterator>
3465 btree_set_container(InputIterator b, InputIterator e,
3466 const key_compare &comp = key_compare(),
3467 const allocator_type &alloc = allocator_type())
3468 : super_type(comp, alloc) {
3469 insert(b, e);
3470 }
3471
3472 btree_set_container(std::initializer_list<init_type> init,
3473 const key_compare &comp = key_compare(),
3474 const allocator_type &alloc = allocator_type())
3475 : btree_set_container(init.begin(), init.end(), comp, alloc) {}
3476
3477 btree_set_container(std::initializer_list<init_type> init,
3478 const allocator_type &alloc)
3479 : btree_set_container(init.begin(), init.end(), alloc) {}
3480
3481 // Lookup routines.
3482 template <typename K = key_type>
3483 size_type count(const key_arg<K> &key) const {
3484 return this->tree_.count_unique(key);
3485 }
3486
3487 // Insertion routines.
3488 std::pair<iterator, bool> insert(const value_type &x) {
3489 return this->tree_.insert_unique(params_type::key(x), x);
3490 }
3491 std::pair<iterator, bool> insert(value_type &&x) {
3492 return this->tree_.insert_unique(params_type::key(x), std::move(x));
3493 }
3494 template <typename... Args>
3495 std::pair<iterator, bool> emplace(Args &&... args) {
3496 init_type v(std::forward<Args>(args)...);
3497 return this->tree_.insert_unique(params_type::key(v), std::move(v));
3498 }
3500 return this->tree_
3501 .insert_hint_unique(iterator(hint), params_type::key(x), x)
3502 .first;
3503 }
3505 return this->tree_
3506 .insert_hint_unique(iterator(hint), params_type::key(x),
3507 std::move(x))
3508 .first;
3509 }
3510
3511 template <typename... Args>
3512 iterator emplace_hint(const_iterator hint, Args &&... args) {
3513 init_type v(std::forward<Args>(args)...);
3514 return this->tree_
3515 .insert_hint_unique(iterator(hint), params_type::key(v),
3516 std::move(v))
3517 .first;
3518 }
3519
3520 template <typename InputIterator>
3521 void insert(InputIterator b, InputIterator e) {
3522 this->tree_.insert_iterator_unique(b, e);
3523 }
3524
3525 void insert(std::initializer_list<init_type> init) {
3526 this->tree_.insert_iterator_unique(init.begin(), init.end());
3527 }
3528
3530 if (!node) return {this->end(), false, node_type()};
3531 std::pair<iterator, bool> res =
3532 this->tree_.insert_unique(params_type::key(CommonAccess::GetSlot(node)),
3533 CommonAccess::GetSlot(node));
3534 if (res.second) {
3535 CommonAccess::Destroy(&node);
3536 return {res.first, true, node_type()};
3537 } else {
3538 return {res.first, false, std::move(node)};
3539 }
3540 }
3541
3543 if (!node) return this->end();
3544 std::pair<iterator, bool> res = this->tree_.insert_hint_unique(
3545 iterator(hint), params_type::key(CommonAccess::GetSlot(node)),
3546 CommonAccess::GetSlot(node));
3547 if (res.second) CommonAccess::Destroy(&node);
3548 return res.first;
3549 }
3550
3551 template <typename K = key_type>
3552 size_type erase(const key_arg<K> &key) { return this->tree_.erase_unique(key); }
3554
3555 template <typename K = key_type>
3557 auto it = this->find(key);
3558 return it == this->end() ? node_type() : extract(it);
3559 }
3560
3562
3563 // Merge routines.
3564 // Moves elements from `src` into `this`. If the element already exists in
3565 // `this`, it is left unmodified in `src`.
3566 template <
3567 typename T,
3568 typename phmap::enable_if_t<
3570 std::is_same<value_type, typename T::value_type>,
3571 std::is_same<allocator_type, typename T::allocator_type>,
3572 std::is_same<typename params_type::is_map_container,
3573 typename T::params_type::is_map_container>>::value,
3574 int> = 0>
3575 void merge(btree_container<T> &src) { // NOLINT
3576 for (auto src_it = src.begin(); src_it != src.end();) {
3577 if (insert(std::move(*src_it)).second) {
3578 src_it = src.erase(src_it);
3579 } else {
3580 ++src_it;
3581 }
3582 }
3583 }
3584
3585 template <
3586 typename T,
3587 typename phmap::enable_if_t<
3589 std::is_same<value_type, typename T::value_type>,
3590 std::is_same<allocator_type, typename T::allocator_type>,
3591 std::is_same<typename params_type::is_map_container,
3592 typename T::params_type::is_map_container>>::value,
3593 int> = 0>
3595 merge(src);
3596 }
3597 };
3598
3599 // Base class for btree_map.
3600 // -------------------------
3601 template <typename Tree>
3604 using params_type = typename Tree::params_type;
3605
3606 protected:
3607 template <class K>
3608 using key_arg = typename super_type::template key_arg<K>;
3609
3610 public:
3611 using key_type = typename Tree::key_type;
3612 using mapped_type = typename params_type::mapped_type;
3613 using value_type = typename Tree::value_type;
3614 using key_compare = typename Tree::key_compare;
3615 using allocator_type = typename Tree::allocator_type;
3616 using iterator = typename Tree::iterator;
3617 using const_iterator = typename Tree::const_iterator;
3618
3619 // Inherit constructors.
3622
3623 // Insertion routines.
3624 template <typename... Args>
3625 std::pair<iterator, bool> try_emplace(const key_type &k, Args &&... args) {
3626 return this->tree_.insert_unique(
3627 k, std::piecewise_construct, std::forward_as_tuple(k),
3628 std::forward_as_tuple(std::forward<Args>(args)...));
3629 }
3630 template <typename... Args>
3631 std::pair<iterator, bool> try_emplace(key_type &&k, Args &&... args) {
3632 // Note: `key_ref` exists to avoid a ClangTidy warning about moving from `k`
3633 // and then using `k` unsequenced. This is safe because the move is into a
3634 // forwarding reference and insert_unique guarantees that `key` is never
3635 // referenced after consuming `args`.
3636 const key_type& key_ref = k;
3637 return this->tree_.insert_unique(
3638 key_ref, std::piecewise_construct, std::forward_as_tuple(std::move(k)),
3639 std::forward_as_tuple(std::forward<Args>(args)...));
3640 }
3641 template <typename... Args>
3643 Args &&... args) {
3644 return this->tree_
3645 .insert_hint_unique(iterator(hint), k, std::piecewise_construct,
3646 std::forward_as_tuple(k),
3647 std::forward_as_tuple(std::forward<Args>(args)...))
3648 .first;
3649 }
3650 template <typename... Args>
3651 iterator try_emplace(const_iterator hint, key_type &&k, Args &&... args) {
3652 // Note: `key_ref` exists to avoid a ClangTidy warning about moving from `k`
3653 // and then using `k` unsequenced. This is safe because the move is into a
3654 // forwarding reference and insert_hint_unique guarantees that `key` is
3655 // never referenced after consuming `args`.
3656 const key_type& key_ref = k;
3657 return this->tree_
3658 .insert_hint_unique(iterator(hint), key_ref, std::piecewise_construct,
3659 std::forward_as_tuple(std::move(k)),
3660 std::forward_as_tuple(std::forward<Args>(args)...))
3661 .first;
3662 }
3664 return try_emplace(k).first->second;
3665 }
3667 return try_emplace(std::move(k)).first->second;
3668 }
3669
3670 template <typename K = key_type>
3672 auto it = this->find(key);
3673 if (it == this->end())
3674 base_internal::ThrowStdOutOfRange("phmap::btree_map::at");
3675 return it->second;
3676 }
3677 template <typename K = key_type>
3678 const mapped_type &at(const key_arg<K> &key) const {
3679 auto it = this->find(key);
3680 if (it == this->end())
3681 base_internal::ThrowStdOutOfRange("phmap::btree_map::at");
3682 return it->second;
3683 }
3684 };
3685
3686 // A common base class for btree_multiset and btree_multimap.
3687 template <typename Tree>
3690 using params_type = typename Tree::params_type;
3691 using init_type = typename params_type::init_type;
3692 using is_key_compare_to = typename params_type::is_key_compare_to;
3693
3694 template <class K>
3695 using key_arg = typename super_type::template key_arg<K>;
3696
3697 public:
3698 using key_type = typename Tree::key_type;
3699 using value_type = typename Tree::value_type;
3700 using size_type = typename Tree::size_type;
3701 using key_compare = typename Tree::key_compare;
3702 using allocator_type = typename Tree::allocator_type;
3703 using iterator = typename Tree::iterator;
3704 using const_iterator = typename Tree::const_iterator;
3706
3707 // Inherit constructors.
3708 using super_type::super_type;
3710
3711 // Range constructor.
3712 template <class InputIterator>
3713 btree_multiset_container(InputIterator b, InputIterator e,
3714 const key_compare &comp = key_compare(),
3715 const allocator_type &alloc = allocator_type())
3716 : super_type(comp, alloc) {
3717 insert(b, e);
3718 }
3719
3720 // Initializer list constructor.
3721 btree_multiset_container(std::initializer_list<init_type> init,
3722 const key_compare &comp = key_compare(),
3723 const allocator_type &alloc = allocator_type())
3724 : btree_multiset_container(init.begin(), init.end(), comp, alloc) {}
3725
3726 // Lookup routines.
3727 template <typename K = key_type>
3728 size_type count(const key_arg<K> &key) const {
3729 return this->tree_.count_multi(key);
3730 }
3731
3732 // Insertion routines.
3733 iterator insert(const value_type &x) { return this->tree_.insert_multi(x); }
3735 return this->tree_.insert_multi(std::move(x));
3736 }
3738 return this->tree_.insert_hint_multi(iterator(hint), x);
3739 }
3741 return this->tree_.insert_hint_multi(iterator(hint), std::move(x));
3742 }
3743 template <typename InputIterator>
3744 void insert(InputIterator b, InputIterator e) {
3745 this->tree_.insert_iterator_multi(b, e);
3746 }
3747 void insert(std::initializer_list<init_type> init) {
3748 this->tree_.insert_iterator_multi(init.begin(), init.end());
3749 }
3750 template <typename... Args>
3751 iterator emplace(Args &&... args) {
3752 return this->tree_.insert_multi(init_type(std::forward<Args>(args)...));
3753 }
3754 template <typename... Args>
3755 iterator emplace_hint(const_iterator hint, Args &&... args) {
3756 return this->tree_.insert_hint_multi(
3757 iterator(hint), init_type(std::forward<Args>(args)...));
3758 }
3760 if (!node) return this->end();
3761 iterator res =
3762 this->tree_.insert_multi(params_type::key(CommonAccess::GetSlot(node)),
3763 CommonAccess::GetSlot(node));
3764 CommonAccess::Destroy(&node);
3765 return res;
3766 }
3768 if (!node) return this->end();
3769 iterator res = this->tree_.insert_hint_multi(
3770 iterator(hint),
3771 std::move(params_type::element(CommonAccess::GetSlot(node))));
3772 CommonAccess::Destroy(&node);
3773 return res;
3774 }
3775
3776 // Deletion routines.
3777 template <typename K = key_type>
3779 return this->tree_.erase_multi(key);
3780 }
3782
3783 // Node extraction routines.
3784 template <typename K = key_type>
3786 auto it = this->find(key);
3787 return it == this->end() ? node_type() : extract(it);
3788 }
3790
3791 // Merge routines.
3792 // Moves all elements from `src` into `this`.
3793 template <
3794 typename T,
3795 typename phmap::enable_if_t<
3797 std::is_same<value_type, typename T::value_type>,
3798 std::is_same<allocator_type, typename T::allocator_type>,
3799 std::is_same<typename params_type::is_map_container,
3800 typename T::params_type::is_map_container>>::value,
3801 int> = 0>
3802 void merge(btree_container<T> &src) { // NOLINT
3803 insert(std::make_move_iterator(src.begin()),
3804 std::make_move_iterator(src.end()));
3805 src.clear();
3806 }
3807
3808 template <
3809 typename T,
3810 typename phmap::enable_if_t<
3812 std::is_same<value_type, typename T::value_type>,
3813 std::is_same<allocator_type, typename T::allocator_type>,
3814 std::is_same<typename params_type::is_map_container,
3815 typename T::params_type::is_map_container>>::value,
3816 int> = 0>
3818 merge(src);
3819 }
3820 };
3821
3822 // A base class for btree_multimap.
3823 template <typename Tree>
3826 using params_type = typename Tree::params_type;
3827
3828 public:
3829 using mapped_type = typename params_type::mapped_type;
3830
3831 // Inherit constructors.
3834 };
3835
3836} // namespace priv
3837
3838
3839
3840 // ----------------------------------------------------------------------
3841 // btree_set - default values in phmap_fwd_decl.h
3842 // ----------------------------------------------------------------------
3843 template <typename Key, typename Compare, typename Alloc>
3845 priv::btree<priv::set_params<
3846 Key, Compare, Alloc, /*TargetNodeSize=*/ 256, /*Multi=*/ false>>>
3847 {
3849
3850 public:
3852 using Base::Base;
3853 using Base::begin;
3854 using Base::cbegin;
3855 using Base::end;
3856 using Base::cend;
3857 using Base::empty;
3858 using Base::max_size;
3859 using Base::size;
3860 using Base::clear;
3861 using Base::erase;
3862 using Base::insert;
3863 using Base::emplace;
3864 using Base::emplace_hint;
3865 using Base::extract;
3866 using Base::merge;
3867 using Base::swap;
3868 using Base::contains;
3869 using Base::count;
3870 using Base::equal_range;
3871 using Base::lower_bound;
3872 using Base::upper_bound;
3873 using Base::find;
3874 using Base::get_allocator;
3875 using Base::key_comp;
3876 using Base::value_comp;
3877 };
3878
3879 // Swaps the contents of two `phmap::btree_set` containers.
3880 // -------------------------------------------------------
3881 template <typename K, typename C, typename A>
3883 return x.swap(y);
3884 }
3885
3886 // Erases all elements that satisfy the predicate pred from the container.
3887 // ----------------------------------------------------------------------
3888 template <typename K, typename C, typename A, typename Pred>
3889 void erase_if(btree_set<K, C, A> &set, Pred pred) {
3890 for (auto it = set.begin(); it != set.end();) {
3891 if (pred(*it)) {
3892 it = set.erase(it);
3893 } else {
3894 ++it;
3895 }
3896 }
3897 }
3898
3899 // ----------------------------------------------------------------------
3900 // btree_multiset - default values in phmap_fwd_decl.h
3901 // ----------------------------------------------------------------------
3902 template <typename Key, typename Compare, typename Alloc>
3904 priv::btree<priv::set_params<
3905 Key, Compare, Alloc, /*TargetNodeSize=*/ 256, /*Multi=*/ true>>>
3906 {
3908
3909 public:
3911 using Base::Base;
3912 using Base::begin;
3913 using Base::cbegin;
3914 using Base::end;
3915 using Base::cend;
3916 using Base::empty;
3917 using Base::max_size;
3918 using Base::size;
3919 using Base::clear;
3920 using Base::erase;
3921 using Base::insert;
3922 using Base::emplace;
3923 using Base::emplace_hint;
3924 using Base::extract;
3925 using Base::merge;
3926 using Base::swap;
3927 using Base::contains;
3928 using Base::count;
3929 using Base::equal_range;
3930 using Base::lower_bound;
3931 using Base::upper_bound;
3932 using Base::find;
3933 using Base::get_allocator;
3934 using Base::key_comp;
3935 using Base::value_comp;
3936 };
3937
3938 // Swaps the contents of two `phmap::btree_multiset` containers.
3939 // ------------------------------------------------------------
3940 template <typename K, typename C, typename A>
3942 return x.swap(y);
3943 }
3944
3945 // Erases all elements that satisfy the predicate pred from the container.
3946 // ----------------------------------------------------------------------
3947 template <typename K, typename C, typename A, typename Pred>
3948 void erase_if(btree_multiset<K, C, A> &set, Pred pred) {
3949 for (auto it = set.begin(); it != set.end();) {
3950 if (pred(*it)) {
3951 it = set.erase(it);
3952 } else {
3953 ++it;
3954 }
3955 }
3956 }
3957
3958
3959 // ----------------------------------------------------------------------
3960 // btree_map - default values in phmap_fwd_decl.h
3961 // ----------------------------------------------------------------------
3962 template <typename Key, typename Value, typename Compare, typename Alloc>
3964 priv::btree<priv::map_params<
3965 Key, Value, Compare, Alloc, /*TargetNodeSize=*/ 256, /*Multi=*/ false>>>
3966 {
3968
3969 public:
3971 using Base::Base;
3972 using Base::begin;
3973 using Base::cbegin;
3974 using Base::end;
3975 using Base::cend;
3976 using Base::empty;
3977 using Base::max_size;
3978 using Base::size;
3979 using Base::clear;
3980 using Base::erase;
3981 using Base::insert;
3982 using Base::emplace;
3983 using Base::emplace_hint;
3984 using Base::try_emplace;
3985 using Base::extract;
3986 using Base::merge;
3987 using Base::swap;
3988 using Base::at;
3989 using Base::contains;
3990 using Base::count;
3991 using Base::equal_range;
3992 using Base::lower_bound;
3993 using Base::upper_bound;
3994 using Base::find;
3995 using Base::operator[];
3996 using Base::get_allocator;
3997 using Base::key_comp;
3998 using Base::value_comp;
3999 };
4000
4001 // Swaps the contents of two `phmap::btree_map` containers.
4002 // -------------------------------------------------------
4003 template <typename K, typename V, typename C, typename A>
4005 return x.swap(y);
4006 }
4007
4008 // ----------------------------------------------------------------------
4009 template <typename K, typename V, typename C, typename A, typename Pred>
4010 void erase_if(btree_map<K, V, C, A> &map, Pred pred) {
4011 for (auto it = map.begin(); it != map.end();) {
4012 if (pred(*it)) {
4013 it = map.erase(it);
4014 } else {
4015 ++it;
4016 }
4017 }
4018 }
4019
4020 // ----------------------------------------------------------------------
4021 // btree_multimap - default values in phmap_fwd_decl.h
4022 // ----------------------------------------------------------------------
4023 template <typename Key, typename Value, typename Compare, typename Alloc>
4025 priv::btree<priv::map_params<
4026 Key, Value, Compare, Alloc, /*TargetNodeSize=*/ 256, /*Multi=*/ true>>>
4027 {
4029
4030 public:
4032 using Base::Base;
4033 using Base::begin;
4034 using Base::cbegin;
4035 using Base::end;
4036 using Base::cend;
4037 using Base::empty;
4038 using Base::max_size;
4039 using Base::size;
4040 using Base::clear;
4041 using Base::erase;
4042 using Base::insert;
4043 using Base::emplace;
4044 using Base::emplace_hint;
4045 using Base::extract;
4046 using Base::merge;
4047 using Base::swap;
4048 using Base::contains;
4049 using Base::count;
4050 using Base::equal_range;
4051 using Base::lower_bound;
4052 using Base::upper_bound;
4053 using Base::find;
4054 using Base::get_allocator;
4055 using Base::key_comp;
4056 using Base::value_comp;
4057 };
4058
4059 // Swaps the contents of two `phmap::btree_multimap` containers.
4060 // ------------------------------------------------------------
4061 template <typename K, typename V, typename C, typename A>
4063 return x.swap(y);
4064 }
4065
4066 // Erases all elements that satisfy the predicate pred from the container.
4067 // ----------------------------------------------------------------------
4068 template <typename K, typename V, typename C, typename A, typename Pred>
4069 void erase_if(btree_multimap<K, V, C, A> &map, Pred pred) {
4070 for (auto it = map.begin(); it != map.end();) {
4071 if (pred(*it)) {
4072 it = map.erase(it);
4073 } else {
4074 ++it;
4075 }
4076 }
4077 }
4078
4079
4080} // namespace btree
4081
4082#ifdef _MSC_VER
4083 #pragma warning(pop)
4084#endif
4085
4086
4087#endif // PHMAP_BTREE_BTREE_CONTAINER_H_
#define PHMAP_COMPARE_INLINE_SUBCLASS_DECL(type, name)
Definition: btree.h:266
#define PHMAP_COMPARE_INLINE_INIT(type, name, init)
Definition: btree.h:268
#define PHMAP_COMPARE_INLINE_BASECLASS_DECL(name)
Definition: btree.h:263
Definition: btree.h:3966
typename btree_map::btree_map_container Base
Definition: btree.h:3967
btree_map()
Definition: btree.h:3970
Definition: btree.h:4027
typename btree_multimap::btree_multimap_container Base
Definition: btree.h:4028
btree_multimap()
Definition: btree.h:4031
Definition: btree.h:3906
btree_multiset()
Definition: btree.h:3910
typename btree_multiset::btree_multiset_container Base
Definition: btree.h:3907
Definition: btree.h:3847
btree_set()
Definition: btree.h:3851
typename btree_set::btree_set_container Base
Definition: btree.h:3848
Definition: btree.h:400
friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>, partial_ordering v) noexcept
Definition: btree.h:450
constexpr partial_ordering(compare_internal::eq v) noexcept
Definition: btree.h:401
friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>, partial_ordering v) noexcept
Definition: btree.h:470
friend constexpr bool operator==(partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept
Definition: btree.h:426
friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>, partial_ordering v) noexcept
Definition: btree.h:466
compare_internal::value_type value_
Definition: btree.h:476
constexpr partial_ordering(compare_internal::ord v) noexcept
Definition: btree.h:403
friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>, partial_ordering v) noexcept
Definition: btree.h:462
friend constexpr bool operator!=(partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept
Definition: btree.h:430
friend constexpr bool operator<(partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept
Definition: btree.h:434
friend constexpr bool operator>=(partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept
Definition: btree.h:446
friend constexpr bool operator>(partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept
Definition: btree.h:442
friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>, partial_ordering v) noexcept
Definition: btree.h:454
constexpr bool is_ordered() const noexcept
Definition: btree.h:409
friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>, partial_ordering v) noexcept
Definition: btree.h:458
friend constexpr bool operator<=(partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept
Definition: btree.h:438
Definition: phmap_base.h:4286
Definition: phmap_base.h:4129
Definition: btree.h:3275
typename Tree::value_type value_type
Definition: btree.h:3290
typename Tree::allocator_type allocator_type
Definition: btree.h:3295
void swap(btree_container &x)
Definition: btree.h:3393
typename KeyArg< IsTransparent< typename Tree::key_compare >::value >::template type< K, typename Tree::key_type > key_arg
Definition: btree.h:3286
const_iterator cend() const
Definition: btree.h:3323
const_iterator end() const
Definition: btree.h:3322
const_reverse_iterator crbegin() const
Definition: btree.h:3326
size_type size() const
Definition: btree.h:3396
node_type extract(iterator position)
Definition: btree.h:3379
reverse_iterator rend()
Definition: btree.h:3327
value_compare value_comp() const
Definition: btree.h:3422
const_reverse_iterator rbegin() const
Definition: btree.h:3325
typename Tree::value_compare value_compare
Definition: btree.h:3294
iterator erase(const_iterator first, const_iterator last)
Definition: btree.h:3371
const_iterator find(const key_arg< K > &key) const
Definition: btree.h:3343
iterator erase(const_iterator iter)
Definition: btree.h:3369
typename Tree::key_compare key_compare
Definition: btree.h:3293
const_iterator cbegin() const
Definition: btree.h:3320
iterator find(const key_arg< K > &key)
Definition: btree.h:3339
friend bool operator>=(const btree_container &x, const btree_container &y)
Definition: btree.h:3415
friend bool operator<(const btree_container &x, const btree_container &y)
Definition: btree.h:3407
const_iterator upper_bound(const key_arg< K > &key) const
Definition: btree.h:3358
const_iterator begin() const
Definition: btree.h:3319
btree_container(const btree_container &x)=default
friend State AbslHashValue(State h, const btree_container &b)
Definition: btree.h:3426
const_reverse_iterator rend() const
Definition: btree.h:3328
std::pair< const_iterator, const_iterator > equal_range(const key_arg< K > &key) const
Definition: btree.h:3364
iterator begin()
Definition: btree.h:3318
void verify() const
Definition: btree.h:3394
iterator upper_bound(const key_arg< K > &key)
Definition: btree.h:3355
btree_container()
Definition: btree.h:3307
typename Tree::reference reference
Definition: btree.h:3296
btree_container & operator=(btree_container &&x) noexcept(std::is_nothrow_move_assignable< Tree >::value)=default
const_reverse_iterator crend() const
Definition: btree.h:3329
friend bool operator<=(const btree_container &x, const btree_container &y)
Definition: btree.h:3413
typename Tree::node_handle_type node_type
Definition: btree.h:3304
typename Tree::reverse_iterator reverse_iterator
Definition: btree.h:3302
iterator end()
Definition: btree.h:3321
void clear()
Definition: btree.h:3392
key_compare key_comp() const
Definition: btree.h:3421
typename Tree::iterator iterator
Definition: btree.h:3300
typename Tree::const_reference const_reference
Definition: btree.h:3297
btree_container(btree_container &&x) noexcept=default
size_type max_size() const
Definition: btree.h:3397
typename Tree::difference_type difference_type
Definition: btree.h:3292
Tree tree_
Definition: btree.h:3434
typename Tree::pointer pointer
Definition: btree.h:3298
iterator erase(iterator iter)
Definition: btree.h:3370
typename Tree::const_iterator const_iterator
Definition: btree.h:3301
btree_container(const key_compare &comp, const allocator_type &alloc=allocator_type())
Definition: btree.h:3308
friend bool operator==(const btree_container &x, const btree_container &y)
Definition: btree.h:3400
typename Tree::size_type size_type
Definition: btree.h:3291
size_type count(const key_arg< K > &key) const
Definition: btree.h:3334
bool empty() const
Definition: btree.h:3398
btree_container & operator=(const btree_container &x)=default
typename Tree::key_type key_type
Definition: btree.h:3289
friend bool operator>(const btree_container &x, const btree_container &y)
Definition: btree.h:3411
allocator_type get_allocator() const
Definition: btree.h:3418
node_type extract(const_iterator position)
Definition: btree.h:3387
bool contains(const key_arg< K > &key) const
Definition: btree.h:3346
friend bool operator!=(const btree_container &x, const btree_container &y)
Definition: btree.h:3405
typename Tree::const_reverse_iterator const_reverse_iterator
Definition: btree.h:3303
const_iterator lower_bound(const key_arg< K > &key) const
Definition: btree.h:3352
reverse_iterator rbegin()
Definition: btree.h:3324
typename Tree::const_pointer const_pointer
Definition: btree.h:3299
typename Tree::params_type params_type
Definition: btree.h:3276
iterator lower_bound(const key_arg< K > &key)
Definition: btree.h:3349
std::pair< iterator, iterator > equal_range(const key_arg< K > &key)
Definition: btree.h:3361
size_type erase(const key_arg< K > &key)
Definition: btree.h:3375
Definition: btree.h:3602
typename Tree::iterator iterator
Definition: btree.h:3616
typename Tree::const_iterator const_iterator
Definition: btree.h:3617
iterator try_emplace(const_iterator hint, key_type &&k, Args &&... args)
Definition: btree.h:3651
std::pair< iterator, bool > try_emplace(key_type &&k, Args &&... args)
Definition: btree.h:3631
typename Tree::value_type value_type
Definition: btree.h:3613
btree_map_container()
Definition: btree.h:3621
mapped_type & operator[](const key_type &k)
Definition: btree.h:3663
mapped_type & at(const key_arg< K > &key)
Definition: btree.h:3671
const mapped_type & at(const key_arg< K > &key) const
Definition: btree.h:3678
iterator try_emplace(const_iterator hint, const key_type &k, Args &&... args)
Definition: btree.h:3642
std::pair< iterator, bool > try_emplace(const key_type &k, Args &&... args)
Definition: btree.h:3625
typename Tree::params_type params_type
Definition: btree.h:3604
typename Tree::key_type key_type
Definition: btree.h:3611
typename super_type::template key_arg< K > key_arg
Definition: btree.h:3608
mapped_type & operator[](key_type &&k)
Definition: btree.h:3666
typename params_type::mapped_type mapped_type
Definition: btree.h:3612
typename Tree::key_compare key_compare
Definition: btree.h:3614
typename Tree::allocator_type allocator_type
Definition: btree.h:3615
typename Tree::params_type params_type
Definition: btree.h:3826
typename params_type::mapped_type mapped_type
Definition: btree.h:3829
btree_multimap_container()
Definition: btree.h:3833
btree_multiset_container(std::initializer_list< init_type > init, const key_compare &comp=key_compare(), const allocator_type &alloc=allocator_type())
Definition: btree.h:3721
void insert(InputIterator b, InputIterator e)
Definition: btree.h:3744
typename Tree::value_type value_type
Definition: btree.h:3699
size_type count(const key_arg< K > &key) const
Definition: btree.h:3728
iterator insert(const_iterator hint, value_type &&x)
Definition: btree.h:3740
typename params_type::init_type init_type
Definition: btree.h:3691
iterator insert(const value_type &x)
Definition: btree.h:3733
iterator insert(value_type &&x)
Definition: btree.h:3734
iterator emplace_hint(const_iterator hint, Args &&... args)
Definition: btree.h:3755
iterator insert(const_iterator hint, node_type &&node)
Definition: btree.h:3767
iterator insert(node_type &&node)
Definition: btree.h:3759
typename Tree::allocator_type allocator_type
Definition: btree.h:3702
iterator emplace(Args &&... args)
Definition: btree.h:3751
iterator insert(const_iterator hint, const value_type &x)
Definition: btree.h:3737
node_type extract(const key_arg< K > &key)
Definition: btree.h:3785
btree_multiset_container(InputIterator b, InputIterator e, const key_compare &comp=key_compare(), const allocator_type &alloc=allocator_type())
Definition: btree.h:3713
void merge(btree_container< T > &&src)
Definition: btree.h:3817
typename Tree::key_type key_type
Definition: btree.h:3698
typename Tree::params_type params_type
Definition: btree.h:3690
typename Tree::const_iterator const_iterator
Definition: btree.h:3704
void merge(btree_container< T > &src)
Definition: btree.h:3802
size_type erase(const key_arg< K > &key)
Definition: btree.h:3778
typename Tree::size_type size_type
Definition: btree.h:3700
typename Tree::iterator iterator
Definition: btree.h:3703
btree_multiset_container()
Definition: btree.h:3709
void insert(std::initializer_list< init_type > init)
Definition: btree.h:3747
typename params_type::is_key_compare_to is_key_compare_to
Definition: btree.h:3692
typename Tree::key_compare key_compare
Definition: btree.h:3701
typename super_type::template key_arg< K > key_arg
Definition: btree.h:3695
typename super_type::node_type node_type
Definition: btree.h:3705
Definition: btree.h:1045
SearchResult< int, true > linear_search_impl(const K &k, int s, const int e, const Compare &comp, std::true_type) const
Definition: btree.h:1283
SearchResult< int, is_key_compare_to::value > lower_bound(const K &k, const key_compare &comp) const
Definition: btree.h:1238
static btree_node * init_leaf(btree_node *n, btree_node *parent, int max_cnt)
Definition: btree.h:1386
field_type max_count() const
Definition: btree.h:1188
phmap::priv::Layout< btree_node *, field_type, slot_type, btree_node * > layout_type
Definition: btree.h:1093
static constexpr size_type Alignment()
Definition: btree.h:1082
typename Params::reference reference
Definition: btree.h:1058
const_reference value(size_type i) const
Definition: btree.h:1211
const slot_type * slot(size_type i) const
Definition: btree.h:1169
field_type start() const
Definition: btree.h:1184
const layout_type::template ElementType< N > * GetField() const
Definition: btree.h:1160
void value_init(const size_type i, allocator_type *alloc, Args &&... args)
Definition: btree.h:1420
typename Params::const_pointer const_pointer
Definition: btree.h:1057
typename Params::difference_type difference_type
Definition: btree.h:1062
layout_type::template ElementType< N > * GetField()
Definition: btree.h:1153
typename Params::pointer pointer
Definition: btree.h:1056
static bool testonly_uses_linear_node_search()
Definition: btree.h:1414
field_type & mutable_count()
Definition: btree.h:1167
reference value(size_type i)
Definition: btree.h:1210
void value_destroy(const size_type i, allocator_type *alloc)
Definition: btree.h:1424
SearchResult< int, btree_is_key_compare_to< Compare, key_type >::value > linear_search(const K &k, const Compare &comp) const
Definition: btree.h:1253
static constexpr size_type SizeWithNValues(size_type n)
Definition: btree.h:1094
static constexpr size_type InternalSize()
Definition: btree.h:1146
typename Params::node_count_type field_type
Definition: btree.h:1048
void init_child(int i, btree_node *c)
Definition: btree.h:1231
void set_start(field_type v)
Definition: btree.h:1171
SearchResult< int, btree_is_key_compare_to< Compare, key_type >::value > binary_search(const K &k, const Compare &comp) const
Definition: btree.h:1260
void destroy(allocator_type *alloc)
Definition: btree.h:1406
btree_node * child(size_type i) const
Definition: btree.h:1218
void clear_child(size_type i)
Definition: btree.h:1220
void value_destroy_n(const size_type i, const size_type n, allocator_type *alloc)
Definition: btree.h:1443
typename Params::key_type key_type
Definition: btree.h:1054
void emplace_value(size_type i, allocator_type *alloc, Args &&... args)
Definition: btree.h:2138
const key_type & key(size_type i) const
Definition: btree.h:1209
void swap(btree_node *src, allocator_type *alloc)
Definition: btree.h:2379
friend class BtreeNodePeer
Definition: btree.h:1454
void split(int insert_position, btree_node *dest, allocator_type *alloc)
Definition: btree.h:2308
void remove_value(int i, allocator_type *alloc)
Definition: btree.h:2162
static constexpr size_type LeafSize(const int max_values=kNodeValues)
Definition: btree.h:1143
field_type position() const
Definition: btree.h:1181
bool leaf() const
Definition: btree.h:1178
void merge(btree_node *sibling, allocator_type *alloc)
Definition: btree.h:2349
btree_node * parent() const
Definition: btree.h:1198
slot_type * slot(size_type i)
Definition: btree.h:1168
void uninitialized_move_n(const size_type n, const size_type i, const size_type j, btree_node *x, allocator_type *alloc)
Definition: btree.h:1431
bool is_root() const
Definition: btree.h:1202
void remove_values_ignore_children(int i, size_type to_erase, allocator_type *alloc)
Definition: btree.h:2175
typename Params::key_compare key_compare
Definition: btree.h:1060
static constexpr size_type MinimumOverhead()
Definition: btree.h:1102
@ kNodeTargetValues
Definition: btree.h:1118
@ kTargetNodeSize
Definition: btree.h:1117
field_type count() const
Definition: btree.h:1187
btree_node *& mutable_child(size_type i)
Definition: btree.h:1219
void set_max_count(field_type v)
Definition: btree.h:1173
void set_child(size_type i, btree_node *c)
Definition: btree.h:1223
btree_node & operator=(btree_node const &)=delete
static constexpr layout_type InternalLayout()
Definition: btree.h:1137
static constexpr size_type NodeTargetValues(const int begin, const int end)
Definition: btree.h:1108
typename Params::value_type value_type
Definition: btree.h:1055
int upper_bound(const K &k, const key_compare &comp) const
Definition: btree.h:1245
void rebalance_left_to_right(int to_move, btree_node *right, allocator_type *alloc)
Definition: btree.h:2227
typename Params::is_multi_container is_multi_container
Definition: btree.h:1047
SearchResult< int, true > binary_search_impl(const K &k, int s, int e, const CompareTo &comp, std::true_type) const
Definition: btree.h:1318
SearchResult< int, false > binary_search_impl(const K &k, int s, int e, const Compare &comp, std::false_type) const
Definition: btree.h:1301
typename Params::is_key_compare_to is_key_compare_to
Definition: btree.h:1046
static btree_node * init_internal(btree_node *n, btree_node *parent)
Definition: btree.h:1397
void set_parent(btree_node *p)
Definition: btree.h:1166
std::integral_constant< bool, std::is_arithmetic< key_type >::value &&(std::is_same< phmap::Less< key_type >, key_compare >::value||std::is_same< std::less< key_type >, key_compare >::value||std::is_same< std::greater< key_type >, key_compare >::value)> use_linear_search
Definition: btree.h:1074
typename Params::allocator_type allocator_type
Definition: btree.h:1049
typename Params::const_reference const_reference
Definition: btree.h:1059
Params params_type
Definition: btree.h:1053
void make_root()
Definition: btree.h:1203
static constexpr layout_type LeafLayout(const int max_values=kNodeValues)
Definition: btree.h:1131
void set_position(field_type v)
Definition: btree.h:1170
btree_node(btree_node const &)=delete
void rebalance_right_to_left(int to_move, btree_node *right, allocator_type *alloc)
Definition: btree.h:2183
typename Params::size_type size_type
Definition: btree.h:1061
typename Params::slot_type slot_type
Definition: btree.h:1050
SearchResult< int, false > linear_search_impl(const K &k, int s, const int e, const Compare &comp, std::false_type) const
Definition: btree.h:1268
void set_count(field_type v)
Definition: btree.h:1172
Definition: btree.h:3440
void insert(std::initializer_list< init_type > init)
Definition: btree.h:3525
size_type erase(const key_arg< K > &key)
Definition: btree.h:3552
iterator emplace_hint(const_iterator hint, Args &&... args)
Definition: btree.h:3512
std::pair< iterator, bool > insert(const value_type &x)
Definition: btree.h:3488
iterator insert(const_iterator hint, value_type &&x)
Definition: btree.h:3504
typename Tree::params_type params_type
Definition: btree.h:3442
typename Tree::size_type size_type
Definition: btree.h:3454
typename Tree::key_type key_type
Definition: btree.h:3452
void insert(InputIterator b, InputIterator e)
Definition: btree.h:3521
node_type extract(const key_arg< K > &key)
Definition: btree.h:3556
friend class BtreeNodePeer
Definition: btree.h:3445
std::pair< iterator, bool > emplace(Args &&... args)
Definition: btree.h:3495
insert_return_type insert(node_type &&node)
Definition: btree.h:3529
typename Tree::key_compare key_compare
Definition: btree.h:3455
typename Tree::iterator iterator
Definition: btree.h:3457
typename Tree::const_iterator const_iterator
Definition: btree.h:3458
btree_set_container()
Definition: btree.h:3462
typename params_type::is_key_compare_to is_key_compare_to
Definition: btree.h:3444
btree_set_container(InputIterator b, InputIterator e, const key_compare &comp=key_compare(), const allocator_type &alloc=allocator_type())
Definition: btree.h:3465
size_type count(const key_arg< K > &key) const
Definition: btree.h:3483
typename Tree::value_type value_type
Definition: btree.h:3453
typename params_type::init_type init_type
Definition: btree.h:3443
std::pair< iterator, bool > insert(value_type &&x)
Definition: btree.h:3491
void merge(btree_container< T > &src)
Definition: btree.h:3575
iterator insert(const_iterator hint, node_type &&node)
Definition: btree.h:3542
typename super_type::template key_arg< K > key_arg
Definition: btree.h:3449
typename super_type::node_type node_type
Definition: btree.h:3459
btree_set_container(std::initializer_list< init_type > init, const allocator_type &alloc)
Definition: btree.h:3477
typename Tree::allocator_type allocator_type
Definition: btree.h:3456
iterator insert(const_iterator hint, const value_type &x)
Definition: btree.h:3499
btree_set_container(std::initializer_list< init_type > init, const key_compare &comp=key_compare(), const allocator_type &alloc=allocator_type())
Definition: btree.h:3472
void merge(btree_container< T > &&src)
Definition: btree.h:3594
Definition: btree.h:1599
void merge_nodes(node_type *left, node_type *right)
Definition: btree.h:3008
size_type bytes_used() const
Definition: btree.h:1918
size_type internal_verify(const node_type *node, const key_type *lo, const key_type *hi) const
Definition: btree.h:3244
size_type erase_multi(const K &key)
btree_iterator< node_type, reference, pointer > iterator
Definition: btree.h:1671
static node_type * EmptyNode()
Definition: btree.h:1623
size_type count_unique(const K &key) const
Definition: btree.h:1849
std::pair< iterator, bool > insert_unique(const key_type &key, Args &&... args)
static constexpr bool static_assert_validation()
Definition: btree.h:2496
static bool testonly_uses_linear_node_search()
Definition: btree.h:2115
std::pair< iterator, iterator > equal_range(const K &key)
Definition: btree.h:1765
node_type * leftmost()
Definition: btree.h:1970
void delete_internal_node(node_type *node)
Definition: btree.h:2014
bool try_merge_or_rebalance(iterator *iter)
Definition: btree.h:3019
reverse_iterator rbegin()
Definition: btree.h:1728
static IterType internal_last(IterType iter)
Definition: btree.h:3093
bool compare_keys(const K &x, const LK &y) const
Definition: btree.h:1874
iterator internal_emplace(iterator iter, Args &&... args)
void try_shrink()
Definition: btree.h:3073
std::pair< iterator, bool > insert_hint_unique(iterator position, const key_type &key, Args &&... args)
allocator_type get_allocator() const
Definition: btree.h:1958
btree_node< Params > node_type
Definition: btree.h:1600
node_type *& mutable_root() noexcept
Definition: btree.h:1966
void swap(btree &x)
Definition: btree.h:2878
const key_compare & key_comp() const noexcept
Definition: btree.h:1870
const_iterator upper_bound(const K &key) const
Definition: btree.h:1757
const_reverse_iterator rend() const
Definition: btree.h:1737
double fullness() const
Definition: btree.h:1943
size_type size_
Definition: btree.h:2131
void clear()
Definition: btree.h:2868
const_reverse_iterator rbegin() const
Definition: btree.h:1731
bool empty() const
Definition: btree.h:1886
iterator erase_from_leaf_node(iterator begin, size_type to_erase)
Definition: btree.h:2827
iterator internal_end(iterator iter)
Definition: btree.h:2039
btree(btree &&x) noexcept
Definition: btree.h:1700
const allocator_type & allocator() const noexcept
Definition: btree.h:1977
typename Params::const_reference const_reference
Definition: btree.h:1668
SearchResult< iterator, true > internal_locate_impl(const K &key, std::true_type) const
const_iterator find(const K &key) const
Definition: btree.h:1843
iterator end()
Definition: btree.h:1724
typename Params::slot_type slot_type
Definition: btree.h:1679
std::pair< const_iterator, const_iterator > equal_range(const K &key) const
Definition: btree.h:1769
typename Params::reference reference
Definition: btree.h:1667
std::pair< size_type, iterator > erase(iterator begin, iterator end)
Definition: btree.h:2764
void insert_iterator_unique(InputIterator b, InputIterator e)
Definition: btree.h:2589
iterator internal_upper_bound(const K &key) const
iterator insert_multi(ValueType &&v)
Definition: btree.h:1801
iterator internal_lower_bound(const K &key) const
btree & operator=(btree &&x) noexcept
Definition: btree.h:2657
typename Params::is_key_compare_to is_key_compare_to
Definition: btree.h:1601
iterator insert_multi(const key_type &key, ValueType &&v)
iterator rebalance_after_delete(iterator iter)
Definition: btree.h:2724
node_type * new_leaf_root_node(const int max_count)
Definition: btree.h:1998
SearchResult< iterator, is_key_compare_to::value > internal_locate(const K &key) const
node_stats internal_stats(const node_type *node) const
Definition: btree.h:2098
typename iterator::const_iterator const_iterator
Definition: btree.h:1672
static double average_bytes_per_value()
Definition: btree.h:1931
value_compare value_comp() const
Definition: btree.h:1878
reverse_iterator rend()
Definition: btree.h:1734
const_iterator internal_end(const_iterator iter) const
Definition: btree.h:2042
Params params_type
Definition: btree.h:1678
node_type * new_leaf_node(node_type *parent)
Definition: btree.h:1994
double overhead() const
Definition: btree.h:1951
size_type size() const
Definition: btree.h:1884
iterator insert_hint_multi(iterator position, ValueType &&v)
typename Params::key_type key_type
Definition: btree.h:1660
size_type max_size() const
Definition: btree.h:1885
size_type height() const
Definition: btree.h:1889
void verify() const
Definition: btree.h:2895
node_type * allocate(const size_type sz)
Definition: btree.h:1983
node_type * root()
Definition: btree.h:1964
size_type count_multi(const K &key) const
Definition: btree.h:1859
void insert_iterator_multi(InputIterator b, InputIterator e)
Definition: btree.h:2634
node_type * rightmost_
Definition: btree.h:2128
typename Params::value_compare value_compare
Definition: btree.h:1665
@ kMinNodeValues
Definition: btree.h:1638
@ kNodeValues
Definition: btree.h:1637
std::reverse_iterator< iterator > reverse_iterator
Definition: btree.h:1673
iterator begin()
Definition: btree.h:1718
size_type nodes() const
Definition: btree.h:1912
typename Params::const_pointer const_pointer
Definition: btree.h:1670
~btree()
Definition: btree.h:1707
iterator erase(iterator iter)
Definition: btree.h:2688
iterator upper_bound(const K &key)
Definition: btree.h:1753
const node_type * root() const
Definition: btree.h:1965
const_iterator begin() const
Definition: btree.h:1721
key_compare * mutable_key_comp() noexcept
Definition: btree.h:1967
void rebalance_or_split(iterator *iter)
Definition: btree.h:2907
value_type && maybe_move_from_iterator(iterator x)
Definition: btree.h:1684
SearchResult< iterator, false > internal_locate_impl(const K &key, std::false_type) const
void internal_clear(node_type *node)
Definition: btree.h:3232
typename Params::pointer pointer
Definition: btree.h:1669
typename Params::allocator_type allocator_type
Definition: btree.h:1666
const node_type * leftmost() const
Definition: btree.h:1971
btree & operator=(const btree &x)
Definition: btree.h:2641
void delete_leaf_node(node_type *node)
Definition: btree.h:2018
typename Params::difference_type difference_type
Definition: btree.h:1663
allocator_type * mutable_allocator() noexcept
Definition: btree.h:1974
const_iterator end() const
Definition: btree.h:1725
typename Params::size_type size_type
Definition: btree.h:1662
iterator internal_find(const K &key) const
iterator find(const K &key)
Definition: btree.h:1839
iterator lower_bound(const K &key)
Definition: btree.h:1743
const_iterator lower_bound(const K &key) const
Definition: btree.h:1747
phmap::priv::CompressedTuple< key_compare, allocator_type, node_type * > root_
Definition: btree.h:2124
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: btree.h:1674
size_type internal_nodes() const
Definition: btree.h:1909
void deallocate(const size_type sz, node_type *node)
Definition: btree.h:2009
const value_type & maybe_move_from_iterator(const_iterator x)
Definition: btree.h:1683
btree(const btree &x)
Definition: btree.h:2531
btree(const key_compare &comp, const allocator_type &alloc)
Definition: btree.h:2527
typename Params::value_type value_type
Definition: btree.h:1661
typename Params::key_compare key_compare
Definition: btree.h:1664
void copy_or_move_values_in_order(Btree *x)
Definition: btree.h:2476
node_type * new_internal_node(node_type *parent)
Definition: btree.h:1990
size_type leaf_nodes() const
Definition: btree.h:1906
size_type erase_unique(const K &key)
void erase_same_node(iterator begin, iterator end)
Definition: btree.h:2799
Definition: phmap_base.h:2833
Definition: btree.h:353
friend constexpr bool operator!=(strong_equality v, compare_internal::OnlyLiteralZero<>) noexcept
Definition: btree.h:374
compare_internal::value_type value_
Definition: btree.h:388
friend constexpr bool operator==(strong_equality v, compare_internal::OnlyLiteralZero<>) noexcept
Definition: btree.h:370
friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>, strong_equality v) noexcept
Definition: btree.h:378
friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>, strong_equality v) noexcept
Definition: btree.h:382
Definition: btree.h:571
friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>, strong_ordering v) noexcept
Definition: btree.h:635
friend constexpr bool operator<(strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept
Definition: btree.h:611
friend constexpr bool operator==(strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept
Definition: btree.h:603
friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>, strong_ordering v) noexcept
Definition: btree.h:639
friend constexpr bool operator>(strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept
Definition: btree.h:619
friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>, strong_ordering v) noexcept
Definition: btree.h:627
constexpr strong_ordering(compare_internal::eq v) noexcept
Definition: btree.h:572
friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>, strong_ordering v) noexcept
Definition: btree.h:643
friend constexpr bool operator>=(strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept
Definition: btree.h:623
friend constexpr bool operator<=(strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept
Definition: btree.h:615
friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>, strong_ordering v) noexcept
Definition: btree.h:647
compare_internal::value_type value_
Definition: btree.h:653
friend constexpr bool operator!=(strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept
Definition: btree.h:607
friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>, strong_ordering v) noexcept
Definition: btree.h:631
typename std::remove_all_extents< T >::type ExtentsRemoved
Definition: btree.h:148
static constexpr bool kIsCopyOrMoveAssignable
Definition: btree.h:152
static constexpr bool kIsCopyOrMoveConstructible
Definition: btree.h:149
static constexpr bool kValue
Definition: btree.h:157
Definition: btree.h:317
friend constexpr bool operator!=(weak_equality v, compare_internal::OnlyLiteralZero<>) noexcept
Definition: btree.h:331
friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>, weak_equality v) noexcept
Definition: btree.h:335
compare_internal::value_type value_
Definition: btree.h:345
friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>, weak_equality v) noexcept
Definition: btree.h:339
Definition: btree.h:488
friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>, weak_ordering v) noexcept
Definition: btree.h:543
compare_internal::value_type value_
Definition: btree.h:561
friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>, weak_ordering v) noexcept
Definition: btree.h:555
constexpr weak_ordering(compare_internal::eq v) noexcept
Definition: btree.h:489
friend constexpr bool operator>(weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept
Definition: btree.h:527
friend constexpr bool operator!=(weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept
Definition: btree.h:515
friend constexpr bool operator<(weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept
Definition: btree.h:519
friend constexpr bool operator==(weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept
Definition: btree.h:511
friend constexpr bool operator<=(weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept
Definition: btree.h:523
friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>, weak_ordering v) noexcept
Definition: btree.h:535
friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>, weak_ordering v) noexcept
Definition: btree.h:539
friend constexpr bool operator>=(weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept
Definition: btree.h:531
friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>, weak_ordering v) noexcept
Definition: btree.h:547
friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>, weak_ordering v) noexcept
Definition: btree.h:551
static void ThrowStdOutOfRange(const std::string &what_arg)
Definition: phmap_base.h:694
constexpr phmap::weak_ordering compare_result_as_ordering(const Int c)
Definition: btree.h:690
constexpr bool do_less_than_comparison(const Compare &compare, const K &x, const LK &y)
Definition: btree.h:680
constexpr bool compare_result_as_less_than(const BoolType r)
Definition: btree.h:674
int8_t value_type
Definition: btree.h:220
constexpr phmap::weak_ordering do_three_way_comparison(const Compare &compare, const K &x, const LK &y)
Definition: btree.h:705
eq
Definition: btree.h:240
ord
Definition: btree.h:247
ncmp
Definition: btree.h:249
std::is_convertible< phmap::invoke_result_t< Compare, const T &, const T & >, phmap::weak_ordering > btree_is_key_compare_to
Definition: btree.h:734
MatchKind
Definition: btree.h:1019
void SanitizerPoisonObject(const T *object)
Definition: phmap_base.h:4407
void SanitizerUnpoisonObject(const T *object)
Definition: phmap_base.h:4412
void SanitizerPoisonMemoryRegion(const void *m, size_t s)
Definition: phmap_base.h:4384
void SanitizerUnpoisonMemoryRegion(const void *m, size_t s)
Definition: phmap_base.h:4395
void Swap(T &lhs, T &rhs) noexcept(IsNothrowSwappable< T >::value)
Definition: btree.h:200
typename std::enable_if< IsNoexcept::value >::type IsNothrowSwappableImpl
Definition: btree.h:189
decltype(swap(std::declval< T & >(), std::declval< T & >())) IsSwappableImpl
Definition: btree.h:183
Definition: btree.h:77
typename std::conditional< B, T, F >::type conditional_t
Definition: phmap_base.h:322
T exchange(T &obj, U &&new_value)
Definition: phmap_base.h:1127
void erase_if(btree_set< K, C, A > &set, Pred pred)
Definition: btree.h:3889
typename std::result_of< F(ArgTypes...)>::type invoke_result_t
Definition: phmap_base.h:335
typename std::enable_if< B, T >::type enable_if_t
Definition: phmap_base.h:319
typename type_traits_internal::VoidTImpl< Ts... >::type void_t
Definition: btree.h:134
STL namespace
#define false
Definition: stdbool.h:33
unsigned char bool
Definition: stdbool.h:25
Definition: phmap_base.h:85
Definition: phmap_base.h:1379
static void construct(Alloc &a, T *p, Args &&... args)
Definition: phmap_base.h:1491
static void destroy(Alloc &a, T *p)
Definition: phmap_base.h:1499
Definition: btree.h:223
constexpr OnlyLiteralZero(NullPtrT) noexcept
Definition: btree.h:229
Definition: phmap_base.h:200
Definition: phmap_base.h:163
Definition: btree.h:141
Definition: phmap_base.h:168
Definition: phmap_base.h:242
static auto GetSlot(const Node &node) -> decltype(node.slot())
Definition: phmap_base.h:2885
static void Destroy(Node *node)
Definition: phmap_base.h:2890
Definition: phmap_base.h:2918
Definition: phmap_base.h:2723
static constexpr bool HasMatch()
Definition: btree.h:1037
V value
Definition: btree.h:1035
static constexpr bool IsEq()
Definition: btree.h:1038
Definition: btree.h:1022
V value
Definition: btree.h:1023
bool IsEq() const
Definition: btree.h:1027
MatchKind match
Definition: btree.h:1024
static constexpr bool HasMatch()
Definition: btree.h:1026
phmap::weak_ordering operator()(std::string lhs, std::string rhs) const
Definition: btree.h:773
StringBtreeDefaultGreater(std::greater< std::string >)
Definition: btree.h:764
void is_transparent
Definition: btree.h:760
StringBtreeDefaultLess(std::less< std::string >)
Definition: btree.h:742
phmap::weak_ordering operator()(std::string lhs, std::string rhs) const
Definition: btree.h:752
void is_transparent
Definition: btree.h:737
Definition: btree.h:1605
node_type * parent
Definition: btree.h:1607
field_type position
Definition: btree.h:1608
constexpr EmptyNodeType(node_type *p)
Definition: btree.h:1619
field_type count
Definition: btree.h:1610
field_type start
Definition: btree.h:1609
field_type max_count
Definition: btree.h:1613
typename node_type::field_type field_type
Definition: btree.h:1606
Definition: btree.h:1641
size_type leaf_nodes
Definition: btree.h:1655
typename Params::size_type size_type
Definition: btree.h:1642
size_type internal_nodes
Definition: btree.h:1656
node_stats(size_type l, size_type i)
Definition: btree.h:1644
node_stats & operator+=(const node_stats &x)
Definition: btree.h:1649
Definition: btree.h:1458
Node * node
Definition: btree.h:1592
const key_type & key() const
Definition: btree.h:1588
btree_iterator & operator--()
Definition: btree.h:1557
btree_iterator(const btree_iterator< N, R, P > &x)
Definition: btree.h:1498
Node node_type
Definition: btree.h:1464
Reference reference
Definition: btree.h:1483
typename std::remove_const< Node >::type normal_node
Definition: btree.h:1465
bool operator!=(const iterator &x) const
Definition: btree.h:1541
Pointer pointer
Definition: btree.h:1482
void decrement()
Definition: btree.h:1523
bool operator!=(const const_iterator &x) const
Definition: btree.h:1535
typename Node::params_type params_type
Definition: btree.h:1462
typename params_type::pointer normal_pointer
Definition: btree.h:1467
bool operator==(const iterator &x) const
Definition: btree.h:1538
typename params_type::reference normal_reference
Definition: btree.h:1468
reference operator*() const
Definition: btree.h:1546
std::bidirectional_iterator_tag iterator_category
Definition: btree.h:1484
int position
Definition: btree.h:1595
btree_iterator operator++(int)
Definition: btree.h:1561
void increment()
Definition: btree.h:1515
typename params_type::const_pointer const_pointer
Definition: btree.h:1469
btree_iterator(Node *n, int p)
Definition: btree.h:1487
pointer operator->() const
Definition: btree.h:1549
btree_iterator< normal_node, normal_reference, normal_pointer > iterator
Definition: btree.h:1474
typename Node::key_type key_type
Definition: btree.h:1460
btree_iterator operator--(int)
Definition: btree.h:1566
void decrement_slow()
Definition: btree.h:2450
friend class base_checker
Definition: btree.h:1586
bool operator==(const const_iterator &x) const
Definition: btree.h:1532
btree_iterator< const_node, const_reference, const_pointer > const_iterator
Definition: btree.h:1476
typename params_type::value_type value_type
Definition: btree.h:1481
void increment_slow()
Definition: btree.h:2427
typename params_type::slot_type slot_type
Definition: btree.h:1471
slot_type * slot()
Definition: btree.h:1589
typename params_type::const_reference const_reference
Definition: btree.h:1470
btree_iterator()
Definition: btree.h:1486
btree_iterator & operator++()
Definition: btree.h:1553
typename Node::difference_type difference_type
Definition: btree.h:1480
typename Node::size_type size_type
Definition: btree.h:1461
const Node const_node
Definition: btree.h:1466
Definition: btree.h:830
const value_type * const_pointer
Definition: btree.h:851
SlotPolicy slot_policy
Definition: btree.h:846
static void move(Alloc *alloc, slot_type *first, slot_type *last, slot_type *result)
Definition: btree.h:900
const value_type & const_reference
Definition: btree.h:853
ptrdiff_t difference_type
Definition: btree.h:841
btree_is_key_compare_to< key_compare, Key > is_key_compare_to
Definition: btree.h:836
Key key_type
Definition: btree.h:839
static void move(Alloc *alloc, slot_type *src, slot_type *dest)
Definition: btree.h:897
static void construct(Alloc *alloc, slot_type *slot, Args &&... args)
Definition: btree.h:881
Alloc allocator_type
Definition: btree.h:838
typename slot_policy::value_type value_type
Definition: btree.h:848
std::integral_constant< bool, Multi > is_multi_container
Definition: btree.h:844
static value_type & element(slot_type *slot)
Definition: btree.h:874
static void transfer(Alloc *alloc, slot_type *new_slot, slot_type *old_slot)
Definition: btree.h:890
typename key_compare_to_adapter< Compare >::type key_compare
Definition: btree.h:833
value_type * pointer
Definition: btree.h:850
static void swap(Alloc *alloc, slot_type *a, slot_type *b)
Definition: btree.h:894
phmap::conditional_t<(kNodeSlotSpace/sizeof(slot_type) >(std::numeric_limits< uint8_t >::max)()), uint16_t, uint8_t > node_count_type
Definition: btree.h:870
typename slot_policy::slot_type slot_type
Definition: btree.h:847
static void destroy(Alloc *alloc, slot_type *slot)
Definition: btree.h:887
@ kNodeSlotSpace
Definition: btree.h:861
@ kTargetNodeSize
Definition: btree.h:856
typename slot_policy::mutable_value_type init_type
Definition: btree.h:849
static const value_type & element(const slot_type *slot)
Definition: btree.h:877
std::size_t size_type
Definition: btree.h:840
value_type & reference
Definition: btree.h:852
static void construct(Alloc *alloc, slot_type *slot, slot_type *other)
Definition: btree.h:884
Compare type
Definition: btree.h:793
value_compare(const key_compare &cmp)
Definition: btree.h:925
auto operator()(const T &left, const U &right) const -> decltype(std::declval< key_compare >()(left.first, right.first))
Definition: btree.h:928
Definition: btree.h:911
static const Key & key(const init_type &x)
Definition: btree.h:936
static const Key & key(const value_type &x)
Definition: btree.h:935
typename super_type::value_type value_type
Definition: btree.h:918
std::true_type is_map_container
Definition: btree.h:933
typename super_type::init_type init_type
Definition: btree.h:919
static mapped_type & value(value_type *value)
Definition: btree.h:938
typename super_type::slot_type slot_type
Definition: btree.h:917
Data mapped_type
Definition: btree.h:913
typename super_type::key_compare key_compare
Definition: btree.h:921
typename map_params::common_params super_type
Definition: btree.h:912
typename super_type::slot_policy slot_policy
Definition: btree.h:916
static const Key & key(const slot_type *x)
Definition: btree.h:937
Definition: btree.h:992
static const Key & key(const slot_type *x)
Definition: btree.h:999
Key value_type
Definition: btree.h:993
typename set_params::common_params::slot_type slot_type
Definition: btree.h:994
typename set_params::common_params::key_compare value_compare
Definition: btree.h:995
std::false_type is_map_container
Definition: btree.h:996
static const Key & key(const value_type &x)
Definition: btree.h:998
Definition: btree.h:944
static void swap(Alloc *, slot_type *a, slot_type *b)
Definition: btree.h:969
Key mutable_value_type
Definition: btree.h:947
static void move(Alloc *alloc, slot_type *first, slot_type *last, slot_type *result)
Definition: btree.h:980
static void move(Alloc *, slot_type *src, slot_type *dest)
Definition: btree.h:975
static const value_type & element(const slot_type *slot)
Definition: btree.h:950
static void construct(Alloc *alloc, slot_type *slot, Args &&... args)
Definition: btree.h:953
static void construct(Alloc *alloc, slot_type *slot, slot_type *other)
Definition: btree.h:959
Key value_type
Definition: btree.h:946
static void destroy(Alloc *alloc, slot_type *slot)
Definition: btree.h:964
Key slot_type
Definition: btree.h:945
static value_type & element(slot_type *slot)
Definition: btree.h:949
Definition: btree.h:1007
Compare comp
Definition: btree.h:1016
bool operator()(const K &a, const LK &b) const
Definition: btree.h:1010
upper_bound_adapter(const Compare &c)
Definition: btree.h:1008
Definition: btree.h:193
Definition: phmap_base.h:95
Definition: phmap_base.h:134