Skip to content

Commit 932a123

Browse files
Hui Xiehuixie90
authored andcommitted
comments
1 parent 90a5d2d commit 932a123

File tree

10 files changed

+499
-136
lines changed

10 files changed

+499
-136
lines changed

libcxx/include/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,7 @@ set(files
365365
__flat_map/key_value_iterator.h
366366
__flat_map/sorted_unique.h
367367
__flat_map/sorted_equivalent.h
368+
__flat_map/utils.h
368369
__format/buffer.h
369370
__format/concepts.h
370371
__format/container_adaptor.h

libcxx/include/__flat_map/flat_map.h

Lines changed: 25 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
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>
@@ -860,22 +861,10 @@ class flat_map {
860861
__containers_.values.erase(__containers_.values.begin() + __dist, __containers_.values.end());
861862
}
862863

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-
875864
template <bool _WasSorted, class _InputIterator, class _Sentinel>
876865
_LIBCPP_HIDE_FROM_ABI void __append_sort_merge_unique(_InputIterator __first, _Sentinel __last) {
877866
auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });
878-
size_t __num_of_appended = __append(std::move(__first), std::move(__last));
867+
size_t __num_of_appended = __flat_map_utils::__append(*this, std::move(__first), std::move(__last));
879868
if (__num_of_appended != 0) {
880869
auto __zv = ranges::views::zip(__containers_.keys, __containers_.values);
881870
auto __append_start_offset = __containers_.keys.size() - __num_of_appended;
@@ -963,7 +952,8 @@ class flat_map {
963952

964953
if (__key_it == __containers_.keys.end() || __compare_(__key, *__key_it)) {
965954
return pair<iterator, bool>(
966-
__try_emplace_exact_hint(
955+
__flat_map_utils::__emplace_exact_pos(
956+
*this,
967957
std::move(__key_it),
968958
std::move(__mapped_it),
969959
std::forward<_KeyArg>(__key),
@@ -989,10 +979,13 @@ class flat_map {
989979
_LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __try_emplace_hint(const_iterator __hint, _Kp&& __key, _Args&&... __args) {
990980
if (__is_hint_correct(__hint, __key)) {
991981
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};
982+
return {__flat_map_utils::__emplace_exact_pos(
983+
*this,
984+
__hint.__key_iter_,
985+
__hint.__mapped_iter_,
986+
std::forward<_Kp>(__key),
987+
std::forward<_Args>(__args)...),
988+
true};
996989
} else {
997990
// key equals
998991
auto __dist = __hint - cbegin();
@@ -1003,49 +996,6 @@ class flat_map {
1003996
}
1004997
}
1005998

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-
1049999
template <class _Kp, class _Mapped>
10501000
_LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __insert_or_assign(_Kp&& __key, _Mapped&& __mapped) {
10511001
auto __r = try_emplace(std::forward<_Kp>(__key), std::forward<_Mapped>(__mapped));
@@ -1087,6 +1037,8 @@ class flat_map {
10871037
friend typename flat_map<_Key2, _Tp2, _Compare2, _KeyContainer2, _MappedContainer2>::size_type
10881038
erase_if(flat_map<_Key2, _Tp2, _Compare2, _KeyContainer2, _MappedContainer2>&, _Predicate);
10891039

1040+
friend __flat_map_utils;
1041+
10901042
containers __containers_;
10911043
[[no_unique_address]] key_compare __compare_;
10921044

@@ -1187,22 +1139,20 @@ template <ranges::input_range _Range,
11871139
class _Compare = less<__range_key_type<_Range>>,
11881140
class _Allocator = allocator<byte>,
11891141
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>>>>;
1142+
flat_map(from_range_t, _Range&&, _Compare = _Compare(), _Allocator = _Allocator()) -> flat_map<
1143+
__range_key_type<_Range>,
1144+
__range_mapped_type<_Range>,
1145+
_Compare,
1146+
vector<__range_key_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_key_type<_Range>>>,
1147+
vector<__range_mapped_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_mapped_type<_Range>>>>;
11971148

11981149
template <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>>>>;
1150+
flat_map(from_range_t, _Range&&, _Allocator) -> flat_map<
1151+
__range_key_type<_Range>,
1152+
__range_mapped_type<_Range>,
1153+
less<__range_key_type<_Range>>,
1154+
vector<__range_key_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_key_type<_Range>>>,
1155+
vector<__range_mapped_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_mapped_type<_Range>>>>;
12061156

12071157
template <class _Key, class _Tp, class _Compare = less<_Key>>
12081158
requires(!__is_allocator<_Compare>::value)

libcxx/include/__flat_map/flat_multimap.h

Lines changed: 8 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <__cstddef/ptrdiff_t.h>
3232
#include <__flat_map/key_value_iterator.h>
3333
#include <__flat_map/sorted_equivalent.h>
34+
#include <__flat_map/utils.h>
3435
#include <__functional/invoke.h>
3536
#include <__functional/is_transparent.h>
3637
#include <__functional/operations.h>
@@ -444,8 +445,8 @@ class flat_multimap {
444445
auto __key_it = ranges::upper_bound(__containers_.keys, __pair.first, __compare_);
445446
auto __mapped_it = __corresponding_mapped_it(*this, __key_it);
446447

447-
return __emplace_exact_pos(
448-
std::move(__key_it), std::move(__mapped_it), std::move(__pair.first), std::move(__pair.second));
448+
return __flat_map_utils::__emplace_exact_pos(
449+
*this, std::move(__key_it), std::move(__mapped_it), std::move(__pair.first), std::move(__pair.second));
449450
}
450451

451452
template <class... _Args>
@@ -486,7 +487,8 @@ class flat_multimap {
486487
__key_iter = ranges::lower_bound(__key_iter, __containers_.keys.end(), __pair.first, __compare_);
487488
__mapped_iter = __corresponding_mapped_it(*this, __key_iter);
488489
}
489-
return __emplace_exact_pos(__key_iter, __mapped_iter, std::move(__pair.first), std::move(__pair.second));
490+
return __flat_map_utils::__emplace_exact_pos(
491+
*this, __key_iter, __mapped_iter, std::move(__pair.first), std::move(__pair.second));
490492
}
491493

492494
_LIBCPP_HIDE_FROM_ABI iterator insert(const value_type& __x) { return emplace(__x); }
@@ -766,22 +768,10 @@ class flat_multimap {
766768
ranges::distance(__self.__containers_.keys.begin(), __key_iter));
767769
}
768770

769-
template <class _InputIterator, class _Sentinel>
770-
_LIBCPP_HIDE_FROM_ABI size_type __append(_InputIterator __first, _Sentinel __last) {
771-
size_type __num_appended = 0;
772-
for (; __first != __last; ++__first) {
773-
value_type __kv = *__first;
774-
__containers_.keys.insert(__containers_.keys.end(), std::move(__kv.first));
775-
__containers_.values.insert(__containers_.values.end(), std::move(__kv.second));
776-
++__num_appended;
777-
}
778-
return __num_appended;
779-
}
780-
781771
template <bool _WasSorted, class _InputIterator, class _Sentinel>
782772
_LIBCPP_HIDE_FROM_ABI void __append_sort_merge(_InputIterator __first, _Sentinel __last) {
783773
auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });
784-
size_t __num_appended = __append(std::move(__first), std::move(__last));
774+
size_t __num_appended = __flat_map_utils::__append(*this, std::move(__first), std::move(__last));
785775
if (__num_appended != 0) {
786776
auto __zv = ranges::views::zip(__containers_.keys, __containers_.values);
787777
auto __append_start_offset = __containers_.keys.size() - __num_appended;
@@ -834,49 +824,6 @@ class flat_multimap {
834824
return _Res(std::move(__key_iter), std::move(__mapped_iter));
835825
}
836826

837-
template <class _IterK, class _IterM, class _KeyArg, class... _MArgs>
838-
_LIBCPP_HIDE_FROM_ABI iterator
839-
__emplace_exact_pos(_IterK&& __it_key, _IterM&& __it_mapped, _KeyArg&& __key, _MArgs&&... __mapped_args) {
840-
auto __on_key_failed = std::__make_exception_guard([&]() noexcept {
841-
if constexpr (__container_traits<_KeyContainer>::__emplacement_has_strong_exception_safety_guarantee) {
842-
// Nothing to roll back!
843-
} else {
844-
// we need to clear both because we don't know the state of our keys anymore
845-
clear() /* noexcept */;
846-
}
847-
});
848-
auto __key_it = __containers_.keys.emplace(__it_key, std::forward<_KeyArg>(__key));
849-
__on_key_failed.__complete();
850-
851-
auto __on_value_failed = std::__make_exception_guard([&]() noexcept {
852-
if constexpr (!__container_traits<_MappedContainer>::__emplacement_has_strong_exception_safety_guarantee) {
853-
// we need to clear both because we don't know the state of our values anymore
854-
clear() /* noexcept */;
855-
} else {
856-
// In this case, we know the values are just like before we attempted emplacement,
857-
// and we also know that the keys have been emplaced successfully. Just roll back the keys.
858-
# if _LIBCPP_HAS_EXCEPTIONS
859-
try {
860-
# endif // _LIBCPP_HAS_EXCEPTIONS
861-
__containers_.keys.erase(__key_it);
862-
# if _LIBCPP_HAS_EXCEPTIONS
863-
} catch (...) {
864-
// Now things are funky for real. We're failing to rollback the keys.
865-
// Just give up and clear the whole thing.
866-
//
867-
// Also, swallow the exception that happened during the rollback and let the
868-
// original value-emplacement exception propagate normally.
869-
clear() /* noexcept */;
870-
}
871-
# endif // _LIBCPP_HAS_EXCEPTIONS
872-
}
873-
});
874-
auto __mapped_it = __containers_.values.emplace(__it_mapped, std::forward<_MArgs>(__mapped_args)...);
875-
__on_value_failed.__complete();
876-
877-
return iterator(std::move(__key_it), std::move(__mapped_it));
878-
}
879-
880827
_LIBCPP_HIDE_FROM_ABI void __reserve(size_t __size) {
881828
if constexpr (requires { __containers_.keys.reserve(__size); }) {
882829
__containers_.keys.reserve(__size);
@@ -900,6 +847,8 @@ class flat_multimap {
900847
friend typename flat_multimap<_Key2, _Tp2, _Compare2, _KeyContainer2, _MappedContainer2>::size_type
901848
erase_if(flat_multimap<_Key2, _Tp2, _Compare2, _KeyContainer2, _MappedContainer2>&, _Predicate);
902849

850+
friend __flat_map_utils;
851+
903852
containers __containers_;
904853
[[no_unique_address]] key_compare __compare_;
905854

libcxx/include/__flat_map/utils.h

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// -*- C++ -*-
2+
//===----------------------------------------------------------------------===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#ifndef _LIBCPP___FLAT_MAP_UTILS_H
11+
#define _LIBCPP___FLAT_MAP_UTILS_H
12+
13+
#include <__config>
14+
#include <__type_traits/container_traits.h>
15+
#include <__utility/exception_guard.h>
16+
#include <__utility/forward.h>
17+
#include <__utility/move.h>
18+
19+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
20+
# pragma GCC system_header
21+
#endif
22+
23+
_LIBCPP_PUSH_MACROS
24+
#include <__undef_macros>
25+
26+
#if _LIBCPP_STD_VER >= 23
27+
28+
_LIBCPP_BEGIN_NAMESPACE_STD
29+
30+
// It is easier to be-friend to have a struct with static functions
31+
struct __flat_map_utils {
32+
template <class _Map, class _IterK, class _IterM, class _KeyArg, class... _MArgs>
33+
_LIBCPP_HIDE_FROM_ABI static typename _Map::iterator __emplace_exact_pos(
34+
_Map& __map, _IterK&& __it_key, _IterM&& __it_mapped, _KeyArg&& __key, _MArgs&&... __mapped_args) {
35+
auto __on_key_failed = std::__make_exception_guard([&]() noexcept {
36+
using _KeyContainer = typename _Map::key_container_type;
37+
if constexpr (__container_traits<_KeyContainer>::__emplacement_has_strong_exception_safety_guarantee) {
38+
// Nothing to roll back!
39+
} else {
40+
// we need to clear both because we don't know the state of our keys anymore
41+
__map.clear() /* noexcept */;
42+
}
43+
});
44+
auto __key_it = __map.__containers_.keys.emplace(__it_key, std::forward<_KeyArg>(__key));
45+
__on_key_failed.__complete();
46+
47+
auto __on_value_failed = std::__make_exception_guard([&]() noexcept {
48+
using _MappedContainer = typename _Map::mapped_container_type;
49+
if constexpr (!__container_traits<_MappedContainer>::__emplacement_has_strong_exception_safety_guarantee) {
50+
// we need to clear both because we don't know the state of our values anymore
51+
__map.clear() /* noexcept */;
52+
} else {
53+
// In this case, we know the values are just like before we attempted emplacement,
54+
// and we also know that the keys have been emplaced successfully. Just roll back the keys.
55+
# if _LIBCPP_HAS_EXCEPTIONS
56+
try {
57+
# endif // _LIBCPP_HAS_EXCEPTIONS
58+
__map.__containers_.keys.erase(__key_it);
59+
# if _LIBCPP_HAS_EXCEPTIONS
60+
} catch (...) {
61+
// Now things are funky for real. We're failing to rollback the keys.
62+
// Just give up and clear the whole thing.
63+
//
64+
// Also, swallow the exception that happened during the rollback and let the
65+
// original value-emplacement exception propagate normally.
66+
__map.clear() /* noexcept */;
67+
}
68+
# endif // _LIBCPP_HAS_EXCEPTIONS
69+
}
70+
});
71+
auto __mapped_it = __map.__containers_.values.emplace(__it_mapped, std::forward<_MArgs>(__mapped_args)...);
72+
__on_value_failed.__complete();
73+
74+
return typename _Map::iterator(std::move(__key_it), std::move(__mapped_it));
75+
}
76+
77+
// https://github.com/llvm/llvm-project/issues/108624
78+
template <class _Map, class _InputIterator, class _Sentinel>
79+
_LIBCPP_HIDE_FROM_ABI static typename _Map::size_type
80+
__append(_Map& __map, _InputIterator __first, _Sentinel __last) {
81+
typename _Map::size_type __num_appended = 0;
82+
for (; __first != __last; ++__first) {
83+
typename _Map::value_type __kv = *__first;
84+
__map.__containers_.keys.insert(__map.__containers_.keys.end(), std::move(__kv.first));
85+
__map.__containers_.values.insert(__map.__containers_.values.end(), std::move(__kv.second));
86+
++__num_appended;
87+
}
88+
return __num_appended;
89+
}
90+
};
91+
_LIBCPP_END_NAMESPACE_STD
92+
93+
#endif // _LIBCPP_STD_VER >= 23
94+
95+
_LIBCPP_POP_MACROS
96+
97+
#endif // #define _LIBCPP___FLAT_MAP_UTILS_H

libcxx/include/module.modulemap

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,11 +1240,18 @@ module std [system] {
12401240
}
12411241

12421242
module flat_map {
1243-
module flat_map { header "__flat_map/flat_map.h" }
1244-
module flat_multimap { header "__flat_map/flat_multimap.h" }
1243+
module flat_map {
1244+
header "__flat_map/flat_map.h"
1245+
export std.vector.vector
1246+
}
1247+
module flat_multimap {
1248+
header "__flat_map/flat_multimap.h"
1249+
export std.vector.vector
1250+
}
12451251
module key_value_iterator { header "__flat_map/key_value_iterator.h" }
12461252
module sorted_unique { header "__flat_map/sorted_unique.h" }
12471253
module sorted_equivalent { header "__flat_map/sorted_equivalent.h" }
1254+
module utils { header "__flat_map/utils.h" }
12481255

12491256
header "flat_map"
12501257
export *

0 commit comments

Comments
 (0)