@@ -21,18 +21,21 @@ namespace FlatContainerInternal {
2121 };
2222
2323 template <typename Left, typename Right, typename Compare>
24- [[nodiscard]] bool keys_equal (const Left& left, const Right& right, const Compare& compare)
24+ [[nodiscard]] bool sorted_keys_equal (const Left& left, const Right& right, [[maybe_unused]] const Compare& compare)
2525 {
2626 if constexpr (EqualityComparable<Left, Right>)
2727 return left == right;
2828 else
29- return !compare (left, right) && ! compare (right, left);
29+ return !compare (left, right); // Sortedness already established ! (right < left)
3030 }
3131
3232 template <typename Left, typename Right, typename Compare>
33- [[nodiscard]] bool ordering_equivalent (const Left& left , const Right& right, const Compare& compare)
33+ [[nodiscard]] bool lower_bound_matches (const Left& stored_key , const Right& query, [[maybe_unused]] const Compare& compare)
3434 {
35- return !compare (left, right) && !compare (right, left);
35+ if constexpr (EqualityComparable<Left, Right>)
36+ return stored_key == query;
37+ else
38+ return !compare (query, stored_key); // lower_bound already established !(stored_key < query)
3639 }
3740
3841 template <typename Key, typename Mapped, typename MappedReference>
@@ -323,6 +326,8 @@ class flat_map
323326 return { position, inserted };
324327 }
325328
329+ iterator erase (iterator position) { return erase (const_iterator (position)); }
330+
326331 iterator erase (const_iterator position)
327332 {
328333 assert_not_batching ();
@@ -437,25 +442,19 @@ class flat_map
437442 template <typename Query>
438443 [[nodiscard]] size_type find_index (const Query& key) const
439444 {
440- const auto first = lower_bound_index (key);
441- const auto last = upper_bound_index (key);
442- for (auto index = first; index < last; ++index) {
443- if (FlatContainerInternal::keys_equal (_keys[index], key, _compare))
444- return index;
445- }
445+ const auto index = lower_bound_index (key);
446+ if (index < size () && FlatContainerInternal::lower_bound_matches (_keys[index], key, _compare))
447+ return index;
446448 return size ();
447449 }
448450
449451 template <typename Query>
450452 [[nodiscard]] std::pair<size_type, size_type> find_or_insertion_index (const Query& key) const
451453 {
452- const auto first = lower_bound_index (key);
453- const auto last = upper_bound_index (key);
454- for (auto index = first; index < last; ++index) {
455- if (FlatContainerInternal::keys_equal (_keys[index], key, _compare))
456- return { index, last };
457- }
458- return { size (), last };
454+ const auto index = lower_bound_index (key);
455+ if (index < size () && FlatContainerInternal::lower_bound_matches (_keys[index], key, _compare))
456+ return { index, index };
457+ return { size (), index };
459458 }
460459
461460 void merge_sorted (std::vector<Key>&& incoming_keys, std::vector<Mapped>&& incoming_values)
@@ -469,73 +468,50 @@ class flat_map
469468 merged_keys.reserve (size () + incoming_keys.size ());
470469 merged_values.reserve (size () + incoming_values.size ());
471470
472- auto append_existing_group = [&](size_type first, size_type last) {
473- for (auto index = first; index < last; ++index) {
474- merged_keys.emplace_back (std::move (_keys[index]));
475- merged_values.emplace_back (std::move (_values[index]));
476- }
471+ auto append_existing = [&](size_type index) {
472+ merged_keys.emplace_back (std::move (_keys[index]));
473+ merged_values.emplace_back (std::move (_values[index]));
477474 };
478- auto append_incoming_group = [&](size_type first, size_type last, size_type merged_group_start) {
479- for (auto index = first; index < last; ++index) {
480- const auto duplicate = std::any_of (merged_keys.begin () + static_cast <difference_type>(merged_group_start), merged_keys.end (),
481- [&](const Key& key) { return FlatContainerInternal::keys_equal (key, incoming_keys[index], _compare); });
482- if (!duplicate) {
483- merged_keys.emplace_back (std::move (incoming_keys[index]));
484- merged_values.emplace_back (std::move (incoming_values[index]));
485- }
475+ auto append_incoming = [&](size_type index) {
476+ if (merged_keys.empty () || !FlatContainerInternal::sorted_keys_equal (merged_keys.back (), incoming_keys[index], _compare)) {
477+ merged_keys.emplace_back (std::move (incoming_keys[index]));
478+ merged_values.emplace_back (std::move (incoming_values[index]));
486479 }
487480 };
488481
489482 auto existing_index = size_type{ 0 };
490483 auto incoming_index = size_type{ 0 };
491- while (existing_index < size () || incoming_index < incoming_keys.size ()) {
492- if (existing_index == size ()) {
493- const auto incoming_group_end = ordering_group_end (incoming_keys, incoming_index);
494- const auto merged_group_start = merged_keys.size ();
495- append_incoming_group (incoming_index, incoming_group_end, merged_group_start);
496- incoming_index = incoming_group_end;
497- continue ;
498- }
499- if (incoming_index == incoming_keys.size ()) {
500- const auto existing_group_end = ordering_group_end (_keys, existing_index);
501- append_existing_group (existing_index, existing_group_end);
502- existing_index = existing_group_end;
503- continue ;
504- }
505-
506- if (_compare (_keys[existing_index], incoming_keys[incoming_index])) {
507- const auto existing_group_end = ordering_group_end (_keys, existing_index);
508- append_existing_group (existing_index, existing_group_end);
509- existing_index = existing_group_end;
510- } else if (_compare (incoming_keys[incoming_index], _keys[existing_index])) {
511- const auto incoming_group_end = ordering_group_end (incoming_keys, incoming_index);
512- const auto merged_group_start = merged_keys.size ();
513- append_incoming_group (incoming_index, incoming_group_end, merged_group_start);
514- incoming_index = incoming_group_end;
484+ while (existing_index < size () && incoming_index < incoming_keys.size ()) {
485+ if constexpr (FlatContainerInternal::EqualityComparable<Key, Key>) {
486+ if (_keys[existing_index] == incoming_keys[incoming_index]) {
487+ append_existing (existing_index++);
488+ ++incoming_index;
489+ } else if (_compare (_keys[existing_index], incoming_keys[incoming_index])) {
490+ append_existing (existing_index++);
491+ } else {
492+ assert (_compare (incoming_keys[incoming_index], _keys[existing_index]));
493+ append_incoming (incoming_index++);
494+ }
515495 } else {
516- const auto existing_group_end = ordering_group_end (_keys, existing_index);
517- const auto incoming_group_end = ordering_group_end (incoming_keys, incoming_index);
518- const auto merged_group_start = merged_keys.size ();
519- append_existing_group (existing_index, existing_group_end);
520- append_incoming_group (incoming_index, incoming_group_end, merged_group_start);
521- existing_index = existing_group_end;
522- incoming_index = incoming_group_end;
496+ if (_compare (_keys[existing_index], incoming_keys[incoming_index])) {
497+ append_existing (existing_index++);
498+ } else if (_compare (incoming_keys[incoming_index], _keys[existing_index])) {
499+ append_incoming (incoming_index++);
500+ } else {
501+ append_existing (existing_index++);
502+ ++incoming_index;
503+ }
523504 }
524505 }
506+ while (existing_index < size ())
507+ append_existing (existing_index++);
508+ while (incoming_index < incoming_keys.size ())
509+ append_incoming (incoming_index++);
525510
526511 _keys = std::move (merged_keys);
527512 _values = std::move (merged_values);
528513 }
529514
530- template <typename Keys>
531- [[nodiscard]] size_type ordering_group_end (const Keys& keys, size_type first) const
532- {
533- auto last = first + 1 ;
534- while (last < keys.size () && FlatContainerInternal::ordering_equivalent (keys[first], keys[last], _compare))
535- ++last;
536- return last;
537- }
538-
539515 std::vector<Key> _keys;
540516 std::vector<Mapped> _values;
541517 [[no_unique_address]] Compare _compare{};
@@ -694,25 +670,19 @@ class flat_set
694670 template <typename Query>
695671 [[nodiscard]] size_type find_index (const Query& key) const
696672 {
697- const auto first = lower_bound_index (key);
698- const auto last = upper_bound_index (key);
699- for (auto index = first; index < last; ++index) {
700- if (FlatContainerInternal::keys_equal (_keys[index], key, _compare))
701- return index;
702- }
673+ const auto index = lower_bound_index (key);
674+ if (index < size () && FlatContainerInternal::lower_bound_matches (_keys[index], key, _compare))
675+ return index;
703676 return size ();
704677 }
705678
706679 template <typename Query>
707680 [[nodiscard]] std::pair<size_type, size_type> find_or_insertion_index (const Query& key) const
708681 {
709- const auto first = lower_bound_index (key);
710- const auto last = upper_bound_index (key);
711- for (auto index = first; index < last; ++index) {
712- if (FlatContainerInternal::keys_equal (_keys[index], key, _compare))
713- return { index, last };
714- }
715- return { size (), last };
682+ const auto index = lower_bound_index (key);
683+ if (index < size () && FlatContainerInternal::lower_bound_matches (_keys[index], key, _compare))
684+ return { index, index };
685+ return { size (), index };
716686 }
717687
718688 void merge_sorted (std::vector<Key>&& incoming_keys)
@@ -723,64 +693,43 @@ class flat_set
723693 std::vector<Key> merged_keys;
724694 merged_keys.reserve (size () + incoming_keys.size ());
725695
726- auto append_incoming_group = [&](size_type first, size_type last, size_type merged_group_start) {
727- for (auto index = first; index < last; ++index) {
728- const auto duplicate = std::any_of (merged_keys.begin () + static_cast <difference_type>(merged_group_start), merged_keys.end (),
729- [&](const Key& key) { return FlatContainerInternal::keys_equal (key, incoming_keys[index], _compare); });
730- if (!duplicate)
731- merged_keys.emplace_back (std::move (incoming_keys[index]));
732- }
696+ auto append_incoming = [&](size_type index) {
697+ if (merged_keys.empty () || !FlatContainerInternal::sorted_keys_equal (merged_keys.back (), incoming_keys[index], _compare))
698+ merged_keys.emplace_back (std::move (incoming_keys[index]));
733699 };
734700
735701 auto existing_index = size_type{ 0 };
736702 auto incoming_index = size_type{ 0 };
737- while (existing_index < size () || incoming_index < incoming_keys.size ()) {
738- if (existing_index == size ()) {
739- const auto incoming_group_end = ordering_group_end (incoming_keys, incoming_index);
740- const auto merged_group_start = merged_keys.size ();
741- append_incoming_group (incoming_index, incoming_group_end, merged_group_start);
742- incoming_index = incoming_group_end;
743- continue ;
744- }
745- if (incoming_index == incoming_keys.size ()) {
746- const auto existing_group_end = ordering_group_end (_keys, existing_index);
747- for (; existing_index < existing_group_end; ++existing_index)
748- merged_keys.emplace_back (std::move (_keys[existing_index]));
749- continue ;
750- }
751-
752- if (_compare (_keys[existing_index], incoming_keys[incoming_index])) {
753- const auto existing_group_end = ordering_group_end (_keys, existing_index);
754- for (; existing_index < existing_group_end; ++existing_index)
755- merged_keys.emplace_back (std::move (_keys[existing_index]));
756- } else if (_compare (incoming_keys[incoming_index], _keys[existing_index])) {
757- const auto incoming_group_end = ordering_group_end (incoming_keys, incoming_index);
758- const auto merged_group_start = merged_keys.size ();
759- append_incoming_group (incoming_index, incoming_group_end, merged_group_start);
760- incoming_index = incoming_group_end;
703+ while (existing_index < size () && incoming_index < incoming_keys.size ()) {
704+ if constexpr (FlatContainerInternal::EqualityComparable<Key, Key>) {
705+ if (_keys[existing_index] == incoming_keys[incoming_index]) {
706+ merged_keys.emplace_back (std::move (_keys[existing_index++]));
707+ ++incoming_index;
708+ } else if (_compare (_keys[existing_index], incoming_keys[incoming_index])) {
709+ merged_keys.emplace_back (std::move (_keys[existing_index++]));
710+ } else {
711+ assert (_compare (incoming_keys[incoming_index], _keys[existing_index]));
712+ append_incoming (incoming_index++);
713+ }
761714 } else {
762- const auto existing_group_end = ordering_group_end (_keys, existing_index);
763- const auto incoming_group_end = ordering_group_end (incoming_keys, incoming_index);
764- const auto merged_group_start = merged_keys.size ();
765- for (; existing_index < existing_group_end; ++existing_index)
766- merged_keys.emplace_back (std::move (_keys[existing_index]));
767- append_incoming_group (incoming_index, incoming_group_end, merged_group_start);
768- incoming_index = incoming_group_end;
715+ if (_compare (_keys[existing_index], incoming_keys[incoming_index])) {
716+ merged_keys.emplace_back (std::move (_keys[existing_index++]));
717+ } else if (_compare (incoming_keys[incoming_index], _keys[existing_index])) {
718+ append_incoming (incoming_index++);
719+ } else {
720+ merged_keys.emplace_back (std::move (_keys[existing_index++]));
721+ ++incoming_index;
722+ }
769723 }
770724 }
725+ while (existing_index < size ())
726+ merged_keys.emplace_back (std::move (_keys[existing_index++]));
727+ while (incoming_index < incoming_keys.size ())
728+ append_incoming (incoming_index++);
771729
772730 _keys = std::move (merged_keys);
773731 }
774732
775- template <typename Keys>
776- [[nodiscard]] size_type ordering_group_end (const Keys& keys, size_type first) const
777- {
778- auto last = first + 1 ;
779- while (last < keys.size () && FlatContainerInternal::ordering_equivalent (keys[first], keys[last], _compare))
780- ++last;
781- return last;
782- }
783-
784733 std::vector<Key> _keys;
785734 [[no_unique_address]] Compare _compare{};
786735 // While a batch is open, only the prefix before _batch_start is ordered and searchable.
0 commit comments