2121#include < __algorithm/ranges_upper_bound.h>
2222#include < __compare/synth_three_way.h>
2323#include < __concepts/convertible_to.h>
24+ #include < __concepts/swappable.h>
2425#include < __config>
2526#include < __flat_map/container_traits.h>
2627#include < __flat_map/sorted_unique.h>
@@ -539,8 +540,8 @@ class flat_map {
539540 }
540541
541542 template <class _Kp >
542- requires __is_compare_transparent && is_constructible_v<key_type, _Kp> && is_constructible_v<mapped_type> &&
543- is_convertible_v<_Kp&&, const_iterator> && is_convertible_v<_Kp&&, iterator>
543+ requires ( __is_compare_transparent && is_constructible_v<key_type, _Kp> && is_constructible_v<mapped_type> &&
544+ ! is_convertible_v<_Kp &&, const_iterator> && ! is_convertible_v<_Kp &&, iterator>)
544545 _LIBCPP_HIDE_FROM_ABI mapped_type& operator [](_Kp&& __x) {
545546 return try_emplace (std::forward<_Kp>(__x)).first ->second ;
546547 }
@@ -597,7 +598,7 @@ class flat_map {
597598 requires is_constructible_v<pair<key_type, mapped_type>, _Args...>
598599 _LIBCPP_HIDE_FROM_ABI iterator emplace_hint (const_iterator __hint, _Args&&... __args) {
599600 std::pair<key_type, mapped_type> __pair (std::forward<_Args>(__args)...);
600- return __try_emplace_hint (__hint, std::move (__pair.first ), std::move (__pair.second ));
601+ return __try_emplace_hint (__hint, std::move (__pair.first ), std::move (__pair.second )). first ;
601602 }
602603
603604 _LIBCPP_HIDE_FROM_ABI pair<iterator, bool > insert (const value_type& __x) { return emplace (__x); }
@@ -689,67 +690,67 @@ class flat_map {
689690 }
690691
691692 template <class _Kp , class ... _Args>
692- requires __is_compare_transparent && is_constructible_v<key_type, _Kp> &&
693- is_constructible_v<mapped_type, _Args...> && is_convertible_v<_Kp&&, const_iterator> &&
694- is_convertible_v<_Kp&&, iterator>
693+ requires ( __is_compare_transparent && is_constructible_v<key_type, _Kp> &&
694+ is_constructible_v<mapped_type, _Args...> && ! is_convertible_v<_Kp &&, const_iterator> &&
695+ ! is_convertible_v<_Kp &&, iterator>)
695696 _LIBCPP_HIDE_FROM_ABI pair<iterator, bool > try_emplace (_Kp&& __key, _Args&&... __args) {
696697 return __try_emplace (std::forward<_Kp>(__key), std::forward<_Args>(__args)...);
697698 }
698699
699700 template <class ... _Args>
700701 requires is_constructible_v<mapped_type, _Args...>
701702 _LIBCPP_HIDE_FROM_ABI iterator try_emplace (const_iterator __hint, const key_type& __key, _Args&&... __args) {
702- return __try_emplace_hint (__hint, __key, std::forward<_Args>(__args)...);
703+ return __try_emplace_hint (__hint, __key, std::forward<_Args>(__args)...). first ;
703704 }
704705
705706 template <class ... _Args>
706707 requires is_constructible_v<mapped_type, _Args...>
707708 _LIBCPP_HIDE_FROM_ABI iterator try_emplace (const_iterator __hint, key_type&& __key, _Args&&... __args) {
708- return __try_emplace_hint (__hint, std::move (__key), std::forward<_Args>(__args)...);
709+ return __try_emplace_hint (__hint, std::move (__key), std::forward<_Args>(__args)...). first ;
709710 }
710711
711712 template <class _Kp , class ... _Args>
712713 requires __is_compare_transparent && is_constructible_v<key_type, _Kp> && is_constructible_v<mapped_type, _Args...>
713714 _LIBCPP_HIDE_FROM_ABI iterator try_emplace (const_iterator __hint, _Kp&& __key, _Args&&... __args) {
714- return __try_emplace_hint (__hint, std::forward<_Kp>(__key), std::forward<_Args>(__args)...);
715+ return __try_emplace_hint (__hint, std::forward<_Kp>(__key), std::forward<_Args>(__args)...). first ;
715716 }
716717
717718 template <class _Mapped >
718719 requires is_assignable_v<mapped_type&, _Mapped> && is_constructible_v<mapped_type, _Mapped>
719720 _LIBCPP_HIDE_FROM_ABI pair<iterator, bool > insert_or_assign (const key_type& __key, _Mapped&& __obj) {
720- return __insert_or_assign_impl (__key, std::forward<_Mapped>(__obj));
721+ return __insert_or_assign (__key, std::forward<_Mapped>(__obj));
721722 }
722723
723724 template <class _Mapped >
724725 requires is_assignable_v<mapped_type&, _Mapped> && is_constructible_v<mapped_type, _Mapped>
725726 _LIBCPP_HIDE_FROM_ABI pair<iterator, bool > insert_or_assign (key_type&& __key, _Mapped&& __obj) {
726- return __insert_or_assign_impl (std::move (__key), std::forward<_Mapped>(__obj));
727+ return __insert_or_assign (std::move (__key), std::forward<_Mapped>(__obj));
727728 }
728729
729730 template <class _Kp , class _Mapped >
730731 requires __is_compare_transparent && is_constructible_v<key_type, _Kp> && is_assignable_v<mapped_type&, _Mapped> &&
731732 is_constructible_v<mapped_type, _Mapped>
732733 _LIBCPP_HIDE_FROM_ABI pair<iterator, bool > insert_or_assign (_Kp&& __key, _Mapped&& __obj) {
733- return __insert_or_assign_impl (std::forward<_Kp>(__key), std::forward<_Mapped>(__obj));
734+ return __insert_or_assign (std::forward<_Kp>(__key), std::forward<_Mapped>(__obj));
734735 }
735736
736737 template <class _Mapped >
737738 requires is_assignable_v<mapped_type&, _Mapped> && is_constructible_v<mapped_type, _Mapped>
738739 _LIBCPP_HIDE_FROM_ABI iterator insert_or_assign (const_iterator __hint, const key_type& __key, _Mapped&& __obj) {
739- return __insert_or_assign_impl ( __key, std::forward<_Mapped>(__obj), __hint). first ;
740+ return __insert_or_assign (__hint, __key, std::forward<_Mapped>(__obj)) ;
740741 }
741742
742743 template <class _Mapped >
743744 requires is_assignable_v<mapped_type&, _Mapped> && is_constructible_v<mapped_type, _Mapped>
744745 _LIBCPP_HIDE_FROM_ABI iterator insert_or_assign (const_iterator __hint, key_type&& __key, _Mapped&& __obj) {
745- return __insert_or_assign_impl ( std::move (__key), std::forward<_Mapped>(__obj), __hint). first ;
746+ return __insert_or_assign (__hint, std::move (__key), std::forward<_Mapped>(__obj)) ;
746747 }
747748
748749 template <class _Kp , class _Mapped >
749750 requires __is_compare_transparent && is_constructible_v<key_type, _Kp> && is_assignable_v<mapped_type&, _Mapped> &&
750751 is_constructible_v<mapped_type, _Mapped>
751752 _LIBCPP_HIDE_FROM_ABI iterator insert_or_assign (const_iterator __hint, _Kp&& __key, _Mapped&& __obj) {
752- return __insert_or_assign_impl ( std::forward<_Kp>(__key), std::forward<_Mapped>(__obj), __hint). first ;
753+ return __insert_or_assign (__hint, std::forward<_Kp>(__key), std::forward<_Mapped>(__obj)) ;
753754 }
754755
755756 _LIBCPP_HIDE_FROM_ABI iterator erase (iterator __position) {
@@ -788,15 +789,20 @@ class flat_map {
788789 }
789790
790791 _LIBCPP_HIDE_FROM_ABI void swap (flat_map& __y) noexcept {
791- auto __guard = std::__make_exception_guard ([&]() noexcept {
792+ # ifndef _LIBCPP_HAS_NO_EXCEPTIONS
793+ try {
794+ # endif
795+ ranges::swap (__compare_, __y.__compare_ );
796+ ranges::swap (__containers_.keys , __y.__containers_ .keys );
797+ ranges::swap (__containers_.values , __y.__containers_ .values );
798+ # ifndef _LIBCPP_HAS_NO_EXCEPTIONS
799+ } catch (...) {
800+ // todo: how can we tell the user that the swap is unsuccessful?
801+ // need to swallow the exception because the function is noexcept
792802 clear () /* noexcept */ ;
793803 __y.clear () /* noexcept*/ ;
794- });
795- using std::swap;
796- swap (__compare_, __y.__compare_ );
797- swap (__containers_.keys , __y.__containers_ .keys );
798- swap (__containers_.values , __y.__containers_ .values );
799- __guard.__complete ();
804+ }
805+ # endif
800806 }
801807
802808 _LIBCPP_HIDE_FROM_ABI void clear () noexcept {
@@ -807,6 +813,8 @@ class flat_map {
807813 // observers
808814 _LIBCPP_HIDE_FROM_ABI key_compare key_comp () const { return __compare_; }
809815 _LIBCPP_HIDE_FROM_ABI value_compare value_comp () const { return value_compare (__compare_); }
816+
817+ // todo: can flat_map | std::views::keys be specialised?
810818 _LIBCPP_HIDE_FROM_ABI const key_container_type& keys () const noexcept { return __containers_.keys ; }
811819 _LIBCPP_HIDE_FROM_ABI const mapped_container_type& values () const noexcept { return __containers_.values ; }
812820
@@ -912,10 +920,10 @@ class flat_map {
912920
913921private:
914922 struct __ctor_uses_allocator_tag {
915- explicit __ctor_uses_allocator_tag () = default;
923+ explicit _LIBCPP_HIDE_FROM_ABI __ctor_uses_allocator_tag () = default;
916924 };
917925 struct __ctor_uses_allocator_empty_tag {
918- explicit __ctor_uses_allocator_empty_tag () = default;
926+ explicit _LIBCPP_HIDE_FROM_ABI __ctor_uses_allocator_empty_tag () = default;
919927 };
920928
921929 template <class _Allocator , class _KeyCont , class _MappedCont , class ... _CompArg>
@@ -1085,18 +1093,20 @@ class flat_map {
10851093 }
10861094
10871095 template <class _Kp , class ... _Args>
1088- _LIBCPP_HIDE_FROM_ABI iterator __try_emplace_hint (const_iterator __hint, _Kp&& __key, _Args&&... __args) {
1096+ _LIBCPP_HIDE_FROM_ABI pair< iterator, bool > __try_emplace_hint (const_iterator __hint, _Kp&& __key, _Args&&... __args) {
10891097 if (__is_hint_correct (__hint, __key)) {
10901098 if (__hint == cend () || __compare_ (__key, __hint->first )) {
1091- return __try_emplace_exact_hint (
1092- __hint.__key_iter_ , __hint.__mapped_iter_ , std::forward<_Kp>(__key), std::forward<_Args>(__args)...);
1099+ return {
1100+ __try_emplace_exact_hint (
1101+ __hint.__key_iter_ , __hint.__mapped_iter_ , std::forward<_Kp>(__key), std::forward<_Args>(__args)...),
1102+ true };
10931103 } else {
10941104 // key equals
10951105 auto __dist = __hint - cbegin ();
1096- return iterator (__containers_.keys .begin () + __dist, __containers_.values .begin () + __dist);
1106+ return { iterator (__containers_.keys .begin () + __dist, __containers_.values .begin () + __dist), false } ;
10971107 }
10981108 } else {
1099- return __try_emplace (std::forward<_Kp>(__key), std::forward<_Args>(__args)...). first ;
1109+ return __try_emplace (std::forward<_Kp>(__key), std::forward<_Args>(__args)...);
11001110 }
11011111 }
11021112
@@ -1139,15 +1149,24 @@ class flat_map {
11391149 return iterator (std::move (__key_it), std::move (__mapped_it));
11401150 }
11411151
1142- template <class _Kp , class _Mapped , class ... _Hint >
1143- _LIBCPP_HIDE_FROM_ABI auto __insert_or_assign_impl (_Kp&& __key, _Mapped&& __mapped, _Hint&&... __hint ) {
1144- auto __r = try_emplace (__hint..., std::forward<_Kp>(__key), std::forward<_Mapped>(__mapped));
1152+ template <class _Kp , class _Mapped >
1153+ _LIBCPP_HIDE_FROM_ABI pair<iterator, bool > __insert_or_assign (_Kp&& __key, _Mapped&& __mapped) {
1154+ auto __r = try_emplace (std::forward<_Kp>(__key), std::forward<_Mapped>(__mapped));
11451155 if (!__r.second ) {
11461156 __r.first ->second = std::forward<_Mapped>(__mapped);
11471157 }
11481158 return __r;
11491159 }
11501160
1161+ template <class _Kp , class _Mapped >
1162+ _LIBCPP_HIDE_FROM_ABI iterator __insert_or_assign (const_iterator __hint, _Kp&& __key, _Mapped&& __mapped) {
1163+ auto __r = __try_emplace_hint (__hint, std::forward<_Kp>(__key), std::forward<_Mapped>(__mapped));
1164+ if (!__r.second ) {
1165+ __r.first ->second = std::forward<_Mapped>(__mapped);
1166+ }
1167+ return __r.first ;
1168+ }
1169+
11511170 _LIBCPP_HIDE_FROM_ABI void __reserve (size_t __size) {
11521171 if constexpr (requires { __containers_.keys .reserve (__size); }) {
11531172 __containers_.keys .reserve (__size);
@@ -1175,8 +1194,8 @@ class flat_map {
11751194 [[no_unique_address]] key_compare __compare_;
11761195
11771196 struct __key_equiv {
1178- __key_equiv (key_compare __c) : __comp_(__c) {}
1179- bool operator ()(const_reference __x, const_reference __y) const {
1197+ _LIBCPP_HIDE_FROM_ABI __key_equiv (key_compare __c) : __comp_(__c) {}
1198+ _LIBCPP_HIDE_FROM_ABI bool operator ()(const_reference __x, const_reference __y) const {
11801199 // todo
11811200 // LWG issue ? spec uses __x.first but zip_view no longer uses pair
11821201 return !__comp_ (std::get<0 >(__x), std::get<0 >(__y)) && !__comp_ (std::get<0 >(__y), std::get<0 >(__x));
0 commit comments