RavEngine
Loading...
Searching...
No Matches
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>
81 struct is_trivially_destructible;
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) &&
160 (kIsCopyOrMoveConstructible || 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
204 using StdSwapIsUnconstrained = IsSwappable<void()>;
205
206 } // namespace swap_internal
207
208 namespace type_traits_internal {
209
210 // Make the swap-related traits/function accessible from this namespace.
211 using swap_internal::IsNothrowSwappable;
212 using swap_internal::IsSwappable;
213 using swap_internal::Swap;
214 using swap_internal::StdSwapIsUnconstrained;
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,
242 equivalent = equal,
243 nonequal = 1,
244 nonequivalent = nonequal,
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>
279 PHMAP_COMPARE_INLINE_BASECLASS_DECL(equivalent)
280 PHMAP_COMPARE_INLINE_BASECLASS_DECL(nonequivalent)
281 };
282
283 template <typename T>
285 PHMAP_COMPARE_INLINE_BASECLASS_DECL(equal)
286 PHMAP_COMPARE_INLINE_BASECLASS_DECL(nonequal)
287 PHMAP_COMPARE_INLINE_BASECLASS_DECL(equivalent)
288 PHMAP_COMPARE_INLINE_BASECLASS_DECL(nonequivalent)
289 };
290
291 template <typename T>
293 PHMAP_COMPARE_INLINE_BASECLASS_DECL(less)
294 PHMAP_COMPARE_INLINE_BASECLASS_DECL(equivalent)
295 PHMAP_COMPARE_INLINE_BASECLASS_DECL(greater)
296 PHMAP_COMPARE_INLINE_BASECLASS_DECL(unordered)
297 };
298
299 template <typename T>
301 PHMAP_COMPARE_INLINE_BASECLASS_DECL(less)
302 PHMAP_COMPARE_INLINE_BASECLASS_DECL(equivalent)
303 PHMAP_COMPARE_INLINE_BASECLASS_DECL(greater)
304 };
305
306 template <typename T>
308 PHMAP_COMPARE_INLINE_BASECLASS_DECL(less)
309 PHMAP_COMPARE_INLINE_BASECLASS_DECL(equal)
310 PHMAP_COMPARE_INLINE_BASECLASS_DECL(equivalent)
311 PHMAP_COMPARE_INLINE_BASECLASS_DECL(greater)
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:
323 PHMAP_COMPARE_INLINE_SUBCLASS_DECL(weak_equality, equivalent)
324 PHMAP_COMPARE_INLINE_SUBCLASS_DECL(weak_equality, nonequivalent)
325
326 // Comparisons
327 friend constexpr bool operator==(
329 return v.value_ == 0;
330 }
331 friend constexpr bool operator!=(
333 return v.value_ != 0;
334 }
335 friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>,
336 weak_equality v) noexcept {
337 return 0 == v.value_;
338 }
339 friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>,
340 weak_equality v) noexcept {
341 return 0 != v.value_;
342 }
343
344 private:
345 compare_internal::value_type value_;
346 };
347 PHMAP_COMPARE_INLINE_INIT(weak_equality, equivalent,
348 compare_internal::eq::equivalent);
349 PHMAP_COMPARE_INLINE_INIT(weak_equality, nonequivalent,
350 compare_internal::eq::nonequivalent);
351
354 explicit constexpr strong_equality(compare_internal::eq v) noexcept
355 : value_(static_cast<compare_internal::value_type>(v)) {}
357
358 public:
359 PHMAP_COMPARE_INLINE_SUBCLASS_DECL(strong_equality, equal)
360 PHMAP_COMPARE_INLINE_SUBCLASS_DECL(strong_equality, nonequal)
361 PHMAP_COMPARE_INLINE_SUBCLASS_DECL(strong_equality, equivalent)
362 PHMAP_COMPARE_INLINE_SUBCLASS_DECL(strong_equality, nonequivalent)
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 }
378 friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>,
379 strong_equality v) noexcept {
380 return 0 == v.value_;
381 }
382 friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>,
383 strong_equality v) noexcept {
384 return 0 != v.value_;
385 }
386
387 private:
388 compare_internal::value_type value_;
389 };
390
391 PHMAP_COMPARE_INLINE_INIT(strong_equality, equal, compare_internal::eq::equal);
392 PHMAP_COMPARE_INLINE_INIT(strong_equality, nonequal,
393 compare_internal::eq::nonequal);
394 PHMAP_COMPARE_INLINE_INIT(strong_equality, equivalent,
395 compare_internal::eq::equivalent);
396 PHMAP_COMPARE_INLINE_INIT(strong_equality, nonequivalent,
397 compare_internal::eq::nonequivalent);
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_ !=
411 compare_internal::value_type(compare_internal::ncmp::unordered);
412 }
413
414 public:
415 PHMAP_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, less)
416 PHMAP_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, equivalent)
417 PHMAP_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, greater)
418 PHMAP_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, unordered)
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 }
450 friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>,
451 partial_ordering v) noexcept {
452 return v.is_ordered() && 0 == v.value_;
453 }
454 friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>,
455 partial_ordering v) noexcept {
456 return !v.is_ordered() || 0 != v.value_;
457 }
458 friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>,
459 partial_ordering v) noexcept {
460 return v.is_ordered() && 0 < v.value_;
461 }
462 friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>,
463 partial_ordering v) noexcept {
464 return v.is_ordered() && 0 <= v.value_;
465 }
466 friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>,
467 partial_ordering v) noexcept {
468 return v.is_ordered() && 0 > v.value_;
469 }
470 friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>,
471 partial_ordering v) noexcept {
472 return v.is_ordered() && 0 >= v.value_;
473 }
474
475 private:
476 compare_internal::value_type value_;
477 };
478
479 PHMAP_COMPARE_INLINE_INIT(partial_ordering, less, compare_internal::ord::less);
480 PHMAP_COMPARE_INLINE_INIT(partial_ordering, equivalent,
481 compare_internal::eq::equivalent);
482 PHMAP_COMPARE_INLINE_INIT(partial_ordering, greater,
483 compare_internal::ord::greater);
484 PHMAP_COMPARE_INLINE_INIT(partial_ordering, unordered,
485 compare_internal::ncmp::unordered);
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:
496 PHMAP_COMPARE_INLINE_SUBCLASS_DECL(weak_ordering, less)
497 PHMAP_COMPARE_INLINE_SUBCLASS_DECL(weak_ordering, equivalent)
498 PHMAP_COMPARE_INLINE_SUBCLASS_DECL(weak_ordering, greater)
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 }
535 friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>,
536 weak_ordering v) noexcept {
537 return 0 == v.value_;
538 }
539 friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>,
540 weak_ordering v) noexcept {
541 return 0 != v.value_;
542 }
543 friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>,
544 weak_ordering v) noexcept {
545 return 0 < v.value_;
546 }
547 friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>,
548 weak_ordering v) noexcept {
549 return 0 <= v.value_;
550 }
551 friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>,
552 weak_ordering v) noexcept {
553 return 0 > v.value_;
554 }
555 friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>,
556 weak_ordering v) noexcept {
557 return 0 >= v.value_;
558 }
559
560 private:
561 compare_internal::value_type value_;
562 };
563
564 PHMAP_COMPARE_INLINE_INIT(weak_ordering, less, compare_internal::ord::less);
565 PHMAP_COMPARE_INLINE_INIT(weak_ordering, equivalent,
566 compare_internal::eq::equivalent);
567 PHMAP_COMPARE_INLINE_INIT(weak_ordering, greater,
568 compare_internal::ord::greater);
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:
579 PHMAP_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, less)
580 PHMAP_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, equal)
581 PHMAP_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, equivalent)
582 PHMAP_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, greater)
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 }
627 friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>,
628 strong_ordering v) noexcept {
629 return 0 == v.value_;
630 }
631 friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>,
632 strong_ordering v) noexcept {
633 return 0 != v.value_;
634 }
635 friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>,
636 strong_ordering v) noexcept {
637 return 0 < v.value_;
638 }
639 friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>,
640 strong_ordering v) noexcept {
641 return 0 <= v.value_;
642 }
643 friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>,
644 strong_ordering v) noexcept {
645 return 0 > v.value_;
646 }
647 friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>,
648 strong_ordering v) noexcept {
649 return 0 >= v.value_;
650 }
651
652 private:
653 compare_internal::value_type value_;
654 };
655 PHMAP_COMPARE_INLINE_INIT(strong_ordering, less, compare_internal::ord::less);
656 PHMAP_COMPARE_INLINE_INIT(strong_ordering, equal, compare_internal::eq::equal);
657 PHMAP_COMPARE_INLINE_INIT(strong_ordering, equivalent,
658 compare_internal::eq::equivalent);
659 PHMAP_COMPARE_INLINE_INIT(strong_ordering, greater,
660 compare_internal::ord::greater);
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,
673 phmap::enable_if_t<std::is_same<bool, BoolType>::value, int> = 0>
674 constexpr bool compare_result_as_less_than(const BoolType r) { return r; }
675 constexpr bool compare_result_as_less_than(const phmap::weak_ordering 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,
689 phmap::enable_if_t<std::is_same<int, Int>::value, int> = 0>
690 constexpr phmap::weak_ordering compare_result_as_ordering(const Int c) {
691 return c < 0 ? phmap::weak_ordering::less
692 : c == 0 ? phmap::weak_ordering::equivalent
693 : phmap::weak_ordering::greater;
694 }
695 constexpr phmap::weak_ordering compare_result_as_ordering(
696 const phmap::weak_ordering c) {
697 return c;
698 }
699
700 template <
701 typename Compare, typename K, typename LK,
702 phmap::enable_if_t<!std::is_same<bool, phmap::invoke_result_t<
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>
732 using btree_is_key_compare_to =
733 std::is_convertible<phmap::invoke_result_t<Compare, const T &, const T &>,
735
736 struct StringBtreeDefaultLess {
737 using is_transparent = void;
738
739 StringBtreeDefaultLess() = default;
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
745 StringBtreeDefaultLess(phmap::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
752 phmap::weak_ordering operator()(std::string lhs,
753 std::string rhs) const {
754 return compare_internal::compare_result_as_ordering(lhs.compare(rhs));
755 }
756#endif
757 };
758
759 struct StringBtreeDefaultGreater {
760 using is_transparent = void;
761
762 StringBtreeDefaultGreater() = default;
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
773 phmap::weak_ordering operator()(std::string lhs,
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>
792 struct key_compare_to_adapter {
793 using type = Compare;
794 };
795
796 template <>
797 struct key_compare_to_adapter<std::less<std::string>> {
798 using type = StringBtreeDefaultLess;
799 };
800
801 template <>
802 struct key_compare_to_adapter<phmap::Less<std::string>> {
803 using type = StringBtreeDefaultLess;
804 };
805
806 template <>
807 struct key_compare_to_adapter<std::greater<std::string>> {
808 using type = StringBtreeDefaultGreater;
809 };
810
811#if PHMAP_HAVE_STD_STRING_VIEW
812 template <>
813 struct key_compare_to_adapter<std::less<std::string_view>> {
814 using type = StringBtreeDefaultLess;
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>
830 struct common_params {
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.
833 using key_compare = typename key_compare_to_adapter<Compare>::type;
834 // A type which indicates if we have a key-compare-to functor or a plain old
835 // key-compare functor.
836 using is_key_compare_to = btree_is_key_compare_to<key_compare, Key>;
837
838 using allocator_type = Alloc;
839 using key_type = Key;
840 using size_type = std::make_signed<size_t>::type;
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;
850 using pointer = value_type *;
851 using const_pointer = const value_type *;
852 using reference = value_type &;
853 using const_reference = 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).
861 kNodeValueSpace =
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.
867 using node_count_type =
868 phmap::conditional_t<(kNodeValueSpace / sizeof(value_type) >
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>
944 struct set_slot_policy {
945 using slot_type = Key;
946 using value_type = Key;
947 using mutable_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>
1007 struct upper_bound_adapter {
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.
1012 return !phmap::compare_internal::compare_result_as_less_than(comp(b, a));
1013 }
1014
1015 private:
1016 Compare comp;
1017 };
1018
1019 enum class MatchKind : uint8_t { kEq, kNe };
1020
1021 template <typename V, bool IsCompareTo>
1022 struct SearchResult {
1023 V value;
1024 MatchKind match;
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> {
1035 V value;
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>
1045 class btree_node {
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:
1092 using layout_type = phmap::priv::Layout<btree_node *, field_type,
1093 slot_type, btree_node *>;
1094 constexpr static size_type SizeWithNValues(size_type n) {
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]; }
1188 field_type max_count() const {
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 // Getters/setter for the child at position i in the node.
1214 btree_node *child(size_type i) const { return GetField<3>()[i]; }
1215 btree_node *&mutable_child(size_type i) { return GetField<3>()[i]; }
1216 void clear_child(size_type i) {
1217 phmap::priv::SanitizerPoisonObject(&mutable_child(i));
1218 }
1219 void set_child(size_type i, btree_node *c) {
1220 phmap::priv::SanitizerUnpoisonObject(&mutable_child(i));
1221 mutable_child(i) = c;
1222 c->set_position((field_type)i);
1223 }
1224 void init_child(int i, btree_node *c) {
1225 set_child(i, c);
1226 c->set_parent(this);
1227 }
1228
1229 // Returns the position of the first value whose key is not less than k.
1230 template <typename K>
1231 SearchResult<int, is_key_compare_to::value> lower_bound(
1232 const K &k, const key_compare &comp) const {
1233 return use_linear_search::value ? linear_search(k, comp)
1234 : binary_search(k, comp);
1235 }
1236 // Returns the position of the first value whose key is greater than k.
1237 template <typename K>
1238 int upper_bound(const K &k, const key_compare &comp) const {
1239 auto upper_compare = upper_bound_adapter<key_compare>(comp);
1240 return use_linear_search::value ? linear_search(k, upper_compare).value
1241 : binary_search(k, upper_compare).value;
1242 }
1243
1244 template <typename K, typename Compare>
1245 SearchResult<int, btree_is_key_compare_to<Compare, key_type>::value>
1246 linear_search(const K &k, const Compare &comp) const {
1247 return linear_search_impl(k, 0, count(), comp,
1248 btree_is_key_compare_to<Compare, key_type>());
1249 }
1250
1251 template <typename K, typename Compare>
1252 SearchResult<int, btree_is_key_compare_to<Compare, key_type>::value>
1253 binary_search(const K &k, const Compare &comp) const {
1254 return binary_search_impl(k, 0, count(), comp,
1255 btree_is_key_compare_to<Compare, key_type>());
1256 }
1257
1258 // Returns the position of the first value whose key is not less than k using
1259 // linear search performed using plain compare.
1260 template <typename K, typename Compare>
1261 SearchResult<int, false> linear_search_impl(
1262 const K &k, int s, const int e, const Compare &comp,
1263 std::false_type /* IsCompareTo */) const {
1264 while (s < e) {
1265 if (!comp(key(s), k)) {
1266 break;
1267 }
1268 ++s;
1269 }
1270 return {s};
1271 }
1272
1273 // Returns the position of the first value whose key is not less than k using
1274 // linear search performed using compare-to.
1275 template <typename K, typename Compare>
1276 SearchResult<int, true> linear_search_impl(
1277 const K &k, int s, const int e, const Compare &comp,
1278 std::true_type /* IsCompareTo */) const {
1279 while (s < e) {
1280 const phmap::weak_ordering c = comp(key(s), k);
1281 if (c == 0) {
1282 return {s, MatchKind::kEq};
1283 } else if (c > 0) {
1284 break;
1285 }
1286 ++s;
1287 }
1288 return {s, MatchKind::kNe};
1289 }
1290
1291 // Returns the position of the first value whose key is not less than k using
1292 // binary search performed using plain compare.
1293 template <typename K, typename Compare>
1294 SearchResult<int, false> binary_search_impl(
1295 const K &k, int s, int e, const Compare &comp,
1296 std::false_type /* IsCompareTo */) const {
1297 while (s != e) {
1298 const int mid = (s + e) >> 1;
1299 if (comp(key(mid), k)) {
1300 s = mid + 1;
1301 } else {
1302 e = mid;
1303 }
1304 }
1305 return {s};
1306 }
1307
1308 // Returns the position of the first value whose key is not less than k using
1309 // binary search performed using compare-to.
1310 template <typename K, typename CompareTo>
1311 SearchResult<int, true> binary_search_impl(
1312 const K &k, int s, int e, const CompareTo &comp,
1313 std::true_type /* IsCompareTo */) const {
1314 if (is_multi_container::value) {
1315 MatchKind exact_match = MatchKind::kNe;
1316 while (s != e) {
1317 const int mid = (s + e) >> 1;
1318 const phmap::weak_ordering c = comp(key(mid), k);
1319 if (c < 0) {
1320 s = mid + 1;
1321 } else {
1322 e = mid;
1323 if (c == 0) {
1324 // Need to return the first value whose key is not less than k,
1325 // which requires continuing the binary search if this is a
1326 // multi-container.
1327 exact_match = MatchKind::kEq;
1328 }
1329 }
1330 }
1331 return {s, exact_match};
1332 } else { // Not a multi-container.
1333 while (s != e) {
1334 const int mid = (s + e) >> 1;
1335 const phmap::weak_ordering c = comp(key(mid), k);
1336 if (c < 0) {
1337 s = mid + 1;
1338 } else if (c > 0) {
1339 e = mid;
1340 } else {
1341 return {mid, MatchKind::kEq};
1342 }
1343 }
1344 return {s, MatchKind::kNe};
1345 }
1346 }
1347
1348 // Emplaces a value at position i, shifting all existing values and
1349 // children at positions >= i to the right by 1.
1350 template <typename... Args>
1351 void emplace_value(size_type i, allocator_type *alloc, Args &&... args);
1352
1353 // Removes the value at position i, shifting all existing values and children
1354 // at positions > i to the left by 1.
1355 void remove_value(int i, allocator_type *alloc);
1356
1357 // Removes the values at positions [i, i + to_erase), shifting all values
1358 // after that range to the left by to_erase. Does not change children at all.
1359 void remove_values_ignore_children(int i, size_type to_erase,
1360 allocator_type *alloc);
1361
1362 // Rebalances a node with its right sibling.
1363 void rebalance_right_to_left(int to_move, btree_node *right,
1364 allocator_type *alloc);
1365 void rebalance_left_to_right(int to_move, btree_node *right,
1366 allocator_type *alloc);
1367
1368 // Splits a node, moving a portion of the node's values to its right sibling.
1369 void split(int insert_position, btree_node *dest, allocator_type *alloc);
1370
1371 // Merges a node with its right sibling, moving all of the values and the
1372 // delimiting key in the parent node onto itself.
1373 void merge(btree_node *sibling, allocator_type *alloc);
1374
1375 // Swap the contents of "this" and "src".
1376 void swap(btree_node *src, allocator_type *alloc);
1377
1378 // Node allocation/deletion routines.
1379 static btree_node *init_leaf(btree_node *n, btree_node *parent,
1380 int max_cnt) {
1381 n->set_parent(parent);
1382 n->set_position(0);
1383 n->set_start(0);
1384 n->set_count(0);
1385 n->set_max_count((field_type)max_cnt);
1386 phmap::priv::SanitizerPoisonMemoryRegion(
1387 n->slot(0), max_cnt * sizeof(slot_type));
1388 return n;
1389 }
1390 static btree_node *init_internal(btree_node *n, btree_node *parent) {
1391 init_leaf(n, parent, kNodeValues);
1392 // Set `max_count` to a sentinel value to indicate that this node is
1393 // internal.
1394 n->set_max_count(kInternalNodeMaxCount);
1395 phmap::priv::SanitizerPoisonMemoryRegion(
1396 &n->mutable_child(0), (kNodeValues + 1) * sizeof(btree_node *));
1397 return n;
1398 }
1399 void destroy(allocator_type *alloc) {
1400 for (int i = 0; i < count(); ++i) {
1401 value_destroy(i, alloc);
1402 }
1403 }
1404
1405 public:
1406 // Exposed only for tests.
1407 static bool testonly_uses_linear_node_search() {
1408 return use_linear_search::value;
1409 }
1410
1411 private:
1412 template <typename... Args>
1413 void value_init(const size_type i, allocator_type *alloc, Args &&... args) {
1414 phmap::priv::SanitizerUnpoisonObject(slot(i));
1415 params_type::construct(alloc, slot(i), std::forward<Args>(args)...);
1416 }
1417 void value_destroy(const size_type i, allocator_type *alloc) {
1418 params_type::destroy(alloc, slot(i));
1419 phmap::priv::SanitizerPoisonObject(slot(i));
1420 }
1421
1422 // Move n values starting at value i in this node into the values starting at
1423 // value j in node x.
1424 void uninitialized_move_n(const size_type n, const size_type i,
1425 const size_type j, btree_node *x,
1426 allocator_type *alloc) {
1427 phmap::priv::SanitizerUnpoisonMemoryRegion(
1428 x->slot(j), n * sizeof(slot_type));
1429 for (slot_type *src = slot(i), *end = src + n, *dest = x->slot(j);
1430 src != end; ++src, ++dest) {
1431 params_type::construct(alloc, dest, src);
1432 }
1433 }
1434
1435 // Destroys a range of n values, starting at index i.
1436 void value_destroy_n(const size_type i, const size_type n,
1437 allocator_type *alloc) {
1438 for (int j = 0; j < n; ++j) {
1439 value_destroy(i + j, alloc);
1440 }
1441 }
1442
1443 template <typename P>
1444 friend class btree;
1445 template <typename N, typename R, typename P>
1446 friend struct btree_iterator;
1447 friend class BtreeNodePeer;
1448 };
1449
1450 template <typename Node, typename Reference, typename Pointer>
1451 struct btree_iterator {
1452 private:
1453 using key_type = typename Node::key_type;
1454 using size_type = typename Node::size_type;
1455 using params_type = typename Node::params_type;
1456
1457 using node_type = Node;
1458 using normal_node = typename std::remove_const<Node>::type;
1459 using const_node = const Node;
1460 using normal_pointer = typename params_type::pointer;
1461 using normal_reference = typename params_type::reference;
1462 using const_pointer = typename params_type::const_pointer;
1463 using const_reference = typename params_type::const_reference;
1464 using slot_type = typename params_type::slot_type;
1465
1466 using iterator =
1467 btree_iterator<normal_node, normal_reference, normal_pointer>;
1468 using const_iterator =
1469 btree_iterator<const_node, const_reference, const_pointer>;
1470
1471 public:
1472 // These aliases are public for std::iterator_traits.
1473 using difference_type = typename Node::difference_type;
1474 using value_type = typename params_type::value_type;
1475 using pointer = Pointer;
1476 using reference = Reference;
1477 using iterator_category = std::bidirectional_iterator_tag;
1478
1479 btree_iterator() : node(nullptr), position(-1) {}
1480 btree_iterator(Node *n, int p) : node(n), position(p) {}
1481
1482 // NOTE: this SFINAE allows for implicit conversions from iterator to
1483 // const_iterator, but it specifically avoids defining copy constructors so
1484 // that btree_iterator can be trivially copyable. This is for performance and
1485 // binary size reasons.
1486 template <typename N, typename R, typename P,
1487 phmap::enable_if_t<
1488 std::is_same<btree_iterator<N, R, P>, iterator>::value &&
1489 std::is_same<btree_iterator, const_iterator>::value,
1490 int> = 0>
1491 btree_iterator(const btree_iterator<N, R, P> &x) // NOLINT
1492 : node(x.node), position(x.position) {}
1493
1494 private:
1495 // This SFINAE allows explicit conversions from const_iterator to
1496 // iterator, but also avoids defining a copy constructor.
1497 // NOTE: the const_cast is safe because this constructor is only called by
1498 // non-const methods and the container owns the nodes.
1499 template <typename N, typename R, typename P,
1500 phmap::enable_if_t<
1501 std::is_same<btree_iterator<N, R, P>, const_iterator>::value &&
1502 std::is_same<btree_iterator, iterator>::value,
1503 int> = 0>
1504 explicit btree_iterator(const btree_iterator<N, R, P> &x)
1505 : node(const_cast<node_type *>(x.node)), position(x.position) {}
1506
1507 // Increment/decrement the iterator.
1508 void increment() {
1509 if (node->leaf() && ++position < node->count()) {
1510 return;
1511 }
1512 increment_slow();
1513 }
1514 void increment_slow();
1515
1516 void decrement() {
1517 if (node->leaf() && --position >= 0) {
1518 return;
1519 }
1520 decrement_slow();
1521 }
1522 void decrement_slow();
1523
1524 public:
1525 bool operator==(const const_iterator &x) const {
1526 return node == x.node && position == x.position;
1527 }
1528 bool operator!=(const const_iterator &x) const {
1529 return node != x.node || position != x.position;
1530 }
1531
1532 // Accessors for the key/value the iterator is pointing at.
1533 reference operator*() const {
1534 return node->value(position);
1535 }
1536 pointer operator->() const {
1537 return &node->value(position);
1538 }
1539
1540 btree_iterator& operator++() {
1541 increment();
1542 return *this;
1543 }
1544 btree_iterator& operator--() {
1545 decrement();
1546 return *this;
1547 }
1548 btree_iterator operator++(int) {
1549 btree_iterator tmp = *this;
1550 ++*this;
1551 return tmp;
1552 }
1553 btree_iterator operator--(int) {
1554 btree_iterator tmp = *this;
1555 --*this;
1556 return tmp;
1557 }
1558
1559 private:
1560 template <typename Params>
1561 friend class btree;
1562 template <typename Tree>
1563 friend class btree_container;
1564 template <typename Tree>
1565 friend class btree_set_container;
1566 template <typename Tree>
1567 friend class btree_map_container;
1568 template <typename Tree>
1569 friend class btree_multiset_container;
1570 template <typename N, typename R, typename P>
1571 friend struct btree_iterator;
1572 template <typename TreeType, typename CheckerType>
1573 friend class base_checker;
1574
1575 const key_type &key() const { return node->key(position); }
1576 slot_type *slot() { return node->slot(position); }
1577
1578 // The node in the tree the iterator is pointing at.
1579 Node *node;
1580 // The position within the node of the tree the iterator is pointing at.
1581 // TODO(ezb): make this a field_type
1582 int position;
1583 };
1584
1585 template <typename Params>
1586 class btree {
1587 using node_type = btree_node<Params>;
1588 using is_key_compare_to = typename Params::is_key_compare_to;
1589
1590 // We use a static empty node for the root/leftmost/rightmost of empty btrees
1591 // in order to avoid branching in begin()/end().
1592 struct alignas(node_type::Alignment()) EmptyNodeType : node_type {
1593 using field_type = typename node_type::field_type;
1594 node_type *parent;
1595 field_type position = 0;
1596 field_type start = 0;
1597 field_type count = 0;
1598 // max_count must be != kInternalNodeMaxCount (so that this node is regarded
1599 // as a leaf node). max_count() is never called when the tree is empty.
1600 field_type max_count = node_type::kInternalNodeMaxCount + 1;
1601
1602#ifdef _MSC_VER
1603 // MSVC has constexpr code generations bugs here.
1604 EmptyNodeType() : parent(this) {}
1605#else
1606 constexpr EmptyNodeType(node_type *p) : parent(p) {}
1607#endif
1608 };
1609
1610 static node_type *EmptyNode() {
1611#ifdef _MSC_VER
1612 static EmptyNodeType* empty_node = new EmptyNodeType;
1613 // This assert fails on some other construction methods.
1614 assert(empty_node->parent == empty_node);
1615 return empty_node;
1616#else
1617 static constexpr EmptyNodeType empty_node(
1618 const_cast<EmptyNodeType *>(&empty_node));
1619 return const_cast<EmptyNodeType *>(&empty_node);
1620#endif
1621 }
1622
1623 enum {
1624 kNodeValues = node_type::kNodeValues,
1625 kMinNodeValues = kNodeValues / 2,
1626 };
1627
1628 struct node_stats {
1629 using size_type = typename Params::size_type;
1630
1631 node_stats(size_type l, size_type i)
1632 : leaf_nodes(l),
1633 internal_nodes(i) {
1634 }
1635
1636 node_stats& operator+=(const node_stats &x) {
1637 leaf_nodes += x.leaf_nodes;
1638 internal_nodes += x.internal_nodes;
1639 return *this;
1640 }
1641
1642 size_type leaf_nodes;
1643 size_type internal_nodes;
1644 };
1645
1646 public:
1647 using key_type = typename Params::key_type;
1648 using value_type = typename Params::value_type;
1649 using size_type = typename Params::size_type;
1650 using difference_type = typename Params::difference_type;
1651 using key_compare = typename Params::key_compare;
1652 using value_compare = typename Params::value_compare;
1653 using allocator_type = typename Params::allocator_type;
1654 using reference = typename Params::reference;
1655 using const_reference = typename Params::const_reference;
1656 using pointer = typename Params::pointer;
1657 using const_pointer = typename Params::const_pointer;
1658 using iterator = btree_iterator<node_type, reference, pointer>;
1659 using const_iterator = typename iterator::const_iterator;
1660 using reverse_iterator = std::reverse_iterator<iterator>;
1661 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
1662 using node_handle_type = node_handle<Params, Params, allocator_type>;
1663
1664 // Internal types made public for use by btree_container types.
1665 using params_type = Params;
1666 using slot_type = typename Params::slot_type;
1667
1668 private:
1669 // For use in copy_or_move_values_in_order.
1670 const value_type &maybe_move_from_iterator(const_iterator x) { return *x; }
1671 value_type &&maybe_move_from_iterator(iterator x) { return std::move(*x); }
1672
1673 // Copies or moves (depending on the template parameter) the values in
1674 // x into this btree in their order in x. This btree must be empty before this
1675 // method is called. This method is used in copy construction, copy
1676 // assignment, and move assignment.
1677 template <typename Btree>
1678 void copy_or_move_values_in_order(Btree *x);
1679
1680 // Validates that various assumptions/requirements are true at compile time.
1681 constexpr static bool static_assert_validation();
1682
1683 public:
1684 btree(const key_compare &comp, const allocator_type &alloc);
1685
1686 btree(const btree &x);
1687 btree(btree &&x) noexcept
1688 : root_(std::move(x.root_)),
1689 rightmost_(phmap::exchange(x.rightmost_, EmptyNode())),
1690 size_(phmap::exchange(x.size_, 0)) {
1691 x.mutable_root() = EmptyNode();
1692 }
1693
1694 ~btree() {
1695 // Put static_asserts in destructor to avoid triggering them before the type
1696 // is complete.
1697 static_assert(static_assert_validation(), "This call must be elided.");
1698 clear();
1699 }
1700
1701 // Assign the contents of x to *this.
1702 btree &operator=(const btree &x);
1703 btree &operator=(btree &&x) noexcept;
1704
1705 iterator begin() {
1706 return iterator(leftmost(), 0);
1707 }
1708 const_iterator begin() const {
1709 return const_iterator(leftmost(), 0);
1710 }
1711 iterator end() { return iterator(rightmost_, rightmost_->count()); }
1712 const_iterator end() const {
1713 return const_iterator(rightmost_, rightmost_->count());
1714 }
1715 reverse_iterator rbegin() {
1716 return reverse_iterator(end());
1717 }
1718 const_reverse_iterator rbegin() const {
1719 return const_reverse_iterator(end());
1720 }
1721 reverse_iterator rend() {
1722 return reverse_iterator(begin());
1723 }
1724 const_reverse_iterator rend() const {
1725 return const_reverse_iterator(begin());
1726 }
1727
1728 // Finds the first element whose key is not less than key.
1729 template <typename K>
1730 iterator lower_bound(const K &key) {
1731 return internal_end(internal_lower_bound(key));
1732 }
1733 template <typename K>
1734 const_iterator lower_bound(const K &key) const {
1735 return internal_end(internal_lower_bound(key));
1736 }
1737
1738 // Finds the first element whose key is greater than key.
1739 template <typename K>
1740 iterator upper_bound(const K &key) {
1741 return internal_end(internal_upper_bound(key));
1742 }
1743 template <typename K>
1744 const_iterator upper_bound(const K &key) const {
1745 return internal_end(internal_upper_bound(key));
1746 }
1747
1748 // Finds the range of values which compare equal to key. The first member of
1749 // the returned pair is equal to lower_bound(key). The second member pair of
1750 // the pair is equal to upper_bound(key).
1751 template <typename K>
1752 std::pair<iterator, iterator> equal_range(const K &key) {
1753 return {lower_bound(key), upper_bound(key)};
1754 }
1755 template <typename K>
1756 std::pair<const_iterator, const_iterator> equal_range(const K &key) const {
1757 return {lower_bound(key), upper_bound(key)};
1758 }
1759
1760 // Inserts a value into the btree only if it does not already exist. The
1761 // boolean return value indicates whether insertion succeeded or failed.
1762 // Requirement: if `key` already exists in the btree, does not consume `args`.
1763 // Requirement: `key` is never referenced after consuming `args`.
1764 template <typename... Args>
1765 std::pair<iterator, bool> insert_unique(const key_type &key, Args &&... args);
1766
1767 // Inserts with hint. Checks to see if the value should be placed immediately
1768 // before `position` in the tree. If so, then the insertion will take
1769 // amortized constant time. If not, the insertion will take amortized
1770 // logarithmic time as if a call to insert_unique() were made.
1771 // Requirement: if `key` already exists in the btree, does not consume `args`.
1772 // Requirement: `key` is never referenced after consuming `args`.
1773 template <typename... Args>
1774 std::pair<iterator, bool> insert_hint_unique(iterator position,
1775 const key_type &key,
1776 Args &&... args);
1777
1778 // Insert a range of values into the btree.
1779 template <typename InputIterator>
1780 void insert_iterator_unique(InputIterator b, InputIterator e);
1781
1782 // Inserts a value into the btree.
1783 template <typename ValueType>
1784 iterator insert_multi(const key_type &key, ValueType &&v);
1785
1786 // Inserts a value into the btree.
1787 template <typename ValueType>
1788 iterator insert_multi(ValueType &&v) {
1789 return insert_multi(params_type::key(v), std::forward<ValueType>(v));
1790 }
1791
1792 // Insert with hint. Check to see if the value should be placed immediately
1793 // before position in the tree. If it does, then the insertion will take
1794 // amortized constant time. If not, the insertion will take amortized
1795 // logarithmic time as if a call to insert_multi(v) were made.
1796 template <typename ValueType>
1797 iterator insert_hint_multi(iterator position, ValueType &&v);
1798
1799 // Insert a range of values into the btree.
1800 template <typename InputIterator>
1801 void insert_iterator_multi(InputIterator b, InputIterator e);
1802
1803 // Erase the specified iterator from the btree. The iterator must be valid
1804 // (i.e. not equal to end()). Return an iterator pointing to the node after
1805 // the one that was erased (or end() if none exists).
1806 // Requirement: does not read the value at `*iter`.
1807 iterator erase(iterator iter);
1808
1809 // Erases range. Returns the number of keys erased and an iterator pointing
1810 // to the element after the last erased element.
1811 std::pair<size_type, iterator> erase(iterator begin, iterator end);
1812
1813 // Erases the specified key from the btree. Returns 1 if an element was
1814 // erased and 0 otherwise.
1815 template <typename K>
1816 size_type erase_unique(const K &key);
1817
1818 // Erases all of the entries matching the specified key from the
1819 // btree. Returns the number of elements erased.
1820 template <typename K>
1821 size_type erase_multi(const K &key);
1822
1823 // Finds the iterator corresponding to a key or returns end() if the key is
1824 // not present.
1825 template <typename K>
1826 iterator find(const K &key) {
1827 return internal_end(internal_find(key));
1828 }
1829 template <typename K>
1830 const_iterator find(const K &key) const {
1831 return internal_end(internal_find(key));
1832 }
1833
1834 // Returns a count of the number of times the key appears in the btree.
1835 template <typename K>
1836 size_type count_unique(const K &key) const {
1837 const iterator beg = internal_find(key);
1838 if (beg.node == nullptr) {
1839 // The key doesn't exist in the tree.
1840 return 0;
1841 }
1842 return 1;
1843 }
1844 // Returns a count of the number of times the key appears in the btree.
1845 template <typename K>
1846 size_type count_multi(const K &key) const {
1847 const auto range = equal_range(key);
1848 return std::distance(range.first, range.second);
1849 }
1850
1851 // Clear the btree, deleting all of the values it contains.
1852 void clear();
1853
1854 // Swap the contents of *this and x.
1855 void swap(btree &x);
1856
1857 const key_compare &key_comp() const noexcept {
1858 return root_.template get<0>();
1859 }
1860 template <typename K, typename LK>
1861 bool compare_keys(const K &x, const LK &y) const {
1862 return compare_internal::compare_result_as_less_than(key_comp()(x, y));
1863 }
1864
1865 value_compare value_comp() const { return value_compare(key_comp()); }
1866
1867 // Verifies the structure of the btree.
1868 void verify() const;
1869
1870 // Size routines.
1871 size_type size() const { return size_; }
1872 size_type max_size() const { return (std::numeric_limits<size_type>::max)(); }
1873 bool empty() const { return size_ == 0; }
1874
1875 // The height of the btree. An empty tree will have height 0.
1876 size_type height() const {
1877 size_type h = 0;
1878 if (!empty()) {
1879 // Count the length of the chain from the leftmost node up to the
1880 // root. We actually count from the root back around to the level below
1881 // the root, but the calculation is the same because of the circularity
1882 // of that traversal.
1883 const node_type *n = root();
1884 do {
1885 ++h;
1886 n = n->parent();
1887 } while (n != root());
1888 }
1889 return h;
1890 }
1891
1892 // The number of internal, leaf and total nodes used by the btree.
1893 size_type leaf_nodes() const {
1894 return internal_stats(root()).leaf_nodes;
1895 }
1896 size_type internal_nodes() const {
1897 return internal_stats(root()).internal_nodes;
1898 }
1899 size_type nodes() const {
1900 node_stats stats = internal_stats(root());
1901 return stats.leaf_nodes + stats.internal_nodes;
1902 }
1903
1904 // The total number of bytes used by the btree.
1905 size_type bytes_used() const {
1906 node_stats stats = internal_stats(root());
1907 if (stats.leaf_nodes == 1 && stats.internal_nodes == 0) {
1908 return sizeof(*this) +
1909 node_type::LeafSize(root()->max_count());
1910 } else {
1911 return sizeof(*this) +
1912 stats.leaf_nodes * node_type::LeafSize() +
1913 stats.internal_nodes * node_type::InternalSize();
1914 }
1915 }
1916
1917 // The average number of bytes used per value stored in the btree.
1918 static double average_bytes_per_value() {
1919 // Returns the number of bytes per value on a leaf node that is 75%
1920 // full. Experimentally, this matches up nicely with the computed number of
1921 // bytes per value in trees that had their values inserted in random order.
1922 return node_type::LeafSize() / (kNodeValues * 0.75);
1923 }
1924
1925 // The fullness of the btree. Computed as the number of elements in the btree
1926 // divided by the maximum number of elements a tree with the current number
1927 // of nodes could hold. A value of 1 indicates perfect space
1928 // utilization. Smaller values indicate space wastage.
1929 // Returns 0 for empty trees.
1930 double fullness() const {
1931 if (empty()) return 0.0;
1932 return static_cast<double>(size()) / (nodes() * kNodeValues);
1933 }
1934 // The overhead of the btree structure in bytes per node. Computed as the
1935 // total number of bytes used by the btree minus the number of bytes used for
1936 // storing elements divided by the number of elements.
1937 // Returns 0 for empty trees.
1938 double overhead() const {
1939 if (empty()) return 0.0;
1940 return (bytes_used() - size() * sizeof(value_type)) /
1941 static_cast<double>(size());
1942 }
1943
1944 // The allocator used by the btree.
1945 allocator_type get_allocator() const {
1946 return allocator();
1947 }
1948
1949 private:
1950 // Internal accessor routines.
1951 node_type *root() { return root_.template get<2>(); }
1952 const node_type *root() const { return root_.template get<2>(); }
1953 node_type *&mutable_root() noexcept { return root_.template get<2>(); }
1954 key_compare *mutable_key_comp() noexcept { return &root_.template get<0>(); }
1955
1956 // The leftmost node is stored as the parent of the root node.
1957 node_type *leftmost() { return root()->parent(); }
1958 const node_type *leftmost() const { return root()->parent(); }
1959
1960 // Allocator routines.
1961 allocator_type *mutable_allocator() noexcept {
1962 return &root_.template get<1>();
1963 }
1964 const allocator_type &allocator() const noexcept {
1965 return root_.template get<1>();
1966 }
1967
1968 // Allocates a correctly aligned node of at least size bytes using the
1969 // allocator.
1970 node_type *allocate(const size_type sz) {
1971 return reinterpret_cast<node_type *>(
1972 phmap::priv::Allocate<node_type::Alignment()>(
1973 mutable_allocator(), (size_t)sz));
1974 }
1975
1976 // Node creation/deletion routines.
1977 node_type* new_internal_node(node_type *parent) {
1978 node_type *p = allocate(node_type::InternalSize());
1979 return node_type::init_internal(p, parent);
1980 }
1981 node_type* new_leaf_node(node_type *parent) {
1982 node_type *p = allocate(node_type::LeafSize());
1983 return node_type::init_leaf(p, parent, kNodeValues);
1984 }
1985 node_type *new_leaf_root_node(const int max_count) {
1986 node_type *p = allocate(node_type::LeafSize(max_count));
1987 return node_type::init_leaf(p, p, max_count);
1988 }
1989
1990 // Deletion helper routines.
1991 void erase_same_node(iterator begin, iterator end);
1992 iterator erase_from_leaf_node(iterator begin, size_type to_erase);
1993 iterator rebalance_after_delete(iterator iter);
1994
1995 // Deallocates a node of a certain size in bytes using the allocator.
1996 void deallocate(const size_type sz, node_type *node) {
1997 phmap::priv::Deallocate<node_type::Alignment()>(
1998 mutable_allocator(), node, (size_t)sz);
1999 }
2000
2001 void delete_internal_node(node_type *node) {
2002 node->destroy(mutable_allocator());
2003 deallocate(node_type::InternalSize(), node);
2004 }
2005 void delete_leaf_node(node_type *node) {
2006 node->destroy(mutable_allocator());
2007 deallocate(node_type::LeafSize(node->max_count()), node);
2008 }
2009
2010 // Rebalances or splits the node iter points to.
2011 void rebalance_or_split(iterator *iter);
2012
2013 // Merges the values of left, right and the delimiting key on their parent
2014 // onto left, removing the delimiting key and deleting right.
2015 void merge_nodes(node_type *left, node_type *right);
2016
2017 // Tries to merge node with its left or right sibling, and failing that,
2018 // rebalance with its left or right sibling. Returns true if a merge
2019 // occurred, at which point it is no longer valid to access node. Returns
2020 // false if no merging took place.
2021 bool try_merge_or_rebalance(iterator *iter);
2022
2023 // Tries to shrink the height of the tree by 1.
2024 void try_shrink();
2025
2026 iterator internal_end(iterator iter) {
2027 return iter.node != nullptr ? iter : end();
2028 }
2029 const_iterator internal_end(const_iterator iter) const {
2030 return iter.node != nullptr ? iter : end();
2031 }
2032
2033 // Emplaces a value into the btree immediately before iter. Requires that
2034 // key(v) <= iter.key() and (--iter).key() <= key(v).
2035 template <typename... Args>
2036 iterator internal_emplace(iterator iter, Args &&... args);
2037
2038 // Returns an iterator pointing to the first value >= the value "iter" is
2039 // pointing at. Note that "iter" might be pointing to an invalid location as
2040 // iter.position == iter.node->count(). This routine simply moves iter up in
2041 // the tree to a valid location.
2042 // Requires: iter.node is non-null.
2043 template <typename IterType>
2044 static IterType internal_last(IterType iter);
2045
2046 // Returns an iterator pointing to the leaf position at which key would
2047 // reside in the tree. We provide 2 versions of internal_locate. The first
2048 // version uses a less-than comparator and is incapable of distinguishing when
2049 // there is an exact match. The second version is for the key-compare-to
2050 // specialization and distinguishes exact matches. The key-compare-to
2051 // specialization allows the caller to avoid a subsequent comparison to
2052 // determine if an exact match was made, which is important for keys with
2053 // expensive comparison, such as strings.
2054 template <typename K>
2055 SearchResult<iterator, is_key_compare_to::value> internal_locate(
2056 const K &key) const;
2057
2058 template <typename K>
2059 SearchResult<iterator, false> internal_locate_impl(
2060 const K &key, std::false_type /* IsCompareTo */) const;
2061
2062 template <typename K>
2063 SearchResult<iterator, true> internal_locate_impl(
2064 const K &key, std::true_type /* IsCompareTo */) const;
2065
2066 // Internal routine which implements lower_bound().
2067 template <typename K>
2068 iterator internal_lower_bound(const K &key) const;
2069
2070 // Internal routine which implements upper_bound().
2071 template <typename K>
2072 iterator internal_upper_bound(const K &key) const;
2073
2074 // Internal routine which implements find().
2075 template <typename K>
2076 iterator internal_find(const K &key) const;
2077
2078 // Deletes a node and all of its children.
2079 void internal_clear(node_type *node);
2080
2081 // Verifies the tree structure of node.
2082 int internal_verify(const node_type *node,
2083 const key_type *lo, const key_type *hi) const;
2084
2085 node_stats internal_stats(const node_type *node) const {
2086 // The root can be a static empty node.
2087 if (node == nullptr || (node == root() && empty())) {
2088 return node_stats(0, 0);
2089 }
2090 if (node->leaf()) {
2091 return node_stats(1, 0);
2092 }
2093 node_stats res(0, 1);
2094 for (int i = 0; i <= node->count(); ++i) {
2095 res += internal_stats(node->child(i));
2096 }
2097 return res;
2098 }
2099
2100 public:
2101 // Exposed only for tests.
2102 static bool testonly_uses_linear_node_search() {
2103 return node_type::testonly_uses_linear_node_search();
2104 }
2105
2106 private:
2107 // We use compressed tuple in order to save space because key_compare and
2108 // allocator_type are usually empty.
2109 phmap::priv::CompressedTuple<key_compare, allocator_type,
2110 node_type *>
2111 root_;
2112
2113 // A pointer to the rightmost node. Note that the leftmost node is stored as
2114 // the root's parent.
2115 node_type *rightmost_;
2116
2117 // Number of values.
2118 size_type size_;
2119 };
2120
2122 // btree_node methods
2123 template <typename P>
2124 template <typename... Args>
2125 inline void btree_node<P>::emplace_value(const size_type i,
2126 allocator_type *alloc,
2127 Args &&... args) {
2128 assert(i <= count());
2129 // Shift old values to create space for new value and then construct it in
2130 // place.
2131 if (i < count()) {
2132 value_init(count(), alloc, slot(count() - 1));
2133 for (size_type j = count() - 1; j > i; --j)
2134 params_type::move(alloc, slot(j - 1), slot(j));
2135 value_destroy(i, alloc);
2136 }
2137 value_init(i, alloc, std::forward<Args>(args)...);
2138 set_count((field_type)(count() + 1));
2139
2140 if (!leaf() && count() > i + 1) {
2141 for (int j = count(); j > i + 1; --j) {
2142 set_child(j, child(j - 1));
2143 }
2144 clear_child(i + 1);
2145 }
2146 }
2147
2148 template <typename P>
2149 inline void btree_node<P>::remove_value(const int i, allocator_type *alloc) {
2150 if (!leaf() && count() > i + 1) {
2151 assert(child(i + 1)->count() == 0);
2152 for (size_type j = i + 1; j < count(); ++j) {
2153 set_child(j, child(j + 1));
2154 }
2155 clear_child(count());
2156 }
2157
2158 remove_values_ignore_children(i, /*to_erase=*/1, alloc);
2159 }
2160
2161 template <typename P>
2162 inline void btree_node<P>::remove_values_ignore_children(
2163 int i, size_type to_erase, allocator_type *alloc) {
2164 params_type::move(alloc, slot(i + to_erase), slot(count()), slot(i));
2165 value_destroy_n(count() - to_erase, to_erase, alloc);
2166 set_count((field_type)(count() - to_erase));
2167 }
2168
2169 template <typename P>
2170 void btree_node<P>::rebalance_right_to_left(const int to_move,
2171 btree_node *right,
2172 allocator_type *alloc) {
2173 assert(parent() == right->parent());
2174 assert(position() + 1 == right->position());
2175 assert(right->count() >= count());
2176 assert(to_move >= 1);
2177 assert(to_move <= right->count());
2178
2179 // 1) Move the delimiting value in the parent to the left node.
2180 value_init(count(), alloc, parent()->slot(position()));
2181
2182 // 2) Move the (to_move - 1) values from the right node to the left node.
2183 right->uninitialized_move_n(to_move - 1, 0, count() + 1, this, alloc);
2184
2185 // 3) Move the new delimiting value to the parent from the right node.
2186 params_type::move(alloc, right->slot(to_move - 1),
2187 parent()->slot(position()));
2188
2189 // 4) Shift the values in the right node to their correct position.
2190 params_type::move(alloc, right->slot(to_move), right->slot(right->count()),
2191 right->slot(0));
2192
2193 // 5) Destroy the now-empty to_move entries in the right node.
2194 right->value_destroy_n(right->count() - to_move, to_move, alloc);
2195
2196 if (!leaf()) {
2197 // Move the child pointers from the right to the left node.
2198 for (int i = 0; i < to_move; ++i) {
2199 init_child(count() + i + 1, right->child(i));
2200 }
2201 for (int i = 0; i <= right->count() - to_move; ++i) {
2202 assert(i + to_move <= right->max_count());
2203 right->init_child(i, right->child(i + to_move));
2204 right->clear_child(i + to_move);
2205 }
2206 }
2207
2208 // Fixup the counts on the left and right nodes.
2209 set_count((field_type)(count() + to_move));
2210 right->set_count((field_type)(right->count() - to_move));
2211 }
2212
2213 template <typename P>
2214 void btree_node<P>::rebalance_left_to_right(const int to_move,
2215 btree_node *right,
2216 allocator_type *alloc) {
2217 assert(parent() == right->parent());
2218 assert(position() + 1 == right->position());
2219 assert(count() >= right->count());
2220 assert(to_move >= 1);
2221 assert(to_move <= count());
2222
2223 // Values in the right node are shifted to the right to make room for the
2224 // new to_move values. Then, the delimiting value in the parent and the
2225 // other (to_move - 1) values in the left node are moved into the right node.
2226 // Lastly, a new delimiting value is moved from the left node into the
2227 // parent, and the remaining empty left node entries are destroyed.
2228
2229 if (right->count() >= to_move) {
2230 // The original location of the right->count() values are sufficient to hold
2231 // the new to_move entries from the parent and left node.
2232
2233 // 1) Shift existing values in the right node to their correct positions.
2234 right->uninitialized_move_n(to_move, right->count() - to_move,
2235 right->count(), right, alloc);
2236 for (slot_type *src = right->slot(right->count() - to_move - 1),
2237 *dest = right->slot(right->count() - 1),
2238 *end = right->slot(0);
2239 src >= end; --src, --dest) {
2240 params_type::move(alloc, src, dest);
2241 }
2242
2243 // 2) Move the delimiting value in the parent to the right node.
2244 params_type::move(alloc, parent()->slot(position()),
2245 right->slot(to_move - 1));
2246
2247 // 3) Move the (to_move - 1) values from the left node to the right node.
2248 params_type::move(alloc, slot(count() - (to_move - 1)), slot(count()),
2249 right->slot(0));
2250 } else {
2251 // The right node does not have enough initialized space to hold the new
2252 // to_move entries, so part of them will move to uninitialized space.
2253
2254 // 1) Shift existing values in the right node to their correct positions.
2255 right->uninitialized_move_n(right->count(), 0, to_move, right, alloc);
2256
2257 // 2) Move the delimiting value in the parent to the right node.
2258 right->value_init(to_move - 1, alloc, parent()->slot(position()));
2259
2260 // 3) Move the (to_move - 1) values from the left node to the right node.
2261 const size_type uninitialized_remaining = to_move - right->count() - 1;
2262 uninitialized_move_n(uninitialized_remaining,
2263 count() - uninitialized_remaining, right->count(),
2264 right, alloc);
2265 params_type::move(alloc, slot(count() - (to_move - 1)),
2266 slot(count() - uninitialized_remaining), right->slot(0));
2267 }
2268
2269 // 4) Move the new delimiting value to the parent from the left node.
2270 params_type::move(alloc, slot(count() - to_move), parent()->slot(position()));
2271
2272 // 5) Destroy the now-empty to_move entries in the left node.
2273 value_destroy_n(count() - to_move, to_move, alloc);
2274
2275 if (!leaf()) {
2276 // Move the child pointers from the left to the right node.
2277 for (int i = right->count(); i >= 0; --i) {
2278 right->init_child(i + to_move, right->child(i));
2279 right->clear_child(i);
2280 }
2281 for (int i = 1; i <= to_move; ++i) {
2282 right->init_child(i - 1, child(count() - to_move + i));
2283 clear_child(count() - to_move + i);
2284 }
2285 }
2286
2287 // Fixup the counts on the left and right nodes.
2288 set_count((field_type)(count() - to_move));
2289 right->set_count((field_type)(right->count() + to_move));
2290 }
2291
2292 template <typename P>
2293 void btree_node<P>::split(const int insert_position, btree_node *dest,
2294 allocator_type *alloc) {
2295 assert(dest->count() == 0);
2296 assert(max_count() == kNodeValues);
2297
2298 // We bias the split based on the position being inserted. If we're
2299 // inserting at the beginning of the left node then bias the split to put
2300 // more values on the right node. If we're inserting at the end of the
2301 // right node then bias the split to put more values on the left node.
2302 if (insert_position == 0) {
2303 dest->set_count((field_type)(count() - 1));
2304 } else if (insert_position == kNodeValues) {
2305 dest->set_count(0);
2306 } else {
2307 dest->set_count((field_type)(count() / 2));
2308 }
2309 set_count((field_type)(count() - dest->count()));
2310 assert(count() >= 1);
2311
2312 // Move values from the left sibling to the right sibling.
2313 uninitialized_move_n(dest->count(), count(), 0, dest, alloc);
2314
2315 // Destroy the now-empty entries in the left node.
2316 value_destroy_n(count(), dest->count(), alloc);
2317
2318 // The split key is the largest value in the left sibling.
2319 set_count((field_type)(count() - 1));
2320 parent()->emplace_value(position(), alloc, slot(count()));
2321 value_destroy(count(), alloc);
2322 parent()->init_child(position() + 1, dest);
2323
2324 if (!leaf()) {
2325 for (int i = 0; i <= dest->count(); ++i) {
2326 assert(child(count() + i + 1) != nullptr);
2327 dest->init_child(i, child(count() + i + 1));
2328 clear_child(count() + i + 1);
2329 }
2330 }
2331 }
2332
2333 template <typename P>
2334 void btree_node<P>::merge(btree_node *src, allocator_type *alloc) {
2335 assert(parent() == src->parent());
2336 assert(position() + 1 == src->position());
2337
2338 // Move the delimiting value to the left node.
2339 value_init(count(), alloc, parent()->slot(position()));
2340
2341 // Move the values from the right to the left node.
2342 src->uninitialized_move_n(src->count(), 0, count() + 1, this, alloc);
2343
2344 // Destroy the now-empty entries in the right node.
2345 src->value_destroy_n(0, src->count(), alloc);
2346
2347 if (!leaf()) {
2348 // Move the child pointers from the right to the left node.
2349 for (int i = 0; i <= src->count(); ++i) {
2350 init_child(count() + i + 1, src->child(i));
2351 src->clear_child(i);
2352 }
2353 }
2354
2355 // Fixup the counts on the src and dest nodes.
2356 set_count((field_type)(1 + count() + src->count()));
2357 src->set_count(0);
2358
2359 // Remove the value on the parent node.
2360 parent()->remove_value(position(), alloc);
2361 }
2362
2363 template <typename P>
2364 void btree_node<P>::swap(btree_node *x, allocator_type *alloc) {
2365 using std::swap;
2366 assert(leaf() == x->leaf());
2367
2368 // Determine which is the smaller/larger node.
2369 btree_node *smaller = this, *larger = x;
2370 if (smaller->count() > larger->count()) {
2371 swap(smaller, larger);
2372 }
2373
2374 // Swap the values.
2375 for (slot_type *a = smaller->slot(0), *b = larger->slot(0),
2376 *end = a + smaller->count();
2377 a != end; ++a, ++b) {
2378 params_type::swap(alloc, a, b);
2379 }
2380
2381 // Move values that can't be swapped.
2382 const size_type to_move = larger->count() - smaller->count();
2383 larger->uninitialized_move_n(to_move, smaller->count(), smaller->count(),
2384 smaller, alloc);
2385 larger->value_destroy_n(smaller->count(), to_move, alloc);
2386
2387 if (!leaf()) {
2388 // Swap the child pointers.
2389 std::swap_ranges(&smaller->mutable_child(0),
2390 &smaller->mutable_child(smaller->count() + 1),
2391 &larger->mutable_child(0));
2392 // Update swapped children's parent pointers.
2393 int i = 0;
2394 for (; i <= smaller->count(); ++i) {
2395 smaller->child(i)->set_parent(smaller);
2396 larger->child(i)->set_parent(larger);
2397 }
2398 // Move the child pointers that couldn't be swapped.
2399 for (; i <= larger->count(); ++i) {
2400 smaller->init_child(i, larger->child(i));
2401 larger->clear_child(i);
2402 }
2403 }
2404
2405 // Swap the counts.
2406 swap(mutable_count(), x->mutable_count());
2407 }
2408
2410 // btree_iterator methods
2411 template <typename N, typename R, typename P>
2412 void btree_iterator<N, R, P>::increment_slow() {
2413 if (node->leaf()) {
2414 assert(position >= node->count());
2415 btree_iterator save(*this);
2416 while (position == node->count() && !node->is_root()) {
2417 assert(node->parent()->child(node->position()) == node);
2418 position = node->position();
2419 node = node->parent();
2420 }
2421 if (position == node->count()) {
2422 *this = save;
2423 }
2424 } else {
2425 assert(position < node->count());
2426 node = node->child(position + 1);
2427 while (!node->leaf()) {
2428 node = node->child(0);
2429 }
2430 position = 0;
2431 }
2432 }
2433
2434 template <typename N, typename R, typename P>
2435 void btree_iterator<N, R, P>::decrement_slow() {
2436 if (node->leaf()) {
2437 assert(position <= -1);
2438 btree_iterator save(*this);
2439 while (position < 0 && !node->is_root()) {
2440 assert(node->parent()->child(node->position()) == node);
2441 position = node->position() - 1;
2442 node = node->parent();
2443 }
2444 if (position < 0) {
2445 *this = save;
2446 }
2447 } else {
2448 assert(position >= 0);
2449 node = node->child(position);
2450 while (!node->leaf()) {
2451 node = node->child(node->count());
2452 }
2453 position = node->count() - 1;
2454 }
2455 }
2456
2458 // btree methods
2459 template <typename P>
2460 template <typename Btree>
2461 void btree<P>::copy_or_move_values_in_order(Btree *x) {
2462 static_assert(std::is_same<btree, Btree>::value ||
2463 std::is_same<const btree, Btree>::value,
2464 "Btree type must be same or const.");
2465 assert(empty());
2466
2467 // We can avoid key comparisons because we know the order of the
2468 // values is the same order we'll store them in.
2469 auto iter = x->begin();
2470 if (iter == x->end()) return;
2471 insert_multi(maybe_move_from_iterator(iter));
2472 ++iter;
2473 for (; iter != x->end(); ++iter) {
2474 // If the btree is not empty, we can just insert the new value at the end
2475 // of the tree.
2476 internal_emplace(end(), maybe_move_from_iterator(iter));
2477 }
2478 }
2479
2480 template <typename P>
2481 constexpr bool btree<P>::static_assert_validation() {
2482 static_assert(std::is_nothrow_copy_constructible<key_compare>::value,
2483 "Key comparison must be nothrow copy constructible");
2484 static_assert(std::is_nothrow_copy_constructible<allocator_type>::value,
2485 "Allocator must be nothrow copy constructible");
2486 static_assert(type_traits_internal::is_trivially_copyable<iterator>::value,
2487 "iterator not trivially copyable.");
2488
2489 // Note: We assert that kTargetValues, which is computed from
2490 // Params::kTargetNodeSize, must fit the node_type::field_type.
2491 static_assert(
2492 kNodeValues < (1 << (8 * sizeof(typename node_type::field_type))),
2493 "target node size too large");
2494
2495 // Verify that key_compare returns an phmap::{weak,strong}_ordering or bool.
2496 using compare_result_type =
2497 phmap::invoke_result_t<key_compare, key_type, key_type>;
2498 static_assert(
2499 std::is_same<compare_result_type, bool>::value ||
2500 std::is_convertible<compare_result_type, phmap::weak_ordering>::value,
2501 "key comparison function must return phmap::{weak,strong}_ordering or "
2502 "bool.");
2503
2504 // Test the assumption made in setting kNodeValueSpace.
2505 static_assert(node_type::MinimumOverhead() >= sizeof(void *) + 4,
2506 "node space assumption incorrect");
2507
2508 return true;
2509 }
2510
2511 template <typename P>
2512 btree<P>::btree(const key_compare &comp, const allocator_type &alloc)
2513 : root_(comp, alloc, EmptyNode()), rightmost_(EmptyNode()), size_(0) {}
2514
2515 template <typename P>
2516 btree<P>::btree(const btree &x) : btree(x.key_comp(), x.allocator()) {
2517 copy_or_move_values_in_order(&x);
2518 }
2519
2520 template <typename P>
2521 template <typename... Args>
2522 auto btree<P>::insert_unique(const key_type &key, Args &&... args)
2523 -> std::pair<iterator, bool> {
2524 if (empty()) {
2525 mutable_root() = rightmost_ = new_leaf_root_node(1);
2526 }
2527
2528 auto res = internal_locate(key);
2529 iterator &iter = res.value;
2530
2531 if (res.HasMatch()) {
2532 if (res.IsEq()) {
2533 // The key already exists in the tree, do nothing.
2534 return {iter, false};
2535 }
2536 } else {
2537 iterator last = internal_last(iter);
2538 if (last.node && !compare_keys(key, last.key())) {
2539 // The key already exists in the tree, do nothing.
2540 return {last, false};
2541 }
2542 }
2543 return {internal_emplace(iter, std::forward<Args>(args)...), true};
2544 }
2545
2546 template <typename P>
2547 template <typename... Args>
2548 inline auto btree<P>::insert_hint_unique(iterator position, const key_type &key,
2549 Args &&... args)
2550 -> std::pair<iterator, bool> {
2551 if (!empty()) {
2552 if (position == end() || compare_keys(key, position.key())) {
2553 iterator prev = position;
2554 if (position == begin() || compare_keys((--prev).key(), key)) {
2555 // prev.key() < key < position.key()
2556 return {internal_emplace(position, std::forward<Args>(args)...), true};
2557 }
2558 } else if (compare_keys(position.key(), key)) {
2559 ++position;
2560 if (position == end() || compare_keys(key, position.key())) {
2561 // {original `position`}.key() < key < {current `position`}.key()
2562 return {internal_emplace(position, std::forward<Args>(args)...), true};
2563 }
2564 } else {
2565 // position.key() == key
2566 return {position, false};
2567 }
2568 }
2569 return insert_unique(key, std::forward<Args>(args)...);
2570 }
2571
2572 template <typename P>
2573 template <typename InputIterator>
2574 void btree<P>::insert_iterator_unique(InputIterator b, InputIterator e) {
2575 for (; b != e; ++b) {
2576 insert_hint_unique(end(), params_type::key(*b), *b);
2577 }
2578 }
2579
2580 template <typename P>
2581 template <typename ValueType>
2582 auto btree<P>::insert_multi(const key_type &key, ValueType &&v) -> iterator {
2583 if (empty()) {
2584 mutable_root() = rightmost_ = new_leaf_root_node(1);
2585 }
2586
2587 iterator iter = internal_upper_bound(key);
2588 if (iter.node == nullptr) {
2589 iter = end();
2590 }
2591 return internal_emplace(iter, std::forward<ValueType>(v));
2592 }
2593
2594 template <typename P>
2595 template <typename ValueType>
2596 auto btree<P>::insert_hint_multi(iterator position, ValueType &&v) -> iterator {
2597 if (!empty()) {
2598 const key_type &key = params_type::key(v);
2599 if (position == end() || !compare_keys(position.key(), key)) {
2600 iterator prev = position;
2601 if (position == begin() || !compare_keys(key, (--prev).key())) {
2602 // prev.key() <= key <= position.key()
2603 return internal_emplace(position, std::forward<ValueType>(v));
2604 }
2605 } else {
2606 iterator next = position;
2607 ++next;
2608 if (next == end() || !compare_keys(next.key(), key)) {
2609 // position.key() < key <= next.key()
2610 return internal_emplace(next, std::forward<ValueType>(v));
2611 }
2612 }
2613 }
2614 return insert_multi(std::forward<ValueType>(v));
2615 }
2616
2617 template <typename P>
2618 template <typename InputIterator>
2619 void btree<P>::insert_iterator_multi(InputIterator b, InputIterator e) {
2620 for (; b != e; ++b) {
2621 insert_hint_multi(end(), *b);
2622 }
2623 }
2624
2625 template <typename P>
2626 auto btree<P>::operator=(const btree &x) -> btree & {
2627 if (this != &x) {
2628 clear();
2629
2630 *mutable_key_comp() = x.key_comp();
2632 allocator_type>::propagate_on_container_copy_assignment::value) {
2633 *mutable_allocator() = x.allocator();
2634 }
2635
2636 copy_or_move_values_in_order(&x);
2637 }
2638 return *this;
2639 }
2640
2641 template <typename P>
2642 auto btree<P>::operator=(btree &&x) noexcept -> btree & {
2643 if (this != &x) {
2644 clear();
2645
2646 using std::swap;
2648 allocator_type>::propagate_on_container_copy_assignment::value) {
2649 // Note: `root_` also contains the allocator and the key comparator.
2650 swap(root_, x.root_);
2651 swap(rightmost_, x.rightmost_);
2652 swap(size_, x.size_);
2653 } else {
2654 if (allocator() == x.allocator()) {
2655 swap(mutable_root(), x.mutable_root());
2656 swap(*mutable_key_comp(), *x.mutable_key_comp());
2657 swap(rightmost_, x.rightmost_);
2658 swap(size_, x.size_);
2659 } else {
2660 // We aren't allowed to propagate the allocator and the allocator is
2661 // different so we can't take over its memory. We must move each element
2662 // individually. We need both `x` and `this` to have `x`s key comparator
2663 // while moving the values so we can't swap the key comparators.
2664 *mutable_key_comp() = x.key_comp();
2665 copy_or_move_values_in_order(&x);
2666 }
2667 }
2668 }
2669 return *this;
2670 }
2671
2672 template <typename P>
2673 auto btree<P>::erase(iterator iter) -> iterator {
2674 bool internal_delete = false;
2675 if (!iter.node->leaf()) {
2676 // Deletion of a value on an internal node. First, move the largest value
2677 // from our left child here, then delete that position (in remove_value()
2678 // below). We can get to the largest value from our left child by
2679 // decrementing iter.
2680 iterator internal_iter(iter);
2681 --iter;
2682 assert(iter.node->leaf());
2683 params_type::move(mutable_allocator(), iter.node->slot(iter.position),
2684 internal_iter.node->slot(internal_iter.position));
2685 internal_delete = true;
2686 }
2687
2688 // Delete the key from the leaf.
2689 iter.node->remove_value(iter.position, mutable_allocator());
2690 --size_;
2691
2692 // We want to return the next value after the one we just erased. If we
2693 // erased from an internal node (internal_delete == true), then the next
2694 // value is ++(++iter). If we erased from a leaf node (internal_delete ==
2695 // false) then the next value is ++iter. Note that ++iter may point to an
2696 // internal node and the value in the internal node may move to a leaf node
2697 // (iter.node) when rebalancing is performed at the leaf level.
2698
2699 iterator res = rebalance_after_delete(iter);
2700
2701 // If we erased from an internal node, advance the iterator.
2702 if (internal_delete) {
2703 ++res;
2704 }
2705 return res;
2706 }
2707
2708 template <typename P>
2709 auto btree<P>::rebalance_after_delete(iterator iter) -> iterator {
2710 // Merge/rebalance as we walk back up the tree.
2711 iterator res(iter);
2712 bool first_iteration = true;
2713 for (;;) {
2714 if (iter.node == root()) {
2715 try_shrink();
2716 if (empty()) {
2717 return end();
2718 }
2719 break;
2720 }
2721 if (iter.node->count() >= kMinNodeValues) {
2722 break;
2723 }
2724 bool merged = try_merge_or_rebalance(&iter);
2725 // On the first iteration, we should update `res` with `iter` because `res`
2726 // may have been invalidated.
2727 if (first_iteration) {
2728 res = iter;
2729 first_iteration = false;
2730 }
2731 if (!merged) {
2732 break;
2733 }
2734 iter.position = iter.node->position();
2735 iter.node = iter.node->parent();
2736 }
2737
2738 // Adjust our return value. If we're pointing at the end of a node, advance
2739 // the iterator.
2740 if (res.position == res.node->count()) {
2741 res.position = res.node->count() - 1;
2742 ++res;
2743 }
2744
2745 return res;
2746 }
2747
2748 template <typename P>
2749 auto btree<P>::erase(iterator _begin, iterator _end)
2750 -> std::pair<size_type, iterator> {
2751 difference_type count = std::distance(_begin, _end);
2752 assert(count >= 0);
2753
2754 if (count == 0) {
2755 return {0, _begin};
2756 }
2757
2758 if (count == size_) {
2759 clear();
2760 return {count, this->end()};
2761 }
2762
2763 if (_begin.node == _end.node) {
2764 erase_same_node(_begin, _end);
2765 size_ -= count;
2766 return {count, rebalance_after_delete(_begin)};
2767 }
2768
2769 const size_type target_size = size_ - count;
2770 while (size_ > target_size) {
2771 if (_begin.node->leaf()) {
2772 const size_type remaining_to_erase = size_ - target_size;
2773 const size_type remaining_in_node = _begin.node->count() - _begin.position;
2774 _begin = erase_from_leaf_node(
2775 _begin, (std::min)(remaining_to_erase, remaining_in_node));
2776 } else {
2777 _begin = erase(_begin);
2778 }
2779 }
2780 return {count, _begin};
2781 }
2782
2783 template <typename P>
2784 void btree<P>::erase_same_node(iterator _begin, iterator _end) {
2785 assert(_begin.node == _end.node);
2786 assert(_end.position > _begin.position);
2787
2788 node_type *node = _begin.node;
2789 size_type to_erase = _end.position - _begin.position;
2790 if (!node->leaf()) {
2791 // Delete all children between _begin and _end.
2792 for (size_type i = 0; i < to_erase; ++i) {
2793 internal_clear(node->child(_begin.position + i + 1));
2794 }
2795 // Rotate children after _end into new positions.
2796 for (size_type i = _begin.position + to_erase + 1; i <= node->count(); ++i) {
2797 node->set_child(i - to_erase, node->child(i));
2798 node->clear_child(i);
2799 }
2800 }
2801 node->remove_values_ignore_children(_begin.position, to_erase,
2802 mutable_allocator());
2803
2804 // Do not need to update rightmost_, because
2805 // * either _end == this->end(), and therefore node == rightmost_, and still
2806 // exists
2807 // * or _end != this->end(), and therefore rightmost_ hasn't been erased, since
2808 // it wasn't covered in [_begin, _end)
2809 }
2810
2811 template <typename P>
2812 auto btree<P>::erase_from_leaf_node(iterator _begin, size_type to_erase)
2813 -> iterator {
2814 node_type *node = _begin.node;
2815 assert(node->leaf());
2816 assert(node->count() > _begin.position);
2817 assert(_begin.position + to_erase <= node->count());
2818
2819 node->remove_values_ignore_children(_begin.position, to_erase,
2820 mutable_allocator());
2821
2822 size_ -= to_erase;
2823
2824 return rebalance_after_delete(_begin);
2825 }
2826
2827 template <typename P>
2828 template <typename K>
2829 auto btree<P>::erase_unique(const K &key) -> size_type {
2830 const iterator iter = internal_find(key);
2831 if (iter.node == nullptr) {
2832 // The key doesn't exist in the tree, return nothing done.
2833 return 0;
2834 }
2835 erase(iter);
2836 return 1;
2837 }
2838
2839 template <typename P>
2840 template <typename K>
2841 auto btree<P>::erase_multi(const K &key) -> size_type {
2842 const iterator _begin = internal_lower_bound(key);
2843 if (_begin.node == nullptr) {
2844 // The key doesn't exist in the tree, return nothing done.
2845 return 0;
2846 }
2847 // Delete all of the keys between _begin and upper_bound(key).
2848 const iterator _end = internal_end(internal_upper_bound(key));
2849 return erase(_begin, _end).first;
2850 }
2851
2852 template <typename P>
2853 void btree<P>::clear() {
2854 if (!empty()) {
2855 internal_clear(root());
2856 }
2857 mutable_root() = EmptyNode();
2858 rightmost_ = EmptyNode();
2859 size_ = 0;
2860 }
2861
2862 template <typename P>
2863 void btree<P>::swap(btree &x) {
2864 using std::swap;
2866 allocator_type>::propagate_on_container_swap::value) {
2867 // Note: `root_` also contains the allocator and the key comparator.
2868 swap(root_, x.root_);
2869 } else {
2870 // It's undefined behavior if the allocators are unequal here.
2871 assert(allocator() == x.allocator());
2872 swap(mutable_root(), x.mutable_root());
2873 swap(*mutable_key_comp(), *x.mutable_key_comp());
2874 }
2875 swap(rightmost_, x.rightmost_);
2876 swap(size_, x.size_);
2877 }
2878
2879 template <typename P>
2880 void btree<P>::verify() const {
2881 assert(root() != nullptr);
2882 assert(leftmost() != nullptr);
2883 assert(rightmost_ != nullptr);
2884 assert(empty() || size() == internal_verify(root(), nullptr, nullptr));
2885 assert(leftmost() == (++const_iterator(root(), -1)).node);
2886 assert(rightmost_ == (--const_iterator(root(), root()->count())).node);
2887 assert(leftmost()->leaf());
2888 assert(rightmost_->leaf());
2889 }
2890
2891 template <typename P>
2892 void btree<P>::rebalance_or_split(iterator *iter) {
2893 node_type *&node = iter->node;
2894 int &insert_position = iter->position;
2895 assert(node->count() == node->max_count());
2896 assert(kNodeValues == node->max_count());
2897
2898 // First try to make room on the node by rebalancing.
2899 node_type *parent = node->parent();
2900 if (node != root()) {
2901 if (node->position() > 0) {
2902 // Try rebalancing with our left sibling.
2903 node_type *left = parent->child(node->position() - 1);
2904 assert(left->max_count() == kNodeValues);
2905 if (left->count() < kNodeValues) {
2906 // We bias rebalancing based on the position being inserted. If we're
2907 // inserting at the end of the right node then we bias rebalancing to
2908 // fill up the left node.
2909 int to_move = (kNodeValues - left->count()) /
2910 (1 + (insert_position < kNodeValues));
2911 to_move = (std::max)(1, to_move);
2912
2913 if (((insert_position - to_move) >= 0) ||
2914 ((left->count() + to_move) < kNodeValues)) {
2915 left->rebalance_right_to_left(to_move, node, mutable_allocator());
2916
2917 assert(node->max_count() - node->count() == to_move);
2918 insert_position = insert_position - to_move;
2919 if (insert_position < 0) {
2920 insert_position = insert_position + left->count() + 1;
2921 node = left;
2922 }
2923
2924 assert(node->count() < node->max_count());
2925 return;
2926 }
2927 }
2928 }
2929
2930 if (node->position() < parent->count()) {
2931 // Try rebalancing with our right sibling.
2932 node_type *right = parent->child(node->position() + 1);
2933 assert(right->max_count() == kNodeValues);
2934 if (right->count() < kNodeValues) {
2935 // We bias rebalancing based on the position being inserted. If we're
2936 // inserting at the _beginning of the left node then we bias rebalancing
2937 // to fill up the right node.
2938 int to_move =
2939 (kNodeValues - right->count()) / (1 + (insert_position > 0));
2940 to_move = (std::max)(1, to_move);
2941
2942 if ((insert_position <= (node->count() - to_move)) ||
2943 ((right->count() + to_move) < kNodeValues)) {
2944 node->rebalance_left_to_right(to_move, right, mutable_allocator());
2945
2946 if (insert_position > node->count()) {
2947 insert_position = insert_position - node->count() - 1;
2948 node = right;
2949 }
2950
2951 assert(node->count() < node->max_count());
2952 return;
2953 }
2954 }
2955 }
2956
2957 // Rebalancing failed, make sure there is room on the parent node for a new
2958 // value.
2959 assert(parent->max_count() == kNodeValues);
2960 if (parent->count() == kNodeValues) {
2961 iterator parent_iter(node->parent(), node->position());
2962 rebalance_or_split(&parent_iter);
2963 }
2964 } else {
2965 // Rebalancing not possible because this is the root node.
2966 // Create a new root node and set the current root node as the child of the
2967 // new root.
2968 parent = new_internal_node(parent);
2969 parent->init_child(0, root());
2970 mutable_root() = parent;
2971 // If the former root was a leaf node, then it's now the rightmost node.
2972 assert(!parent->child(0)->leaf() || parent->child(0) == rightmost_);
2973 }
2974
2975 // Split the node.
2976 node_type *split_node;
2977 if (node->leaf()) {
2978 split_node = new_leaf_node(parent);
2979 node->split(insert_position, split_node, mutable_allocator());
2980 if (rightmost_ == node) rightmost_ = split_node;
2981 } else {
2982 split_node = new_internal_node(parent);
2983 node->split(insert_position, split_node, mutable_allocator());
2984 }
2985
2986 if (insert_position > node->count()) {
2987 insert_position = insert_position - node->count() - 1;
2988 node = split_node;
2989 }
2990 }
2991
2992 template <typename P>
2993 void btree<P>::merge_nodes(node_type *left, node_type *right) {
2994 left->merge(right, mutable_allocator());
2995 if (right->leaf()) {
2996 if (rightmost_ == right) rightmost_ = left;
2997 delete_leaf_node(right);
2998 } else {
2999 delete_internal_node(right);
3000 }
3001 }
3002
3003 template <typename P>
3004 bool btree<P>::try_merge_or_rebalance(iterator *iter) {
3005 node_type *parent = iter->node->parent();
3006 if (iter->node->position() > 0) {
3007 // Try merging with our left sibling.
3008 node_type *left = parent->child(iter->node->position() - 1);
3009 assert(left->max_count() == kNodeValues);
3010 if ((1 + left->count() + iter->node->count()) <= kNodeValues) {
3011 iter->position += 1 + left->count();
3012 merge_nodes(left, iter->node);
3013 iter->node = left;
3014 return true;
3015 }
3016 }
3017 if (iter->node->position() < parent->count()) {
3018 // Try merging with our right sibling.
3019 node_type *right = parent->child(iter->node->position() + 1);
3020 assert(right->max_count() == kNodeValues);
3021 if ((1 + iter->node->count() + right->count()) <= kNodeValues) {
3022 merge_nodes(iter->node, right);
3023 return true;
3024 }
3025 // Try rebalancing with our right sibling. We don't perform rebalancing if
3026 // we deleted the first element from iter->node and the node is not
3027 // empty. This is a small optimization for the common pattern of deleting
3028 // from the front of the tree.
3029 if ((right->count() > kMinNodeValues) &&
3030 ((iter->node->count() == 0) ||
3031 (iter->position > 0))) {
3032 int to_move = (right->count() - iter->node->count()) / 2;
3033 to_move = (std::min)(to_move, right->count() - 1);
3034 iter->node->rebalance_right_to_left(to_move, right, mutable_allocator());
3035 return false;
3036 }
3037 }
3038 if (iter->node->position() > 0) {
3039 // Try rebalancing with our left sibling. We don't perform rebalancing if
3040 // we deleted the last element from iter->node and the node is not
3041 // empty. This is a small optimization for the common pattern of deleting
3042 // from the back of the tree.
3043 node_type *left = parent->child(iter->node->position() - 1);
3044 if ((left->count() > kMinNodeValues) &&
3045 ((iter->node->count() == 0) ||
3046 (iter->position < iter->node->count()))) {
3047 int to_move = (left->count() - iter->node->count()) / 2;
3048 to_move = (std::min)(to_move, left->count() - 1);
3049 left->rebalance_left_to_right(to_move, iter->node, mutable_allocator());
3050 iter->position += to_move;
3051 return false;
3052 }
3053 }
3054 return false;
3055 }
3056
3057 template <typename P>
3058 void btree<P>::try_shrink() {
3059 if (root()->count() > 0) {
3060 return;
3061 }
3062 // Deleted the last item on the root node, shrink the height of the tree.
3063 if (root()->leaf()) {
3064 assert(size() == 0);
3065 delete_leaf_node(root());
3066 mutable_root() = EmptyNode();
3067 rightmost_ = EmptyNode();
3068 } else {
3069 node_type *child = root()->child(0);
3070 child->make_root();
3071 delete_internal_node(root());
3072 mutable_root() = child;
3073 }
3074 }
3075
3076 template <typename P>
3077 template <typename IterType>
3078 inline IterType btree<P>::internal_last(IterType iter) {
3079 assert(iter.node != nullptr);
3080 while (iter.position == iter.node->count()) {
3081 iter.position = iter.node->position();
3082 iter.node = iter.node->parent();
3083 if (iter.node->leaf()) {
3084 iter.node = nullptr;
3085 break;
3086 }
3087 }
3088 return iter;
3089 }
3090
3091 template <typename P>
3092 template <typename... Args>
3093 inline auto btree<P>::internal_emplace(iterator iter, Args &&... args)
3094 -> iterator {
3095 if (!iter.node->leaf()) {
3096 // We can't insert on an internal node. Instead, we'll insert after the
3097 // previous value which is guaranteed to be on a leaf node.
3098 --iter;
3099 ++iter.position;
3100 }
3101 const int max_count = iter.node->max_count();
3102 if (iter.node->count() == max_count) {
3103 // Make room in the leaf for the new item.
3104 if (max_count < kNodeValues) {
3105 // Insertion into the root where the root is smaller than the full node
3106 // size. Simply grow the size of the root node.
3107 assert(iter.node == root());
3108 iter.node =
3109 new_leaf_root_node((std::min<int>)(kNodeValues, 2 * max_count));
3110 iter.node->swap(root(), mutable_allocator());
3111 delete_leaf_node(root());
3112 mutable_root() = iter.node;
3113 rightmost_ = iter.node;
3114 } else {
3115 rebalance_or_split(&iter);
3116 }
3117 }
3118 iter.node->emplace_value(iter.position, mutable_allocator(),
3119 std::forward<Args>(args)...);
3120 ++size_;
3121 return iter;
3122 }
3123
3124 template <typename P>
3125 template <typename K>
3126 inline auto btree<P>::internal_locate(const K &key) const
3127 -> SearchResult<iterator, is_key_compare_to::value> {
3128 return internal_locate_impl(key, is_key_compare_to());
3129 }
3130
3131 template <typename P>
3132 template <typename K>
3133 inline auto btree<P>::internal_locate_impl(
3134 const K &key, std::false_type /* IsCompareTo */) const
3135 -> SearchResult<iterator, false> {
3136 iterator iter(const_cast<node_type *>(root()), 0);
3137 for (;;) {
3138 iter.position = iter.node->lower_bound(key, key_comp()).value;
3139 // NOTE: we don't need to walk all the way down the tree if the keys are
3140 // equal, but determining equality would require doing an extra comparison
3141 // on each node on the way down, and we will need to go all the way to the
3142 // leaf node in the expected case.
3143 if (iter.node->leaf()) {
3144 break;
3145 }
3146 iter.node = iter.node->child(iter.position);
3147 }
3148 return {iter};
3149 }
3150
3151 template <typename P>
3152 template <typename K>
3153 inline auto btree<P>::internal_locate_impl(
3154 const K &key, std::true_type /* IsCompareTo */) const
3155 -> SearchResult<iterator, true> {
3156 iterator iter(const_cast<node_type *>(root()), 0);
3157 for (;;) {
3158 SearchResult<int, true> res = iter.node->lower_bound(key, key_comp());
3159 iter.position = res.value;
3160 if (res.match == MatchKind::kEq) {
3161 return {iter, MatchKind::kEq};
3162 }
3163 if (iter.node->leaf()) {
3164 break;
3165 }
3166 iter.node = iter.node->child(iter.position);
3167 }
3168 return {iter, MatchKind::kNe};
3169 }
3170
3171 template <typename P>
3172 template <typename K>
3173 auto btree<P>::internal_lower_bound(const K &key) const -> iterator {
3174 iterator iter(const_cast<node_type *>(root()), 0);
3175 for (;;) {
3176 iter.position = iter.node->lower_bound(key, key_comp()).value;
3177 if (iter.node->leaf()) {
3178 break;
3179 }
3180 iter.node = iter.node->child(iter.position);
3181 }
3182 return internal_last(iter);
3183 }
3184
3185 template <typename P>
3186 template <typename K>
3187 auto btree<P>::internal_upper_bound(const K &key) const -> iterator {
3188 iterator iter(const_cast<node_type *>(root()), 0);
3189 for (;;) {
3190 iter.position = iter.node->upper_bound(key, key_comp());
3191 if (iter.node->leaf()) {
3192 break;
3193 }
3194 iter.node = iter.node->child(iter.position);
3195 }
3196 return internal_last(iter);
3197 }
3198
3199 template <typename P>
3200 template <typename K>
3201 auto btree<P>::internal_find(const K &key) const -> iterator {
3202 auto res = internal_locate(key);
3203 if (res.HasMatch()) {
3204 if (res.IsEq()) {
3205 return res.value;
3206 }
3207 } else {
3208 const iterator iter = internal_last(res.value);
3209 if (iter.node != nullptr && !compare_keys(key, iter.key())) {
3210 return iter;
3211 }
3212 }
3213 return {nullptr, 0};
3214 }
3215
3216 template <typename P>
3217 void btree<P>::internal_clear(node_type *node) {
3218 if (!node->leaf()) {
3219 for (int i = 0; i <= node->count(); ++i) {
3220 internal_clear(node->child(i));
3221 }
3222 delete_internal_node(node);
3223 } else {
3224 delete_leaf_node(node);
3225 }
3226 }
3227
3228 template <typename P>
3229 int btree<P>::internal_verify(
3230 const node_type *node, const key_type *lo, const key_type *hi) const {
3231 assert(node->count() > 0);
3232 assert(node->count() <= node->max_count());
3233 if (lo) {
3234 assert(!compare_keys(node->key(0), *lo));
3235 }
3236 if (hi) {
3237 assert(!compare_keys(*hi, node->key(node->count() - 1)));
3238 }
3239 for (int i = 1; i < node->count(); ++i) {
3240 assert(!compare_keys(node->key(i), node->key(i - 1)));
3241 }
3242 int count = node->count();
3243 if (!node->leaf()) {
3244 for (int i = 0; i <= node->count(); ++i) {
3245 assert(node->child(i) != nullptr);
3246 assert(node->child(i)->parent() == node);
3247 assert(node->child(i)->position() == i);
3248 count += internal_verify(
3249 node->child(i),
3250 (i == 0) ? lo : &node->key(i - 1),
3251 (i == node->count()) ? hi : &node->key(i));
3252 }
3253 }
3254 return count;
3255 }
3256
3257 // A common base class for btree_set, btree_map, btree_multiset, and btree_multimap.
3258 // ---------------------------------------------------------------------------------
3259 template <typename Tree>
3260 class btree_container {
3261 using params_type = typename Tree::params_type;
3262
3263 protected:
3264 // Alias used for heterogeneous lookup functions.
3265 // `key_arg<K>` evaluates to `K` when the functors are transparent and to
3266 // `key_type` otherwise. It permits template argument deduction on `K` for the
3267 // transparent case.
3268 template <class K>
3269 using key_arg =
3270 typename KeyArg<IsTransparent<typename Tree::key_compare>::value>::
3271 template type<K, typename Tree::key_type>;
3272
3273 public:
3274 using key_type = typename Tree::key_type;
3275 using value_type = typename Tree::value_type;
3276 using size_type = typename Tree::size_type;
3277 using difference_type = typename Tree::difference_type;
3278 using key_compare = typename Tree::key_compare;
3279 using value_compare = typename Tree::value_compare;
3280 using allocator_type = typename Tree::allocator_type;
3281 using reference = typename Tree::reference;
3282 using const_reference = typename Tree::const_reference;
3283 using pointer = typename Tree::pointer;
3284 using const_pointer = typename Tree::const_pointer;
3285 using iterator = typename Tree::iterator;
3286 using const_iterator = typename Tree::const_iterator;
3287 using reverse_iterator = typename Tree::reverse_iterator;
3288 using const_reverse_iterator = typename Tree::const_reverse_iterator;
3289 using node_type = typename Tree::node_handle_type;
3290
3291 // Constructors/assignments.
3292 btree_container() : tree_(key_compare(), allocator_type()) {}
3293 explicit btree_container(const key_compare &comp,
3294 const allocator_type &alloc = allocator_type())
3295 : tree_(comp, alloc) {}
3296 btree_container(const btree_container &x) = default;
3297 btree_container(btree_container &&x) noexcept = default;
3298 btree_container &operator=(const btree_container &x) = default;
3299 btree_container &operator=(btree_container &&x) noexcept(
3300 std::is_nothrow_move_assignable<Tree>::value) = default;
3301
3302 // Iterator routines.
3303 iterator begin() { return tree_.begin(); }
3304 const_iterator begin() const { return tree_.begin(); }
3305 const_iterator cbegin() const { return tree_.begin(); }
3306 iterator end() { return tree_.end(); }
3307 const_iterator end() const { return tree_.end(); }
3308 const_iterator cend() const { return tree_.end(); }
3309 reverse_iterator rbegin() { return tree_.rbegin(); }
3310 const_reverse_iterator rbegin() const { return tree_.rbegin(); }
3311 const_reverse_iterator crbegin() const { return tree_.rbegin(); }
3312 reverse_iterator rend() { return tree_.rend(); }
3313 const_reverse_iterator rend() const { return tree_.rend(); }
3314 const_reverse_iterator crend() const { return tree_.rend(); }
3315
3316 // Lookup routines.
3317 template <typename K = key_type>
3318 iterator find(const key_arg<K> &key) {
3319 return tree_.find(key);
3320 }
3321 template <typename K = key_type>
3322 const_iterator find(const key_arg<K> &key) const { return tree_.find(key); }
3323
3324 template <typename K = key_type>
3325 bool contains(const key_arg<K> &key) const { return find(key) != end(); }
3326
3327 template <typename K = key_type>
3328 iterator lower_bound(const key_arg<K> &key) { return tree_.lower_bound(key); }
3329
3330 template <typename K = key_type>
3331 const_iterator lower_bound(const key_arg<K> &key) const { return tree_.lower_bound(key); }
3332
3333 template <typename K = key_type>
3334 iterator upper_bound(const key_arg<K> &key) { return tree_.upper_bound(key); }
3335
3336 template <typename K = key_type>
3337 const_iterator upper_bound(const key_arg<K> &key) const { return tree_.upper_bound(key); }
3338
3339 template <typename K = key_type>
3340 std::pair<iterator, iterator> equal_range(const key_arg<K> &key) { return tree_.equal_range(key); }
3341
3342 template <typename K = key_type>
3343 std::pair<const_iterator, const_iterator> equal_range(
3344 const key_arg<K> &key) const {
3345 return tree_.equal_range(key);
3346 }
3347
3348 iterator erase(const_iterator iter) { return tree_.erase(iterator(iter)); }
3349 iterator erase(iterator iter) { return tree_.erase(iter); }
3350 iterator erase(const_iterator first, const_iterator last) {
3351 return tree_.erase(iterator(first), iterator(last)).second;
3352 }
3353
3354 node_type extract(iterator position) {
3355 // Use Move instead of Transfer, because the rebalancing code expects to
3356 // have a valid object to scribble metadata bits on top of.
3357 auto node = CommonAccess::Move<node_type>(get_allocator(), position.slot());
3358 erase(position);
3359 return node;
3360 }
3361
3362 node_type extract(const_iterator position) {
3363 return extract(iterator(position));
3364 }
3365
3366 public:
3367 void clear() { tree_.clear(); }
3368 void swap(btree_container &x) { tree_.swap(x.tree_); }
3369 void verify() const { tree_.verify(); }
3370
3371 size_type size() const { return tree_.size(); }
3372 size_type max_size() const { return tree_.max_size(); }
3373 bool empty() const { return tree_.empty(); }
3374
3375 friend bool operator==(const btree_container &x, const btree_container &y) {
3376 if (x.size() != y.size()) return false;
3377 return std::equal(x.begin(), x.end(), y.begin());
3378 }
3379
3380 friend bool operator!=(const btree_container &x, const btree_container &y) { return !(x == y); }
3381
3382 friend bool operator<(const btree_container &x, const btree_container &y) {
3383 return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
3384 }
3385
3386 friend bool operator>(const btree_container &x, const btree_container &y) { return y < x; }
3387
3388 friend bool operator<=(const btree_container &x, const btree_container &y) { return !(y < x); }
3389
3390 friend bool operator>=(const btree_container &x, const btree_container &y) { return !(x < y); }
3391
3392 // The allocator used by the btree.
3393 allocator_type get_allocator() const { return tree_.get_allocator(); }
3394
3395 // The key comparator used by the btree.
3396 key_compare key_comp() const { return tree_.key_comp(); }
3397 value_compare value_comp() const { return tree_.value_comp(); }
3398
3399 // Support absl::Hash.
3400 template <typename State>
3401 friend State AbslHashValue(State h, const btree_container &b) {
3402 for (const auto &v : b) {
3403 h = State::combine(std::move(h), v);
3404 }
3405 return State::combine(std::move(h), b.size());
3406 }
3407
3408 protected:
3409 Tree tree_;
3410 };
3411
3412 // A common base class for btree_set and btree_map.
3413 // -----------------------------------------------
3414 template <typename Tree>
3415 class btree_set_container : public btree_container<Tree> {
3416 using super_type = btree_container<Tree>;
3417 using params_type = typename Tree::params_type;
3418 using init_type = typename params_type::init_type;
3419 using is_key_compare_to = typename params_type::is_key_compare_to;
3420 friend class BtreeNodePeer;
3421
3422 protected:
3423 template <class K>
3424 using key_arg = typename super_type::template key_arg<K>;
3425
3426 public:
3427 using key_type = typename Tree::key_type;
3428 using value_type = typename Tree::value_type;
3429 using size_type = typename Tree::size_type;
3430 using key_compare = typename Tree::key_compare;
3431 using allocator_type = typename Tree::allocator_type;
3432 using iterator = typename Tree::iterator;
3433 using const_iterator = typename Tree::const_iterator;
3434 using node_type = typename super_type::node_type;
3435 using insert_return_type = InsertReturnType<iterator, node_type>;
3436 using super_type::super_type;
3437 btree_set_container() {}
3438
3439 template <class InputIterator>
3440 btree_set_container(InputIterator b, InputIterator e,
3441 const key_compare &comp = key_compare(),
3442 const allocator_type &alloc = allocator_type())
3443 : super_type(comp, alloc) {
3444 insert(b, e);
3445 }
3446
3447 btree_set_container(std::initializer_list<init_type> init,
3448 const key_compare &comp = key_compare(),
3449 const allocator_type &alloc = allocator_type())
3450 : btree_set_container(init.begin(), init.end(), comp, alloc) {}
3451
3452 // Lookup routines.
3453 template <typename K = key_type>
3454 size_type count(const key_arg<K> &key) const {
3455 return this->tree_.count_unique(key);
3456 }
3457
3458 // Insertion routines.
3459 std::pair<iterator, bool> insert(const value_type &x) {
3460 return this->tree_.insert_unique(params_type::key(x), x);
3461 }
3462 std::pair<iterator, bool> insert(value_type &&x) {
3463 return this->tree_.insert_unique(params_type::key(x), std::move(x));
3464 }
3465 template <typename... Args>
3466 std::pair<iterator, bool> emplace(Args &&... args) {
3467 init_type v(std::forward<Args>(args)...);
3468 return this->tree_.insert_unique(params_type::key(v), std::move(v));
3469 }
3470 iterator insert(const_iterator position, const value_type &x) {
3471 return this->tree_
3472 .insert_hint_unique(iterator(position), params_type::key(x), x)
3473 .first;
3474 }
3475 iterator insert(const_iterator position, value_type &&x) {
3476 return this->tree_
3477 .insert_hint_unique(iterator(position), params_type::key(x),
3478 std::move(x))
3479 .first;
3480 }
3481
3482 template <typename... Args>
3483 iterator emplace_hint(const_iterator position, Args &&... args) {
3484 init_type v(std::forward<Args>(args)...);
3485 return this->tree_
3486 .insert_hint_unique(iterator(position), params_type::key(v),
3487 std::move(v))
3488 .first;
3489 }
3490
3491 template <typename InputIterator>
3492 void insert(InputIterator b, InputIterator e) {
3493 this->tree_.insert_iterator_unique(b, e);
3494 }
3495
3496 void insert(std::initializer_list<init_type> init) {
3497 this->tree_.insert_iterator_unique(init.begin(), init.end());
3498 }
3499
3500 insert_return_type insert(node_type &&node) {
3501 if (!node) return {this->end(), false, node_type()};
3502 std::pair<iterator, bool> res =
3503 this->tree_.insert_unique(params_type::key(CommonAccess::GetSlot(node)),
3504 CommonAccess::GetSlot(node));
3505 if (res.second) {
3506 CommonAccess::Destroy(&node);
3507 return {res.first, true, node_type()};
3508 } else {
3509 return {res.first, false, std::move(node)};
3510 }
3511 }
3512
3513 iterator insert(const_iterator hint, node_type &&node) {
3514 if (!node) return this->end();
3515 std::pair<iterator, bool> res = this->tree_.insert_hint_unique(
3516 iterator(hint), params_type::key(CommonAccess::GetSlot(node)),
3517 CommonAccess::GetSlot(node));
3518 if (res.second) CommonAccess::Destroy(&node);
3519 return res.first;
3520 }
3521
3522 template <typename K = key_type>
3523 size_type erase(const key_arg<K> &key) { return this->tree_.erase_unique(key); }
3524 using super_type::erase;
3525
3526 template <typename K = key_type>
3527 node_type extract(const key_arg<K> &key) {
3528 auto it = this->find(key);
3529 return it == this->end() ? node_type() : extract(it);
3530 }
3531
3532 using super_type::extract;
3533
3534 // Merge routines.
3535 // Moves elements from `src` into `this`. If the element already exists in
3536 // `this`, it is left unmodified in `src`.
3537 template <
3538 typename T,
3539 typename phmap::enable_if_t<
3541 std::is_same<value_type, typename T::value_type>,
3542 std::is_same<allocator_type, typename T::allocator_type>,
3543 std::is_same<typename params_type::is_map_container,
3544 typename T::params_type::is_map_container>>::value,
3545 int> = 0>
3546 void merge(btree_container<T> &src) { // NOLINT
3547 for (auto src_it = src.begin(); src_it != src.end();) {
3548 if (insert(std::move(*src_it)).second) {
3549 src_it = src.erase(src_it);
3550 } else {
3551 ++src_it;
3552 }
3553 }
3554 }
3555
3556 template <
3557 typename T,
3558 typename phmap::enable_if_t<
3560 std::is_same<value_type, typename T::value_type>,
3561 std::is_same<allocator_type, typename T::allocator_type>,
3562 std::is_same<typename params_type::is_map_container,
3563 typename T::params_type::is_map_container>>::value,
3564 int> = 0>
3565 void merge(btree_container<T> &&src) {
3566 merge(src);
3567 }
3568 };
3569
3570 // Base class for btree_map.
3571 // -------------------------
3572 template <typename Tree>
3573 class btree_map_container : public btree_set_container<Tree> {
3574 using super_type = btree_set_container<Tree>;
3575 using params_type = typename Tree::params_type;
3576
3577 protected:
3578 template <class K>
3579 using key_arg = typename super_type::template key_arg<K>;
3580
3581 public:
3582 using key_type = typename Tree::key_type;
3583 using mapped_type = typename params_type::mapped_type;
3584 using value_type = typename Tree::value_type;
3585 using key_compare = typename Tree::key_compare;
3586 using allocator_type = typename Tree::allocator_type;
3587 using iterator = typename Tree::iterator;
3588 using const_iterator = typename Tree::const_iterator;
3589
3590 // Inherit constructors.
3591 using super_type::super_type;
3592 btree_map_container() {}
3593
3594 // Insertion routines.
3595 template <typename... Args>
3596 std::pair<iterator, bool> try_emplace(const key_type &k, Args &&... args) {
3597 return this->tree_.insert_unique(
3598 k, std::piecewise_construct, std::forward_as_tuple(k),
3599 std::forward_as_tuple(std::forward<Args>(args)...));
3600 }
3601 template <typename... Args>
3602 std::pair<iterator, bool> try_emplace(key_type &&k, Args &&... args) {
3603 // Note: `key_ref` exists to avoid a ClangTidy warning about moving from `k`
3604 // and then using `k` unsequenced. This is safe because the move is into a
3605 // forwarding reference and insert_unique guarantees that `key` is never
3606 // referenced after consuming `args`.
3607 const key_type& key_ref = k;
3608 return this->tree_.insert_unique(
3609 key_ref, std::piecewise_construct, std::forward_as_tuple(std::move(k)),
3610 std::forward_as_tuple(std::forward<Args>(args)...));
3611 }
3612 template <typename... Args>
3613 iterator try_emplace(const_iterator hint, const key_type &k,
3614 Args &&... args) {
3615 return this->tree_
3616 .insert_hint_unique(iterator(hint), k, std::piecewise_construct,
3617 std::forward_as_tuple(k),
3618 std::forward_as_tuple(std::forward<Args>(args)...))
3619 .first;
3620 }
3621 template <typename... Args>
3622 iterator try_emplace(const_iterator hint, key_type &&k, Args &&... args) {
3623 // Note: `key_ref` exists to avoid a ClangTidy warning about moving from `k`
3624 // and then using `k` unsequenced. This is safe because the move is into a
3625 // forwarding reference and insert_hint_unique guarantees that `key` is
3626 // never referenced after consuming `args`.
3627 const key_type& key_ref = k;
3628 return this->tree_
3629 .insert_hint_unique(iterator(hint), key_ref, std::piecewise_construct,
3630 std::forward_as_tuple(std::move(k)),
3631 std::forward_as_tuple(std::forward<Args>(args)...))
3632 .first;
3633 }
3634 mapped_type &operator[](const key_type &k) {
3635 return try_emplace(k).first->second;
3636 }
3637 mapped_type &operator[](key_type &&k) {
3638 return try_emplace(std::move(k)).first->second;
3639 }
3640
3641 template <typename K = key_type>
3642 mapped_type &at(const key_arg<K> &key) {
3643 auto it = this->find(key);
3644 if (it == this->end())
3645 base_internal::ThrowStdOutOfRange("phmap::btree_map::at");
3646 return it->second;
3647 }
3648 template <typename K = key_type>
3649 const mapped_type &at(const key_arg<K> &key) const {
3650 auto it = this->find(key);
3651 if (it == this->end())
3652 base_internal::ThrowStdOutOfRange("phmap::btree_map::at");
3653 return it->second;
3654 }
3655 };
3656
3657 // A common base class for btree_multiset and btree_multimap.
3658 template <typename Tree>
3659 class btree_multiset_container : public btree_container<Tree> {
3660 using super_type = btree_container<Tree>;
3661 using params_type = typename Tree::params_type;
3662 using init_type = typename params_type::init_type;
3663 using is_key_compare_to = typename params_type::is_key_compare_to;
3664
3665 template <class K>
3666 using key_arg = typename super_type::template key_arg<K>;
3667
3668 public:
3669 using key_type = typename Tree::key_type;
3670 using value_type = typename Tree::value_type;
3671 using size_type = typename Tree::size_type;
3672 using key_compare = typename Tree::key_compare;
3673 using allocator_type = typename Tree::allocator_type;
3674 using iterator = typename Tree::iterator;
3675 using const_iterator = typename Tree::const_iterator;
3676 using node_type = typename super_type::node_type;
3677
3678 // Inherit constructors.
3679 using super_type::super_type;
3680 btree_multiset_container() {}
3681
3682 // Range constructor.
3683 template <class InputIterator>
3684 btree_multiset_container(InputIterator b, InputIterator e,
3685 const key_compare &comp = key_compare(),
3686 const allocator_type &alloc = allocator_type())
3687 : super_type(comp, alloc) {
3688 insert(b, e);
3689 }
3690
3691 // Initializer list constructor.
3692 btree_multiset_container(std::initializer_list<init_type> init,
3693 const key_compare &comp = key_compare(),
3694 const allocator_type &alloc = allocator_type())
3695 : btree_multiset_container(init.begin(), init.end(), comp, alloc) {}
3696
3697 // Lookup routines.
3698 template <typename K = key_type>
3699 size_type count(const key_arg<K> &key) const {
3700 return this->tree_.count_multi(key);
3701 }
3702
3703 // Insertion routines.
3704 iterator insert(const value_type &x) { return this->tree_.insert_multi(x); }
3705 iterator insert(value_type &&x) {
3706 return this->tree_.insert_multi(std::move(x));
3707 }
3708 iterator insert(const_iterator position, const value_type &x) {
3709 return this->tree_.insert_hint_multi(iterator(position), x);
3710 }
3711 iterator insert(const_iterator position, value_type &&x) {
3712 return this->tree_.insert_hint_multi(iterator(position), std::move(x));
3713 }
3714 template <typename InputIterator>
3715 void insert(InputIterator b, InputIterator e) {
3716 this->tree_.insert_iterator_multi(b, e);
3717 }
3718 void insert(std::initializer_list<init_type> init) {
3719 this->tree_.insert_iterator_multi(init.begin(), init.end());
3720 }
3721 template <typename... Args>
3722 iterator emplace(Args &&... args) {
3723 return this->tree_.insert_multi(init_type(std::forward<Args>(args)...));
3724 }
3725 template <typename... Args>
3726 iterator emplace_hint(const_iterator position, Args &&... args) {
3727 return this->tree_.insert_hint_multi(
3728 iterator(position), init_type(std::forward<Args>(args)...));
3729 }
3730 iterator insert(node_type &&node) {
3731 if (!node) return this->end();
3732 iterator res =
3733 this->tree_.insert_multi(params_type::key(CommonAccess::GetSlot(node)),
3734 CommonAccess::GetSlot(node));
3735 CommonAccess::Destroy(&node);
3736 return res;
3737 }
3738 iterator insert(const_iterator hint, node_type &&node) {
3739 if (!node) return this->end();
3740 iterator res = this->tree_.insert_hint_multi(
3741 iterator(hint),
3742 std::move(params_type::element(CommonAccess::GetSlot(node))));
3743 CommonAccess::Destroy(&node);
3744 return res;
3745 }
3746
3747 // Deletion routines.
3748 template <typename K = key_type>
3749 size_type erase(const key_arg<K> &key) {
3750 return this->tree_.erase_multi(key);
3751 }
3752 using super_type::erase;
3753
3754 // Node extraction routines.
3755 template <typename K = key_type>
3756 node_type extract(const key_arg<K> &key) {
3757 auto it = this->find(key);
3758 return it == this->end() ? node_type() : extract(it);
3759 }
3760 using super_type::extract;
3761
3762 // Merge routines.
3763 // Moves all elements from `src` into `this`.
3764 template <
3765 typename T,
3766 typename phmap::enable_if_t<
3768 std::is_same<value_type, typename T::value_type>,
3769 std::is_same<allocator_type, typename T::allocator_type>,
3770 std::is_same<typename params_type::is_map_container,
3771 typename T::params_type::is_map_container>>::value,
3772 int> = 0>
3773 void merge(btree_container<T> &src) { // NOLINT
3774 insert(std::make_move_iterator(src.begin()),
3775 std::make_move_iterator(src.end()));
3776 src.clear();
3777 }
3778
3779 template <
3780 typename T,
3781 typename phmap::enable_if_t<
3783 std::is_same<value_type, typename T::value_type>,
3784 std::is_same<allocator_type, typename T::allocator_type>,
3785 std::is_same<typename params_type::is_map_container,
3786 typename T::params_type::is_map_container>>::value,
3787 int> = 0>
3788 void merge(btree_container<T> &&src) {
3789 merge(src);
3790 }
3791 };
3792
3793 // A base class for btree_multimap.
3794 template <typename Tree>
3795 class btree_multimap_container : public btree_multiset_container<Tree> {
3796 using super_type = btree_multiset_container<Tree>;
3797 using params_type = typename Tree::params_type;
3798
3799 public:
3800 using mapped_type = typename params_type::mapped_type;
3801
3802 // Inherit constructors.
3803 using super_type::super_type;
3804 btree_multimap_container() {}
3805 };
3806
3807} // namespace priv
3808
3809
3810
3811 // ----------------------------------------------------------------------
3812 // btree_set - default values in phmap_fwd_decl.h
3813 // ----------------------------------------------------------------------
3814 template <typename Key, typename Compare, typename Alloc>
3815 class btree_set : public priv::btree_set_container<
3816 priv::btree<priv::set_params<
3817 Key, Compare, Alloc, /*TargetNodeSize=*/ 256, /*Multi=*/ false>>>
3818 {
3819 using Base = typename btree_set::btree_set_container;
3820
3821 public:
3822 btree_set() {}
3823 using Base::Base;
3824 using Base::begin;
3825 using Base::cbegin;
3826 using Base::end;
3827 using Base::cend;
3828 using Base::empty;
3829 using Base::max_size;
3830 using Base::size;
3831 using Base::clear;
3832 using Base::erase;
3833 using Base::insert;
3834 using Base::emplace;
3835 using Base::emplace_hint;
3836 using Base::extract;
3837 using Base::merge;
3838 using Base::swap;
3839 using Base::contains;
3840 using Base::count;
3841 using Base::equal_range;
3842 using Base::find;
3843 using Base::get_allocator;
3844 using Base::key_comp;
3845 using Base::value_comp;
3846 };
3847
3848 // Swaps the contents of two `phmap::btree_set` containers.
3849 // -------------------------------------------------------
3850 template <typename K, typename C, typename A>
3851 void swap(btree_set<K, C, A> &x, btree_set<K, C, A> &y) {
3852 return x.swap(y);
3853 }
3854
3855 // Erases all elements that satisfy the predicate pred from the container.
3856 // ----------------------------------------------------------------------
3857 template <typename K, typename C, typename A, typename Pred>
3858 void erase_if(btree_set<K, C, A> &set, Pred pred) {
3859 for (auto it = set.begin(); it != set.end();) {
3860 if (pred(*it)) {
3861 it = set.erase(it);
3862 } else {
3863 ++it;
3864 }
3865 }
3866 }
3867
3868 // ----------------------------------------------------------------------
3869 // btree_multiset - default values in phmap_fwd_decl.h
3870 // ----------------------------------------------------------------------
3871 template <typename Key, typename Compare, typename Alloc>
3872 class btree_multiset : public priv::btree_multiset_container<
3873 priv::btree<priv::set_params<
3874 Key, Compare, Alloc, /*TargetNodeSize=*/ 256, /*Multi=*/ true>>>
3875 {
3876 using Base = typename btree_multiset::btree_multiset_container;
3877
3878 public:
3879 btree_multiset() {}
3880 using Base::Base;
3881 using Base::begin;
3882 using Base::cbegin;
3883 using Base::end;
3884 using Base::cend;
3885 using Base::empty;
3886 using Base::max_size;
3887 using Base::size;
3888 using Base::clear;
3889 using Base::erase;
3890 using Base::insert;
3891 using Base::emplace;
3892 using Base::emplace_hint;
3893 using Base::extract;
3894 using Base::merge;
3895 using Base::swap;
3896 using Base::contains;
3897 using Base::count;
3898 using Base::equal_range;
3899 using Base::find;
3900 using Base::get_allocator;
3901 using Base::key_comp;
3902 using Base::value_comp;
3903 };
3904
3905 // Swaps the contents of two `phmap::btree_multiset` containers.
3906 // ------------------------------------------------------------
3907 template <typename K, typename C, typename A>
3908 void swap(btree_multiset<K, C, A> &x, btree_multiset<K, C, A> &y) {
3909 return x.swap(y);
3910 }
3911
3912 // Erases all elements that satisfy the predicate pred from the container.
3913 // ----------------------------------------------------------------------
3914 template <typename K, typename C, typename A, typename Pred>
3915 void erase_if(btree_multiset<K, C, A> &set, Pred pred) {
3916 for (auto it = set.begin(); it != set.end();) {
3917 if (pred(*it)) {
3918 it = set.erase(it);
3919 } else {
3920 ++it;
3921 }
3922 }
3923 }
3924
3925
3926 // ----------------------------------------------------------------------
3927 // btree_map - default values in phmap_fwd_decl.h
3928 // ----------------------------------------------------------------------
3929 template <typename Key, typename Value, typename Compare, typename Alloc>
3930 class btree_map : public priv::btree_map_container<
3931 priv::btree<priv::map_params<
3932 Key, Value, Compare, Alloc, /*TargetNodeSize=*/ 256, /*Multi=*/ false>>>
3933 {
3934 using Base = typename btree_map::btree_map_container;
3935
3936 public:
3937 btree_map() {}
3938 using Base::Base;
3939 using Base::begin;
3940 using Base::cbegin;
3941 using Base::end;
3942 using Base::cend;
3943 using Base::empty;
3944 using Base::max_size;
3945 using Base::size;
3946 using Base::clear;
3947 using Base::erase;
3948 using Base::insert;
3949 using Base::emplace;
3950 using Base::emplace_hint;
3951 using Base::try_emplace;
3952 using Base::extract;
3953 using Base::merge;
3954 using Base::swap;
3955 using Base::at;
3956 using Base::contains;
3957 using Base::count;
3958 using Base::equal_range;
3959 using Base::find;
3960 using Base::operator[];
3961 using Base::get_allocator;
3962 using Base::key_comp;
3963 using Base::value_comp;
3964 };
3965
3966 // Swaps the contents of two `phmap::btree_map` containers.
3967 // -------------------------------------------------------
3968 template <typename K, typename V, typename C, typename A>
3969 void swap(btree_map<K, V, C, A> &x, btree_map<K, V, C, A> &y) {
3970 return x.swap(y);
3971 }
3972
3973 // ----------------------------------------------------------------------
3974 template <typename K, typename V, typename C, typename A, typename Pred>
3975 void erase_if(btree_map<K, V, C, A> &map, Pred pred) {
3976 for (auto it = map.begin(); it != map.end();) {
3977 if (pred(*it)) {
3978 it = map.erase(it);
3979 } else {
3980 ++it;
3981 }
3982 }
3983 }
3984
3985 // ----------------------------------------------------------------------
3986 // btree_multimap - default values in phmap_fwd_decl.h
3987 // ----------------------------------------------------------------------
3988 template <typename Key, typename Value, typename Compare, typename Alloc>
3989 class btree_multimap : public priv::btree_multimap_container<
3990 priv::btree<priv::map_params<
3991 Key, Value, Compare, Alloc, /*TargetNodeSize=*/ 256, /*Multi=*/ true>>>
3992 {
3993 using Base = typename btree_multimap::btree_multimap_container;
3994
3995 public:
3996 btree_multimap() {}
3997 using Base::Base;
3998 using Base::begin;
3999 using Base::cbegin;
4000 using Base::end;
4001 using Base::cend;
4002 using Base::empty;
4003 using Base::max_size;
4004 using Base::size;
4005 using Base::clear;
4006 using Base::erase;
4007 using Base::insert;
4008 using Base::emplace;
4009 using Base::emplace_hint;
4010 using Base::extract;
4011 using Base::merge;
4012 using Base::swap;
4013 using Base::contains;
4014 using Base::count;
4015 using Base::equal_range;
4016 using Base::find;
4017 using Base::get_allocator;
4018 using Base::key_comp;
4019 using Base::value_comp;
4020 };
4021
4022 // Swaps the contents of two `phmap::btree_multimap` containers.
4023 // ------------------------------------------------------------
4024 template <typename K, typename V, typename C, typename A>
4025 void swap(btree_multimap<K, V, C, A> &x, btree_multimap<K, V, C, A> &y) {
4026 return x.swap(y);
4027 }
4028
4029 // Erases all elements that satisfy the predicate pred from the container.
4030 // ----------------------------------------------------------------------
4031 template <typename K, typename V, typename C, typename A, typename Pred>
4032 void erase_if(btree_multimap<K, V, C, A> &map, Pred pred) {
4033 for (auto it = map.begin(); it != map.end();) {
4034 if (pred(*it)) {
4035 it = map.erase(it);
4036 } else {
4037 ++it;
4038 }
4039 }
4040 }
4041
4042
4043} // namespace btree
4044
4045#ifdef _MSC_VER
4046 #pragma warning(pop)
4047#endif
4048
4049
4050#endif // PHMAP_BTREE_BTREE_CONTAINER_H_
Definition btree.h:400
Definition phmap_base.h:4293
Definition btree.h:353
Definition btree.h:571
Definition btree.h:317
Definition btree.h:488
int8 int8_t
Definition fwd.hpp:43
uint8 uint8_t
Definition fwd.hpp:103
uint16 uint16_t
Definition fwd.hpp:117
Definition phmap_base.h:85
Definition phmap_base.h:1379
Definition btree.h:223
Definition phmap_base.h:200
Definition phmap_base.h:163
Definition btree.h:141
Definition phmap_base.h:168
Definition phmap_base.h:242
Definition btree.h:193
Definition phmap_base.h:95
Definition phmap_base.h:134