Skip to content

Commit 7013b51

Browse files
authored
[libc++] Implement std::flat_multiset (llvm#128363)
fixes llvm#105193
1 parent 8d71a2a commit 7013b51

File tree

92 files changed

+9029
-614
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

92 files changed

+9029
-614
lines changed

libcxx/docs/FeatureTestMacroTable.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ Status
332332
---------------------------------------------------------- -----------------
333333
``__cpp_lib_flat_map`` ``202207L``
334334
---------------------------------------------------------- -----------------
335-
``__cpp_lib_flat_set`` *unimplemented*
335+
``__cpp_lib_flat_set`` ``202207L``
336336
---------------------------------------------------------- -----------------
337337
``__cpp_lib_format_ranges`` ``202207L``
338338
---------------------------------------------------------- -----------------

libcxx/docs/ReleaseNotes/21.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ Implemented Papers
4343
- P1361R2: Integration of chrono with text formatting (`Github <https://github.com/llvm/llvm-project/issues/100014>`__)
4444
- P2255R2: A type trait to detect reference binding to temporary (implemented the type traits only) (`Github <https://github.com/llvm/llvm-project/issues/105180>`__)
4545
- P2562R1: ``constexpr`` Stable Sorting (`Github <https://github.com/llvm/llvm-project/issues/105360>`__)
46-
- P1222R4: A Standard ``flat_set`` is partially implemented and ``flat_set`` is provided (`Github <https://github.com/llvm/llvm-project/issues/105193>`__)
4746
- P0472R3: Put std::monostate in <utility> (`Github <https://github.com/llvm/llvm-project/issues/127874>`__)
47+
- P1222R4: A Standard ``flat_set`` (`Github <https://github.com/llvm/llvm-project/issues/105193>`__)
4848

4949
Improvements and New Features
5050
-----------------------------

libcxx/docs/Status/Cxx23Papers.csv

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
"`P0009R18 <https://wg21.link/P0009R18>`__","mdspan: A Non-Owning Multidimensional Array Reference","2022-07 (Virtual)","|Complete|","18",""
5555
"`P0429R9 <https://wg21.link/P0429R9>`__","A Standard ``flat_map``","2022-07 (Virtual)","|Complete|","20",""
5656
"`P1169R4 <https://wg21.link/P1169R4>`__","``static operator()``","2022-07 (Virtual)","|Complete|","16",""
57-
"`P1222R4 <https://wg21.link/P1222R4>`__","A Standard ``flat_set``","2022-07 (Virtual)","|In progress|","",""
57+
"`P1222R4 <https://wg21.link/P1222R4>`__","A Standard ``flat_set``","2022-07 (Virtual)","|Complete|","21",""
5858
"`P1223R5 <https://wg21.link/P1223R5>`__","``ranges::find_last()``, ``ranges::find_last_if()``, and ``ranges::find_last_if_not()``","2022-07 (Virtual)","|Complete|","19",""
5959
"`P1467R9 <https://wg21.link/P1467R9>`__","Extended ``floating-point`` types and standard names","2022-07 (Virtual)","","",""
6060
"`P1642R11 <https://wg21.link/P1642R11>`__","Freestanding ``[utilities]``, ``[ranges]``, and ``[iterators]``","2022-07 (Virtual)","","",""

libcxx/include/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -370,8 +370,10 @@ set(files
370370
__flat_map/sorted_equivalent.h
371371
__flat_map/sorted_unique.h
372372
__flat_map/utils.h
373+
__flat_set/flat_multiset.h
373374
__flat_set/flat_set.h
374375
__flat_set/ra_iterator.h
376+
__flat_set/utils.h
375377
__format/buffer.h
376378
__format/concepts.h
377379
__format/container_adaptor.h

libcxx/include/__flat_set/flat_multiset.h

+792
Large diffs are not rendered by default.

libcxx/include/__flat_set/flat_set.h

+6-35
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <__cstddef/ptrdiff_t.h>
2929
#include <__flat_map/sorted_unique.h>
3030
#include <__flat_set/ra_iterator.h>
31+
#include <__flat_set/utils.h>
3132
#include <__functional/invoke.h>
3233
#include <__functional/is_transparent.h>
3334
#include <__functional/operations.h>
@@ -82,6 +83,8 @@ class flat_set {
8283
template <class, class, class>
8384
friend class flat_set;
8485

86+
friend __flat_set_utils;
87+
8588
static_assert(is_same_v<_Key, typename _KeyContainer::value_type>);
8689
static_assert(!is_same_v<_KeyContainer, std::vector<bool>>, "vector<bool> is not a sequence container");
8790

@@ -619,31 +622,11 @@ class flat_set {
619622
__keys_.erase(__dup_start, __keys_.end());
620623
}
621624

622-
template <class _InputIterator>
623-
_LIBCPP_HIDE_FROM_ABI void __append(_InputIterator __first, _InputIterator __last) {
624-
__keys_.insert(__keys_.end(), std::move(__first), std::move(__last));
625-
}
626-
627-
template <class _Range>
628-
_LIBCPP_HIDE_FROM_ABI void __append(_Range&& __rng) {
629-
if constexpr (requires { __keys_.insert_range(__keys_.end(), std::forward<_Range>(__rng)); }) {
630-
// C++23 Sequence Container should have insert_range member function
631-
// Note that not all Sequence Containers provide append_range.
632-
__keys_.insert_range(__keys_.end(), std::forward<_Range>(__rng));
633-
} else if constexpr (ranges::common_range<_Range>) {
634-
__keys_.insert(__keys_.end(), ranges::begin(__rng), ranges::end(__rng));
635-
} else {
636-
for (auto&& __x : __rng) {
637-
__keys_.insert(__keys_.end(), std::forward<decltype(__x)>(__x));
638-
}
639-
}
640-
}
641-
642625
template <bool _WasSorted, class... _Args>
643626
_LIBCPP_HIDE_FROM_ABI void __append_sort_merge_unique(_Args&&... __args) {
644627
auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });
645628
size_type __old_size = size();
646-
__append(std::forward<_Args>(__args)...);
629+
__flat_set_utils::__append(*this, std::forward<_Args>(__args)...);
647630
if (size() != __old_size) {
648631
if constexpr (!_WasSorted) {
649632
ranges::sort(__keys_.begin() + __old_size, __keys_.end(), __compare_);
@@ -680,23 +663,11 @@ class flat_set {
680663
return std::make_pair(__iter(__it), __iter(std::next(__it)));
681664
}
682665

683-
template <class _KeyArg>
684-
_LIBCPP_HIDE_FROM_ABI iterator __emplace_exact_pos(const_iterator __it, _KeyArg&& __key) {
685-
auto __on_failure = std::__make_exception_guard([&]() noexcept {
686-
if constexpr (!__container_traits<_KeyContainer>::__emplacement_has_strong_exception_safety_guarantee) {
687-
clear() /* noexcept */;
688-
}
689-
});
690-
auto __key_it = __keys_.emplace(__it.__base(), std::forward<_KeyArg>(__key));
691-
__on_failure.__complete();
692-
return iterator(std::move(__key_it));
693-
}
694-
695666
template <class _Kp>
696667
_LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace(_Kp&& __key) {
697668
auto __it = lower_bound(__key);
698669
if (__it == end() || __compare_(__key, *__it)) {
699-
return pair<iterator, bool>(__emplace_exact_pos(__it, std::forward<_Kp>(__key)), true);
670+
return pair<iterator, bool>(__flat_set_utils::__emplace_exact_pos(*this, __it, std::forward<_Kp>(__key)), true);
700671
} else {
701672
return pair<iterator, bool>(std::move(__it), false);
702673
}
@@ -717,7 +688,7 @@ class flat_set {
717688
_LIBCPP_HIDE_FROM_ABI iterator __emplace_hint(const_iterator __hint, _Kp&& __key) {
718689
if (__is_hint_correct(__hint, __key)) {
719690
if (__hint == cend() || __compare_(__key, *__hint)) {
720-
return __emplace_exact_pos(__hint, std::forward<_Kp>(__key));
691+
return __flat_set_utils::__emplace_exact_pos(*this, __hint, std::forward<_Kp>(__key));
721692
} else {
722693
// we already have an equal key
723694
return __hint;

libcxx/include/__flat_set/utils.h

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
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_SET_UTILS_H
11+
#define _LIBCPP___FLAT_SET_UTILS_H
12+
13+
#include <__config>
14+
#include <__ranges/access.h>
15+
#include <__ranges/concepts.h>
16+
#include <__type_traits/container_traits.h>
17+
#include <__type_traits/decay.h>
18+
#include <__utility/exception_guard.h>
19+
#include <__utility/forward.h>
20+
#include <__utility/move.h>
21+
22+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
23+
# pragma GCC system_header
24+
#endif
25+
26+
_LIBCPP_PUSH_MACROS
27+
#include <__undef_macros>
28+
29+
#if _LIBCPP_STD_VER >= 23
30+
31+
_LIBCPP_BEGIN_NAMESPACE_STD
32+
33+
// These utilities are defined in a class instead of a namespace so that this class can be befriended more easily.
34+
struct __flat_set_utils {
35+
// Emplace a key into a flat_{multi}set, at the exact position that
36+
// __it point to, assuming that the key is not already present in the set.
37+
// When an exception is thrown during the emplacement, the function will clear the set if the container does not
38+
// have strong exception safety guarantee on emplacement.
39+
template <class _Set, class _Iter, class _KeyArg>
40+
_LIBCPP_HIDE_FROM_ABI static auto __emplace_exact_pos(_Set& __set, _Iter&& __iter, _KeyArg&& __key) {
41+
using _KeyContainer = typename decay_t<_Set>::container_type;
42+
auto __on_failure = std::__make_exception_guard([&]() noexcept {
43+
if constexpr (!__container_traits<_KeyContainer>::__emplacement_has_strong_exception_safety_guarantee) {
44+
__set.clear() /* noexcept */;
45+
}
46+
});
47+
auto __key_it = __set.__keys_.emplace(__iter.__base(), std::forward<_KeyArg>(__key));
48+
__on_failure.__complete();
49+
return typename decay_t<_Set>::iterator(std::move(__key_it));
50+
}
51+
52+
template <class _Set, class _InputIterator>
53+
_LIBCPP_HIDE_FROM_ABI static void __append(_Set& __set, _InputIterator __first, _InputIterator __last) {
54+
__set.__keys_.insert(__set.__keys_.end(), std::move(__first), std::move(__last));
55+
}
56+
57+
template <class _Set, class _Range>
58+
_LIBCPP_HIDE_FROM_ABI static void __append(_Set& __set, _Range&& __rng) {
59+
if constexpr (requires { __set.__keys_.insert_range(__set.__keys_.end(), std::forward<_Range>(__rng)); }) {
60+
// C++23 Sequence Container should have insert_range member function
61+
// Note that not all Sequence Containers provide append_range.
62+
__set.__keys_.insert_range(__set.__keys_.end(), std::forward<_Range>(__rng));
63+
} else if constexpr (ranges::common_range<_Range>) {
64+
__set.__keys_.insert(__set.__keys_.end(), ranges::begin(__rng), ranges::end(__rng));
65+
} else {
66+
for (auto&& __x : __rng) {
67+
__set.__keys_.insert(__set.__keys_.end(), std::forward<decltype(__x)>(__x));
68+
}
69+
}
70+
}
71+
};
72+
_LIBCPP_END_NAMESPACE_STD
73+
74+
#endif // _LIBCPP_STD_VER >= 23
75+
76+
_LIBCPP_POP_MACROS
77+
78+
#endif // #define _LIBCPP___FLAT_SET_UTILS_H

libcxx/include/flat_set

+17
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,21 @@ namespace std {
3131
template<class Key, class Compare, class KeyContainer, class Predicate>
3232
typename flat_set<Key, Compare, KeyContainer>::size_type
3333
erase_if(flat_set<Key, Compare, KeyContainer>& c, Predicate pred);
34+
35+
// [flat.multiset], class template flat_multiset
36+
template<class Key, class Compare = less<Key>, class KeyContainer = vector<Key>>
37+
class flat_multiset;
38+
39+
struct sorted_equivalent_t { explicit sorted_equivalent_t() = default; };
40+
inline constexpr sorted_equivalent_t sorted_equivalent{};
41+
42+
template<class Key, class Compare, class KeyContainer, class Allocator>
43+
struct uses_allocator<flat_multiset<Key, Compare, KeyContainer>, Allocator>;
44+
45+
// [flat.multiset.erasure], erasure for flat_multiset
46+
template<class Key, class Compare, class KeyContainer, class Predicate>
47+
typename flat_multiset<Key, Compare, KeyContainer>::size_type
48+
erase_if(flat_multiset<Key, Compare, KeyContainer>& c, Predicate pred);
3449
}
3550
*/
3651

@@ -40,7 +55,9 @@ namespace std {
4055
# include <__config>
4156

4257
# if _LIBCPP_STD_VER >= 23
58+
# include <__flat_map/sorted_equivalent.h>
4359
# include <__flat_map/sorted_unique.h>
60+
# include <__flat_set/flat_multiset.h>
4461
# include <__flat_set/flat_set.h>
4562
# endif
4663

libcxx/include/module.modulemap

+3
Original file line numberDiff line numberDiff line change
@@ -1305,13 +1305,16 @@ module std [system] {
13051305
module flat_set {
13061306
module flat_set {
13071307
header "__flat_set/flat_set.h"
1308+
header "__flat_set/flat_multiset.h"
13081309
export std.vector.vector
13091310
export std.vector.fwd
13101311
}
13111312
module ra_iterator { header "__flat_set/ra_iterator.h" }
1313+
module utils { header "__flat_set/utils.h" }
13121314

13131315
header "flat_set"
13141316
export std.flat_map.sorted_unique
1317+
export std.flat_map.sorted_equivalent
13151318
export *
13161319
}
13171320

libcxx/include/version

+1-1
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,7 @@ __cpp_lib_void_t 201411L <type_traits>
486486
# define __cpp_lib_containers_ranges 202202L
487487
# define __cpp_lib_expected 202211L
488488
# define __cpp_lib_flat_map 202207L
489-
// # define __cpp_lib_flat_set 202207L
489+
# define __cpp_lib_flat_set 202207L
490490
# define __cpp_lib_format_ranges 202207L
491491
// # define __cpp_lib_formatters 202302L
492492
# define __cpp_lib_forward_like 202207L

libcxx/modules/std/flat_set.inc

+1-3
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,11 @@ export namespace std {
1919

2020
// [flat.set.erasure], erasure for flat_­set
2121
using std::erase_if;
22-
#endif // _LIBCPP_STD_VER >= 23
2322

24-
#if 0
2523
// [flat.multiset], class template flat_­multiset
2624
using std::flat_multiset;
2725

2826
using std::sorted_equivalent;
2927
using std::sorted_equivalent_t;
30-
#endif
28+
#endif // _LIBCPP_STD_VER >= 23
3129
} // namespace std

0 commit comments

Comments
 (0)