2929#include < __cstddef/ptrdiff_t.h>
3030#include < __flat_map/key_value_iterator.h>
3131#include < __flat_map/sorted_unique.h>
32+ #include < __flat_map/utils.h>
3233#include < __functional/invoke.h>
3334#include < __functional/is_transparent.h>
3435#include < __functional/operations.h>
36+ #include < __fwd/vector.h>
3537#include < __iterator/concepts.h>
3638#include < __iterator/distance.h>
3739#include < __iterator/iterator_traits.h>
@@ -131,7 +133,7 @@ class flat_map {
131133 _LIBCPP_HIDE_FROM_ABI static constexpr bool __allocator_ctor_constraint =
132134 _And<uses_allocator<key_container_type, _Allocator>, uses_allocator<mapped_container_type, _Allocator>>::value;
133135
134- _LIBCPP_HIDE_FROM_ABI static constexpr bool __is_compare_transparent = __is_transparent_v<_Compare, _Compare >;
136+ _LIBCPP_HIDE_FROM_ABI static constexpr bool __is_compare_transparent = __is_transparent_v<_Compare>;
135137
136138public:
137139 // [flat.map.cons], construct/copy/destroy
@@ -153,7 +155,7 @@ class flat_map {
153155# if _LIBCPP_HAS_EXCEPTIONS
154156 } catch (...) {
155157 __other.clear ();
156- // gcc does not like the `throw` keyword in a conditional noexcept function
158+ // gcc does not like the `throw` keyword in a conditionally noexcept function
157159 if constexpr (!(is_nothrow_move_constructible_v<_KeyContainer> &&
158160 is_nothrow_move_constructible_v<_MappedContainer> && is_nothrow_move_constructible_v<_Compare>)) {
159161 throw ;
@@ -518,16 +520,16 @@ class flat_map {
518520 return emplace_hint (__hint, std::move (__x));
519521 }
520522
521- template <class _Pp >
522- requires is_constructible_v<pair<key_type, mapped_type>, _Pp >
523- _LIBCPP_HIDE_FROM_ABI pair<iterator, bool > insert (_Pp && __x) {
524- return emplace (std::forward<_Pp >(__x));
523+ template <class _PairLike >
524+ requires is_constructible_v<pair<key_type, mapped_type>, _PairLike >
525+ _LIBCPP_HIDE_FROM_ABI pair<iterator, bool > insert (_PairLike && __x) {
526+ return emplace (std::forward<_PairLike >(__x));
525527 }
526528
527- template <class _Pp >
528- requires is_constructible_v<pair<key_type, mapped_type>, _Pp >
529- _LIBCPP_HIDE_FROM_ABI iterator insert (const_iterator __hint, _Pp && __x) {
530- return emplace_hint (__hint, std::forward<_Pp >(__x));
529+ template <class _PairLike >
530+ requires is_constructible_v<pair<key_type, mapped_type>, _PairLike >
531+ _LIBCPP_HIDE_FROM_ABI iterator insert (const_iterator __hint, _PairLike && __x) {
532+ return emplace_hint (__hint, std::forward<_PairLike >(__x));
531533 }
532534
533535 template <class _InputIterator >
@@ -860,22 +862,10 @@ class flat_map {
860862 __containers_.values .erase (__containers_.values .begin () + __dist, __containers_.values .end ());
861863 }
862864
863- template <class _InputIterator , class _Sentinel >
864- _LIBCPP_HIDE_FROM_ABI size_type __append (_InputIterator __first, _Sentinel __last) {
865- size_type __num_of_appended = 0 ;
866- for (; __first != __last; ++__first) {
867- value_type __kv = *__first;
868- __containers_.keys .insert (__containers_.keys .end (), std::move (__kv.first ));
869- __containers_.values .insert (__containers_.values .end (), std::move (__kv.second ));
870- ++__num_of_appended;
871- }
872- return __num_of_appended;
873- }
874-
875865 template <bool _WasSorted, class _InputIterator , class _Sentinel >
876866 _LIBCPP_HIDE_FROM_ABI void __append_sort_merge_unique (_InputIterator __first, _Sentinel __last) {
877867 auto __on_failure = std::__make_exception_guard ([&]() noexcept { clear () /* noexcept */ ; });
878- size_t __num_of_appended = __append (std::move (__first), std::move (__last));
868+ size_t __num_of_appended = __flat_map_utils:: __append (* this , std::move (__first), std::move (__last));
879869 if (__num_of_appended != 0 ) {
880870 auto __zv = ranges::views::zip (__containers_.keys , __containers_.values );
881871 auto __append_start_offset = __containers_.keys .size () - __num_of_appended;
@@ -963,7 +953,8 @@ class flat_map {
963953
964954 if (__key_it == __containers_.keys .end () || __compare_ (__key, *__key_it)) {
965955 return pair<iterator, bool >(
966- __try_emplace_exact_hint (
956+ __flat_map_utils::__emplace_exact_pos (
957+ *this ,
967958 std::move (__key_it),
968959 std::move (__mapped_it),
969960 std::forward<_KeyArg>(__key),
@@ -989,10 +980,13 @@ class flat_map {
989980 _LIBCPP_HIDE_FROM_ABI pair<iterator, bool > __try_emplace_hint (const_iterator __hint, _Kp&& __key, _Args&&... __args) {
990981 if (__is_hint_correct (__hint, __key)) {
991982 if (__hint == cend () || __compare_ (__key, __hint->first )) {
992- return {
993- __try_emplace_exact_hint (
994- __hint.__key_iter_ , __hint.__mapped_iter_ , std::forward<_Kp>(__key), std::forward<_Args>(__args)...),
995- true };
983+ return {__flat_map_utils::__emplace_exact_pos (
984+ *this ,
985+ __hint.__key_iter_ ,
986+ __hint.__mapped_iter_ ,
987+ std::forward<_Kp>(__key),
988+ std::forward<_Args>(__args)...),
989+ true };
996990 } else {
997991 // key equals
998992 auto __dist = __hint - cbegin ();
@@ -1003,49 +997,6 @@ class flat_map {
1003997 }
1004998 }
1005999
1006- template <class _IterK , class _IterM , class _KeyArg , class ... _MArgs>
1007- _LIBCPP_HIDE_FROM_ABI iterator
1008- __try_emplace_exact_hint (_IterK&& __it_key, _IterM&& __it_mapped, _KeyArg&& __key, _MArgs&&... __mapped_args) {
1009- auto __on_key_failed = std::__make_exception_guard ([&]() noexcept {
1010- if constexpr (__container_traits<_KeyContainer>::__emplacement_has_strong_exception_safety_guarantee) {
1011- // Nothing to roll back!
1012- } else {
1013- // we need to clear both because we don't know the state of our keys anymore
1014- clear () /* noexcept */ ;
1015- }
1016- });
1017- auto __key_it = __containers_.keys .emplace (__it_key, std::forward<_KeyArg>(__key));
1018- __on_key_failed.__complete ();
1019-
1020- auto __on_value_failed = std::__make_exception_guard ([&]() noexcept {
1021- if constexpr (!__container_traits<_MappedContainer>::__emplacement_has_strong_exception_safety_guarantee) {
1022- // we need to clear both because we don't know the state of our values anymore
1023- clear () /* noexcept */ ;
1024- } else {
1025- // In this case, we know the values are just like before we attempted emplacement,
1026- // and we also know that the keys have been emplaced successfully. Just roll back the keys.
1027- # if _LIBCPP_HAS_EXCEPTIONS
1028- try {
1029- # endif // _LIBCPP_HAS_EXCEPTIONS
1030- __containers_.keys .erase (__key_it);
1031- # if _LIBCPP_HAS_EXCEPTIONS
1032- } catch (...) {
1033- // Now things are funky for real. We're failing to rollback the keys.
1034- // Just give up and clear the whole thing.
1035- //
1036- // Also, swallow the exception that happened during the rollback and let the
1037- // original value-emplacement exception propagate normally.
1038- clear () /* noexcept */ ;
1039- }
1040- # endif // _LIBCPP_HAS_EXCEPTIONS
1041- }
1042- });
1043- auto __mapped_it = __containers_.values .emplace (__it_mapped, std::forward<_MArgs>(__mapped_args)...);
1044- __on_value_failed.__complete ();
1045-
1046- return iterator (std::move (__key_it), std::move (__mapped_it));
1047- }
1048-
10491000 template <class _Kp , class _Mapped >
10501001 _LIBCPP_HIDE_FROM_ABI pair<iterator, bool > __insert_or_assign (_Kp&& __key, _Mapped&& __mapped) {
10511002 auto __r = try_emplace (std::forward<_Kp>(__key), std::forward<_Mapped>(__mapped));
@@ -1087,8 +1038,10 @@ class flat_map {
10871038 friend typename flat_map<_Key2, _Tp2, _Compare2, _KeyContainer2, _MappedContainer2>::size_type
10881039 erase_if (flat_map<_Key2, _Tp2, _Compare2, _KeyContainer2, _MappedContainer2>&, _Predicate);
10891040
1041+ friend __flat_map_utils;
1042+
10901043 containers __containers_;
1091- [[no_unique_address]] key_compare __compare_;
1044+ _LIBCPP_NO_UNIQUE_ADDRESS key_compare __compare_;
10921045
10931046 struct __key_equiv {
10941047 _LIBCPP_HIDE_FROM_ABI __key_equiv (key_compare __c) : __comp_(__c) {}
@@ -1187,22 +1140,20 @@ template <ranges::input_range _Range,
11871140 class _Compare = less<__range_key_type<_Range>>,
11881141 class _Allocator = allocator<byte>,
11891142 class = __enable_if_t <!__is_allocator<_Compare>::value && __is_allocator<_Allocator>::value>>
1190- flat_map (from_range_t , _Range&&, _Compare = _Compare (), _Allocator = _Allocator ())
1191- -> flat_map<
1192- __range_key_type<_Range>,
1193- __range_mapped_type<_Range>,
1194- _Compare,
1195- vector<__range_key_type<_Range>, __allocator_traits_rebind_t <_Allocator, __range_key_type<_Range>>>,
1196- vector<__range_mapped_type<_Range>, __allocator_traits_rebind_t <_Allocator, __range_mapped_type<_Range>>>>;
1143+ flat_map (from_range_t , _Range&&, _Compare = _Compare (), _Allocator = _Allocator ()) -> flat_map<
1144+ __range_key_type<_Range>,
1145+ __range_mapped_type<_Range>,
1146+ _Compare,
1147+ vector<__range_key_type<_Range>, __allocator_traits_rebind_t <_Allocator, __range_key_type<_Range>>>,
1148+ vector<__range_mapped_type<_Range>, __allocator_traits_rebind_t <_Allocator, __range_mapped_type<_Range>>>>;
11971149
11981150template <ranges::input_range _Range, class _Allocator , class = __enable_if_t <__is_allocator<_Allocator>::value>>
1199- flat_map (from_range_t , _Range&&, _Allocator)
1200- -> flat_map<
1201- __range_key_type<_Range>,
1202- __range_mapped_type<_Range>,
1203- less<__range_key_type<_Range>>,
1204- vector<__range_key_type<_Range>, __allocator_traits_rebind_t <_Allocator, __range_key_type<_Range>>>,
1205- vector<__range_mapped_type<_Range>, __allocator_traits_rebind_t <_Allocator, __range_mapped_type<_Range>>>>;
1151+ flat_map (from_range_t , _Range&&, _Allocator) -> flat_map<
1152+ __range_key_type<_Range>,
1153+ __range_mapped_type<_Range>,
1154+ less<__range_key_type<_Range>>,
1155+ vector<__range_key_type<_Range>, __allocator_traits_rebind_t <_Allocator, __range_key_type<_Range>>>,
1156+ vector<__range_mapped_type<_Range>, __allocator_traits_rebind_t <_Allocator, __range_mapped_type<_Range>>>>;
12061157
12071158template <class _Key , class _Tp , class _Compare = less<_Key>>
12081159 requires (!__is_allocator<_Compare>::value)
0 commit comments