Skip to content

Commit 65fb506

Browse files
Hui XieHui Xie
authored andcommitted
comments
1 parent cf3905d commit 65fb506

File tree

12 files changed

+499
-137
lines changed

12 files changed

+499
-137
lines changed

libcxx/include/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,7 @@ set(files
364364
__flat_map/key_value_iterator.h
365365
__flat_map/sorted_unique.h
366366
__flat_map/sorted_equivalent.h
367+
__flat_map/utils.h
367368
__format/buffer.h
368369
__format/concepts.h
369370
__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>
@@ -862,22 +863,10 @@ class flat_map {
862863
__containers_.values.erase(__containers_.values.begin() + __dist, __containers_.values.end());
863864
}
864865

865-
template <class _InputIterator, class _Sentinel>
866-
_LIBCPP_HIDE_FROM_ABI size_type __append(_InputIterator __first, _Sentinel __last) {
867-
size_type __num_of_appended = 0;
868-
for (; __first != __last; ++__first) {
869-
value_type __kv = *__first;
870-
__containers_.keys.insert(__containers_.keys.end(), std::move(__kv.first));
871-
__containers_.values.insert(__containers_.values.end(), std::move(__kv.second));
872-
++__num_of_appended;
873-
}
874-
return __num_of_appended;
875-
}
876-
877866
template <bool _WasSorted, class _InputIterator, class _Sentinel>
878867
_LIBCPP_HIDE_FROM_ABI void __append_sort_merge_unique(_InputIterator __first, _Sentinel __last) {
879868
auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });
880-
size_t __num_of_appended = __append(std::move(__first), std::move(__last));
869+
size_t __num_of_appended = __flat_map_utils::__append(*this, std::move(__first), std::move(__last));
881870
if (__num_of_appended != 0) {
882871
auto __zv = ranges::views::zip(__containers_.keys, __containers_.values);
883872
auto __append_start_offset = __containers_.keys.size() - __num_of_appended;
@@ -965,7 +954,8 @@ class flat_map {
965954

966955
if (__key_it == __containers_.keys.end() || __compare_(__key, *__key_it)) {
967956
return pair<iterator, bool>(
968-
__try_emplace_exact_hint(
957+
__flat_map_utils::__emplace_exact_pos(
958+
*this,
969959
std::move(__key_it),
970960
std::move(__mapped_it),
971961
std::forward<_KeyArg>(__key),
@@ -991,10 +981,13 @@ class flat_map {
991981
_LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __try_emplace_hint(const_iterator __hint, _Kp&& __key, _Args&&... __args) {
992982
if (__is_hint_correct(__hint, __key)) {
993983
if (__hint == cend() || __compare_(__key, __hint->first)) {
994-
return {
995-
__try_emplace_exact_hint(
996-
__hint.__key_iter_, __hint.__mapped_iter_, std::forward<_Kp>(__key), std::forward<_Args>(__args)...),
997-
true};
984+
return {__flat_map_utils::__emplace_exact_pos(
985+
*this,
986+
__hint.__key_iter_,
987+
__hint.__mapped_iter_,
988+
std::forward<_Kp>(__key),
989+
std::forward<_Args>(__args)...),
990+
true};
998991
} else {
999992
// key equals
1000993
auto __dist = __hint - cbegin();
@@ -1005,49 +998,6 @@ class flat_map {
1005998
}
1006999
}
10071000

1008-
template <class _IterK, class _IterM, class _KeyArg, class... _MArgs>
1009-
_LIBCPP_HIDE_FROM_ABI iterator
1010-
__try_emplace_exact_hint(_IterK&& __it_key, _IterM&& __it_mapped, _KeyArg&& __key, _MArgs&&... __mapped_args) {
1011-
auto __on_key_failed = std::__make_exception_guard([&]() noexcept {
1012-
if constexpr (__container_traits<_KeyContainer>::__emplacement_has_strong_exception_safety_guarantee) {
1013-
// Nothing to roll back!
1014-
} else {
1015-
// we need to clear both because we don't know the state of our keys anymore
1016-
clear() /* noexcept */;
1017-
}
1018-
});
1019-
auto __key_it = __containers_.keys.emplace(__it_key, std::forward<_KeyArg>(__key));
1020-
__on_key_failed.__complete();
1021-
1022-
auto __on_value_failed = std::__make_exception_guard([&]() noexcept {
1023-
if constexpr (!__container_traits<_MappedContainer>::__emplacement_has_strong_exception_safety_guarantee) {
1024-
// we need to clear both because we don't know the state of our values anymore
1025-
clear() /* noexcept */;
1026-
} else {
1027-
// In this case, we know the values are just like before we attempted emplacement,
1028-
// and we also know that the keys have been emplaced successfully. Just roll back the keys.
1029-
# if _LIBCPP_HAS_EXCEPTIONS
1030-
try {
1031-
# endif // _LIBCPP_HAS_EXCEPTIONS
1032-
__containers_.keys.erase(__key_it);
1033-
# if _LIBCPP_HAS_EXCEPTIONS
1034-
} catch (...) {
1035-
// Now things are funky for real. We're failing to rollback the keys.
1036-
// Just give up and clear the whole thing.
1037-
//
1038-
// Also, swallow the exception that happened during the rollback and let the
1039-
// original value-emplacement exception propagate normally.
1040-
clear() /* noexcept */;
1041-
}
1042-
# endif // _LIBCPP_HAS_EXCEPTIONS
1043-
}
1044-
});
1045-
auto __mapped_it = __containers_.values.emplace(__it_mapped, std::forward<_MArgs>(__mapped_args)...);
1046-
__on_value_failed.__complete();
1047-
1048-
return iterator(std::move(__key_it), std::move(__mapped_it));
1049-
}
1050-
10511001
template <class _Kp, class _Mapped>
10521002
_LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __insert_or_assign(_Kp&& __key, _Mapped&& __mapped) {
10531003
auto __r = try_emplace(std::forward<_Kp>(__key), std::forward<_Mapped>(__mapped));
@@ -1089,6 +1039,8 @@ class flat_map {
10891039
friend typename flat_map<_Key2, _Tp2, _Compare2, _KeyContainer2, _MappedContainer2>::size_type
10901040
erase_if(flat_map<_Key2, _Tp2, _Compare2, _KeyContainer2, _MappedContainer2>&, _Predicate);
10911041

1042+
friend __flat_map_utils;
1043+
10921044
containers __containers_;
10931045
[[no_unique_address]] key_compare __compare_;
10941046

@@ -1189,22 +1141,20 @@ template <ranges::input_range _Range,
11891141
class _Compare = less<__range_key_type<_Range>>,
11901142
class _Allocator = allocator<byte>,
11911143
class = __enable_if_t<!__is_allocator<_Compare>::value && __is_allocator<_Allocator>::value>>
1192-
flat_map(from_range_t, _Range&&, _Compare = _Compare(), _Allocator = _Allocator())
1193-
->flat_map<
1194-
__range_key_type<_Range>,
1195-
__range_mapped_type<_Range>,
1196-
_Compare,
1197-
vector<__range_key_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_key_type<_Range>>>,
1198-
vector<__range_mapped_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_mapped_type<_Range>>>>;
1144+
flat_map(from_range_t, _Range&&, _Compare = _Compare(), _Allocator = _Allocator()) -> flat_map<
1145+
__range_key_type<_Range>,
1146+
__range_mapped_type<_Range>,
1147+
_Compare,
1148+
vector<__range_key_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_key_type<_Range>>>,
1149+
vector<__range_mapped_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_mapped_type<_Range>>>>;
11991150

12001151
template <ranges::input_range _Range, class _Allocator, class = __enable_if_t<__is_allocator<_Allocator>::value>>
1201-
flat_map(from_range_t, _Range&&, _Allocator)
1202-
->flat_map<
1203-
__range_key_type<_Range>,
1204-
__range_mapped_type<_Range>,
1205-
less<__range_key_type<_Range>>,
1206-
vector<__range_key_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_key_type<_Range>>>,
1207-
vector<__range_mapped_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_mapped_type<_Range>>>>;
1152+
flat_map(from_range_t, _Range&&, _Allocator) -> flat_map<
1153+
__range_key_type<_Range>,
1154+
__range_mapped_type<_Range>,
1155+
less<__range_key_type<_Range>>,
1156+
vector<__range_key_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_key_type<_Range>>>,
1157+
vector<__range_mapped_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_mapped_type<_Range>>>>;
12081158

12091159
template <class _Key, class _Tp, class _Compare = less<_Key>>
12101160
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
@@ -1234,11 +1234,18 @@ module std [system] {
12341234
}
12351235

12361236
module flat_map {
1237-
module flat_map { header "__flat_map/flat_map.h" }
1238-
module flat_multimap { header "__flat_map/flat_multimap.h" }
1237+
module flat_map {
1238+
header "__flat_map/flat_map.h"
1239+
export std.vector.vector
1240+
}
1241+
module flat_multimap {
1242+
header "__flat_map/flat_multimap.h"
1243+
export std.vector.vector
1244+
}
12391245
module key_value_iterator { header "__flat_map/key_value_iterator.h" }
12401246
module sorted_unique { header "__flat_map/sorted_unique.h" }
12411247
module sorted_equivalent { header "__flat_map/sorted_equivalent.h" }
1248+
module utils { header "__flat_map/utils.h" }
12421249

12431250
header "flat_map"
12441251
export *

0 commit comments

Comments
 (0)