From 126dbbf3a3154e80ec276159215bc213e89d2126 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Fri, 14 Jul 2023 15:55:18 +0800 Subject: [PATCH 001/100] Prepare for new header --- stl/CMakeLists.txt | 1 + stl/inc/__msvc_all_public_headers.hpp | 1 + 2 files changed, 2 insertions(+) diff --git a/stl/CMakeLists.txt b/stl/CMakeLists.txt index f82705a800b..369957a3310 100644 --- a/stl/CMakeLists.txt +++ b/stl/CMakeLists.txt @@ -157,6 +157,7 @@ set(HEADERS ${CMAKE_CURRENT_LIST_DIR}/inc/experimental/unordered_set ${CMAKE_CURRENT_LIST_DIR}/inc/experimental/vector ${CMAKE_CURRENT_LIST_DIR}/inc/filesystem + ${CMAKE_CURRENT_LIST_DIR}/inc/flat_map ${CMAKE_CURRENT_LIST_DIR}/inc/format ${CMAKE_CURRENT_LIST_DIR}/inc/forward_list ${CMAKE_CURRENT_LIST_DIR}/inc/fstream diff --git a/stl/inc/__msvc_all_public_headers.hpp b/stl/inc/__msvc_all_public_headers.hpp index 268f3a862f6..0ef854b2036 100644 --- a/stl/inc/__msvc_all_public_headers.hpp +++ b/stl/inc/__msvc_all_public_headers.hpp @@ -92,6 +92,7 @@ #include #include #include +#include #include #include #include From 0f968f0aed1a4d77f4b20297851a470b0e49c845 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Fri, 14 Jul 2023 15:55:48 +0800 Subject: [PATCH 002/100] Add empty header --- stl/inc/flat_map | 1 + 1 file changed, 1 insertion(+) create mode 100644 stl/inc/flat_map diff --git a/stl/inc/flat_map b/stl/inc/flat_map new file mode 100644 index 00000000000..50e96676b70 --- /dev/null +++ b/stl/inc/flat_map @@ -0,0 +1 @@ +#pragma once From bc4bc8ae09ffb8fa4961df284c4983b23b17db5b Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Fri, 14 Jul 2023 16:01:48 +0800 Subject: [PATCH 003/100] More preparation work --- stl/inc/header-units.json | 1 + stl/inc/yvals_core.h | 3 +++ 2 files changed, 4 insertions(+) diff --git a/stl/inc/header-units.json b/stl/inc/header-units.json index 74d6d4699e5..9d7610eaed0 100644 --- a/stl/inc/header-units.json +++ b/stl/inc/header-units.json @@ -64,6 +64,7 @@ "execution", "expected", "filesystem", + "flat_map", "format", "forward_list", "fstream", diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index ed808bf9d97..7d8e1e24254 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -322,6 +322,7 @@ // P0288R9 move_only_function // P0323R12 // P0401R6 Providing Size Feedback In The Allocator Interface +// P0429R9 // P0448R4 // P0627R6 unreachable() // P0798R8 Monadic Operations For optional @@ -1866,6 +1867,8 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #endif // defined(__cpp_lib_concepts) #define __cpp_lib_unreachable 202202L + +#define __cpp_lib_flat_map 202207L #endif // _HAS_CXX23 // macros with language mode sensitivity From 03051cd1057bdeedad492bcb80667218d352b6ec Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Mon, 17 Jul 2023 13:15:24 +0800 Subject: [PATCH 004/100] Add test structure --- stl/inc/flat_map | 2 ++ stl/modules/std.ixx | 1 + tests/std/include/test_header_units_and_modules.hpp | 8 ++++++++ tests/std/test.lst | 1 + tests/std/tests/P0429R9_flat_map/env.lst | 4 ++++ tests/std/tests/P0429R9_flat_map/test.cpp | 10 ++++++++++ 6 files changed, 26 insertions(+) create mode 100644 tests/std/tests/P0429R9_flat_map/env.lst create mode 100644 tests/std/tests/P0429R9_flat_map/test.cpp diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 50e96676b70..b0363a55147 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -1 +1,3 @@ #pragma once + +#error "Not implemented" diff --git a/stl/modules/std.ixx b/stl/modules/std.ixx index 7a5fdbf7cef..36bd4afbdbf 100644 --- a/stl/modules/std.ixx +++ b/stl/modules/std.ixx @@ -61,6 +61,7 @@ export module std; #include #endif // _HAS_CXX23 #include +#include #include #include #include diff --git a/tests/std/include/test_header_units_and_modules.hpp b/tests/std/include/test_header_units_and_modules.hpp index ae0e81eda4e..c268b02dde7 100644 --- a/tests/std/include/test_header_units_and_modules.hpp +++ b/tests/std/include/test_header_units_and_modules.hpp @@ -236,6 +236,13 @@ void test_filesystem() { assert(info.capacity != static_cast(-1)); } +void test_flatmap() { + using namespace std; + puts("Testing ."); + + // FIXME! ADD TEST COVERAGE HERE! +} + void test_format() { using namespace std; puts("Testing ."); @@ -1140,6 +1147,7 @@ void all_cpp_header_tests() { test_expected(); #endif // TEST_STANDARD >= 23 test_filesystem(); + test_flat_map(); test_format(); test_forward_list(); test_fstream(); diff --git a/tests/std/test.lst b/tests/std/test.lst index ee4fa316ece..0d5956b3042 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -329,6 +329,7 @@ tests\P0408R7_efficient_access_to_stringbuf_buffer tests\P0414R2_shared_ptr_for_arrays tests\P0415R1_constexpr_complex tests\P0426R1_constexpr_char_traits +tests\P0429R9_flat_map tests\P0433R2_deduction_guides tests\P0448R4_iosfwd tests\P0448R4_spanstream diff --git a/tests/std/tests/P0429R9_flat_map/env.lst b/tests/std/tests/P0429R9_flat_map/env.lst new file mode 100644 index 00000000000..18e2d7c71ec --- /dev/null +++ b/tests/std/tests/P0429R9_flat_map/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\concepts_latest_matrix.lst diff --git a/tests/std/tests/P0429R9_flat_map/test.cpp b/tests/std/tests/P0429R9_flat_map/test.cpp new file mode 100644 index 00000000000..114b223c67a --- /dev/null +++ b/tests/std/tests/P0429R9_flat_map/test.cpp @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include + +using namespace std; + +int main() { + return 0; +} From 64a528d2c5bbe31e113653c257d18a78172d9e8c Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Mon, 17 Jul 2023 14:42:21 +0800 Subject: [PATCH 005/100] Define types for flat_map --- stl/inc/flat_map | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index b0363a55147..5af70c83fde 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -1,3 +1,46 @@ #pragma once -#error "Not implemented" +#include +#include +#include +#include +#include +#include +#include +#include + +_STD_BEGIN + +template , class KeyContainer = vector, class MappedContainer = vector> requires same_as && same_as +class flat_map; + +struct sorted_unique_t { explicit sorted_unique_t() = default; }; +inline constexpr sorted_unique_t sorted_unique {}; + +// Implementation + +template requires same_as && same_as +class flat_map { + public: + using key_type = Key; + using mapped_type = T; + using value_type = pair; + using key_compare = Compare; + using reference = pair; + using const_reference = pair; + using size_type = size_t; + using difference_type = ptrdiff_t; + using key_container_type = KeyContainer; + using mapped_container_type = MappedContainer; + + private: + using _Underlying_container = _RANGES zip_view<_RANGES views::all_t, _RANGES views::all_t>; + + public: + using iterator = _RANGES iterator_t<_Underlying_container>; + using const_iterator = _RANGES const_iterator_t<_Underlying_container>; + using reverse_iterator = _STD reverse_iterator; + using const_reverse_iterator = _STD reverse_iterator; +}; + +_STD_END From 497415284a10a7ddbee64e19c1075061bc689f2c Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Mon, 17 Jul 2023 17:18:28 +0800 Subject: [PATCH 006/100] Use split storage --- stl/inc/flat_map | 52 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 8 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 5af70c83fde..486c1f41b74 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include @@ -32,15 +31,52 @@ class flat_map { using difference_type = ptrdiff_t; using key_container_type = KeyContainer; using mapped_container_type = MappedContainer; - - private: - using _Underlying_container = _RANGES zip_view<_RANGES views::all_t, _RANGES views::all_t>; - - public: - using iterator = _RANGES iterator_t<_Underlying_container>; - using const_iterator = _RANGES const_iterator_t<_Underlying_container>; + using iterator = typename key_container_type::iterator; + using const_iterator = typename key_container_type::const_iterator; using reverse_iterator = _STD reverse_iterator; using const_reverse_iterator = _STD reverse_iterator; + + class value_compare { + public: + value_compare(key_compare _Comp) : _Key_compare_for_val(_Comp) {} + + bool operator () (const_reference _X, const_reference _Y) const { + return _Key_compare_for_val(_X.first, _Y.first); + } + + private: + key_compare _Key_compare_for_val; + }; + + struct containers { + key_container_type keys; + mapped_container_type values; + }; + + // 24.6.8.3 construct / copy / destroy + explicit flat_map(const key_compare& _Comp) : _Key_compare(_Comp) {} + flat_map(): flat_map(key_compare()) {} + + // observers + key_compare key_comp() const { + return _Key_compare; + } + + value_compare value_comp() const { + return value_compare(_Key_compare); + } + + const key_container_type& keys() const noexcept { + return _Data.keys; + } + + const mapped_container_type& values() const noexcept { + return _Data.values; + } + + private: + key_compare _Key_compare; + containers _Data; }; _STD_END From b40802713021bace4c7736a33fb9195c107785a0 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Tue, 18 Jul 2023 18:10:19 +0800 Subject: [PATCH 007/100] Add partial implementation --- stl/inc/flat_map | 64 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 486c1f41b74..c2b9a398b04 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -1,9 +1,12 @@ #pragma once +#include #include #include #include #include +#include +#include #include #include #include @@ -36,6 +39,8 @@ class flat_map { using reverse_iterator = _STD reverse_iterator; using const_reverse_iterator = _STD reverse_iterator; + static_assert(_STD random_access_iterator); + class value_compare { public: value_compare(key_compare _Comp) : _Key_compare_for_val(_Comp) {} @@ -54,9 +59,24 @@ class flat_map { }; // 24.6.8.3 construct / copy / destroy - explicit flat_map(const key_compare& _Comp) : _Key_compare(_Comp) {} + explicit flat_map(const key_compare& _Comp) : _Key_compare(_Comp), _Data() {} flat_map(): flat_map(key_compare()) {} + flat_map(key_container_type _Key_cont, mapped_container_type _Mapped_cont): _Key_compare(key_compare()), _Data() { + _Data.keys = _STD move(_Key_cont); + _Data.values = _STD move(_Mapped_cont); + + _Sort_and_dedup(); + } + + template + flat_map(const key_container_type& _Key_cont, const mapped_container_type& _Mapped_cont, const Allocator& _Alloc) requires uses_allocator_v && uses_allocator_v : _Key_compare(key_compare()), _Data() { + _Data.keys = _STD make_obj_using_allocator(_Alloc, _Key_cont); + _Data.values = _STD make_obj_using_allocator(_Alloc, _Mapped_cont); + + _Sort_and_dedup(); + } + // observers key_compare key_comp() const { return _Key_compare; @@ -77,6 +97,48 @@ class flat_map { private: key_compare _Key_compare; containers _Data; + + struct _Key_equal { + key_compare _Key_compare; + _Key_equal(key_compare _Comp) : _Key_compare(_Comp) {} + bool operator () (const_reference _X, const_reference _Y) const { + return !_Key_compare(_X.first, _Y.first) && !_Key_compare(_Y.first, _X.first); + } + }; + + void _Sort_and_dedup(){ + auto _Zip_view = _RANGES views::zip(_Data.keys, _Data.values); + _STD sort(_Zip_view.begin(), _Zip_view.end(), value_compare(_Key_compare)); + + auto _Subrange = _RANGES unique(_Zip_view, _Key_equal(_Key_compare)); + auto _Remaining_count = _STD distance(_Zip_view.begin(), _Subrange.begin()); + + _Data.keys.erase(_Data.keys.begin() + _Remaining_count, _Data.keys.end()); + _Data.values.erase(_Data.values.begin() + _Remaining_count, _Data.values.end()); + }; + + class _Flat_map_iterator{ + public: + _Flat_map_iterator() = default; + // Copy-constructible + _Flat_map_iterator(const _Flat_map_iterator&) = default; + // Copy-assignable + _Flat_map_iterator& operator = (const _Flat_map_iterator&) = default; + // Swappable + static_assert(std::swappable<_Flat_map_iterator>); + // Destructible + ~_Flat_map_iterator() = default; + + using iterator_category = _STD random_access_iterator_tag; + using difference_type = ptrdiff_t; + using value_type = flat_map::value_type; + using pointer = value_type*; + using reference = value_type&; + + private: + typename key_container_type::iterator _Key_it; + typename mapped_container_type::iterator _Mapped_it; + }; }; _STD_END From e19d34675419aedb3e6fb32303afb36372865b63 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Thu, 20 Jul 2023 15:34:18 +0800 Subject: [PATCH 008/100] Finish all constructors (except copy / move constructors). Set up simple skeleton for iterator. --- stl/inc/flat_map | 138 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 105 insertions(+), 33 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index c2b9a398b04..39bd0c69b98 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -10,6 +10,7 @@ #include #include #include +#include _STD_BEGIN @@ -19,10 +20,44 @@ class flat_map; struct sorted_unique_t { explicit sorted_unique_t() = default; }; inline constexpr sorted_unique_t sorted_unique {}; +template +concept _Valid_Allocator_for_flat_map = _STD uses_allocator_v<_Key_container, _Alloc> && _STD uses_allocator_v<_Mapped_container, _Alloc>; + // Implementation +_EXPORT_STD template requires same_as && same_as class flat_map { + private: + template <_STD random_access_iterator _Key_iterator_t, _STD random_access_iterator _Mapped_iterator_t> + class _Flat_map_iterator_Impl{ + public: + class type{ + public: + type() = default; + // Copy-constructible + type(const type&) = default; + // Copy-assignable + type& operator = (const type&) = default; + // Move-assignable + type& operator = (type&&) = default; + // Swappable + // Destructible + ~type() = default; + + using iterator_category = _STD random_access_iterator_tag; + using difference_type = ptrdiff_t; + using value_type = flat_map::value_type; + using pointer = value_type*; + using reference = value_type&; + + private: + _Key_iterator_t _Key_it; + _Mapped_iterator_t _Mapped_it; + }; + + static_assert(_STD swappable); + }; public: using key_type = Key; using mapped_type = T; @@ -34,8 +69,8 @@ class flat_map { using difference_type = ptrdiff_t; using key_container_type = KeyContainer; using mapped_container_type = MappedContainer; - using iterator = typename key_container_type::iterator; - using const_iterator = typename key_container_type::const_iterator; + using iterator = _Flat_map_iterator_Impl::type; + using const_iterator = _Flat_map_iterator_Impl::type; using reverse_iterator = _STD reverse_iterator; using const_reverse_iterator = _STD reverse_iterator; @@ -62,21 +97,81 @@ class flat_map { explicit flat_map(const key_compare& _Comp) : _Key_compare(_Comp), _Data() {} flat_map(): flat_map(key_compare()) {} - flat_map(key_container_type _Key_cont, mapped_container_type _Mapped_cont): _Key_compare(key_compare()), _Data() { - _Data.keys = _STD move(_Key_cont); - _Data.values = _STD move(_Mapped_cont); + template <_Valid_Allocator_for_flat_map Allocator> + explicit flat_map(const Allocator& _Alloc) : flat_map(key_compare(), _Alloc) {} + + template <_Valid_Allocator_for_flat_map Allocator> + explicit flat_map(const key_compare& _Comp, const Allocator& _Alloc): _Key_compare(_Comp), _Data{.keys = _STD make_obj_using_allocator(_Alloc), .values = _STD make_obj_using_allocator(_Alloc)} {} + flat_map(key_container_type _Key_cont, mapped_container_type _Mapped_cont): flat_map(sorted_unique_t(), _Key_cont, _Mapped_cont) { _Sort_and_dedup(); } - template - flat_map(const key_container_type& _Key_cont, const mapped_container_type& _Mapped_cont, const Allocator& _Alloc) requires uses_allocator_v && uses_allocator_v : _Key_compare(key_compare()), _Data() { - _Data.keys = _STD make_obj_using_allocator(_Alloc, _Key_cont); - _Data.values = _STD make_obj_using_allocator(_Alloc, _Mapped_cont); - + template <_Valid_Allocator_for_flat_map Allocator> + flat_map(const key_container_type& _Key_cont, const mapped_container_type& _Mapped_cont, const Allocator& _Alloc): flat_map(sorted_unique_t(), _Key_cont, _Mapped_cont, _Alloc) { _Sort_and_dedup(); } + flat_map(sorted_unique_t _Sorted_unique, key_container_type _Key_cont, mapped_container_type _Mapped_cont): _Key_compare(key_compare()), _Data {.keys = _STD move(_Key_cont), .values = _STD move(_Mapped_cont)} {} + + template <_Valid_Allocator_for_flat_map Allocator> + flat_map(sorted_unique_t _Sorted_unique, const key_container_type& _Key_cont, const mapped_container_type& _Mapped_cont, const Allocator& _Alloc): _Key_compare(key_compare()), _Data{.keys = _STD make_obj_using_allocator(_Alloc, _Key_cont), .values = _STD make_obj_using_allocator(_Alloc, _Mapped_cont)} {} + + template <_STD input_iterator _InputIterator> + flat_map(_InputIterator _First, _InputIterator _Last, const key_compare& _Comp = key_compare()) : flat_map(_Comp) { + insert(_First, _Last); + } + + template <_STD input_iterator _InputIterator, _Valid_Allocator_for_flat_map Allocator> + flat_map(_InputIterator _First, _InputIterator _Last, const key_compare& _Comp, const Allocator& _Alloc): flat_map(_Comp, _Alloc) { + insert(_First, _Last); + } + + template <_Container_compatible_range R> + flat_map(_STD from_range_t _From_range, R&& _Range) : flat_map(_From_range, _STD forward(_Range), key_compare()) {} + + template <_Container_compatible_range R, _Valid_Allocator_for_flat_map Allocator> + flat_map(_STD from_range_t _From_range, R&& _Range, const Allocator& _Alloc): flat_map(_From_range, _STD forward(_Range), key_compare(), _Alloc) {} + + template <_Container_compatible_range R> + flat_map(_STD from_range_t _From_range, R&& _Range, const key_compare& _Comp) : flat_map(_Comp) { + insert_range(_STD forward(_Range)); + } + + template <_Container_compatible_range R, _Valid_Allocator_for_flat_map Allocator> + flat_map(_STD from_range_t _From_range, R&& _Range, const key_compare& _Comp, const Allocator& _Alloc): flat_map(_Comp, _Alloc) { + insert_range(_STD forward(_Range)); + } + + template <_STD input_iterator _InputIterator> + flat_map(sorted_unique_t _S, _InputIterator _First, _InputIterator _Last, const key_compare& _Comp = key_compare()): flat_map(_Comp) { + insert(_S, _First, _Last); + } + + template <_STD input_iterator _InputIterator, _Valid_Allocator_for_flat_map Allocator> + flat_map(sorted_unique_t _S, _InputIterator _First, _InputIterator _Last, const key_compare& _Comp, const Allocator& _Alloc): flat_map(_Comp, _Alloc) { + insert(_S, _First, _Last); + } + + template <_STD input_iterator _InputIterator, _Valid_Allocator_for_flat_map Allocator> + flat_map(sorted_unique_t _S, _InputIterator _First, _InputIterator _Last, const Allocator& _Alloc): flat_map(_S, _First, _Last, key_compare(), _Alloc) {} + + flat_map(initializer_list _I, const key_compare& _Comp = key_compare()): flat_map(_I.begin(), _I.end(), _Comp) {} + + template <_Valid_Allocator_for_flat_map Allocator> + flat_map(initializer_list _I, const key_compare& _Comp, const Allocator& _Alloc): flat_map(_I.begin(), _I.end(), _Comp, _Alloc) {} + + template <_Valid_Allocator_for_flat_map Allocator> + flat_map(initializer_list _I, const Allocator& _Alloc): flat_map(_I, key_compare(), _Alloc) {} + + flat_map(sorted_unique_t _S, initializer_list _I, const key_compare& _Comp = key_compare()): flat_map(_S, _I.begin(), _I.end(), _Comp) {} + + template <_Valid_Allocator_for_flat_map Allocator> + flat_map(sorted_unique_t _S, initializer_list _I, const key_compare& _Comp, const Allocator& _Alloc): flat_map(_S, _I.begin(), _I.end(), _Comp, _Alloc) {} + + template <_Valid_Allocator_for_flat_map Allocator> + flat_map(sorted_unique_t _S, initializer_list _I, const Allocator& _Alloc): flat_map(_S, _I, key_compare(), _Alloc) {} + // observers key_compare key_comp() const { return _Key_compare; @@ -116,29 +211,6 @@ class flat_map { _Data.keys.erase(_Data.keys.begin() + _Remaining_count, _Data.keys.end()); _Data.values.erase(_Data.values.begin() + _Remaining_count, _Data.values.end()); }; - - class _Flat_map_iterator{ - public: - _Flat_map_iterator() = default; - // Copy-constructible - _Flat_map_iterator(const _Flat_map_iterator&) = default; - // Copy-assignable - _Flat_map_iterator& operator = (const _Flat_map_iterator&) = default; - // Swappable - static_assert(std::swappable<_Flat_map_iterator>); - // Destructible - ~_Flat_map_iterator() = default; - - using iterator_category = _STD random_access_iterator_tag; - using difference_type = ptrdiff_t; - using value_type = flat_map::value_type; - using pointer = value_type*; - using reference = value_type&; - - private: - typename key_container_type::iterator _Key_it; - typename mapped_container_type::iterator _Mapped_it; - }; }; _STD_END From e97f528165a549cac82a49aa8a73d35093a2e300 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Thu, 20 Jul 2023 18:09:00 +0800 Subject: [PATCH 009/100] Continue implementing iterator --- stl/inc/flat_map | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 39bd0c69b98..a5cdb228a3b 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -48,8 +48,28 @@ class flat_map { using iterator_category = _STD random_access_iterator_tag; using difference_type = ptrdiff_t; using value_type = flat_map::value_type; - using pointer = value_type*; - using reference = value_type&; + using pointer = void; // Not a pointer + using reference = value_type; + + reference operator * () const { + return std::make_pair(*_Key_it, *_Mapped_it); + } + + type& operator ++ () { + ++_Key_it; + ++_Mapped_it; + return *this; + } + + type operator ++ (int) { + type _Tmp = *this; + ++*this; + return _Tmp; + } + + auto operator <=> (const type& _Right) const { + return _Key_it <=> _Right._Key_it; + } private: _Key_iterator_t _Key_it; From ab27b1e0ff96c34f919ba215ca4f550186a899a9 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Fri, 21 Jul 2023 15:48:24 +0800 Subject: [PATCH 010/100] Finish iterator --- stl/inc/flat_map | 196 +++++++++++++++++++++++++++++++---------------- 1 file changed, 130 insertions(+), 66 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index a5cdb228a3b..5fa2f02dd4c 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -23,61 +23,139 @@ inline constexpr sorted_unique_t sorted_unique {}; template concept _Valid_Allocator_for_flat_map = _STD uses_allocator_v<_Key_container, _Alloc> && _STD uses_allocator_v<_Mapped_container, _Alloc>; +template +struct _Flat_value_compare { + struct type{ + public: + bool operator () (_STD pair _X, _STD pair _Y) const { + return _Key_compare_for_val(_X.first, _Y.first); + } + + type(_Key_compare _Comp) : _Key_compare_for_val(_Comp) {} + + private: + _Key_compare _Key_compare_for_val; + }; +}; + +template +struct _Flat_Container { + struct type { + _Key_container keys; + _Mapped_container values; + }; +}; + // Implementation +template <_STD random_access_iterator _Key_iterator_t, _STD random_access_iterator _Mapped_iterator_t> +class _Flat_map_iterator_Impl{ + public: + class type{ + public: + type() = default; + // Copy-constructible + type(const type&) = default; + // Copy-assignable + type& operator = (const type&) = default; + // Move-assignable + type& operator = (type&&) = default; + // Swappable + // Destructible + ~type() = default; + + using iterator_category = _STD random_access_iterator_tag; + using difference_type = ptrdiff_t; + using value_type = _STD pair<_STD iter_value_t<_Key_iterator_t>, _STD iter_value_t<_Mapped_iterator_t>>; + using pointer = void; // Not a pointer + using reference = value_type; + + reference operator * () const { + return _STD make_pair(*_Key_it, *_Mapped_it); + } + + type& operator ++ () { + ++_Key_it; + ++_Mapped_it; + return *this; + } + + type operator ++ (int) { + type _Tmp = *this; + ++*this; + return _Tmp; + } + + bool operator == (const type& _Right) const { + return _Key_it == _Right._Key_it; + } + + bool operator <=> (const type& _Right) const { + return _Key_it <=> _Right._Key_it; + } + + type& operator -- () { + --_Key_it; + --_Mapped_it; + return *this; + } + + type operator -- (int) { + type _Tmp = *this; + --*this; + return _Tmp; + } + + type& operator += (difference_type _Off) { + _Key_it += _Off; + _Mapped_it += _Off; + return *this; + } + + type& operator -= (difference_type _Off) { + _Key_it -= _Off; + _Mapped_it -= _Off; + return *this; + } + + type operator + (difference_type _Off) const { + type _Tmp = *this; + return _Tmp += _Off; + } + + type operator - (difference_type _Off) const { + type _Tmp = *this; + return _Tmp -= _Off; + } + + reference operator [] (difference_type _Off) const { + return *(*this + _Off); + } + + friend difference_type operator - (const type& _Left, const type& _Right); + friend type operator + (difference_type _Off, const type& _Right); + + private: + _Key_iterator_t _Key_it; + _Mapped_iterator_t _Mapped_it; + }; + + static_assert(_STD swappable); +}; + +template <_STD random_access_iterator _Key_iterator_t, _STD random_access_iterator _Mapped_iterator_t> +_EXPORT_STD typename _Flat_map_iterator_Impl<_Key_iterator_t, _Mapped_iterator_t>::type::difference_type operator - (const typename _Flat_map_iterator_Impl<_Key_iterator_t, _Mapped_iterator_t>::type& _Left, const typename _Flat_map_iterator_Impl<_Key_iterator_t, _Mapped_iterator_t>::type& _Right) { + return _Left._Key_it - _Right._Key_it; +} + +template <_STD random_access_iterator _Key_iterator_t, _STD random_access_iterator _Mapped_iterator_t> +_EXPORT_STD typename _Flat_map_iterator_Impl<_Key_iterator_t, _Mapped_iterator_t>::type operator + (typename _Flat_map_iterator_Impl<_Key_iterator_t, _Mapped_iterator_t>::type::difference_type _Off, const typename _Flat_map_iterator_Impl<_Key_iterator_t, _Mapped_iterator_t>::type& _Right) { + return _Right + _Off; +} + _EXPORT_STD template requires same_as && same_as class flat_map { - private: - template <_STD random_access_iterator _Key_iterator_t, _STD random_access_iterator _Mapped_iterator_t> - class _Flat_map_iterator_Impl{ - public: - class type{ - public: - type() = default; - // Copy-constructible - type(const type&) = default; - // Copy-assignable - type& operator = (const type&) = default; - // Move-assignable - type& operator = (type&&) = default; - // Swappable - // Destructible - ~type() = default; - - using iterator_category = _STD random_access_iterator_tag; - using difference_type = ptrdiff_t; - using value_type = flat_map::value_type; - using pointer = void; // Not a pointer - using reference = value_type; - - reference operator * () const { - return std::make_pair(*_Key_it, *_Mapped_it); - } - - type& operator ++ () { - ++_Key_it; - ++_Mapped_it; - return *this; - } - - type operator ++ (int) { - type _Tmp = *this; - ++*this; - return _Tmp; - } - - auto operator <=> (const type& _Right) const { - return _Key_it <=> _Right._Key_it; - } - - private: - _Key_iterator_t _Key_it; - _Mapped_iterator_t _Mapped_it; - }; - - static_assert(_STD swappable); - }; public: using key_type = Key; using mapped_type = T; @@ -96,22 +174,8 @@ class flat_map { static_assert(_STD random_access_iterator); - class value_compare { - public: - value_compare(key_compare _Comp) : _Key_compare_for_val(_Comp) {} - - bool operator () (const_reference _X, const_reference _Y) const { - return _Key_compare_for_val(_X.first, _Y.first); - } - - private: - key_compare _Key_compare_for_val; - }; - - struct containers { - key_container_type keys; - mapped_container_type values; - }; + using value_compare = typename _Flat_value_compare::type; + using containers = typename _Flat_Container::type; // 24.6.8.3 construct / copy / destroy explicit flat_map(const key_compare& _Comp) : _Key_compare(_Comp), _Data() {} From 54625c6dd661af564f43778e80145627ae831fae Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Fri, 21 Jul 2023 21:29:04 +0800 Subject: [PATCH 011/100] clang-format --- stl/inc/flat_map | 199 ++++++++++++++++++++++++++++------------------- 1 file changed, 119 insertions(+), 80 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 5fa2f02dd4c..1f07970da2f 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -1,10 +1,10 @@ #pragma once #include -#include #include #include #include +#include #include #include #include @@ -14,26 +14,31 @@ _STD_BEGIN -template , class KeyContainer = vector, class MappedContainer = vector> requires same_as && same_as +template , class KeyContainer = vector, + class MappedContainer = vector> + requires same_as && same_as class flat_map; -struct sorted_unique_t { explicit sorted_unique_t() = default; }; -inline constexpr sorted_unique_t sorted_unique {}; +struct sorted_unique_t { + explicit sorted_unique_t() = default; +}; +inline constexpr sorted_unique_t sorted_unique{}; template -concept _Valid_Allocator_for_flat_map = _STD uses_allocator_v<_Key_container, _Alloc> && _STD uses_allocator_v<_Mapped_container, _Alloc>; +concept _Valid_Allocator_for_flat_map = + _STD uses_allocator_v<_Key_container, _Alloc> && _STD uses_allocator_v<_Mapped_container, _Alloc>; template struct _Flat_value_compare { - struct type{ - public: - bool operator () (_STD pair _X, _STD pair _Y) const { + struct type { + public: + bool operator()(_STD pair _X, _STD pair _Y) const { return _Key_compare_for_val(_X.first, _Y.first); } type(_Key_compare _Comp) : _Key_compare_for_val(_Comp) {} - private: + private: _Key_compare _Key_compare_for_val; }; }; @@ -49,93 +54,93 @@ struct _Flat_Container { // Implementation template <_STD random_access_iterator _Key_iterator_t, _STD random_access_iterator _Mapped_iterator_t> -class _Flat_map_iterator_Impl{ +class _Flat_map_iterator_Impl { +public: + class type { public: - class type{ - public: type() = default; // Copy-constructible type(const type&) = default; // Copy-assignable - type& operator = (const type&) = default; + type& operator=(const type&) = default; // Move-assignable - type& operator = (type&&) = default; + type& operator=(type&&) = default; // Swappable // Destructible ~type() = default; using iterator_category = _STD random_access_iterator_tag; - using difference_type = ptrdiff_t; - using value_type = _STD pair<_STD iter_value_t<_Key_iterator_t>, _STD iter_value_t<_Mapped_iterator_t>>; - using pointer = void; // Not a pointer - using reference = value_type; + using difference_type = ptrdiff_t; + using value_type = _STD pair<_STD iter_value_t<_Key_iterator_t>, _STD iter_value_t<_Mapped_iterator_t>>; + using pointer = void; // Not a pointer + using reference = value_type; - reference operator * () const { + reference operator*() const { return _STD make_pair(*_Key_it, *_Mapped_it); } - type& operator ++ () { + type& operator++() { ++_Key_it; ++_Mapped_it; return *this; } - type operator ++ (int) { + type operator++(int) { type _Tmp = *this; ++*this; return _Tmp; } - bool operator == (const type& _Right) const { + bool operator==(const type& _Right) const { return _Key_it == _Right._Key_it; } - bool operator <=> (const type& _Right) const { + bool operator<=>(const type& _Right) const { return _Key_it <=> _Right._Key_it; } - type& operator -- () { + type& operator--() { --_Key_it; --_Mapped_it; return *this; } - type operator -- (int) { + type operator--(int) { type _Tmp = *this; --*this; return _Tmp; } - type& operator += (difference_type _Off) { + type& operator+=(difference_type _Off) { _Key_it += _Off; _Mapped_it += _Off; return *this; } - type& operator -= (difference_type _Off) { + type& operator-=(difference_type _Off) { _Key_it -= _Off; _Mapped_it -= _Off; return *this; } - type operator + (difference_type _Off) const { + type operator+(difference_type _Off) const { type _Tmp = *this; return _Tmp += _Off; } - type operator - (difference_type _Off) const { + type operator-(difference_type _Off) const { type _Tmp = *this; return _Tmp -= _Off; } - reference operator [] (difference_type _Off) const { + reference operator[](difference_type _Off) const { return *(*this + _Off); } - friend difference_type operator - (const type& _Left, const type& _Right); - friend type operator + (difference_type _Off, const type& _Right); + friend difference_type operator-(const type& _Left, const type& _Right); + friend type operator+(difference_type _Off, const type& _Right); - private: + private: _Key_iterator_t _Key_it; _Mapped_iterator_t _Mapped_it; }; @@ -144,117 +149,151 @@ class _Flat_map_iterator_Impl{ }; template <_STD random_access_iterator _Key_iterator_t, _STD random_access_iterator _Mapped_iterator_t> -_EXPORT_STD typename _Flat_map_iterator_Impl<_Key_iterator_t, _Mapped_iterator_t>::type::difference_type operator - (const typename _Flat_map_iterator_Impl<_Key_iterator_t, _Mapped_iterator_t>::type& _Left, const typename _Flat_map_iterator_Impl<_Key_iterator_t, _Mapped_iterator_t>::type& _Right) { +_EXPORT_STD typename _Flat_map_iterator_Impl<_Key_iterator_t, _Mapped_iterator_t>::type::difference_type operator-( + const typename _Flat_map_iterator_Impl<_Key_iterator_t, _Mapped_iterator_t>::type& _Left, + const typename _Flat_map_iterator_Impl<_Key_iterator_t, _Mapped_iterator_t>::type& _Right) { return _Left._Key_it - _Right._Key_it; } template <_STD random_access_iterator _Key_iterator_t, _STD random_access_iterator _Mapped_iterator_t> -_EXPORT_STD typename _Flat_map_iterator_Impl<_Key_iterator_t, _Mapped_iterator_t>::type operator + (typename _Flat_map_iterator_Impl<_Key_iterator_t, _Mapped_iterator_t>::type::difference_type _Off, const typename _Flat_map_iterator_Impl<_Key_iterator_t, _Mapped_iterator_t>::type& _Right) { +_EXPORT_STD typename _Flat_map_iterator_Impl<_Key_iterator_t, _Mapped_iterator_t>::type operator+( + typename _Flat_map_iterator_Impl<_Key_iterator_t, _Mapped_iterator_t>::type::difference_type _Off, + const typename _Flat_map_iterator_Impl<_Key_iterator_t, _Mapped_iterator_t>::type& _Right) { return _Right + _Off; } _EXPORT_STD -template requires same_as && same_as +template + requires same_as && same_as class flat_map { - public: - using key_type = Key; - using mapped_type = T; - using value_type = pair; - using key_compare = Compare; - using reference = pair; - using const_reference = pair; - using size_type = size_t; - using difference_type = ptrdiff_t; - using key_container_type = KeyContainer; - using mapped_container_type = MappedContainer; - using iterator = _Flat_map_iterator_Impl::type; - using const_iterator = _Flat_map_iterator_Impl::type; - using reverse_iterator = _STD reverse_iterator; +public: + using key_type = Key; + using mapped_type = T; + using value_type = pair; + using key_compare = Compare; + using reference = pair; + using const_reference = pair; + using size_type = size_t; + using difference_type = ptrdiff_t; + using key_container_type = KeyContainer; + using mapped_container_type = MappedContainer; + using iterator = _Flat_map_iterator_Impl::type; + using const_iterator = _Flat_map_iterator_Impl::type; + using reverse_iterator = _STD reverse_iterator; using const_reverse_iterator = _STD reverse_iterator; static_assert(_STD random_access_iterator); using value_compare = typename _Flat_value_compare::type; - using containers = typename _Flat_Container::type; + using containers = typename _Flat_Container::type; // 24.6.8.3 construct / copy / destroy explicit flat_map(const key_compare& _Comp) : _Key_compare(_Comp), _Data() {} - flat_map(): flat_map(key_compare()) {} + flat_map() : flat_map(key_compare()) {} template <_Valid_Allocator_for_flat_map Allocator> explicit flat_map(const Allocator& _Alloc) : flat_map(key_compare(), _Alloc) {} template <_Valid_Allocator_for_flat_map Allocator> - explicit flat_map(const key_compare& _Comp, const Allocator& _Alloc): _Key_compare(_Comp), _Data{.keys = _STD make_obj_using_allocator(_Alloc), .values = _STD make_obj_using_allocator(_Alloc)} {} + explicit flat_map(const key_compare& _Comp, const Allocator& _Alloc) + : _Key_compare(_Comp), _Data{.keys = _STD make_obj_using_allocator(_Alloc), + .values = _STD make_obj_using_allocator(_Alloc)} {} - flat_map(key_container_type _Key_cont, mapped_container_type _Mapped_cont): flat_map(sorted_unique_t(), _Key_cont, _Mapped_cont) { + flat_map(key_container_type _Key_cont, mapped_container_type _Mapped_cont) + : flat_map(sorted_unique_t(), _Key_cont, _Mapped_cont) { _Sort_and_dedup(); } template <_Valid_Allocator_for_flat_map Allocator> - flat_map(const key_container_type& _Key_cont, const mapped_container_type& _Mapped_cont, const Allocator& _Alloc): flat_map(sorted_unique_t(), _Key_cont, _Mapped_cont, _Alloc) { + flat_map(const key_container_type& _Key_cont, const mapped_container_type& _Mapped_cont, const Allocator& _Alloc) + : flat_map(sorted_unique_t(), _Key_cont, _Mapped_cont, _Alloc) { _Sort_and_dedup(); } - flat_map(sorted_unique_t _Sorted_unique, key_container_type _Key_cont, mapped_container_type _Mapped_cont): _Key_compare(key_compare()), _Data {.keys = _STD move(_Key_cont), .values = _STD move(_Mapped_cont)} {} + flat_map(sorted_unique_t _Sorted_unique, key_container_type _Key_cont, mapped_container_type _Mapped_cont) + : _Key_compare(key_compare()), _Data{.keys = _STD move(_Key_cont), .values = _STD move(_Mapped_cont)} {} template <_Valid_Allocator_for_flat_map Allocator> - flat_map(sorted_unique_t _Sorted_unique, const key_container_type& _Key_cont, const mapped_container_type& _Mapped_cont, const Allocator& _Alloc): _Key_compare(key_compare()), _Data{.keys = _STD make_obj_using_allocator(_Alloc, _Key_cont), .values = _STD make_obj_using_allocator(_Alloc, _Mapped_cont)} {} + flat_map(sorted_unique_t _Sorted_unique, const key_container_type& _Key_cont, + const mapped_container_type& _Mapped_cont, const Allocator& _Alloc) + : _Key_compare(key_compare()), + _Data{.keys = _STD make_obj_using_allocator(_Alloc, _Key_cont), + .values = _STD make_obj_using_allocator(_Alloc, _Mapped_cont)} {} template <_STD input_iterator _InputIterator> flat_map(_InputIterator _First, _InputIterator _Last, const key_compare& _Comp = key_compare()) : flat_map(_Comp) { insert(_First, _Last); } - template <_STD input_iterator _InputIterator, _Valid_Allocator_for_flat_map Allocator> - flat_map(_InputIterator _First, _InputIterator _Last, const key_compare& _Comp, const Allocator& _Alloc): flat_map(_Comp, _Alloc) { + template <_STD input_iterator _InputIterator, + _Valid_Allocator_for_flat_map Allocator> + flat_map(_InputIterator _First, _InputIterator _Last, const key_compare& _Comp, const Allocator& _Alloc) + : flat_map(_Comp, _Alloc) { insert(_First, _Last); } template <_Container_compatible_range R> - flat_map(_STD from_range_t _From_range, R&& _Range) : flat_map(_From_range, _STD forward(_Range), key_compare()) {} + flat_map(_STD from_range_t _From_range, R&& _Range) + : flat_map(_From_range, _STD forward(_Range), key_compare()) {} - template <_Container_compatible_range R, _Valid_Allocator_for_flat_map Allocator> - flat_map(_STD from_range_t _From_range, R&& _Range, const Allocator& _Alloc): flat_map(_From_range, _STD forward(_Range), key_compare(), _Alloc) {} + template <_Container_compatible_range R, + _Valid_Allocator_for_flat_map Allocator> + flat_map(_STD from_range_t _From_range, R&& _Range, const Allocator& _Alloc) + : flat_map(_From_range, _STD forward(_Range), key_compare(), _Alloc) {} template <_Container_compatible_range R> flat_map(_STD from_range_t _From_range, R&& _Range, const key_compare& _Comp) : flat_map(_Comp) { insert_range(_STD forward(_Range)); } - template <_Container_compatible_range R, _Valid_Allocator_for_flat_map Allocator> - flat_map(_STD from_range_t _From_range, R&& _Range, const key_compare& _Comp, const Allocator& _Alloc): flat_map(_Comp, _Alloc) { + template <_Container_compatible_range R, + _Valid_Allocator_for_flat_map Allocator> + flat_map(_STD from_range_t _From_range, R&& _Range, const key_compare& _Comp, const Allocator& _Alloc) + : flat_map(_Comp, _Alloc) { insert_range(_STD forward(_Range)); } template <_STD input_iterator _InputIterator> - flat_map(sorted_unique_t _S, _InputIterator _First, _InputIterator _Last, const key_compare& _Comp = key_compare()): flat_map(_Comp) { + flat_map(sorted_unique_t _S, _InputIterator _First, _InputIterator _Last, const key_compare& _Comp = key_compare()) + : flat_map(_Comp) { insert(_S, _First, _Last); } - template <_STD input_iterator _InputIterator, _Valid_Allocator_for_flat_map Allocator> - flat_map(sorted_unique_t _S, _InputIterator _First, _InputIterator _Last, const key_compare& _Comp, const Allocator& _Alloc): flat_map(_Comp, _Alloc) { + template <_STD input_iterator _InputIterator, + _Valid_Allocator_for_flat_map Allocator> + flat_map(sorted_unique_t _S, _InputIterator _First, _InputIterator _Last, const key_compare& _Comp, + const Allocator& _Alloc) + : flat_map(_Comp, _Alloc) { insert(_S, _First, _Last); } - template <_STD input_iterator _InputIterator, _Valid_Allocator_for_flat_map Allocator> - flat_map(sorted_unique_t _S, _InputIterator _First, _InputIterator _Last, const Allocator& _Alloc): flat_map(_S, _First, _Last, key_compare(), _Alloc) {} + template <_STD input_iterator _InputIterator, + _Valid_Allocator_for_flat_map Allocator> + flat_map(sorted_unique_t _S, _InputIterator _First, _InputIterator _Last, const Allocator& _Alloc) + : flat_map(_S, _First, _Last, key_compare(), _Alloc) {} - flat_map(initializer_list _I, const key_compare& _Comp = key_compare()): flat_map(_I.begin(), _I.end(), _Comp) {} + flat_map(initializer_list _I, const key_compare& _Comp = key_compare()) + : flat_map(_I.begin(), _I.end(), _Comp) {} template <_Valid_Allocator_for_flat_map Allocator> - flat_map(initializer_list _I, const key_compare& _Comp, const Allocator& _Alloc): flat_map(_I.begin(), _I.end(), _Comp, _Alloc) {} + flat_map(initializer_list _I, const key_compare& _Comp, const Allocator& _Alloc) + : flat_map(_I.begin(), _I.end(), _Comp, _Alloc) {} template <_Valid_Allocator_for_flat_map Allocator> - flat_map(initializer_list _I, const Allocator& _Alloc): flat_map(_I, key_compare(), _Alloc) {} + flat_map(initializer_list _I, const Allocator& _Alloc) : flat_map(_I, key_compare(), _Alloc) {} - flat_map(sorted_unique_t _S, initializer_list _I, const key_compare& _Comp = key_compare()): flat_map(_S, _I.begin(), _I.end(), _Comp) {} + flat_map(sorted_unique_t _S, initializer_list _I, const key_compare& _Comp = key_compare()) + : flat_map(_S, _I.begin(), _I.end(), _Comp) {} template <_Valid_Allocator_for_flat_map Allocator> - flat_map(sorted_unique_t _S, initializer_list _I, const key_compare& _Comp, const Allocator& _Alloc): flat_map(_S, _I.begin(), _I.end(), _Comp, _Alloc) {} + flat_map(sorted_unique_t _S, initializer_list _I, const key_compare& _Comp, const Allocator& _Alloc) + : flat_map(_S, _I.begin(), _I.end(), _Comp, _Alloc) {} template <_Valid_Allocator_for_flat_map Allocator> - flat_map(sorted_unique_t _S, initializer_list _I, const Allocator& _Alloc): flat_map(_S, _I, key_compare(), _Alloc) {} + flat_map(sorted_unique_t _S, initializer_list _I, const Allocator& _Alloc) + : flat_map(_S, _I, key_compare(), _Alloc) {} // observers key_compare key_comp() const { @@ -273,28 +312,28 @@ class flat_map { return _Data.values; } - private: +private: key_compare _Key_compare; containers _Data; struct _Key_equal { key_compare _Key_compare; _Key_equal(key_compare _Comp) : _Key_compare(_Comp) {} - bool operator () (const_reference _X, const_reference _Y) const { + bool operator()(const_reference _X, const_reference _Y) const { return !_Key_compare(_X.first, _Y.first) && !_Key_compare(_Y.first, _X.first); } }; - void _Sort_and_dedup(){ + void _Sort_and_dedup() { auto _Zip_view = _RANGES views::zip(_Data.keys, _Data.values); _STD sort(_Zip_view.begin(), _Zip_view.end(), value_compare(_Key_compare)); - auto _Subrange = _RANGES unique(_Zip_view, _Key_equal(_Key_compare)); + auto _Subrange = _RANGES unique(_Zip_view, _Key_equal(_Key_compare)); auto _Remaining_count = _STD distance(_Zip_view.begin(), _Subrange.begin()); _Data.keys.erase(_Data.keys.begin() + _Remaining_count, _Data.keys.end()); _Data.values.erase(_Data.values.begin() + _Remaining_count, _Data.values.end()); - }; + } }; _STD_END From 4db32dd817bd3bddf12e0c7c76f8c4b0be1742fc Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Fri, 21 Jul 2023 21:29:32 +0800 Subject: [PATCH 012/100] Fix: return type of <=> should not be bool --- stl/inc/flat_map | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 1f07970da2f..bb3af2577b9 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -95,7 +95,7 @@ public: return _Key_it == _Right._Key_it; } - bool operator<=>(const type& _Right) const { + auto operator<=>(const type& _Right) const { return _Key_it <=> _Right._Key_it; } From 8d704c77aec8aef1881c2a67d71e75dc5a686540 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Fri, 21 Jul 2023 21:32:02 +0800 Subject: [PATCH 013/100] Overload operator - as a member function --- stl/inc/flat_map | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index bb3af2577b9..bafe12a2819 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -137,7 +137,10 @@ public: return *(*this + _Off); } - friend difference_type operator-(const type& _Left, const type& _Right); + difference_type operator-(const type& _Right) const { + return _Key_it - _Right._Key_it; + } + friend type operator+(difference_type _Off, const type& _Right); private: @@ -148,13 +151,6 @@ public: static_assert(_STD swappable); }; -template <_STD random_access_iterator _Key_iterator_t, _STD random_access_iterator _Mapped_iterator_t> -_EXPORT_STD typename _Flat_map_iterator_Impl<_Key_iterator_t, _Mapped_iterator_t>::type::difference_type operator-( - const typename _Flat_map_iterator_Impl<_Key_iterator_t, _Mapped_iterator_t>::type& _Left, - const typename _Flat_map_iterator_Impl<_Key_iterator_t, _Mapped_iterator_t>::type& _Right) { - return _Left._Key_it - _Right._Key_it; -} - template <_STD random_access_iterator _Key_iterator_t, _STD random_access_iterator _Mapped_iterator_t> _EXPORT_STD typename _Flat_map_iterator_Impl<_Key_iterator_t, _Mapped_iterator_t>::type operator+( typename _Flat_map_iterator_Impl<_Key_iterator_t, _Mapped_iterator_t>::type::difference_type _Off, From e90802370bffa9ce9791aaa6abaa4d536afb7f38 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Fri, 21 Jul 2023 21:33:53 +0800 Subject: [PATCH 014/100] Use traditional header guards --- stl/inc/flat_map | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index bafe12a2819..b0647729bdd 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -1,4 +1,5 @@ -#pragma once +#ifndef _FLAT_MAP_ +#define _FLAT_MAP_ #include #include @@ -333,3 +334,5 @@ private: }; _STD_END + +#endif // _FLAT_MAP_ From 33d79c29772f7ab07292213e926b2e29fe0a200b Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Fri, 21 Jul 2023 23:19:25 +0800 Subject: [PATCH 015/100] Add common header stuff --- stl/inc/flat_map | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index b0647729bdd..544c0703d5a 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -1,5 +1,12 @@ +// flat_map standard header + +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + #ifndef _FLAT_MAP_ #define _FLAT_MAP_ +#include +#if _STL_COMPILER_PREPROCESSOR #include #include @@ -13,6 +20,13 @@ #include #include +#pragma pack(push, _CRT_PACKING) +#pragma warning(push, _STL_WARNING_LEVEL) +#pragma warning(disable : _STL_DISABLED_WARNINGS) +_STL_DISABLE_CLANG_WARNINGS +#pragma push_macro("new") +#undef new + _STD_BEGIN template , class KeyContainer = vector, @@ -335,4 +349,9 @@ private: _STD_END +#pragma pop_macro("new") +_STL_RESTORE_CLANG_WARNINGS +#pragma warning(pop) +#pragma pack(pop) +#endif // _STL_COMPILER_PREPROCESSOR #endif // _FLAT_MAP_ From 64228a032fbdc8ef260edf3a5f79b4f8448bef27 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Fri, 21 Jul 2023 23:59:07 +0800 Subject: [PATCH 016/100] Add capacity functions --- stl/inc/flat_map | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 544c0703d5a..c5071d7b034 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -306,6 +306,19 @@ public: flat_map(sorted_unique_t _S, initializer_list _I, const Allocator& _Alloc) : flat_map(_S, _I, key_compare(), _Alloc) {} + // 24.6.8.4 capacity + [[nodiscard]] bool empty() const noexcept { + return _Data.keys.empty(); + } + + size_type size() const noexcept { + return _Data.keys.size(); + } + + size_type max_size() const noexcept { + return _STD min(_Data.keys.max_size(), _Data.values.max_size()); + } + // observers key_compare key_comp() const { return _Key_compare; @@ -335,9 +348,9 @@ private: } }; - void _Sort_and_dedup() { + void _SortAndDedup() { auto _Zip_view = _RANGES views::zip(_Data.keys, _Data.values); - _STD sort(_Zip_view.begin(), _Zip_view.end(), value_compare(_Key_compare)); + _RANGES sort(_Zip_view.begin(), _Zip_view.end(), value_compare(_Key_compare)); auto _Subrange = _RANGES unique(_Zip_view, _Key_equal(_Key_compare)); auto _Remaining_count = _STD distance(_Zip_view.begin(), _Subrange.begin()); From 6f360d4cc33fa524b40f59f32d3dd4f76a9285b0 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Sat, 22 Jul 2023 00:39:48 +0800 Subject: [PATCH 017/100] Add function signatures for elemental access --- stl/inc/flat_map | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index c5071d7b034..e81efe95cfa 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -43,6 +43,9 @@ template concept _Valid_Allocator_for_flat_map = _STD uses_allocator_v<_Key_container, _Alloc> && _STD uses_allocator_v<_Mapped_container, _Alloc>; +template +concept _Compare_is_transparent = requires { typename _Compare::is_transparent; } + template struct _Flat_value_compare { struct type { @@ -319,6 +322,19 @@ public: return _STD min(_Data.keys.max_size(), _Data.values.max_size()); } + // 24.6.8.5 elemental access + mapped_type& operator[](const key_type& _Key); // TODO: implement + mapped_type& operator[](key_type&& _Key); // TODO: implement + template + mapped_type& operator[](_C&& _Key) + requires _Compare_is_transparent; // TODO: implement + + template + auto&& at(this _Self_t&& _Self, const key_type& _Key); // TODO: implement + template + auto&& at(this _Self_t&& _Self, const _C& _Key) + requires _Compare_is_transparent; // TODO: implement + // observers key_compare key_comp() const { return _Key_compare; From 1414cf928e9ddd0d3d0a63229f6ad5641bc26ee3 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Mon, 24 Jul 2023 13:59:26 +0800 Subject: [PATCH 018/100] Improve iterator implementation --- stl/inc/flat_map | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index e81efe95cfa..777719753cf 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -87,14 +87,28 @@ public: // Destructible ~type() = default; - using iterator_category = _STD random_access_iterator_tag; + using iterator_category = _STD input_iterator_tag; using difference_type = ptrdiff_t; using value_type = _STD pair<_STD iter_value_t<_Key_iterator_t>, _STD iter_value_t<_Mapped_iterator_t>>; - using pointer = void; // Not a pointer - using reference = value_type; + + private: + class _Arrow_Proxy: public _STD pair<_STD iter_value_t<_Key_iterator_t>, _STD iter_value_t<_Mapped_iterator_t>> { + public: + _Arrow_Proxy* operator->() noexcept { + return this; + } + }; + + public: + using pointer = _Arrow_Proxy; + using reference = _STD pair<_STD iter_const_reference_t<_Key_iterator_t>, _STD iter_reference_t<_Mapped_iterator_t>>; reference operator*() const { - return _STD make_pair(*_Key_it, *_Mapped_it); + return reference {*_Key_it, *_Mapped_it}; + } + + pointer operator->() const { + return pointer {*_Key_it, *_Mapped_it}; } type& operator++() { From 90668a5549e8ddcda73c873b817b81a2bd62cb99 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Mon, 24 Jul 2023 13:59:55 +0800 Subject: [PATCH 019/100] Implement operator=(std::initializer_list) --- stl/inc/flat_map | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 777719753cf..0348d9157c7 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -323,6 +323,12 @@ public: flat_map(sorted_unique_t _S, initializer_list _I, const Allocator& _Alloc) : flat_map(_S, _I, key_compare(), _Alloc) {} + flat_map& operator=(initializer_list _I) { + clear(); + insert(_I.begin(), _I.end()); + return *this; + } + // 24.6.8.4 capacity [[nodiscard]] bool empty() const noexcept { return _Data.keys.empty(); From 44dd88a0ae746780bd03a2585875b60460ecfe0c Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Mon, 24 Jul 2023 16:06:25 +0800 Subject: [PATCH 020/100] Implement iterator functions and fix compile errors --- stl/inc/flat_map | 62 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 4 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 0348d9157c7..0f36ce547a0 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -44,7 +44,7 @@ concept _Valid_Allocator_for_flat_map = _STD uses_allocator_v<_Key_container, _Alloc> && _STD uses_allocator_v<_Mapped_container, _Alloc>; template -concept _Compare_is_transparent = requires { typename _Compare::is_transparent; } +concept _Compare_is_transparent = requires { typename _Compare::is_transparent; }; template struct _Flat_value_compare { @@ -77,6 +77,7 @@ public: class type { public: type() = default; + type(_Key_iterator_t _Key_it, _Mapped_iterator_t _Mapped_it) : _Key_it(_Key_it), _Mapped_it(_Mapped_it) {} // Copy-constructible type(const type&) = default; // Copy-assignable @@ -212,7 +213,7 @@ public: using reverse_iterator = _STD reverse_iterator; using const_reverse_iterator = _STD reverse_iterator; - static_assert(_STD random_access_iterator); + static_assert(_STD input_iterator); using value_compare = typename _Flat_value_compare::type; using containers = typename _Flat_Container::type; @@ -231,13 +232,13 @@ public: flat_map(key_container_type _Key_cont, mapped_container_type _Mapped_cont) : flat_map(sorted_unique_t(), _Key_cont, _Mapped_cont) { - _Sort_and_dedup(); + _SortAndDedup(); } template <_Valid_Allocator_for_flat_map Allocator> flat_map(const key_container_type& _Key_cont, const mapped_container_type& _Mapped_cont, const Allocator& _Alloc) : flat_map(sorted_unique_t(), _Key_cont, _Mapped_cont, _Alloc) { - _Sort_and_dedup(); + _SortAndDedup(); } flat_map(sorted_unique_t _Sorted_unique, key_container_type _Key_cont, mapped_container_type _Mapped_cont) @@ -329,6 +330,54 @@ public: return *this; } + iterator begin() noexcept { + return iterator {_Data.keys.cbegin(), _Data.values.begin()}; + } + + const_iterator begin() const noexcept { + return const_iterator {_Data.keys.cbegin(), _Data.values.cbegin()}; + } + + iterator end() noexcept { + return iterator {_Data.keys.cend(), _Data.values.end()}; + } + + const_iterator end() const noexcept { + return const_iterator {_Data.keys.cend(), _Data.values.cend()}; + } + + reverse_iterator rbegin() noexcept { + return _STD make_reverse_iterator(end()); + } + + const_reverse_iterator rbegin() const noexcept { + return _STD make_reverse_iterator(cend()); + } + + reverse_iterator rend() noexcept { + return _STD make_reverse_iterator(begin()); + } + + const_reverse_iterator rend() const noexcept { + return _STD make_reverse_iterator(cbegin()); + } + + const_iterator cbegin() const noexcept { + return const_iterator {_Data.keys.cbegin(), _Data.values.cbegin()}; + } + + const_iterator cend() const noexcept { + return const_iterator {_Data.keys.cend(), _Data.values.cend()}; + } + + const_reverse_iterator crbegin() const noexcept { + return _STD make_reverse_iterator(cend()); + } + + const_reverse_iterator crend() const noexcept { + return _STD make_reverse_iterator(cbegin()); + } + // 24.6.8.4 capacity [[nodiscard]] bool empty() const noexcept { return _Data.keys.empty(); @@ -355,6 +404,11 @@ public: auto&& at(this _Self_t&& _Self, const _C& _Key) requires _Compare_is_transparent; // TODO: implement + void clear() noexcept { + _Data.keys.clear(); + _Data.values.clear(); + } + // observers key_compare key_comp() const { return _Key_compare; From ea0f6d6d2d66ac465125ac4196f9dcd55b2aafa9 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Mon, 24 Jul 2023 16:07:09 +0800 Subject: [PATCH 021/100] Take review comments Co-authored-by: A. Jiang --- stl/inc/flat_map | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 0f36ce547a0..178210e7c31 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -391,7 +391,7 @@ public: return _STD min(_Data.keys.max_size(), _Data.values.max_size()); } - // 24.6.8.5 elemental access + // [flat.map.access] Access mapped_type& operator[](const key_type& _Key); // TODO: implement mapped_type& operator[](key_type&& _Key); // TODO: implement template From 6c0b4397866467c438f23b2cbb0e3d995a2cf665 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Mon, 24 Jul 2023 16:07:30 +0800 Subject: [PATCH 022/100] Take review comments Co-authored-by: A. Jiang --- stl/inc/flat_map | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 178210e7c31..b4d5023f612 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -218,7 +218,7 @@ public: using value_compare = typename _Flat_value_compare::type; using containers = typename _Flat_Container::type; - // 24.6.8.3 construct / copy / destroy + // [flat.map.cons] Constructors explicit flat_map(const key_compare& _Comp) : _Key_compare(_Comp), _Data() {} flat_map() : flat_map(key_compare()) {} From 1996c46e1ae4cc83febecd6727df9017b92fa0d5 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Mon, 24 Jul 2023 16:07:45 +0800 Subject: [PATCH 023/100] Take review comments Co-authored-by: A. Jiang --- stl/inc/flat_map | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index b4d5023f612..d8a8b635a0e 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -378,7 +378,7 @@ public: return _STD make_reverse_iterator(cbegin()); } - // 24.6.8.4 capacity + // [flat.map.capacity] Capacity [[nodiscard]] bool empty() const noexcept { return _Data.keys.empty(); } From 4a303d8d1aa54fd279ff0bebbd1b9d77ae438ce4 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Mon, 24 Jul 2023 16:19:45 +0800 Subject: [PATCH 024/100] Add _NODISCARD --- stl/inc/flat_map | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index d8a8b635a0e..18abff0821a 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -330,78 +330,78 @@ public: return *this; } - iterator begin() noexcept { + _NODISCARD iterator begin() noexcept { return iterator {_Data.keys.cbegin(), _Data.values.begin()}; } - const_iterator begin() const noexcept { + _NODISCARD const_iterator begin() const noexcept { return const_iterator {_Data.keys.cbegin(), _Data.values.cbegin()}; } - iterator end() noexcept { + _NODISCARD iterator end() noexcept { return iterator {_Data.keys.cend(), _Data.values.end()}; } - const_iterator end() const noexcept { + _NODISCARD const_iterator end() const noexcept { return const_iterator {_Data.keys.cend(), _Data.values.cend()}; } - reverse_iterator rbegin() noexcept { + _NODISCARD reverse_iterator rbegin() noexcept { return _STD make_reverse_iterator(end()); } - const_reverse_iterator rbegin() const noexcept { + _NODISCARD const_reverse_iterator rbegin() const noexcept { return _STD make_reverse_iterator(cend()); } - reverse_iterator rend() noexcept { + _NODISCARD reverse_iterator rend() noexcept { return _STD make_reverse_iterator(begin()); } - const_reverse_iterator rend() const noexcept { + _NODISCARD const_reverse_iterator rend() const noexcept { return _STD make_reverse_iterator(cbegin()); } - const_iterator cbegin() const noexcept { + _NODISCARD const_iterator cbegin() const noexcept { return const_iterator {_Data.keys.cbegin(), _Data.values.cbegin()}; } - const_iterator cend() const noexcept { + _NODISCARD const_iterator cend() const noexcept { return const_iterator {_Data.keys.cend(), _Data.values.cend()}; } - const_reverse_iterator crbegin() const noexcept { + _NODISCARD const_reverse_iterator crbegin() const noexcept { return _STD make_reverse_iterator(cend()); } - const_reverse_iterator crend() const noexcept { + _NODISCARD const_reverse_iterator crend() const noexcept { return _STD make_reverse_iterator(cbegin()); } // [flat.map.capacity] Capacity - [[nodiscard]] bool empty() const noexcept { + _NODISCARD_EMPTY_MEMBER bool empty() const noexcept { return _Data.keys.empty(); } - size_type size() const noexcept { + _NODISCARD size_type size() const noexcept { return _Data.keys.size(); } - size_type max_size() const noexcept { + _NODISCARD size_type max_size() const noexcept { return _STD min(_Data.keys.max_size(), _Data.values.max_size()); } // [flat.map.access] Access - mapped_type& operator[](const key_type& _Key); // TODO: implement - mapped_type& operator[](key_type&& _Key); // TODO: implement + _NODISCARD mapped_type& operator[](const key_type& _Key); // TODO: implement + _NODISCARD mapped_type& operator[](key_type&& _Key); // TODO: implement template - mapped_type& operator[](_C&& _Key) + _NODISCARD mapped_type& operator[](_C&& _Key) requires _Compare_is_transparent; // TODO: implement template - auto&& at(this _Self_t&& _Self, const key_type& _Key); // TODO: implement + _NODISCARD auto&& at(this _Self_t&& _Self, const key_type& _Key); // TODO: implement template - auto&& at(this _Self_t&& _Self, const _C& _Key) + _NODISCARD auto&& at(this _Self_t&& _Self, const _C& _Key) requires _Compare_is_transparent; // TODO: implement void clear() noexcept { From e203f63b9782f4989dd9053fef31bed17f2d9957 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Mon, 24 Jul 2023 16:20:51 +0800 Subject: [PATCH 025/100] Move __cpp_lib_flat_map definition --- stl/inc/yvals_core.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 7d8e1e24254..4e2b748dddc 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -1819,6 +1819,7 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #ifdef __cpp_lib_concepts #define __cpp_lib_containers_ranges 202202L #define __cpp_lib_expected 202211L +#define __cpp_lib_flat_map 202207L #define __cpp_lib_formatters 202302L #endif // defined(__cpp_lib_concepts) @@ -1867,8 +1868,6 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect #endif // defined(__cpp_lib_concepts) #define __cpp_lib_unreachable 202202L - -#define __cpp_lib_flat_map 202207L #endif // _HAS_CXX23 // macros with language mode sensitivity From db09e1fb2d164253faad47401e841674915cb271 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Mon, 24 Jul 2023 16:23:08 +0800 Subject: [PATCH 026/100] Use ranges syntax --- stl/inc/flat_map | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 18abff0821a..90f65f350ac 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -440,7 +440,7 @@ private: void _SortAndDedup() { auto _Zip_view = _RANGES views::zip(_Data.keys, _Data.values); - _RANGES sort(_Zip_view.begin(), _Zip_view.end(), value_compare(_Key_compare)); + _RANGES sort(_Zip_view, value_compare(_Key_compare)); auto _Subrange = _RANGES unique(_Zip_view, _Key_equal(_Key_compare)); auto _Remaining_count = _STD distance(_Zip_view.begin(), _Subrange.begin()); From 2a72290a4452c615d2ae9f551bb42a38310315b7 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Tue, 25 Jul 2023 13:51:15 +0800 Subject: [PATCH 027/100] Adjust iterator category and iterator concept --- stl/inc/flat_map | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 90f65f350ac..d4a24ca7362 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -88,7 +88,8 @@ public: // Destructible ~type() = default; - using iterator_category = _STD input_iterator_tag; + using iterator_category = input_iterator_tag; + using iterator_concept = random_access_iterator_tag; using difference_type = ptrdiff_t; using value_type = _STD pair<_STD iter_value_t<_Key_iterator_t>, _STD iter_value_t<_Mapped_iterator_t>>; From 9b7ae5a87ab9e55db1f23bc0bea5f4343aea9c35 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Tue, 25 Jul 2023 13:52:23 +0800 Subject: [PATCH 028/100] Fix type names for injected-class-name --- stl/inc/flat_map | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index d4a24ca7362..69ef364b90e 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -48,13 +48,13 @@ concept _Compare_is_transparent = requires { typename _Compare::is_transparent; template struct _Flat_value_compare { - struct type { + struct value_compare { public: bool operator()(_STD pair _X, _STD pair _Y) const { return _Key_compare_for_val(_X.first, _Y.first); } - type(_Key_compare _Comp) : _Key_compare_for_val(_Comp) {} + value_compare(_Key_compare _Comp) : _Key_compare_for_val(_Comp) {} private: _Key_compare _Key_compare_for_val; @@ -63,7 +63,7 @@ struct _Flat_value_compare { template struct _Flat_Container { - struct type { + struct container { _Key_container keys; _Mapped_container values; }; @@ -216,8 +216,8 @@ public: static_assert(_STD input_iterator); - using value_compare = typename _Flat_value_compare::type; - using containers = typename _Flat_Container::type; + using value_compare = typename _Flat_value_compare::value_compare; + using containers = typename _Flat_Container::container; // [flat.map.cons] Constructors explicit flat_map(const key_compare& _Comp) : _Key_compare(_Comp), _Data() {} From 029b8d38bdd851a05c3b18d8faf018d3aaa43a42 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Tue, 25 Jul 2023 15:25:33 +0800 Subject: [PATCH 029/100] Refine iterator --- stl/inc/flat_map | 46 ++++++++++++++++++++-------------------------- 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 69ef364b90e..d9a877f70e6 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -94,8 +94,9 @@ public: using value_type = _STD pair<_STD iter_value_t<_Key_iterator_t>, _STD iter_value_t<_Mapped_iterator_t>>; private: - class _Arrow_Proxy: public _STD pair<_STD iter_value_t<_Key_iterator_t>, _STD iter_value_t<_Mapped_iterator_t>> { + class _Arrow_Proxy: public _STD pair<_STD iter_const_reference_t<_Key_iterator_t>, _STD iter_reference_t<_Mapped_iterator_t>> { public: + using _STD pair<_STD iter_const_reference_t<_Key_iterator_t>, _STD iter_reference_t<_Mapped_iterator_t>>::pair; _Arrow_Proxy* operator->() noexcept { return this; } @@ -214,11 +215,16 @@ public: using reverse_iterator = _STD reverse_iterator; using const_reverse_iterator = _STD reverse_iterator; - static_assert(_STD input_iterator); + static_assert(_STD random_access_iterator); using value_compare = typename _Flat_value_compare::value_compare; using containers = typename _Flat_Container::container; +private: + template requires same_as, flat_map> + using _Maybe_const_iterator_t = _STD conditional_t<_STD is_const_v<_STD remove_reference_t>, const_iterator, iterator>; + +public: // [flat.map.cons] Constructors explicit flat_map(const key_compare& _Comp) : _Key_compare(_Comp), _Data() {} flat_map() : flat_map(key_compare()) {} @@ -331,36 +337,24 @@ public: return *this; } - _NODISCARD iterator begin() noexcept { - return iterator {_Data.keys.cbegin(), _Data.values.begin()}; - } - - _NODISCARD const_iterator begin() const noexcept { - return const_iterator {_Data.keys.cbegin(), _Data.values.cbegin()}; - } - - _NODISCARD iterator end() noexcept { - return iterator {_Data.keys.cend(), _Data.values.end()}; - } - - _NODISCARD const_iterator end() const noexcept { - return const_iterator {_Data.keys.cend(), _Data.values.cend()}; - } - - _NODISCARD reverse_iterator rbegin() noexcept { - return _STD make_reverse_iterator(end()); + template + _NODISCARD auto begin(this _Self_t&& _Self) noexcept { + return _Maybe_const_iterator_t<_Self_t&&> { _Self._Data.keys.cbegin(), _Self._Data.values.begin() }; } - _NODISCARD const_reverse_iterator rbegin() const noexcept { - return _STD make_reverse_iterator(cend()); + template + _NODISCARD auto end(this _Self_t&& _Self) noexcept { + return _Maybe_const_iterator_t<_Self_t&&> { _Self._Data.keys.cend(), _Self._Data.values.end() }; } - _NODISCARD reverse_iterator rend() noexcept { - return _STD make_reverse_iterator(begin()); + template + _NODISCARD auto rbegin(this _Self_t&& _Self) noexcept { + return _STD make_reverse_iterator(_Self.end()); } - _NODISCARD const_reverse_iterator rend() const noexcept { - return _STD make_reverse_iterator(cbegin()); + template + _NODISCARD auto rend(this _Self_t&& _Self) noexcept { + return _STD make_reverse_iterator(_Self.begin()); } _NODISCARD const_iterator cbegin() const noexcept { From 7643245827739beff63b56aedaed2a166d5582d2 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Tue, 25 Jul 2023 15:55:27 +0800 Subject: [PATCH 030/100] Add a few _STD --- stl/inc/flat_map | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index d9a877f70e6..adc9723983e 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -208,17 +208,17 @@ public: using difference_type = ptrdiff_t; using key_container_type = KeyContainer; using mapped_container_type = MappedContainer; - using iterator = _Flat_map_iterator_Impl::type; - using const_iterator = _Flat_map_iterator_Impl::type; using reverse_iterator = _STD reverse_iterator; using const_reverse_iterator = _STD reverse_iterator; static_assert(_STD random_access_iterator); - using value_compare = typename _Flat_value_compare::value_compare; - using containers = typename _Flat_Container::container; + using value_compare = typename _STD _Flat_value_compare::value_compare; + using containers = typename _STD _Flat_Container::container; private: template requires same_as, flat_map> From fe27493942e7c8fd54b5f4d2dea3fe3ccc83f4a3 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Tue, 25 Jul 2023 16:43:48 +0800 Subject: [PATCH 031/100] Fix citation --- stl/inc/flat_map | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index adc9723983e..df6b3ae6800 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -225,7 +225,7 @@ private: using _Maybe_const_iterator_t = _STD conditional_t<_STD is_const_v<_STD remove_reference_t>, const_iterator, iterator>; public: - // [flat.map.cons] Constructors + // [flatmap.cons] Constructors explicit flat_map(const key_compare& _Comp) : _Key_compare(_Comp), _Data() {} flat_map() : flat_map(key_compare()) {} @@ -373,7 +373,7 @@ public: return _STD make_reverse_iterator(cbegin()); } - // [flat.map.capacity] Capacity + // [flatmap.capacity] Capacity _NODISCARD_EMPTY_MEMBER bool empty() const noexcept { return _Data.keys.empty(); } @@ -386,7 +386,7 @@ public: return _STD min(_Data.keys.max_size(), _Data.values.max_size()); } - // [flat.map.access] Access + // [flatmap.access] Access _NODISCARD mapped_type& operator[](const key_type& _Key); // TODO: implement _NODISCARD mapped_type& operator[](key_type&& _Key); // TODO: implement template From ba631dea5619f382eebf1ad34e40b858ed0b4348 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Tue, 25 Jul 2023 18:36:54 +0800 Subject: [PATCH 032/100] Start implementing modifiers --- stl/inc/flat_map | 43 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index df6b3ae6800..fc2495a1cd8 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -76,6 +76,8 @@ class _Flat_map_iterator_Impl { public: class type { public: + template requires same_as && same_as + friend class flat_map; type() = default; type(_Key_iterator_t _Key_it, _Mapped_iterator_t _Mapped_it) : _Key_it(_Key_it), _Mapped_it(_Mapped_it) {} // Copy-constructible @@ -208,9 +210,9 @@ public: using difference_type = ptrdiff_t; using key_container_type = KeyContainer; using mapped_container_type = MappedContainer; - using iterator = _STD _Flat_map_iterator_Impl::type; - using const_iterator = _STD _Flat_map_iterator_Impl::type; using reverse_iterator = _STD reverse_iterator; using const_reverse_iterator = _STD reverse_iterator; @@ -337,6 +339,7 @@ public: return *this; } + // [container.reqmts] iterators template _NODISCARD auto begin(this _Self_t&& _Self) noexcept { return _Maybe_const_iterator_t<_Self_t&&> { _Self._Data.keys.cbegin(), _Self._Data.values.begin() }; @@ -373,6 +376,12 @@ public: return _STD make_reverse_iterator(cbegin()); } + // [container.reqmts] clear + void clear() noexcept { + _Data.keys.clear(); + _Data.values.clear(); + } + // [flatmap.capacity] Capacity _NODISCARD_EMPTY_MEMBER bool empty() const noexcept { return _Data.keys.empty(); @@ -399,9 +408,24 @@ public: _NODISCARD auto&& at(this _Self_t&& _Self, const _C& _Key) requires _Compare_is_transparent; // TODO: implement - void clear() noexcept { - _Data.keys.clear(); - _Data.values.clear(); + // [flatmap.modifiers] Modifiers + template + _STD pair emplace(_Args_t&&... _Args) requires _STD is_constructible_v { + value_type _Val(_STD forward<_Args_t>(_Args)...); + iterator _It = lower_bound(_Data.keys.begin(), _Data.keys.end(), _Val.first, _Key_compare); + + if(_It != end() && *(_It._Key_it) == _Val.first) { + // Already exists + return _STD make_pair(_It, false); + } + else{ + // Need to insert + auto _Index = _STD distance(begin(), _It); + _Data.keys.insert(_It._Key_it, _STD move(_Val.first)); + _Data.values.insert(_It._Mapped_it, _STD move(_Val.second)); + // Note: Consider _It invalidated by the insert operation + return _STD make_pair(begin() + _Index, true); + } } // observers @@ -421,6 +445,15 @@ public: return _Data.values; } + // map operations + template + auto lower_bound(this _Self_t&& _Self, const key_type& _X) { + auto _Key_it = _STD lower_bound(_Self._Data.keys.begin(), _Self._Data.keys.end(), _X, _Self._Key_compare); + auto _Dist = _STD distance(_Self._Data.keys.begin(), _Key_it); + auto _Val_it = _Self._Data.values.begin() + _Dist; + return _Maybe_const_iterator_t<_Self_t&&> { _STD move(_Key_it), _STD move(_Val_it) }; + } + private: key_compare _Key_compare; containers _Data; From d5f6e69a3f6ccbaaf59c06f31a0e24026d8f3c98 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Wed, 26 Jul 2023 14:39:38 +0800 Subject: [PATCH 033/100] Revert "Fix citation" This reverts commit 3660aa67bac3484d849ccb4094527868a53eec27. --- stl/inc/flat_map | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index fc2495a1cd8..636ec46d98b 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -227,7 +227,7 @@ private: using _Maybe_const_iterator_t = _STD conditional_t<_STD is_const_v<_STD remove_reference_t>, const_iterator, iterator>; public: - // [flatmap.cons] Constructors + // [flat.map.cons] Constructors explicit flat_map(const key_compare& _Comp) : _Key_compare(_Comp), _Data() {} flat_map() : flat_map(key_compare()) {} @@ -382,7 +382,7 @@ public: _Data.values.clear(); } - // [flatmap.capacity] Capacity + // [flat.map.capacity] Capacity _NODISCARD_EMPTY_MEMBER bool empty() const noexcept { return _Data.keys.empty(); } @@ -395,7 +395,7 @@ public: return _STD min(_Data.keys.max_size(), _Data.values.max_size()); } - // [flatmap.access] Access + // [flat.map.access] Access _NODISCARD mapped_type& operator[](const key_type& _Key); // TODO: implement _NODISCARD mapped_type& operator[](key_type&& _Key); // TODO: implement template From 7914ffebe8dd686577abfcacc07c6b73f096ca60 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Wed, 26 Jul 2023 16:35:46 +0800 Subject: [PATCH 034/100] Fix citation --- stl/inc/flat_map | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 636ec46d98b..f2e82919964 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -408,7 +408,7 @@ public: _NODISCARD auto&& at(this _Self_t&& _Self, const _C& _Key) requires _Compare_is_transparent; // TODO: implement - // [flatmap.modifiers] Modifiers + // [flat.map.modifiers] Modifiers template _STD pair emplace(_Args_t&&... _Args) requires _STD is_constructible_v { value_type _Val(_STD forward<_Args_t>(_Args)...); From 4055f0032822a708ae93cf0855eceb4999074d63 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Wed, 26 Jul 2023 18:28:30 +0800 Subject: [PATCH 035/100] Add one signature of insert --- stl/inc/flat_map | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index f2e82919964..2b2d0ee6104 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -69,6 +69,18 @@ struct _Flat_Container { }; }; +template +struct _NODISCARD _Clear_flat_map_scope_guard { + _Ty* _Clearable; + _Clear_flat_map_scope_guard(_Ty* _Clearable) : _Clearable(_Clearable) {} + + ~_Clear_flat_map_scope_guard() { + if (_Clearable) { + _Clearable->clear(); + } + } +}; + // Implementation template <_STD random_access_iterator _Key_iterator_t, _STD random_access_iterator _Mapped_iterator_t> @@ -420,14 +432,21 @@ public: } else{ // Need to insert + _Clear_flat_map_scope_guard _Guard { this }; auto _Index = _STD distance(begin(), _It); _Data.keys.insert(_It._Key_it, _STD move(_Val.first)); _Data.values.insert(_It._Mapped_it, _STD move(_Val.second)); // Note: Consider _It invalidated by the insert operation + _Guard._Clearable = nullptr; return _STD make_pair(begin() + _Index, true); } } + template + _STD pair insert(_V&& _X) requires same_as<_STD remove_cvref_t, value_type> { + return emplace(_STD forward<_V>(_X)); + } + // observers key_compare key_comp() const { return _Key_compare; @@ -467,6 +486,7 @@ private: }; void _SortAndDedup() { + _Clear_flat_map_scope_guard _Guard { this }; auto _Zip_view = _RANGES views::zip(_Data.keys, _Data.values); _RANGES sort(_Zip_view, value_compare(_Key_compare)); @@ -475,6 +495,7 @@ private: _Data.keys.erase(_Data.keys.begin() + _Remaining_count, _Data.keys.end()); _Data.values.erase(_Data.values.begin() + _Remaining_count, _Data.values.end()); + _Guard._Clearable = nullptr; } }; From 2ae7ac29124338dc632f7c2f9fdf53a6dd45887b Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Tue, 8 Aug 2023 15:06:21 +0800 Subject: [PATCH 036/100] Implement emplace_hint --- stl/inc/flat_map | 98 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 79 insertions(+), 19 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 2b2d0ee6104..ab37eb5e2da 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -83,9 +83,11 @@ struct _NODISCARD _Clear_flat_map_scope_guard { // Implementation -template <_STD random_access_iterator _Key_iterator_t, _STD random_access_iterator _Mapped_iterator_t> +template class _Flat_map_iterator_Impl { public: + using _Key_iterator_t = typename _KeyContainer::const_iterator; + using _Mapped_iterator_t = _STD conditional_t<_IsConst, typename _MappedContainer::const_iterator, typename _MappedContainer::iterator>; class type { public: template requires same_as && same_as @@ -192,6 +194,11 @@ public: friend type operator+(difference_type _Off, const type& _Right); + template = 0> + operator typename _Flat_map_iterator_Impl<_KeyContainer, _MappedContainer, true>::type () const { + return typename _Flat_map_iterator_Impl<_KeyContainer, _MappedContainer, true>::type {_Key_it, _Mapped_it}; + } + private: _Key_iterator_t _Key_it; _Mapped_iterator_t _Mapped_it; @@ -200,10 +207,10 @@ public: static_assert(_STD swappable); }; -template <_STD random_access_iterator _Key_iterator_t, _STD random_access_iterator _Mapped_iterator_t> -_EXPORT_STD typename _Flat_map_iterator_Impl<_Key_iterator_t, _Mapped_iterator_t>::type operator+( - typename _Flat_map_iterator_Impl<_Key_iterator_t, _Mapped_iterator_t>::type::difference_type _Off, - const typename _Flat_map_iterator_Impl<_Key_iterator_t, _Mapped_iterator_t>::type& _Right) { +template +_EXPORT_STD typename _Flat_map_iterator_Impl<_KeyContainer, _MappedContainer, _IsConst>::type operator+( + typename _Flat_map_iterator_Impl<_KeyContainer, _MappedContainer, _IsConst>::type::difference_type _Off, + const typename _Flat_map_iterator_Impl<_KeyContainer, _MappedContainer, _IsConst>::type& _Right) { return _Right + _Off; } @@ -222,14 +229,13 @@ public: using difference_type = ptrdiff_t; using key_container_type = KeyContainer; using mapped_container_type = MappedContainer; - using iterator = typename _STD _Flat_map_iterator_Impl::type; - using const_iterator = typename _STD _Flat_map_iterator_Impl::type; + using iterator = typename _STD _Flat_map_iterator_Impl::type; + using const_iterator = typename _STD _Flat_map_iterator_Impl::type; using reverse_iterator = _STD reverse_iterator; using const_reverse_iterator = _STD reverse_iterator; static_assert(_STD random_access_iterator); + static_assert(_STD convertible_to); using value_compare = typename _STD _Flat_value_compare::value_compare; using containers = typename _STD _Flat_Container::container; @@ -424,26 +430,69 @@ public: template _STD pair emplace(_Args_t&&... _Args) requires _STD is_constructible_v { value_type _Val(_STD forward<_Args_t>(_Args)...); - iterator _It = lower_bound(_Data.keys.begin(), _Data.keys.end(), _Val.first, _Key_compare); + auto _Key_It = lower_bound(_Data.keys.begin(), _Data.keys.end(), _Val.first, _Key_compare); + iterator _It = begin() + _STD distance(_Data.keys.begin(), _Key_It); - if(_It != end() && *(_It._Key_it) == _Val.first) { + if(_It != end() && _Key_equal(*(_It._Key_it), _Val.first)) { // Already exists return _STD make_pair(_It, false); } else{ // Need to insert - _Clear_flat_map_scope_guard _Guard { this }; auto _Index = _STD distance(begin(), _It); - _Data.keys.insert(_It._Key_it, _STD move(_Val.first)); - _Data.values.insert(_It._Mapped_it, _STD move(_Val.second)); + _Insert_exact(_It, _STD move(_Val)); // Note: Consider _It invalidated by the insert operation - _Guard._Clearable = nullptr; return _STD make_pair(begin() + _Index, true); } } + template + iterator emplace(const_iterator _Position, _Args_t&&... _Args) requires _STD is_constructible_v { + value_type _Val(_STD forward<_Args_t>(_Args)...); + + const const_iterator _Begin = cbegin(); + const const_iterator _End = cend(); + + // Adjust _Position + if(_Position == _End || !_Key_compare(*(_Position._Key_it), _Val.first)) { + // _Val should be inserted at or before _Position + if(_Position == _Begin || !_Key_compare(_Val.first, *((_Position - 1)._Key_it))){ + // _Val should be inserted at or after _Position + // The hint _Position is accurate + } + else{ + auto _Key_Position = _STD upper_bound(_Data.keys.cbegin(), _Position._Key_it, _Val.first, _Key_compare); + auto _Distance = _STD distance(_Data.keys.cbegin(), _Key_Position); + _Position = _Begin + _Distance; + } + } + else{ + auto _Key_Position = _STD lower_bound(_Position._Key_it + 1, _Data.keys.cend(), _Val.first, _Key_compare); + auto _Distance = _STD distance(_Data.keys.cbegin(), _Key_Position); + _Position = _Begin + _Distance; + } + + bool _Should_insert = false; + if(_Position == _End){ + _Should_insert = true; + } + else if(_Key_equal(*(_Position._Key_it), _Val.first)){ + _Should_insert = false; + } + else{ + _Should_insert = true; + } + + auto _Distance = _STD distance(_Begin, _Position); + if(_Should_insert){ + _Insert_exact(_Position, _STD move(_Val)); + } + // Consider _Position invalidated by the insert operation + return begin() + _Distance; + } + template - _STD pair insert(_V&& _X) requires same_as<_STD remove_cvref_t, value_type> { + _STD pair insert(_V&& _X) requires same_as<_STD remove_cvref_t<_V&&>, value_type> { return emplace(_STD forward<_V>(_X)); } @@ -477,26 +526,37 @@ private: key_compare _Key_compare; containers _Data; - struct _Key_equal { + struct _Key_equal_for_ref { key_compare _Key_compare; - _Key_equal(key_compare _Comp) : _Key_compare(_Comp) {} + _Key_equal_for_ref(key_compare _Comp) : _Key_compare(_Comp) {} bool operator()(const_reference _X, const_reference _Y) const { return !_Key_compare(_X.first, _Y.first) && !_Key_compare(_Y.first, _X.first); } }; + bool _Key_equal(const Key& _X, const Key& _Y) const { + return !_Key_compare(_X, _Y) && !_Key_compare(_Y, _X); + } + void _SortAndDedup() { _Clear_flat_map_scope_guard _Guard { this }; auto _Zip_view = _RANGES views::zip(_Data.keys, _Data.values); _RANGES sort(_Zip_view, value_compare(_Key_compare)); - auto _Subrange = _RANGES unique(_Zip_view, _Key_equal(_Key_compare)); + auto _Subrange = _RANGES unique(_Zip_view, _Key_equal_for_ref(_Key_compare)); auto _Remaining_count = _STD distance(_Zip_view.begin(), _Subrange.begin()); _Data.keys.erase(_Data.keys.begin() + _Remaining_count, _Data.keys.end()); _Data.values.erase(_Data.values.begin() + _Remaining_count, _Data.values.end()); _Guard._Clearable = nullptr; } + + void _Insert_exact(const_iterator _Position, value_type&& _Val){ + _Clear_flat_map_scope_guard _Guard { this }; + _Data.keys.insert(_Position._Key_it, _STD move(_Val.first)); + _Data.values.insert(_Position._Mapped_it, _STD move(_Val.second)); + _Guard._Clearable = nullptr; + } }; _STD_END From ee6fc3acc2172eb5f9a3f6292857774b27d402ab Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Tue, 8 Aug 2023 15:16:25 +0800 Subject: [PATCH 037/100] Fix name of emplace_hint; Add another insert interface; Remove _Key_equal_for_ref --- stl/inc/flat_map | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index ab37eb5e2da..19288e1a37b 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -447,7 +447,7 @@ public: } template - iterator emplace(const_iterator _Position, _Args_t&&... _Args) requires _STD is_constructible_v { + iterator emplace_hint(const_iterator _Position, _Args_t&&... _Args) requires _STD is_constructible_v { value_type _Val(_STD forward<_Args_t>(_Args)...); const const_iterator _Begin = cbegin(); @@ -496,6 +496,11 @@ public: return emplace(_STD forward<_V>(_X)); } + template + iterator insert(const_iterator _Position, _V&& _X) requires same_as<_STD remove_cvref_t<_V&&>, value_type> { + return emplace_hint(_Position, _STD forward<_V>(_X)); + } + // observers key_compare key_comp() const { return _Key_compare; @@ -526,14 +531,6 @@ private: key_compare _Key_compare; containers _Data; - struct _Key_equal_for_ref { - key_compare _Key_compare; - _Key_equal_for_ref(key_compare _Comp) : _Key_compare(_Comp) {} - bool operator()(const_reference _X, const_reference _Y) const { - return !_Key_compare(_X.first, _Y.first) && !_Key_compare(_Y.first, _X.first); - } - }; - bool _Key_equal(const Key& _X, const Key& _Y) const { return !_Key_compare(_X, _Y) && !_Key_compare(_Y, _X); } @@ -543,7 +540,7 @@ private: auto _Zip_view = _RANGES views::zip(_Data.keys, _Data.values); _RANGES sort(_Zip_view, value_compare(_Key_compare)); - auto _Subrange = _RANGES unique(_Zip_view, _Key_equal_for_ref(_Key_compare)); + auto _Subrange = _RANGES unique(_Zip_view, [](const_reference _X, const_reference _Y) { return _Key_equal(_X.first, _Y.first); }); auto _Remaining_count = _STD distance(_Zip_view.begin(), _Subrange.begin()); _Data.keys.erase(_Data.keys.begin() + _Remaining_count, _Data.keys.end()); From 03737d2bf2ad0d4aa60bc4f0425f509a464cf6c4 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Tue, 8 Aug 2023 15:23:14 +0800 Subject: [PATCH 038/100] Relax constraint to implement another interface of insert(); Fix lambda --- stl/inc/flat_map | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 19288e1a37b..f1e359cd575 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -492,12 +492,12 @@ public: } template - _STD pair insert(_V&& _X) requires same_as<_STD remove_cvref_t<_V&&>, value_type> { + _STD pair insert(_V&& _X) requires (same_as<_STD remove_cvref_t<_V&&>, value_type> || constructible_from) { return emplace(_STD forward<_V>(_X)); } template - iterator insert(const_iterator _Position, _V&& _X) requires same_as<_STD remove_cvref_t<_V&&>, value_type> { + iterator insert(const_iterator _Position, _V&& _X) requires (same_as<_STD remove_cvref_t<_V&&>, value_type> || constructible_from) { return emplace_hint(_Position, _STD forward<_V>(_X)); } @@ -540,7 +540,7 @@ private: auto _Zip_view = _RANGES views::zip(_Data.keys, _Data.values); _RANGES sort(_Zip_view, value_compare(_Key_compare)); - auto _Subrange = _RANGES unique(_Zip_view, [](const_reference _X, const_reference _Y) { return _Key_equal(_X.first, _Y.first); }); + auto _Subrange = _RANGES unique(_Zip_view, [this](const_reference _X, const_reference _Y) { return this->_Key_equal(_X.first, _Y.first); }); auto _Remaining_count = _STD distance(_Zip_view.begin(), _Subrange.begin()); _Data.keys.erase(_Data.keys.begin() + _Remaining_count, _Data.keys.end()); From f04fc5ae34a434341bee2e346d481359e5e3548f Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Tue, 8 Aug 2023 15:30:39 +0800 Subject: [PATCH 039/100] Add _STD --- stl/inc/flat_map | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index f1e359cd575..f51d09b5ba1 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -430,7 +430,7 @@ public: template _STD pair emplace(_Args_t&&... _Args) requires _STD is_constructible_v { value_type _Val(_STD forward<_Args_t>(_Args)...); - auto _Key_It = lower_bound(_Data.keys.begin(), _Data.keys.end(), _Val.first, _Key_compare); + auto _Key_It = _STD lower_bound(_Data.keys.begin(), _Data.keys.end(), _Val.first, _Key_compare); iterator _It = begin() + _STD distance(_Data.keys.begin(), _Key_It); if(_It != end() && _Key_equal(*(_It._Key_it), _Val.first)) { From 566d1234d308813f36d463d6a4132f2065946bf3 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Tue, 8 Aug 2023 15:59:04 +0800 Subject: [PATCH 040/100] Remove usage of deducing this --- stl/inc/flat_map | 57 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 18 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index f51d09b5ba1..9a779fad100 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -358,23 +358,35 @@ public: } // [container.reqmts] iterators - template - _NODISCARD auto begin(this _Self_t&& _Self) noexcept { - return _Maybe_const_iterator_t<_Self_t&&> { _Self._Data.keys.cbegin(), _Self._Data.values.begin() }; + _NODISCARD iterator begin() noexcept { + return iterator { _Self._Data.keys.cbegin(), _Self._Data.values.begin() }; } - template - _NODISCARD auto end(this _Self_t&& _Self) noexcept { - return _Maybe_const_iterator_t<_Self_t&&> { _Self._Data.keys.cend(), _Self._Data.values.end() }; + _NODISCARD const_iterator begin() const noexcept { + return const_iterator { _Self._Data.keys.cbegin(), _Self._Data.values.begin() }; } - template - _NODISCARD auto rbegin(this _Self_t&& _Self) noexcept { - return _STD make_reverse_iterator(_Self.end()); + _NODISCARD iterator end() noexcept { + return iterator { _Self._Data.keys.cend(), _Self._Data.values.end() }; } - template - _NODISCARD auto rend(this _Self_t&& _Self) noexcept { + _NODISCARD const_iterator end() const noexcept { + return const_iterator { _Self._Data.keys.cend(), _Self._Data.values.end() }; + } + + _NODISCARD iterator rbegin() noexcept { + return _STD make_reverse_iterator(end()); + } + + _NODISCARD const_iterator rbegin() const noexcept { + return _STD make_reverse_iterator(end()); + } + + _NODISCARD iterator rend() noexcept { + return _STD make_reverse_iterator(_Self.begin()); + } + + _NODISCARD const_iterator rend() const noexcept { return _STD make_reverse_iterator(_Self.begin()); } @@ -420,10 +432,13 @@ public: _NODISCARD mapped_type& operator[](_C&& _Key) requires _Compare_is_transparent; // TODO: implement - template - _NODISCARD auto&& at(this _Self_t&& _Self, const key_type& _Key); // TODO: implement - template - _NODISCARD auto&& at(this _Self_t&& _Self, const _C& _Key) + _NODISCARD mapped_type& at(const key_type& _Key); // TODO: implement + _NODISCARD const mapped_type& at(const key_type& _Key) const; // TODO: implement + template + _NODISCARD mapped_type& at(const _C& _Key) + requires _Compare_is_transparent; // TODO: implement + template + _NODISCARD const mapped_type& at(const _C& _Key) const requires _Compare_is_transparent; // TODO: implement // [flat.map.modifiers] Modifiers @@ -519,12 +534,18 @@ public: } // map operations - template - auto lower_bound(this _Self_t&& _Self, const key_type& _X) { + iterator lower_bound(const key_type& _X) { auto _Key_it = _STD lower_bound(_Self._Data.keys.begin(), _Self._Data.keys.end(), _X, _Self._Key_compare); auto _Dist = _STD distance(_Self._Data.keys.begin(), _Key_it); auto _Val_it = _Self._Data.values.begin() + _Dist; - return _Maybe_const_iterator_t<_Self_t&&> { _STD move(_Key_it), _STD move(_Val_it) }; + return iterator { _STD move(_Key_it), _STD move(_Val_it) }; + } + + const_iterator lower_bound(const key_type& _X) const { + auto _Key_it = _STD lower_bound(_Self._Data.keys.cbegin(), _Self._Data.keys.cend(), _X, _Self._Key_compare); + auto _Dist = _STD distance(_Self._Data.keys.cbegin(), _Key_it); + auto _Val_it = _Self._Data.values.cbegin() + _Dist; + return const_iterator { _STD move(_Key_it), _STD move(_Val_it) }; } private: From 86fdc4149dedee033623625a750cb74f5b1a7835 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Tue, 8 Aug 2023 18:00:34 +0800 Subject: [PATCH 041/100] Fix _Self --- stl/inc/flat_map | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 9a779fad100..e87362a1bab 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -359,35 +359,35 @@ public: // [container.reqmts] iterators _NODISCARD iterator begin() noexcept { - return iterator { _Self._Data.keys.cbegin(), _Self._Data.values.begin() }; + return iterator { _Data.keys.cbegin(), _Data.values.begin() }; } _NODISCARD const_iterator begin() const noexcept { - return const_iterator { _Self._Data.keys.cbegin(), _Self._Data.values.begin() }; + return const_iterator { _Data.keys.cbegin(), _Data.values.begin() }; } _NODISCARD iterator end() noexcept { - return iterator { _Self._Data.keys.cend(), _Self._Data.values.end() }; + return iterator { _Data.keys.cend(), _Data.values.end() }; } _NODISCARD const_iterator end() const noexcept { - return const_iterator { _Self._Data.keys.cend(), _Self._Data.values.end() }; + return const_iterator { _Data.keys.cend(), _Data.values.end() }; } - _NODISCARD iterator rbegin() noexcept { + _NODISCARD reverse_iterator rbegin() noexcept { return _STD make_reverse_iterator(end()); } - _NODISCARD const_iterator rbegin() const noexcept { + _NODISCARD const_reverse_iterator rbegin() const noexcept { return _STD make_reverse_iterator(end()); } - _NODISCARD iterator rend() noexcept { - return _STD make_reverse_iterator(_Self.begin()); + _NODISCARD reverse_iterator rend() noexcept { + return _STD make_reverse_iterator(begin()); } - _NODISCARD const_iterator rend() const noexcept { - return _STD make_reverse_iterator(_Self.begin()); + _NODISCARD const_reverse_iterator rend() const noexcept { + return _STD make_reverse_iterator(begin()); } _NODISCARD const_iterator cbegin() const noexcept { @@ -535,16 +535,16 @@ public: // map operations iterator lower_bound(const key_type& _X) { - auto _Key_it = _STD lower_bound(_Self._Data.keys.begin(), _Self._Data.keys.end(), _X, _Self._Key_compare); - auto _Dist = _STD distance(_Self._Data.keys.begin(), _Key_it); - auto _Val_it = _Self._Data.values.begin() + _Dist; + auto _Key_it = _STD lower_bound(_Data.keys.begin(), _Data.keys.end(), _X, _Key_compare); + auto _Dist = _STD distance(_Data.keys.begin(), _Key_it); + auto _Val_it = _Data.values.begin() + _Dist; return iterator { _STD move(_Key_it), _STD move(_Val_it) }; } const_iterator lower_bound(const key_type& _X) const { - auto _Key_it = _STD lower_bound(_Self._Data.keys.cbegin(), _Self._Data.keys.cend(), _X, _Self._Key_compare); - auto _Dist = _STD distance(_Self._Data.keys.cbegin(), _Key_it); - auto _Val_it = _Self._Data.values.cbegin() + _Dist; + auto _Key_it = _STD lower_bound(_Data.keys.cbegin(), _Data.keys.cend(), _X, _Key_compare); + auto _Dist = _STD distance(_Data.keys.cbegin(), _Key_it); + auto _Val_it = _Data.values.cbegin() + _Dist; return const_iterator { _STD move(_Key_it), _STD move(_Val_it) }; } From 4b5e6087d29d1b34194e7aacff6b307042cee496 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Wed, 9 Aug 2023 18:00:31 +0800 Subject: [PATCH 042/100] Remove std::input_iterator constraint --- stl/inc/flat_map | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index e87362a1bab..c1947c0d2f5 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -19,6 +19,7 @@ #include #include #include +#include #pragma pack(push, _CRT_PACKING) #pragma warning(push, _STL_WARNING_LEVEL) @@ -278,13 +279,14 @@ public: _Data{.keys = _STD make_obj_using_allocator(_Alloc, _Key_cont), .values = _STD make_obj_using_allocator(_Alloc, _Mapped_cont)} {} - template <_STD input_iterator _InputIterator> + template requires _Is_iterator_v<_InputIterator> flat_map(_InputIterator _First, _InputIterator _Last, const key_compare& _Comp = key_compare()) : flat_map(_Comp) { insert(_First, _Last); } - template <_STD input_iterator _InputIterator, + template Allocator> + requires _Is_iterator_v<_InputIterator> flat_map(_InputIterator _First, _InputIterator _Last, const key_compare& _Comp, const Allocator& _Alloc) : flat_map(_Comp, _Alloc) { insert(_First, _Last); @@ -311,22 +313,24 @@ public: insert_range(_STD forward(_Range)); } - template <_STD input_iterator _InputIterator> + template requires _Is_iterator_v<_InputIterator> flat_map(sorted_unique_t _S, _InputIterator _First, _InputIterator _Last, const key_compare& _Comp = key_compare()) : flat_map(_Comp) { insert(_S, _First, _Last); } - template <_STD input_iterator _InputIterator, + template Allocator> + requires _Is_iterator_v<_InputIterator> flat_map(sorted_unique_t _S, _InputIterator _First, _InputIterator _Last, const key_compare& _Comp, const Allocator& _Alloc) : flat_map(_Comp, _Alloc) { insert(_S, _First, _Last); } - template <_STD input_iterator _InputIterator, + template Allocator> + requires _Is_iterator_v<_InputIterator> flat_map(sorted_unique_t _S, _InputIterator _First, _InputIterator _Last, const Allocator& _Alloc) : flat_map(_S, _First, _Last, key_compare(), _Alloc) {} From 0bbfa5b35b937f1b98f149ce184d025bb0951a5b Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Thu, 10 Aug 2023 17:18:22 +0800 Subject: [PATCH 043/100] Add try_emplace --- stl/inc/flat_map | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index c1947c0d2f5..2e1d38f92fb 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -520,6 +520,29 @@ public: return emplace_hint(_Position, _STD forward<_V>(_X)); } + template + _STD pair try_emplace(_K&& _Key, _Args_t&&... _Args) + requires constructible_from + && (same_as<_STD remove_cvref_t<_K&&>, key_type> + || (constructible_from + && _Compare_is_transparent + && !convertible_to<_K&&, const_iterator> + && !convertible_to<_K&&, iterator>) + ) { + auto _Key_It = _STD lower_bound(_Data.keys.begin(), _Data.keys.end(), _Key, _Key_compare); + if(_Key_equal(_Key, *_Key_It)){ + // Already exists + auto _Distance = _STD distance(_Data.keys.begin(), _Key_It); + return _STD make_pair(begin() + _Distance, false); + } + else{ + // Need to insert + auto _Distance = _STD distance(_Data.keys.begin(), _Key_It); + _Insert_exact(begin() + _Distance, std::make_pair(key_type(_STD forward<_K>(_Key)), mapped_type(_STD forward<_Args_t>(_Args)...))); + return _STD make_pair(begin() + _Distance, true); + } + } + // observers key_compare key_comp() const { return _Key_compare; From bc9fb2d9022d9a8aa6ce8e9fdaed0c2718a00b3b Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Thu, 10 Aug 2023 17:23:18 +0800 Subject: [PATCH 044/100] Refactor --- stl/inc/flat_map | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 2e1d38f92fb..bb0795b76b7 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -529,18 +529,8 @@ public: && !convertible_to<_K&&, const_iterator> && !convertible_to<_K&&, iterator>) ) { - auto _Key_It = _STD lower_bound(_Data.keys.begin(), _Data.keys.end(), _Key, _Key_compare); - if(_Key_equal(_Key, *_Key_It)){ - // Already exists - auto _Distance = _STD distance(_Data.keys.begin(), _Key_It); - return _STD make_pair(begin() + _Distance, false); - } - else{ - // Need to insert - auto _Distance = _STD distance(_Data.keys.begin(), _Key_It); - _Insert_exact(begin() + _Distance, std::make_pair(key_type(_STD forward<_K>(_Key)), mapped_type(_STD forward<_Args_t>(_Args)...))); - return _STD make_pair(begin() + _Distance, true); - } + value_type _Val = std::make_pair(key_type(_STD forward<_K>(_Key)), mapped_type(_STD forward<_Args_t>(_Args)...)); + return emplace(_STD move(_Val)); } // observers From c3fbe2dc816bfa72215182cb5494475f953b3f48 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Thu, 10 Aug 2023 17:35:49 +0800 Subject: [PATCH 045/100] Implement other signatures of try_emplate and implement operator [] --- stl/inc/flat_map | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index bb0795b76b7..02238b89388 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -430,11 +430,12 @@ public: } // [flat.map.access] Access - _NODISCARD mapped_type& operator[](const key_type& _Key); // TODO: implement - _NODISCARD mapped_type& operator[](key_type&& _Key); // TODO: implement - template - _NODISCARD mapped_type& operator[](_C&& _Key) - requires _Compare_is_transparent; // TODO: implement + template + _NODISCARD mapped_type& operator[](_K&& _Key) + requires same_as, key_type> + || (_Compare_is_transparent && convertible_to<_K&&, key_type>){ + return try_emplace(_STD forward<_K>(_Key)).first->second; + } _NODISCARD mapped_type& at(const key_type& _Key); // TODO: implement _NODISCARD const mapped_type& at(const key_type& _Key) const; // TODO: implement @@ -533,6 +534,17 @@ public: return emplace(_STD move(_Val)); } + template + _STD pair try_emplace(const_iterator _Position, _K&& _Key, _Args_t&&... _Args) + requires constructible_from + && (same_as<_STD remove_cvref_t<_K&&>, key_type> + || (constructible_from + && _Compare_is_transparent) + ) { + value_type _Val = std::make_pair(key_type(_STD forward<_K>(_Key)), mapped_type(_STD forward<_Args_t>(_Args)...)); + return emplace_hint(_Position, _STD move(_Val)); + } + // observers key_compare key_comp() const { return _Key_compare; From 2c1918be5fa97e5e30e3e1c452f6cd3104964042 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Wed, 23 Aug 2023 11:59:38 +0800 Subject: [PATCH 046/100] Fix modifier functions for transparent comparators --- stl/inc/flat_map | 149 +++++++++++++++++++++++++---------------------- 1 file changed, 78 insertions(+), 71 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 02238b89388..3e8fa8ee800 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -433,82 +433,31 @@ public: template _NODISCARD mapped_type& operator[](_K&& _Key) requires same_as, key_type> - || (_Compare_is_transparent && convertible_to<_K&&, key_type>){ + || (_Compare_is_transparent && constructible_from){ return try_emplace(_STD forward<_K>(_Key)).first->second; } _NODISCARD mapped_type& at(const key_type& _Key); // TODO: implement _NODISCARD const mapped_type& at(const key_type& _Key) const; // TODO: implement - template - _NODISCARD mapped_type& at(const _C& _Key) + template + _NODISCARD mapped_type& at(const _K& _Key) requires _Compare_is_transparent; // TODO: implement - template - _NODISCARD const mapped_type& at(const _C& _Key) const + template + _NODISCARD const mapped_type& at(const _K& _Key) const requires _Compare_is_transparent; // TODO: implement // [flat.map.modifiers] Modifiers template _STD pair emplace(_Args_t&&... _Args) requires _STD is_constructible_v { value_type _Val(_STD forward<_Args_t>(_Args)...); - auto _Key_It = _STD lower_bound(_Data.keys.begin(), _Data.keys.end(), _Val.first, _Key_compare); - iterator _It = begin() + _STD distance(_Data.keys.begin(), _Key_It); - - if(_It != end() && _Key_equal(*(_It._Key_it), _Val.first)) { - // Already exists - return _STD make_pair(_It, false); - } - else{ - // Need to insert - auto _Index = _STD distance(begin(), _It); - _Insert_exact(_It, _STD move(_Val)); - // Note: Consider _It invalidated by the insert operation - return _STD make_pair(begin() + _Index, true); - } + return try_emplace(_STD move(_Val.first), _STD move(_Val.second)); } template iterator emplace_hint(const_iterator _Position, _Args_t&&... _Args) requires _STD is_constructible_v { value_type _Val(_STD forward<_Args_t>(_Args)...); - const const_iterator _Begin = cbegin(); - const const_iterator _End = cend(); - - // Adjust _Position - if(_Position == _End || !_Key_compare(*(_Position._Key_it), _Val.first)) { - // _Val should be inserted at or before _Position - if(_Position == _Begin || !_Key_compare(_Val.first, *((_Position - 1)._Key_it))){ - // _Val should be inserted at or after _Position - // The hint _Position is accurate - } - else{ - auto _Key_Position = _STD upper_bound(_Data.keys.cbegin(), _Position._Key_it, _Val.first, _Key_compare); - auto _Distance = _STD distance(_Data.keys.cbegin(), _Key_Position); - _Position = _Begin + _Distance; - } - } - else{ - auto _Key_Position = _STD lower_bound(_Position._Key_it + 1, _Data.keys.cend(), _Val.first, _Key_compare); - auto _Distance = _STD distance(_Data.keys.cbegin(), _Key_Position); - _Position = _Begin + _Distance; - } - - bool _Should_insert = false; - if(_Position == _End){ - _Should_insert = true; - } - else if(_Key_equal(*(_Position._Key_it), _Val.first)){ - _Should_insert = false; - } - else{ - _Should_insert = true; - } - - auto _Distance = _STD distance(_Begin, _Position); - if(_Should_insert){ - _Insert_exact(_Position, _STD move(_Val)); - } - // Consider _Position invalidated by the insert operation - return begin() + _Distance; + return _Emplace_hint(_Position, _STD move(_Val.first), _STD move(_Val.second)); } template @@ -521,17 +470,26 @@ public: return emplace_hint(_Position, _STD forward<_V>(_X)); } - template - _STD pair try_emplace(_K&& _Key, _Args_t&&... _Args) + template + _STD pair try_emplace(_Key_constructible_t&& _Key_constructible, _Args_t&&... _Args) requires constructible_from - && (same_as<_STD remove_cvref_t<_K&&>, key_type> - || (constructible_from + && (same_as<_STD remove_cvref_t<_Key_constructible_t&&>, key_type> + || (constructible_from && _Compare_is_transparent - && !convertible_to<_K&&, const_iterator> - && !convertible_to<_K&&, iterator>) - ) { - value_type _Val = std::make_pair(key_type(_STD forward<_K>(_Key)), mapped_type(_STD forward<_Args_t>(_Args)...)); - return emplace(_STD move(_Val)); + && !convertible_to<_Key_constructible_t&&, const_iterator> + && !convertible_to<_Key_constructible_t&&, iterator>)){ + auto _Key_It = _STD lower_bound(_Data.keys.begin(), _Data.keys.end(), _STD forward<_Key_constructible_t>(_Key_constructible), _Key_compare); + if(_Key_equal(*_Key_It, _STD forward<_Key_constructible_t>(_Key_constructible))){ + // Already exists + return _STD make_pair(begin() + _STD distance(_Data.keys.begin(), _Key_It), false); + } + else{ + // Need to insert + value_type _Val = std::make_pair(key_type(_STD forward<_Key_constructible_t>(_Key_constructible)), mapped_type(_STD forward<_Args_t>(_Args)...)); + auto _Index = _STD distance(_Data.keys.begin(), _Key_It); + _Insert_exact(begin() + _Index, _STD move(_Val)); + return _STD make_pair(begin() + _Index, true); + } } template @@ -541,8 +499,7 @@ public: || (constructible_from && _Compare_is_transparent) ) { - value_type _Val = std::make_pair(key_type(_STD forward<_K>(_Key)), mapped_type(_STD forward<_Args_t>(_Args)...)); - return emplace_hint(_Position, _STD move(_Val)); + return _Emplace_hint(_Position, _STD forward<_K>(_Key), _STD forward<_Args_t>(_Args)...); } // observers @@ -581,8 +538,11 @@ private: key_compare _Key_compare; containers _Data; - bool _Key_equal(const Key& _X, const Key& _Y) const { - return !_Key_compare(_X, _Y) && !_Key_compare(_Y, _X); + template + requires (same_as, key_type> && same_as, key_type>) + || (constructible_from && constructible_from && _Compare_is_transparent) + bool _Key_equal(_K1&& _X, _K2&& _Y) const { + return !_Key_compare(_STD forward<_K1>(_X), _STD forward<_K2>(_Y)) && !_Key_compare(_STD forward<_K2>(_Y), _STD forward<_K1>(_X)); } void _SortAndDedup() { @@ -604,6 +564,53 @@ private: _Data.values.insert(_Position._Mapped_it, _STD move(_Val.second)); _Guard._Clearable = nullptr; } + + template + iterator _Emplace_hint(const_iterator _Position, _K&& _Key, _Mapped_args_t&&... _Args) + requires _STD is_constructible_v + && (same_as<_STD remove_cvref_t<_K&&>, key_type> + || (constructible_from + && _Compare_is_transparent)) { + const const_iterator _Begin = cbegin(); + const const_iterator _End = cend(); + + // Adjust _Position + if(_Position == _End || !_Key_compare(*(_Position._Key_it), _Key)) { + // _Val should be inserted at or before _Position + if(_Position == _Begin || !_Key_compare(_Key, *((_Position - 1)._Key_it))){ + // _Val should be inserted at or after _Position + // The hint _Position is accurate + } + else{ + auto _Key_Position = _STD upper_bound(_Data.keys.cbegin(), _Position._Key_it, _Key, _Key_compare); + auto _Distance = _STD distance(_Data.keys.cbegin(), _Key_Position); + _Position = _Begin + _Distance; + } + } + else{ + auto _Key_Position = _STD lower_bound(_Position._Key_it + 1, _Data.keys.cend(), _Key, _Key_compare); + auto _Distance = _STD distance(_Data.keys.cbegin(), _Key_Position); + _Position = _Begin + _Distance; + } + + bool _Should_insert = false; + if(_Position == _End){ + _Should_insert = true; + } + else if(_Key_equal(*(_Position._Key_it), _Key)){ + _Should_insert = false; + } + else{ + _Should_insert = true; + } + + auto _Distance = _STD distance(_Begin, _Position); + if(_Should_insert){ + _Insert_exact(_Position, value_type(_STD forward<_K>(_Key), _STD forward<_Mapped_args_t>(_Args)...)); + } + // Consider _Position invalidated by the insert operation + return begin() + _Distance; + } }; _STD_END From 6e32c45aaf8975906f01655f0fb88bc335bf6344 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Wed, 23 Aug 2023 14:58:04 +0800 Subject: [PATCH 047/100] Implement range insertion --- stl/inc/flat_map | 59 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 3e8fa8ee800..59507545b8d 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -470,6 +470,16 @@ public: return emplace_hint(_Position, _STD forward<_V>(_X)); } + template requires _Is_iterator_v<_InputIterator> + void insert(_InputIterator _First, _InputIterator _Last) { + _Insert_range<_InputIterator, true, true>(_First, _Last); + } + + template requires _Is_iterator_v<_InputIterator> + void insert(sorted_unique_t, _InputIterator _First, _InputIterator _Last) { + _Insert_range<_InputIterator, false, true>(_First, _Last); + } + template _STD pair try_emplace(_Key_constructible_t&& _Key_constructible, _Args_t&&... _Args) requires constructible_from @@ -479,7 +489,7 @@ public: && !convertible_to<_Key_constructible_t&&, const_iterator> && !convertible_to<_Key_constructible_t&&, iterator>)){ auto _Key_It = _STD lower_bound(_Data.keys.begin(), _Data.keys.end(), _STD forward<_Key_constructible_t>(_Key_constructible), _Key_compare); - if(_Key_equal(*_Key_It, _STD forward<_Key_constructible_t>(_Key_constructible))){ + if(_Key_It != _Data.keys.end() && _Key_equal(*_Key_It, _STD forward<_Key_constructible_t>(_Key_constructible))){ // Already exists return _STD make_pair(begin() + _STD distance(_Data.keys.begin(), _Key_It), false); } @@ -546,13 +556,22 @@ private: } void _SortAndDedup() { + _Sort(); + _Dedup(); + } + + void _Sort(){ _Clear_flat_map_scope_guard _Guard { this }; auto _Zip_view = _RANGES views::zip(_Data.keys, _Data.values); _RANGES sort(_Zip_view, value_compare(_Key_compare)); + _Guard._Clearable = nullptr; + } - auto _Subrange = _RANGES unique(_Zip_view, [this](const_reference _X, const_reference _Y) { return this->_Key_equal(_X.first, _Y.first); }); + void _Dedup() { + _Clear_flat_map_scope_guard _Guard { this }; + auto _Zip_view = _RANGES views::zip(_Data.keys, _Data.values); + auto _Subrange = _RANGES unique(_Zip_view, [this](const_reference _X, const_reference _Y) { return this->_Key_equal(_X.first, _Y.first); }); auto _Remaining_count = _STD distance(_Zip_view.begin(), _Subrange.begin()); - _Data.keys.erase(_Data.keys.begin() + _Remaining_count, _Data.keys.end()); _Data.values.erase(_Data.values.begin() + _Remaining_count, _Data.values.end()); _Guard._Clearable = nullptr; @@ -611,6 +630,40 @@ private: // Consider _Position invalidated by the insert operation return begin() + _Distance; } + + template + requires _Is_iterator_v<_InputIterator> + void _Insert_range(_InputIterator _First, _InputIterator _Last){ + _Clear_flat_map_scope_guard _Guard { this }; + + // Insert the new elements at the end + size_t _OldSize = size(); + size_t _NewSize = _STD distance(_First, _Last); + + _Data.keys.reserve(_Data.keys.size() + _NewSize); + _Data.values.reserve(_Data.values.size() + _NewSize); + + for(; _First != _Last; ++_First){ + _Data.keys.emplace_back(_STD move(_First->first)); + _Data.values.emplace_back(_STD move(_First->second)); + } + + // Sort the newly inserted elements + auto _Zip_view = _RANGES views::zip(_Data.keys, _Data.values); + if constexpr (_NeedSorting) { + auto _Zip_view_new_elements = _Zip_view | _RANGES views::drop(_OldSize); + _RANGES sort(_Zip_view_new_elements, value_compare(_Key_compare)); + } + + // Merge the newly inserted elements with the existing elements + _RANGES inplace_merge(_Zip_view, _Zip_view.begin() + _OldSize, value_compare(_Key_compare)); + + if constexpr (_NeedDeduping) { + _Dedup(); + } + + _Guard._Clearable = nullptr; + } }; _STD_END From 7f28eebfc1f78f4f6f3523314215fe8e8895dc35 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Wed, 23 Aug 2023 15:01:46 +0800 Subject: [PATCH 048/100] Implement range insertion --- stl/inc/flat_map | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 59507545b8d..f9aa0d83154 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -480,6 +480,11 @@ public: _Insert_range<_InputIterator, false, true>(_First, _Last); } + template <_Container_compatible_range R> + void insert_range(R&& _Range) { + insert(_RANGES begin(_Range), _RANGES end(_Range)); + } + template _STD pair try_emplace(_Key_constructible_t&& _Key_constructible, _Args_t&&... _Args) requires constructible_from From d62b6097e9d1044cfc6a4bfafb014603de853380 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Wed, 23 Aug 2023 15:12:39 +0800 Subject: [PATCH 049/100] Implement insert for initializer_list --- stl/inc/flat_map | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index f9aa0d83154..9b9b02ce368 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -485,6 +485,14 @@ public: insert(_RANGES begin(_Range), _RANGES end(_Range)); } + void insert(initializer_list _I) { + insert(_I.begin(), _I.end()); + } + + void insert(sorted_unique_t _S, initializer_list _I) { + insert(_S, _I.begin(), _I.end()); + } + template _STD pair try_emplace(_Key_constructible_t&& _Key_constructible, _Args_t&&... _Args) requires constructible_from From 578bfd0e8ba014e3f949f0be79fc07f601cb4b1d Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Wed, 23 Aug 2023 15:24:13 +0800 Subject: [PATCH 050/100] Implement extract, replace and swap --- stl/inc/flat_map | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 9b9b02ce368..3166b1a426e 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -410,6 +410,12 @@ public: return _STD make_reverse_iterator(cbegin()); } + void swap(flat_map& _Other) noexcept { + _STD swap(_Key_compare, _Other._Key_compare); + _Data.keys.swap(_Other._Data.keys); + _Data.values.swap(_Other._Data.values); + } + // [container.reqmts] clear void clear() noexcept { _Data.keys.clear(); @@ -525,6 +531,18 @@ public: return _Emplace_hint(_Position, _STD forward<_K>(_Key), _STD forward<_Args_t>(_Args)...); } + containers extract() && { + _Clear_flat_map_scope_guard _Guard { this }; + return _STD move(_Data); + } + + void replace(key_container_type&& _Key_cont, mapped_container_type&& _Mapped_cont) { + _Clear_flat_map_scope_guard _Guard { this }; + _Data.keys = _STD move(_Key_cont); + _Data.values = _STD move(_Mapped_cont); + _Guard._Clearable = nullptr; + } + // observers key_compare key_comp() const { return _Key_compare; From d3842d77a2c4819a6944075272f21ec3bc544248 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Wed, 23 Aug 2023 15:31:23 +0800 Subject: [PATCH 051/100] Run clang-format --- stl/inc/flat_map | 228 +++++++++++++++++++++++++---------------------- 1 file changed, 123 insertions(+), 105 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 3166b1a426e..1c97f3c6fb1 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -87,11 +87,13 @@ struct _NODISCARD _Clear_flat_map_scope_guard { template class _Flat_map_iterator_Impl { public: - using _Key_iterator_t = typename _KeyContainer::const_iterator; - using _Mapped_iterator_t = _STD conditional_t<_IsConst, typename _MappedContainer::const_iterator, typename _MappedContainer::iterator>; + using _Key_iterator_t = typename _KeyContainer::const_iterator; + using _Mapped_iterator_t = + _STD conditional_t<_IsConst, typename _MappedContainer::const_iterator, typename _MappedContainer::iterator>; class type { public: - template requires same_as && same_as + template + requires same_as && same_as friend class flat_map; type() = default; type(_Key_iterator_t _Key_it, _Mapped_iterator_t _Mapped_it) : _Key_it(_Key_it), _Mapped_it(_Mapped_it) {} @@ -111,24 +113,28 @@ public: using value_type = _STD pair<_STD iter_value_t<_Key_iterator_t>, _STD iter_value_t<_Mapped_iterator_t>>; private: - class _Arrow_Proxy: public _STD pair<_STD iter_const_reference_t<_Key_iterator_t>, _STD iter_reference_t<_Mapped_iterator_t>> { + class _Arrow_Proxy + : public _STD + pair<_STD iter_const_reference_t<_Key_iterator_t>, _STD iter_reference_t<_Mapped_iterator_t>> { public: - using _STD pair<_STD iter_const_reference_t<_Key_iterator_t>, _STD iter_reference_t<_Mapped_iterator_t>>::pair; + using _STD + pair<_STD iter_const_reference_t<_Key_iterator_t>, _STD iter_reference_t<_Mapped_iterator_t>>::pair; _Arrow_Proxy* operator->() noexcept { return this; } }; public: - using pointer = _Arrow_Proxy; - using reference = _STD pair<_STD iter_const_reference_t<_Key_iterator_t>, _STD iter_reference_t<_Mapped_iterator_t>>; + using pointer = _Arrow_Proxy; + using reference = + _STD pair<_STD iter_const_reference_t<_Key_iterator_t>, _STD iter_reference_t<_Mapped_iterator_t>>; reference operator*() const { - return reference {*_Key_it, *_Mapped_it}; + return reference{*_Key_it, *_Mapped_it}; } pointer operator->() const { - return pointer {*_Key_it, *_Mapped_it}; + return pointer{*_Key_it, *_Mapped_it}; } type& operator++() { @@ -196,8 +202,8 @@ public: friend type operator+(difference_type _Off, const type& _Right); template = 0> - operator typename _Flat_map_iterator_Impl<_KeyContainer, _MappedContainer, true>::type () const { - return typename _Flat_map_iterator_Impl<_KeyContainer, _MappedContainer, true>::type {_Key_it, _Mapped_it}; + operator typename _Flat_map_iterator_Impl<_KeyContainer, _MappedContainer, true>::type() const { + return typename _Flat_map_iterator_Impl<_KeyContainer, _MappedContainer, true>::type{_Key_it, _Mapped_it}; } private: @@ -220,18 +226,18 @@ template && same_as class flat_map { public: - using key_type = Key; - using mapped_type = T; - using value_type = pair; - using key_compare = Compare; - using reference = pair; - using const_reference = pair; - using size_type = size_t; - using difference_type = ptrdiff_t; - using key_container_type = KeyContainer; - using mapped_container_type = MappedContainer; - using iterator = typename _STD _Flat_map_iterator_Impl::type; - using const_iterator = typename _STD _Flat_map_iterator_Impl::type; + using key_type = Key; + using mapped_type = T; + using value_type = pair; + using key_compare = Compare; + using reference = pair; + using const_reference = pair; + using size_type = size_t; + using difference_type = ptrdiff_t; + using key_container_type = KeyContainer; + using mapped_container_type = MappedContainer; + using iterator = typename _STD _Flat_map_iterator_Impl::type; + using const_iterator = typename _STD _Flat_map_iterator_Impl::type; using reverse_iterator = _STD reverse_iterator; using const_reverse_iterator = _STD reverse_iterator; @@ -242,8 +248,10 @@ public: using containers = typename _STD _Flat_Container::container; private: - template requires same_as, flat_map> - using _Maybe_const_iterator_t = _STD conditional_t<_STD is_const_v<_STD remove_reference_t>, const_iterator, iterator>; + template + requires same_as, flat_map> + using _Maybe_const_iterator_t = + _STD conditional_t<_STD is_const_v<_STD remove_reference_t>, const_iterator, iterator>; public: // [flat.map.cons] Constructors @@ -279,13 +287,13 @@ public: _Data{.keys = _STD make_obj_using_allocator(_Alloc, _Key_cont), .values = _STD make_obj_using_allocator(_Alloc, _Mapped_cont)} {} - template requires _Is_iterator_v<_InputIterator> + template + requires _Is_iterator_v<_InputIterator> flat_map(_InputIterator _First, _InputIterator _Last, const key_compare& _Comp = key_compare()) : flat_map(_Comp) { insert(_First, _Last); } - template Allocator> + template Allocator> requires _Is_iterator_v<_InputIterator> flat_map(_InputIterator _First, _InputIterator _Last, const key_compare& _Comp, const Allocator& _Alloc) : flat_map(_Comp, _Alloc) { @@ -313,14 +321,14 @@ public: insert_range(_STD forward(_Range)); } - template requires _Is_iterator_v<_InputIterator> + template + requires _Is_iterator_v<_InputIterator> flat_map(sorted_unique_t _S, _InputIterator _First, _InputIterator _Last, const key_compare& _Comp = key_compare()) : flat_map(_Comp) { insert(_S, _First, _Last); } - template Allocator> + template Allocator> requires _Is_iterator_v<_InputIterator> flat_map(sorted_unique_t _S, _InputIterator _First, _InputIterator _Last, const key_compare& _Comp, const Allocator& _Alloc) @@ -328,8 +336,7 @@ public: insert(_S, _First, _Last); } - template Allocator> + template Allocator> requires _Is_iterator_v<_InputIterator> flat_map(sorted_unique_t _S, _InputIterator _First, _InputIterator _Last, const Allocator& _Alloc) : flat_map(_S, _First, _Last, key_compare(), _Alloc) {} @@ -363,19 +370,19 @@ public: // [container.reqmts] iterators _NODISCARD iterator begin() noexcept { - return iterator { _Data.keys.cbegin(), _Data.values.begin() }; + return iterator{_Data.keys.cbegin(), _Data.values.begin()}; } _NODISCARD const_iterator begin() const noexcept { - return const_iterator { _Data.keys.cbegin(), _Data.values.begin() }; + return const_iterator{_Data.keys.cbegin(), _Data.values.begin()}; } _NODISCARD iterator end() noexcept { - return iterator { _Data.keys.cend(), _Data.values.end() }; + return iterator{_Data.keys.cend(), _Data.values.end()}; } _NODISCARD const_iterator end() const noexcept { - return const_iterator { _Data.keys.cend(), _Data.values.end() }; + return const_iterator{_Data.keys.cend(), _Data.values.end()}; } _NODISCARD reverse_iterator rbegin() noexcept { @@ -395,11 +402,11 @@ public: } _NODISCARD const_iterator cbegin() const noexcept { - return const_iterator {_Data.keys.cbegin(), _Data.values.cbegin()}; + return const_iterator{_Data.keys.cbegin(), _Data.values.cbegin()}; } _NODISCARD const_iterator cend() const noexcept { - return const_iterator {_Data.keys.cend(), _Data.values.cend()}; + return const_iterator{_Data.keys.cend(), _Data.values.cend()}; } _NODISCARD const_reverse_iterator crbegin() const noexcept { @@ -436,10 +443,11 @@ public: } // [flat.map.access] Access - template + template _NODISCARD mapped_type& operator[](_K&& _Key) requires same_as, key_type> - || (_Compare_is_transparent && constructible_from){ + || (_Compare_is_transparent && constructible_from) + { return try_emplace(_STD forward<_K>(_Key)).first->second; } @@ -454,34 +462,44 @@ public: // [flat.map.modifiers] Modifiers template - _STD pair emplace(_Args_t&&... _Args) requires _STD is_constructible_v { + _STD pair emplace(_Args_t&&... _Args) + requires _STD + is_constructible_v { value_type _Val(_STD forward<_Args_t>(_Args)...); return try_emplace(_STD move(_Val.first), _STD move(_Val.second)); } template - iterator emplace_hint(const_iterator _Position, _Args_t&&... _Args) requires _STD is_constructible_v { + iterator emplace_hint(const_iterator _Position, _Args_t&&... _Args) + requires _STD + is_constructible_v { value_type _Val(_STD forward<_Args_t>(_Args)...); return _Emplace_hint(_Position, _STD move(_Val.first), _STD move(_Val.second)); } template - _STD pair insert(_V&& _X) requires (same_as<_STD remove_cvref_t<_V&&>, value_type> || constructible_from) { + _STD pair insert(_V&& _X) + requires (same_as<_STD remove_cvref_t<_V &&>, value_type> || constructible_from) + { return emplace(_STD forward<_V>(_X)); } template - iterator insert(const_iterator _Position, _V&& _X) requires (same_as<_STD remove_cvref_t<_V&&>, value_type> || constructible_from) { + iterator insert(const_iterator _Position, _V&& _X) + requires (same_as<_STD remove_cvref_t<_V &&>, value_type> || constructible_from) + { return emplace_hint(_Position, _STD forward<_V>(_X)); } - template requires _Is_iterator_v<_InputIterator> + template + requires _Is_iterator_v<_InputIterator> void insert(_InputIterator _First, _InputIterator _Last) { _Insert_range<_InputIterator, true, true>(_First, _Last); } - template requires _Is_iterator_v<_InputIterator> + template + requires _Is_iterator_v<_InputIterator> void insert(sorted_unique_t, _InputIterator _First, _InputIterator _Last) { _Insert_range<_InputIterator, false, true>(_First, _Last); } @@ -502,20 +520,22 @@ public: template _STD pair try_emplace(_Key_constructible_t&& _Key_constructible, _Args_t&&... _Args) requires constructible_from - && (same_as<_STD remove_cvref_t<_Key_constructible_t&&>, key_type> - || (constructible_from - && _Compare_is_transparent - && !convertible_to<_Key_constructible_t&&, const_iterator> - && !convertible_to<_Key_constructible_t&&, iterator>)){ - auto _Key_It = _STD lower_bound(_Data.keys.begin(), _Data.keys.end(), _STD forward<_Key_constructible_t>(_Key_constructible), _Key_compare); - if(_Key_It != _Data.keys.end() && _Key_equal(*_Key_It, _STD forward<_Key_constructible_t>(_Key_constructible))){ + && (same_as<_STD remove_cvref_t<_Key_constructible_t &&>, key_type> + || (constructible_from && _Compare_is_transparent + && !convertible_to<_Key_constructible_t&&, const_iterator> + && !convertible_to<_Key_constructible_t&&, iterator>) ) + { + auto _Key_It = _STD lower_bound( + _Data.keys.begin(), _Data.keys.end(), _STD forward<_Key_constructible_t>(_Key_constructible), _Key_compare); + if (_Key_It != _Data.keys.end() + && _Key_equal(*_Key_It, _STD forward<_Key_constructible_t>(_Key_constructible))) { // Already exists return _STD make_pair(begin() + _STD distance(_Data.keys.begin(), _Key_It), false); - } - else{ + } else { // Need to insert - value_type _Val = std::make_pair(key_type(_STD forward<_Key_constructible_t>(_Key_constructible)), mapped_type(_STD forward<_Args_t>(_Args)...)); - auto _Index = _STD distance(_Data.keys.begin(), _Key_It); + value_type _Val = std::make_pair(key_type(_STD forward<_Key_constructible_t>(_Key_constructible)), + mapped_type(_STD forward<_Args_t>(_Args)...)); + auto _Index = _STD distance(_Data.keys.begin(), _Key_It); _Insert_exact(begin() + _Index, _STD move(_Val)); return _STD make_pair(begin() + _Index, true); } @@ -524,22 +544,21 @@ public: template _STD pair try_emplace(const_iterator _Position, _K&& _Key, _Args_t&&... _Args) requires constructible_from - && (same_as<_STD remove_cvref_t<_K&&>, key_type> - || (constructible_from - && _Compare_is_transparent) - ) { + && (same_as<_STD remove_cvref_t<_K &&>, key_type> + || (constructible_from && _Compare_is_transparent) ) + { return _Emplace_hint(_Position, _STD forward<_K>(_Key), _STD forward<_Args_t>(_Args)...); } containers extract() && { - _Clear_flat_map_scope_guard _Guard { this }; + _Clear_flat_map_scope_guard _Guard{this}; return _STD move(_Data); } void replace(key_container_type&& _Key_cont, mapped_container_type&& _Mapped_cont) { - _Clear_flat_map_scope_guard _Guard { this }; - _Data.keys = _STD move(_Key_cont); - _Data.values = _STD move(_Mapped_cont); + _Clear_flat_map_scope_guard _Guard{this}; + _Data.keys = _STD move(_Key_cont); + _Data.values = _STD move(_Mapped_cont); _Guard._Clearable = nullptr; } @@ -563,27 +582,29 @@ public: // map operations iterator lower_bound(const key_type& _X) { auto _Key_it = _STD lower_bound(_Data.keys.begin(), _Data.keys.end(), _X, _Key_compare); - auto _Dist = _STD distance(_Data.keys.begin(), _Key_it); + auto _Dist = _STD distance(_Data.keys.begin(), _Key_it); auto _Val_it = _Data.values.begin() + _Dist; - return iterator { _STD move(_Key_it), _STD move(_Val_it) }; + return iterator{_STD move(_Key_it), _STD move(_Val_it)}; } const_iterator lower_bound(const key_type& _X) const { auto _Key_it = _STD lower_bound(_Data.keys.cbegin(), _Data.keys.cend(), _X, _Key_compare); - auto _Dist = _STD distance(_Data.keys.cbegin(), _Key_it); + auto _Dist = _STD distance(_Data.keys.cbegin(), _Key_it); auto _Val_it = _Data.values.cbegin() + _Dist; - return const_iterator { _STD move(_Key_it), _STD move(_Val_it) }; + return const_iterator{_STD move(_Key_it), _STD move(_Val_it)}; } private: key_compare _Key_compare; containers _Data; - template - requires (same_as, key_type> && same_as, key_type>) - || (constructible_from && constructible_from && _Compare_is_transparent) + template + requires (same_as, key_type> && same_as, key_type>) + || (constructible_from && constructible_from + && _Compare_is_transparent) bool _Key_equal(_K1&& _X, _K2&& _Y) const { - return !_Key_compare(_STD forward<_K1>(_X), _STD forward<_K2>(_Y)) && !_Key_compare(_STD forward<_K2>(_Y), _STD forward<_K1>(_X)); + return !_Key_compare(_STD forward<_K1>(_X), _STD forward<_K2>(_Y)) + && !_Key_compare(_STD forward<_K2>(_Y), _STD forward<_K1>(_X)); } void _SortAndDedup() { @@ -591,25 +612,26 @@ private: _Dedup(); } - void _Sort(){ - _Clear_flat_map_scope_guard _Guard { this }; + void _Sort() { + _Clear_flat_map_scope_guard _Guard{this}; auto _Zip_view = _RANGES views::zip(_Data.keys, _Data.values); _RANGES sort(_Zip_view, value_compare(_Key_compare)); _Guard._Clearable = nullptr; } void _Dedup() { - _Clear_flat_map_scope_guard _Guard { this }; + _Clear_flat_map_scope_guard _Guard{this}; auto _Zip_view = _RANGES views::zip(_Data.keys, _Data.values); - auto _Subrange = _RANGES unique(_Zip_view, [this](const_reference _X, const_reference _Y) { return this->_Key_equal(_X.first, _Y.first); }); + auto _Subrange = _RANGES unique( + _Zip_view, [this](const_reference _X, const_reference _Y) { return this->_Key_equal(_X.first, _Y.first); }); auto _Remaining_count = _STD distance(_Zip_view.begin(), _Subrange.begin()); _Data.keys.erase(_Data.keys.begin() + _Remaining_count, _Data.keys.end()); _Data.values.erase(_Data.values.begin() + _Remaining_count, _Data.values.end()); _Guard._Clearable = nullptr; } - void _Insert_exact(const_iterator _Position, value_type&& _Val){ - _Clear_flat_map_scope_guard _Guard { this }; + void _Insert_exact(const_iterator _Position, value_type&& _Val) { + _Clear_flat_map_scope_guard _Guard{this}; _Data.keys.insert(_Position._Key_it, _STD move(_Val.first)); _Data.values.insert(_Position._Mapped_it, _STD move(_Val.second)); _Guard._Clearable = nullptr; @@ -617,55 +639,51 @@ private: template iterator _Emplace_hint(const_iterator _Position, _K&& _Key, _Mapped_args_t&&... _Args) - requires _STD is_constructible_v - && (same_as<_STD remove_cvref_t<_K&&>, key_type> - || (constructible_from - && _Compare_is_transparent)) { + requires _STD + is_constructible_v + && (same_as<_STD remove_cvref_t<_K&&>, key_type> + || (constructible_from && _Compare_is_transparent) ) { const const_iterator _Begin = cbegin(); - const const_iterator _End = cend(); + const const_iterator _End = cend(); // Adjust _Position - if(_Position == _End || !_Key_compare(*(_Position._Key_it), _Key)) { + if (_Position == _End || !_Key_compare(*(_Position._Key_it), _Key)) { // _Val should be inserted at or before _Position - if(_Position == _Begin || !_Key_compare(_Key, *((_Position - 1)._Key_it))){ + if (_Position == _Begin || !_Key_compare(_Key, *((_Position - 1)._Key_it))) { // _Val should be inserted at or after _Position // The hint _Position is accurate - } - else{ + } else { auto _Key_Position = _STD upper_bound(_Data.keys.cbegin(), _Position._Key_it, _Key, _Key_compare); - auto _Distance = _STD distance(_Data.keys.cbegin(), _Key_Position); - _Position = _Begin + _Distance; + auto _Distance = _STD distance(_Data.keys.cbegin(), _Key_Position); + _Position = _Begin + _Distance; } - } - else{ + } else { auto _Key_Position = _STD lower_bound(_Position._Key_it + 1, _Data.keys.cend(), _Key, _Key_compare); - auto _Distance = _STD distance(_Data.keys.cbegin(), _Key_Position); - _Position = _Begin + _Distance; + auto _Distance = _STD distance(_Data.keys.cbegin(), _Key_Position); + _Position = _Begin + _Distance; } bool _Should_insert = false; - if(_Position == _End){ + if (_Position == _End) { _Should_insert = true; - } - else if(_Key_equal(*(_Position._Key_it), _Key)){ + } else if (_Key_equal(*(_Position._Key_it), _Key)) { _Should_insert = false; - } - else{ + } else { _Should_insert = true; } auto _Distance = _STD distance(_Begin, _Position); - if(_Should_insert){ + if (_Should_insert) { _Insert_exact(_Position, value_type(_STD forward<_K>(_Key), _STD forward<_Mapped_args_t>(_Args)...)); } // Consider _Position invalidated by the insert operation return begin() + _Distance; } - template + template requires _Is_iterator_v<_InputIterator> - void _Insert_range(_InputIterator _First, _InputIterator _Last){ - _Clear_flat_map_scope_guard _Guard { this }; + void _Insert_range(_InputIterator _First, _InputIterator _Last) { + _Clear_flat_map_scope_guard _Guard{this}; // Insert the new elements at the end size_t _OldSize = size(); @@ -674,7 +692,7 @@ private: _Data.keys.reserve(_Data.keys.size() + _NewSize); _Data.values.reserve(_Data.values.size() + _NewSize); - for(; _First != _Last; ++_First){ + for (; _First != _Last; ++_First) { _Data.keys.emplace_back(_STD move(_First->first)); _Data.values.emplace_back(_STD move(_First->second)); } From b0197bdf36274e2ff7de510da7e09fb7c16d3cba Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Wed, 23 Aug 2023 16:49:59 +0800 Subject: [PATCH 052/100] Take review comments about _Arrow_proxy --- stl/inc/flat_map | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 1c97f3c6fb1..e5dcfa0f136 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -111,30 +111,31 @@ public: using iterator_concept = random_access_iterator_tag; using difference_type = ptrdiff_t; using value_type = _STD pair<_STD iter_value_t<_Key_iterator_t>, _STD iter_value_t<_Mapped_iterator_t>>; + using reference = + _STD pair<_STD iter_const_reference_t<_Key_iterator_t>, _STD iter_reference_t<_Mapped_iterator_t>>; private: - class _Arrow_Proxy - : public _STD - pair<_STD iter_const_reference_t<_Key_iterator_t>, _STD iter_reference_t<_Mapped_iterator_t>> { + class _Arrow_proxy { public: - using _STD - pair<_STD iter_const_reference_t<_Key_iterator_t>, _STD iter_reference_t<_Mapped_iterator_t>>::pair; - _Arrow_Proxy* operator->() noexcept { - return this; + explicit _Arrow_proxy(const reference& _Rx) noexcept : _Ref{_Rx} {} + + const reference* operator->() const noexcept { + return _STD addressof(_Ref); } + + private: + reference _Ref; }; public: - using pointer = _Arrow_Proxy; - using reference = - _STD pair<_STD iter_const_reference_t<_Key_iterator_t>, _STD iter_reference_t<_Mapped_iterator_t>>; + using pointer = _Arrow_proxy; reference operator*() const { return reference{*_Key_it, *_Mapped_it}; } pointer operator->() const { - return pointer{*_Key_it, *_Mapped_it}; + return pointer{*(*this)}; } type& operator++() { From 068394de7ba60d6634c7200945ae6c3ad008223f Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Thu, 24 Aug 2023 18:16:29 +0800 Subject: [PATCH 053/100] Implement insert_or_assign --- stl/inc/flat_map | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index e5dcfa0f136..65aa2184efc 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -476,7 +476,8 @@ public: is_constructible_v { value_type _Val(_STD forward<_Args_t>(_Args)...); - return _Emplace_hint(_Position, _STD move(_Val.first), _STD move(_Val.second)); + return _Emplace_hint( + _Position, _STD move(_Val.first), _STD move(_Val.second)); } template @@ -548,7 +549,34 @@ public: && (same_as<_STD remove_cvref_t<_K &&>, key_type> || (constructible_from && _Compare_is_transparent) ) { - return _Emplace_hint(_Position, _STD forward<_K>(_Key), _STD forward<_Args_t>(_Args)...); + return _Emplace_hint( + _Position, _STD forward<_K>(_Key), _STD forward<_Args_t>(_Args)...); + } + + template + pair insert_or_assign(_K&& _Key, _M&& _Obj) + requires assignable_from && constructible_from + && (same_as, key_type> + || (constructible_from && _Compare_is_transparent) ) + { + auto _Res = try_emplace(_STD forward<_K>(_Key), _STD forward<_M>(_Obj)); + if (_Res.second) { + // Insertion took place + return _Res; + } else { + // Already exists + *(_Res.first._Mapped_it) = _STD forward<_M>(_Obj); + return _Res; + } + } + + template + iterator insert_or_assign(const_iterator _Position, _K&& _Key, _M&& _Obj) + requires assignable_from && constructible_from + && (same_as, key_type> + || (constructible_from && _Compare_is_transparent) ) + { + return _Emplace_hint(_Position, _STD forward<_K>(_Key), _STD forward<_M>(_Obj)); } containers extract() && { @@ -638,7 +666,7 @@ private: _Guard._Clearable = nullptr; } - template + template iterator _Emplace_hint(const_iterator _Position, _K&& _Key, _Mapped_args_t&&... _Args) requires _STD is_constructible_v @@ -676,6 +704,9 @@ private: auto _Distance = _STD distance(_Begin, _Position); if (_Should_insert) { _Insert_exact(_Position, value_type(_STD forward<_K>(_Key), _STD forward<_Mapped_args_t>(_Args)...)); + } else if constexpr (_Override_if_exists) { + auto _It = begin() + _Distance; + *(_It._Mapped_it) = mapped_type(_STD forward<_Mapped_args_t>(_Args)...); } // Consider _Position invalidated by the insert operation return begin() + _Distance; From 769b7b2121cd3c084b8d7248d36b726eba978053 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Thu, 24 Aug 2023 18:24:55 +0800 Subject: [PATCH 054/100] Implement lower_bound for transparent comparators --- stl/inc/flat_map | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 65aa2184efc..b1fab8d1324 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -609,18 +609,24 @@ public: } // map operations - iterator lower_bound(const key_type& _X) { + template + iterator lower_bound(const _K& _X) + requires same_as<_K, key_type> || _Compare_is_transparent + { auto _Key_it = _STD lower_bound(_Data.keys.begin(), _Data.keys.end(), _X, _Key_compare); auto _Dist = _STD distance(_Data.keys.begin(), _Key_it); auto _Val_it = _Data.values.begin() + _Dist; return iterator{_STD move(_Key_it), _STD move(_Val_it)}; } - const_iterator lower_bound(const key_type& _X) const { - auto _Key_it = _STD lower_bound(_Data.keys.cbegin(), _Data.keys.cend(), _X, _Key_compare); - auto _Dist = _STD distance(_Data.keys.cbegin(), _Key_it); - auto _Val_it = _Data.values.cbegin() + _Dist; - return const_iterator{_STD move(_Key_it), _STD move(_Val_it)}; + template + const_iterator lower_bound(const _K& _X) const + requires same_as<_K, key_type> || _Compare_is_transparent + { + auto _Key_it = _STD lower_bound(_Data.keys.begin(), _Data.keys.end(), _X, _Key_compare); + auto _Dist = _STD distance(_Data.keys.begin(), _Key_it); + auto _Val_it = _Data.values.begin() + _Dist; + return iterator{_STD move(_Key_it), _STD move(_Val_it)}; } private: From 3dc94d0a8caa321fc3a8a716bd59fe56e1043859 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Fri, 25 Aug 2023 18:22:55 +0800 Subject: [PATCH 055/100] Implement find --- stl/inc/flat_map | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index b1fab8d1324..9260be30d9c 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -609,13 +609,39 @@ public: } // map operations + template + iterator find(const _K& _X) + requires same_as<_K, key_type> || _Compare_is_transparent + { + iterator _Position = lower_bound(_X); + if (_Position != end() && _Key_equal(_Position->first, _X)) { + return _Position; + } else { + return end(); + } + } + + template + const_iterator find(const _K& _X) const + requires same_as<_K, key_type> || _Compare_is_transparent + { + const_iterator _Position = lower_bound(_X); + if (_Position != cend() && _Key_equal(_Position->first, _X)) { + return _Position; + } else { + return cend(); + } + } + + template iterator lower_bound(const _K& _X) requires same_as<_K, key_type> || _Compare_is_transparent { - auto _Key_it = _STD lower_bound(_Data.keys.begin(), _Data.keys.end(), _X, _Key_compare); - auto _Dist = _STD distance(_Data.keys.begin(), _Key_it); - auto _Val_it = _Data.values.begin() + _Dist; + typename KeyContainer::const_iterator _Key_it = + _STD lower_bound(_Data.keys.cbegin(), _Data.keys.cend(), _X, _Key_compare); + auto _Dist = _STD distance(_Data.keys.cbegin(), _Key_it); + typename MappedContainer::iterator _Val_it = _Data.values.begin() + _Dist; return iterator{_STD move(_Key_it), _STD move(_Val_it)}; } @@ -623,10 +649,11 @@ public: const_iterator lower_bound(const _K& _X) const requires same_as<_K, key_type> || _Compare_is_transparent { - auto _Key_it = _STD lower_bound(_Data.keys.begin(), _Data.keys.end(), _X, _Key_compare); - auto _Dist = _STD distance(_Data.keys.begin(), _Key_it); - auto _Val_it = _Data.values.begin() + _Dist; - return iterator{_STD move(_Key_it), _STD move(_Val_it)}; + typename KeyContainer::const_iterator _Key_it = + _STD lower_bound(_Data.keys.cbegin(), _Data.keys.cend(), _X, _Key_compare); + auto _Dist = _STD distance(_Data.keys.cbegin(), _Key_it); + typename MappedContainer::const_iterator _Val_it = _Data.values.cbegin() + _Dist; + return const_iterator{_STD move(_Key_it), _STD move(_Val_it)}; } private: From 5427279542640a055ab00008c374782ea0c0f4c5 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Fri, 25 Aug 2023 18:25:49 +0800 Subject: [PATCH 056/100] Implement contains --- stl/inc/flat_map | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 9260be30d9c..508fa0f2e20 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -633,6 +633,12 @@ public: } } + template + bool contains(const _K& _X) const + requires same_as<_K, key_type> || _Compare_is_transparent + { + return find(_X) != cend(); + } template iterator lower_bound(const _K& _X) From 07d9472e8e13271c90b2d813f32b7eac040879ba Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Mon, 4 Sep 2023 14:43:41 +0800 Subject: [PATCH 057/100] Implement upper_bound --- stl/inc/flat_map | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 508fa0f2e20..9b3969763d1 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -662,6 +662,28 @@ public: return const_iterator{_STD move(_Key_it), _STD move(_Val_it)}; } + template + iterator upper_bound(const _K& _X) + requires same_as<_K, key_type> || _Compare_is_transparent + { + typename KeyContainer::const_iterator _Key_it = + _STD upper_bound(_Data.keys.cbegin(), _Data.keys.cend(), _X, _Key_compare); + auto _Dist = _STD distance(_Data.keys.cbegin(), _Key_it); + typename MappedContainer::iterator _Val_it = _Data.values.begin() + _Dist; + return iterator{_STD move(_Key_it), _STD move(_Val_it)}; + } + + template + const_iterator upper_bound(const _K& _X) const + requires same_as<_K, key_type> || _Compare_is_transparent + { + typename KeyContainer::const_iterator _Key_it = + _STD upper_bound(_Data.keys.cbegin(), _Data.keys.cend(), _X, _Key_compare); + auto _Dist = _STD distance(_Data.keys.cbegin(), _Key_it); + typename MappedContainer::const_iterator _Val_it = _Data.values.cbegin() + _Dist; + return const_iterator{_STD move(_Key_it), _STD move(_Val_it)}; + } + private: key_compare _Key_compare; containers _Data; From 47bbc292f94ea6366244082c25bed38137d09cdb Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Mon, 4 Sep 2023 16:01:46 +0800 Subject: [PATCH 058/100] Implement at and count --- stl/inc/flat_map | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 9b3969763d1..aea15463de6 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -452,14 +452,29 @@ public: return try_emplace(_STD forward<_K>(_Key)).first->second; } - _NODISCARD mapped_type& at(const key_type& _Key); // TODO: implement - _NODISCARD const mapped_type& at(const key_type& _Key) const; // TODO: implement template _NODISCARD mapped_type& at(const _K& _Key) - requires _Compare_is_transparent; // TODO: implement + requires same_as<_K, key_type> || _Compare_is_transparent + { + iterator _Position = find(_Key); + if (_Position == end()) { + throw _STD out_of_range("std::flat_map::at: the specified key does not exist."); + } else { + return _Position->second; + } + } + template _NODISCARD const mapped_type& at(const _K& _Key) const - requires _Compare_is_transparent; // TODO: implement + requires same_as<_K, key_type> || _Compare_is_transparent + { + const_iterator _Position = find(_Key); + if (_Position == cend()) { + throw _STD out_of_range("std::flat_map::at: the specified key does not exist."); + } else { + return _Position->second; + } + } // [flat.map.modifiers] Modifiers template @@ -633,6 +648,13 @@ public: } } + template + size_type count(const _K& _X) const + requires same_as<_K, key_type> || _Compare_is_transparent + { + return upper_bound(_X) - lower_bound(_X); + } + template bool contains(const _K& _X) const requires same_as<_K, key_type> || _Compare_is_transparent From b61e8a05ef4175a904893415d82ffa2c06258bf1 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Mon, 4 Sep 2023 18:02:55 +0800 Subject: [PATCH 059/100] Implement erase --- stl/inc/flat_map | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index aea15463de6..ac75e70a327 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -594,6 +594,39 @@ public: return _Emplace_hint(_Position, _STD forward<_K>(_Key), _STD forward<_M>(_Obj)); } + iterator erase(iterator _Position) { + return erase(static_cast(_Position)); + } + + iterator erase(const_iterator _Position) { + _Clear_flat_map_scope_guard _Guard{this}; + auto _Key_it = _Data.keys.erase(_Position._Key_it); + auto _Val_it = _Data.values.erase(_Position._Val_it); + _Guard._Clearable = nullptr; + return iterator{_STD move(_Key_it), _STD move(_Val_it)}; + } + + iterator erase(const_iterator _First, const_iterator _Last) { + _Clear_flat_map_scope_guard _Guard{this}; + auto _Key_it = _Data.keys.erase(_First._Key_it, _Last._Key_it); + auto _Val_it = _Data.values.erase(_First._Val_it, _Last._Val_it); + _Guard._Clearable = nullptr; + return iterator{_STD move(_Key_it), _STD move(_Val_it)}; + } + + template + size_type erase(_K&& _Key) + requires same_as<_K&&, const key_type&> + || (_Compare_is_transparent && !convertible_to<_K &&, iterator> + && !convertible_to<_K &&, const_iterator>) + { + const_iterator _Pos_begin = lower_bound(_STD forward<_K>(_Key)); + const_iterator _Pos_end = upper_bound(_STD forward<_K>(_Key)); + size_type _Count = _Pos_end - _Pos_begin; + erase(_Pos_begin, _Pos_end); + return _Count; + } + containers extract() && { _Clear_flat_map_scope_guard _Guard{this}; return _STD move(_Data); From 611a5f1873b05cb969735914e3319ef04d95623a Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Mon, 4 Sep 2023 18:23:56 +0800 Subject: [PATCH 060/100] Fix compile error --- stl/inc/flat_map | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index ac75e70a327..fd77659cc47 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -601,7 +601,7 @@ public: iterator erase(const_iterator _Position) { _Clear_flat_map_scope_guard _Guard{this}; auto _Key_it = _Data.keys.erase(_Position._Key_it); - auto _Val_it = _Data.values.erase(_Position._Val_it); + auto _Val_it = _Data.values.erase(_Position._Mapped_it); _Guard._Clearable = nullptr; return iterator{_STD move(_Key_it), _STD move(_Val_it)}; } @@ -609,14 +609,14 @@ public: iterator erase(const_iterator _First, const_iterator _Last) { _Clear_flat_map_scope_guard _Guard{this}; auto _Key_it = _Data.keys.erase(_First._Key_it, _Last._Key_it); - auto _Val_it = _Data.values.erase(_First._Val_it, _Last._Val_it); + auto _Val_it = _Data.values.erase(_First._Mapped_it, _Last._Mapped_it); _Guard._Clearable = nullptr; return iterator{_STD move(_Key_it), _STD move(_Val_it)}; } template size_type erase(_K&& _Key) - requires same_as<_K&&, const key_type&> + requires convertible_to<_K&&, const key_type&> || (_Compare_is_transparent && !convertible_to<_K &&, iterator> && !convertible_to<_K &&, const_iterator>) { From 86262ca91b1ac96c81ea49c5cb0c209e072909ae Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Wed, 6 Sep 2023 10:44:40 +0800 Subject: [PATCH 061/100] Take review comments Co-authored-by: A. Jiang --- stl/inc/flat_map | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index fd77659cc47..154c121066c 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -42,7 +42,7 @@ inline constexpr sorted_unique_t sorted_unique{}; template concept _Valid_Allocator_for_flat_map = - _STD uses_allocator_v<_Key_container, _Alloc> && _STD uses_allocator_v<_Mapped_container, _Alloc>; + uses_allocator_v<_Key_container, _Alloc> && uses_allocator_v<_Mapped_container, _Alloc>; template concept _Compare_is_transparent = requires { typename _Compare::is_transparent; }; From 91f6c94fe0dc4482370b1d5c04b855584c816ce0 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Wed, 6 Sep 2023 10:50:03 +0800 Subject: [PATCH 062/100] Apply suggestions from code review Co-authored-by: A. Jiang --- stl/inc/flat_map | 74 +++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 39 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 154c121066c..aa677f318ab 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -51,7 +51,7 @@ template struct _Flat_value_compare { struct value_compare { public: - bool operator()(_STD pair _X, _STD pair _Y) const { + bool operator()(pair _X, pair _Y) const { return _Key_compare_for_val(_X.first, _Y.first); } @@ -89,7 +89,7 @@ class _Flat_map_iterator_Impl { public: using _Key_iterator_t = typename _KeyContainer::const_iterator; using _Mapped_iterator_t = - _STD conditional_t<_IsConst, typename _MappedContainer::const_iterator, typename _MappedContainer::iterator>; + conditional_t<_IsConst, typename _MappedContainer::const_iterator, typename _MappedContainer::iterator>; class type { public: template @@ -110,9 +110,8 @@ public: using iterator_category = input_iterator_tag; using iterator_concept = random_access_iterator_tag; using difference_type = ptrdiff_t; - using value_type = _STD pair<_STD iter_value_t<_Key_iterator_t>, _STD iter_value_t<_Mapped_iterator_t>>; - using reference = - _STD pair<_STD iter_const_reference_t<_Key_iterator_t>, _STD iter_reference_t<_Mapped_iterator_t>>; + using value_type = pair, iter_value_t<_Mapped_iterator_t>>; + using reference = pair, iter_reference_t<_Mapped_iterator_t>>; private: class _Arrow_proxy { @@ -202,7 +201,7 @@ public: friend type operator+(difference_type _Off, const type& _Right); - template = 0> + template = 0> operator typename _Flat_map_iterator_Impl<_KeyContainer, _MappedContainer, true>::type() const { return typename _Flat_map_iterator_Impl<_KeyContainer, _MappedContainer, true>::type{_Key_it, _Mapped_it}; } @@ -212,7 +211,7 @@ public: _Mapped_iterator_t _Mapped_it; }; - static_assert(_STD swappable); + static_assert(swappable); }; template @@ -237,16 +236,16 @@ public: using difference_type = ptrdiff_t; using key_container_type = KeyContainer; using mapped_container_type = MappedContainer; - using iterator = typename _STD _Flat_map_iterator_Impl::type; - using const_iterator = typename _STD _Flat_map_iterator_Impl::type; + using iterator = _Flat_map_iterator_Impl::type; + using const_iterator = _Flat_map_iterator_Impl::type; using reverse_iterator = _STD reverse_iterator; using const_reverse_iterator = _STD reverse_iterator; - static_assert(_STD random_access_iterator); - static_assert(_STD convertible_to); + static_assert(random_access_iterator); + static_assert(convertible_to); - using value_compare = typename _STD _Flat_value_compare::value_compare; - using containers = typename _STD _Flat_Container::container; + using value_compare = _Flat_value_compare::value_compare; + using containers = _Flat_Container::container; private: template @@ -302,22 +301,22 @@ public: } template <_Container_compatible_range R> - flat_map(_STD from_range_t _From_range, R&& _Range) + flat_map(from_range_t _From_range, R&& _Range) : flat_map(_From_range, _STD forward(_Range), key_compare()) {} template <_Container_compatible_range R, _Valid_Allocator_for_flat_map Allocator> - flat_map(_STD from_range_t _From_range, R&& _Range, const Allocator& _Alloc) + flat_map(from_range_t _From_range, R&& _Range, const Allocator& _Alloc) : flat_map(_From_range, _STD forward(_Range), key_compare(), _Alloc) {} template <_Container_compatible_range R> - flat_map(_STD from_range_t _From_range, R&& _Range, const key_compare& _Comp) : flat_map(_Comp) { + flat_map(from_range_t _From_range, R&& _Range, const key_compare& _Comp) : flat_map(_Comp) { insert_range(_STD forward(_Range)); } template <_Container_compatible_range R, _Valid_Allocator_for_flat_map Allocator> - flat_map(_STD from_range_t _From_range, R&& _Range, const key_compare& _Comp, const Allocator& _Alloc) + flat_map(from_range_t _From_range, R&& _Range, const key_compare& _Comp, const Allocator& _Alloc) : flat_map(_Comp, _Alloc) { insert_range(_STD forward(_Range)); } @@ -419,9 +418,9 @@ public: } void swap(flat_map& _Other) noexcept { - _STD swap(_Key_compare, _Other._Key_compare); - _Data.keys.swap(_Other._Data.keys); - _Data.values.swap(_Other._Data.values); + _RANGES swap(_Key_compare, _Other._Key_compare); + _RANGES swap(_Data.keys, _Other._Data.keys); + _RANGES swap(_Data.values, _Other._Data.values); } // [container.reqmts] clear @@ -458,7 +457,7 @@ public: { iterator _Position = find(_Key); if (_Position == end()) { - throw _STD out_of_range("std::flat_map::at: the specified key does not exist."); + _Xout_of_range("std::flat_map::at: the specified key does not exist."); } else { return _Position->second; } @@ -470,7 +469,7 @@ public: { const_iterator _Position = find(_Key); if (_Position == cend()) { - throw _STD out_of_range("std::flat_map::at: the specified key does not exist."); + _Xout_of_range("std::flat_map::at: the specified key does not exist."); } else { return _Position->second; } @@ -478,17 +477,15 @@ public: // [flat.map.modifiers] Modifiers template - _STD pair emplace(_Args_t&&... _Args) - requires _STD - is_constructible_v { + pair emplace(_Args_t&&... _Args) + requires is_constructible_v { value_type _Val(_STD forward<_Args_t>(_Args)...); return try_emplace(_STD move(_Val.first), _STD move(_Val.second)); } template iterator emplace_hint(const_iterator _Position, _Args_t&&... _Args) - requires _STD - is_constructible_v { + requires is_constructible_v { value_type _Val(_STD forward<_Args_t>(_Args)...); return _Emplace_hint( @@ -496,15 +493,15 @@ public: } template - _STD pair insert(_V&& _X) - requires (same_as<_STD remove_cvref_t<_V &&>, value_type> || constructible_from) + pair insert(_V&& _X) + requires (same_as, value_type> || constructible_from) { return emplace(_STD forward<_V>(_X)); } template iterator insert(const_iterator _Position, _V&& _X) - requires (same_as<_STD remove_cvref_t<_V &&>, value_type> || constructible_from) + requires (same_as, value_type> || constructible_from) { return emplace_hint(_Position, _STD forward<_V>(_X)); } @@ -535,9 +532,9 @@ public: } template - _STD pair try_emplace(_Key_constructible_t&& _Key_constructible, _Args_t&&... _Args) + pair try_emplace(_Key_constructible_t&& _Key_constructible, _Args_t&&... _Args) requires constructible_from - && (same_as<_STD remove_cvref_t<_Key_constructible_t &&>, key_type> + && (same_as, key_type> || (constructible_from && _Compare_is_transparent && !convertible_to<_Key_constructible_t&&, const_iterator> && !convertible_to<_Key_constructible_t&&, iterator>) ) @@ -547,21 +544,21 @@ public: if (_Key_It != _Data.keys.end() && _Key_equal(*_Key_It, _STD forward<_Key_constructible_t>(_Key_constructible))) { // Already exists - return _STD make_pair(begin() + _STD distance(_Data.keys.begin(), _Key_It), false); + return {begin() + _STD distance(_Data.keys.begin(), _Key_It), false}; } else { // Need to insert value_type _Val = std::make_pair(key_type(_STD forward<_Key_constructible_t>(_Key_constructible)), mapped_type(_STD forward<_Args_t>(_Args)...)); auto _Index = _STD distance(_Data.keys.begin(), _Key_It); _Insert_exact(begin() + _Index, _STD move(_Val)); - return _STD make_pair(begin() + _Index, true); + return {begin() + _Index, true}; } } template - _STD pair try_emplace(const_iterator _Position, _K&& _Key, _Args_t&&... _Args) + pair try_emplace(const_iterator _Position, _K&& _Key, _Args_t&&... _Args) requires constructible_from - && (same_as<_STD remove_cvref_t<_K &&>, key_type> + && (same_as, key_type> || (constructible_from && _Compare_is_transparent) ) { return _Emplace_hint( @@ -784,9 +781,8 @@ private: template iterator _Emplace_hint(const_iterator _Position, _K&& _Key, _Mapped_args_t&&... _Args) - requires _STD - is_constructible_v - && (same_as<_STD remove_cvref_t<_K&&>, key_type> + requires is_constructible_v + && (same_as, key_type> || (constructible_from && _Compare_is_transparent) ) { const const_iterator _Begin = cbegin(); const const_iterator _End = cend(); From 36b23addfb65b58bc9d93c2e124995d9a35d3562 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Wed, 6 Sep 2023 11:00:14 +0800 Subject: [PATCH 063/100] Auto style fix; Fix return type of try_emplace --- stl/inc/flat_map | 44 +++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index aa677f318ab..024af2eb81d 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -226,18 +226,18 @@ template && same_as class flat_map { public: - using key_type = Key; - using mapped_type = T; - using value_type = pair; - using key_compare = Compare; - using reference = pair; - using const_reference = pair; - using size_type = size_t; - using difference_type = ptrdiff_t; - using key_container_type = KeyContainer; - using mapped_container_type = MappedContainer; - using iterator = _Flat_map_iterator_Impl::type; - using const_iterator = _Flat_map_iterator_Impl::type; + using key_type = Key; + using mapped_type = T; + using value_type = pair; + using key_compare = Compare; + using reference = pair; + using const_reference = pair; + using size_type = size_t; + using difference_type = ptrdiff_t; + using key_container_type = KeyContainer; + using mapped_container_type = MappedContainer; + using iterator = _Flat_map_iterator_Impl::type; + using const_iterator = _Flat_map_iterator_Impl::type; using reverse_iterator = _STD reverse_iterator; using const_reverse_iterator = _STD reverse_iterator; @@ -301,8 +301,7 @@ public: } template <_Container_compatible_range R> - flat_map(from_range_t _From_range, R&& _Range) - : flat_map(_From_range, _STD forward(_Range), key_compare()) {} + flat_map(from_range_t _From_range, R&& _Range) : flat_map(_From_range, _STD forward(_Range), key_compare()) {} template <_Container_compatible_range R, _Valid_Allocator_for_flat_map Allocator> @@ -478,14 +477,16 @@ public: // [flat.map.modifiers] Modifiers template pair emplace(_Args_t&&... _Args) - requires is_constructible_v { + requires is_constructible_v + { value_type _Val(_STD forward<_Args_t>(_Args)...); return try_emplace(_STD move(_Val.first), _STD move(_Val.second)); } template iterator emplace_hint(const_iterator _Position, _Args_t&&... _Args) - requires is_constructible_v { + requires is_constructible_v + { value_type _Val(_STD forward<_Args_t>(_Args)...); return _Emplace_hint( @@ -547,8 +548,8 @@ public: return {begin() + _STD distance(_Data.keys.begin(), _Key_It), false}; } else { // Need to insert - value_type _Val = std::make_pair(key_type(_STD forward<_Key_constructible_t>(_Key_constructible)), - mapped_type(_STD forward<_Args_t>(_Args)...)); + value_type _Val = {key_type(_STD forward<_Key_constructible_t>(_Key_constructible)), + mapped_type(_STD forward<_Args_t>(_Args)...)}; auto _Index = _STD distance(_Data.keys.begin(), _Key_It); _Insert_exact(begin() + _Index, _STD move(_Val)); return {begin() + _Index, true}; @@ -556,7 +557,7 @@ public: } template - pair try_emplace(const_iterator _Position, _K&& _Key, _Args_t&&... _Args) + iterator try_emplace(const_iterator _Position, _K&& _Key, _Args_t&&... _Args) requires constructible_from && (same_as, key_type> || (constructible_from && _Compare_is_transparent) ) @@ -782,8 +783,9 @@ private: template iterator _Emplace_hint(const_iterator _Position, _K&& _Key, _Mapped_args_t&&... _Args) requires is_constructible_v - && (same_as, key_type> - || (constructible_from && _Compare_is_transparent) ) { + && (same_as, key_type> + || (constructible_from && _Compare_is_transparent) ) + { const const_iterator _Begin = cbegin(); const const_iterator _End = cend(); From a7d773e636e59a0e093f033ac607c73deecebd1b Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Wed, 6 Sep 2023 11:01:44 +0800 Subject: [PATCH 064/100] Replace size_t with size_type --- stl/inc/flat_map | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 024af2eb81d..2dc74f2d509 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -832,8 +832,8 @@ private: _Clear_flat_map_scope_guard _Guard{this}; // Insert the new elements at the end - size_t _OldSize = size(); - size_t _NewSize = _STD distance(_First, _Last); + size_type _OldSize = size(); + size_type _NewSize = _STD distance(_First, _Last); _Data.keys.reserve(_Data.keys.size() + _NewSize); _Data.values.reserve(_Data.values.size() + _NewSize); From f5e17842ec1cfc09a91798b168d3f5b9bb0ff96c Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Wed, 6 Sep 2023 11:04:37 +0800 Subject: [PATCH 065/100] Auto deduce template arguments --- stl/inc/flat_map | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 2dc74f2d509..dc40c8ecb8e 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -489,8 +489,7 @@ public: { value_type _Val(_STD forward<_Args_t>(_Args)...); - return _Emplace_hint( - _Position, _STD move(_Val.first), _STD move(_Val.second)); + return _Emplace_hint(_Position, _STD move(_Val.first), _STD move(_Val.second)); } template @@ -562,8 +561,7 @@ public: && (same_as, key_type> || (constructible_from && _Compare_is_transparent) ) { - return _Emplace_hint( - _Position, _STD forward<_K>(_Key), _STD forward<_Args_t>(_Args)...); + return _Emplace_hint(_Position, _STD forward<_K>(_Key), _STD forward<_Args_t>(_Args)...); } template @@ -589,7 +587,7 @@ public: && (same_as, key_type> || (constructible_from && _Compare_is_transparent) ) { - return _Emplace_hint(_Position, _STD forward<_K>(_Key), _STD forward<_M>(_Obj)); + return _Emplace_hint(_Position, _STD forward<_K>(_Key), _STD forward<_M>(_Obj)); } iterator erase(iterator _Position) { From 9d4c521cc6b1764af54d9a12e66c744139e9a843 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Wed, 6 Sep 2023 11:10:42 +0800 Subject: [PATCH 066/100] Reorder template arguments and enable auto deducing --- stl/inc/flat_map | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index dc40c8ecb8e..7ea6e669fff 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -509,13 +509,13 @@ public: template requires _Is_iterator_v<_InputIterator> void insert(_InputIterator _First, _InputIterator _Last) { - _Insert_range<_InputIterator, true, true>(_First, _Last); + _Insert_range(_First, _Last); } template requires _Is_iterator_v<_InputIterator> void insert(sorted_unique_t, _InputIterator _First, _InputIterator _Last) { - _Insert_range<_InputIterator, false, true>(_First, _Last); + _Insert_range(_First, _Last); } template <_Container_compatible_range R> @@ -824,7 +824,7 @@ private: return begin() + _Distance; } - template + template requires _Is_iterator_v<_InputIterator> void _Insert_range(_InputIterator _First, _InputIterator _Last) { _Clear_flat_map_scope_guard _Guard{this}; From 0f4f52900ee365cbb74ffdaa131f594efba27948 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Mon, 11 Sep 2023 16:07:13 +0800 Subject: [PATCH 067/100] Implement equal_range --- stl/inc/flat_map | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 7ea6e669fff..e8f9a46c8d1 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -735,6 +735,21 @@ public: return const_iterator{_STD move(_Key_it), _STD move(_Val_it)}; } + template + pair equal_range(const _K& _X) + requires same_as<_K, key_type> || _Compare_is_transparent + { + return {lower_bound(_X), upper_bound(_X)}; + } + + template + pair equal_range(const _K& _X) const + requires same_as<_K, key_type> || _Compare_is_transparent + { + return {lower_bound(_X), upper_bound(_X)}; + } + + private: key_compare _Key_compare; containers _Data; From 227d4ee99565a3bbb78df091238a8153b23e00e2 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Mon, 11 Sep 2023 16:11:35 +0800 Subject: [PATCH 068/100] Avoid using moved values in try_emplace --- stl/inc/flat_map | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index e8f9a46c8d1..4187860d90b 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -539,8 +539,7 @@ public: && !convertible_to<_Key_constructible_t&&, const_iterator> && !convertible_to<_Key_constructible_t&&, iterator>) ) { - auto _Key_It = _STD lower_bound( - _Data.keys.begin(), _Data.keys.end(), _STD forward<_Key_constructible_t>(_Key_constructible), _Key_compare); + auto _Key_It = _STD lower_bound(_Data.keys.begin(), _Data.keys.end(), _Key_constructible, _Key_compare); if (_Key_It != _Data.keys.end() && _Key_equal(*_Key_It, _STD forward<_Key_constructible_t>(_Key_constructible))) { // Already exists From 39852260983bc71e9c84df4b366aaa52583fea92 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Mon, 11 Sep 2023 16:15:50 +0800 Subject: [PATCH 069/100] Use piecewise_construct to construct value_type --- stl/inc/flat_map | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 4187860d90b..83f24b4ca37 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -546,9 +546,10 @@ public: return {begin() + _STD distance(_Data.keys.begin(), _Key_It), false}; } else { // Need to insert - value_type _Val = {key_type(_STD forward<_Key_constructible_t>(_Key_constructible)), - mapped_type(_STD forward<_Args_t>(_Args)...)}; - auto _Index = _STD distance(_Data.keys.begin(), _Key_It); + value_type _Val{piecewise_construct, + forward_as_tuple(_STD forward<_Key_constructible_t>(_Key_constructible)), + forward_as_tuple(_STD forward<_Args_t>(_Args)...)}; + auto _Index = _STD distance(_Data.keys.begin(), _Key_It); _Insert_exact(begin() + _Index, _STD move(_Val)); return {begin() + _Index, true}; } From d92fc5075cf783f4a95a94a25f9d5d202342d018 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Tue, 19 Sep 2023 11:09:10 +0800 Subject: [PATCH 070/100] Wording --- stl/inc/flat_map | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 83f24b4ca37..6ff1ac5bbc9 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -793,7 +793,7 @@ private: _Guard._Clearable = nullptr; } - template + template iterator _Emplace_hint(const_iterator _Position, _K&& _Key, _Mapped_args_t&&... _Args) requires is_constructible_v && (same_as, key_type> @@ -831,7 +831,7 @@ private: auto _Distance = _STD distance(_Begin, _Position); if (_Should_insert) { _Insert_exact(_Position, value_type(_STD forward<_K>(_Key), _STD forward<_Mapped_args_t>(_Args)...)); - } else if constexpr (_Override_if_exists) { + } else if constexpr (_Overwrite_if_exists) { auto _It = begin() + _Distance; *(_It._Mapped_it) = mapped_type(_STD forward<_Mapped_args_t>(_Args)...); } From 0c11a49e4747835846c017906f2613fe0061db03 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Tue, 19 Sep 2023 15:38:50 +0800 Subject: [PATCH 071/100] Rewrite _Emplace_hint --- stl/inc/flat_map | 72 ++++++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 33 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 6ff1ac5bbc9..c7d8a5ff597 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -489,7 +489,7 @@ public: { value_type _Val(_STD forward<_Args_t>(_Args)...); - return _Emplace_hint(_Position, _STD move(_Val.first), _STD move(_Val.second)); + return _Emplace_hint(_Position, _STD move(_Val.first), _STD move(_Val.second)); } template @@ -561,7 +561,7 @@ public: && (same_as, key_type> || (constructible_from && _Compare_is_transparent) ) { - return _Emplace_hint(_Position, _STD forward<_K>(_Key), _STD forward<_Args_t>(_Args)...); + return _Emplace_hint(_Position, _STD forward<_K>(_Key), _STD forward<_Args_t>(_Args)...); } template @@ -587,7 +587,7 @@ public: && (same_as, key_type> || (constructible_from && _Compare_is_transparent) ) { - return _Emplace_hint(_Position, _STD forward<_K>(_Key), _STD forward<_M>(_Obj)); + return _Emplace_hint(_Position, _STD forward<_K>(_Key), _STD forward<_M>(_Obj)); } iterator erase(iterator _Position) { @@ -793,50 +793,56 @@ private: _Guard._Clearable = nullptr; } - template + template iterator _Emplace_hint(const_iterator _Position, _K&& _Key, _Mapped_args_t&&... _Args) requires is_constructible_v && (same_as, key_type> || (constructible_from && _Compare_is_transparent) ) { + static_assert(!(_Multi && _Overwrite_if_exists), + "Overwriting is not supported when the container allows multiple copies of a key."); const const_iterator _Begin = cbegin(); const const_iterator _End = cend(); - // Adjust _Position - if (_Position == _End || !_Key_compare(*(_Position._Key_it), _Key)) { - // _Val should be inserted at or before _Position - if (_Position == _Begin || !_Key_compare(_Key, *((_Position - 1)._Key_it))) { - // _Val should be inserted at or after _Position - // The hint _Position is accurate - } else { - auto _Key_Position = _STD upper_bound(_Data.keys.cbegin(), _Position._Key_it, _Key, _Key_compare); - auto _Distance = _STD distance(_Data.keys.cbegin(), _Key_Position); - _Position = _Begin + _Distance; - } + bool _Insert_before_position = false; + bool _Insert_after_position_minus_1 = false; + if constexpr (_Multi) { + _Insert_before_position = (_Position == _End) || !_Key_compare(*(_Position._Key_it), _Key); + _Insert_after_position_minus_1 = (_Position == _Begin) || !_Key_compare(_Key, *(_Position._Key_it - 1)); } else { - auto _Key_Position = _STD lower_bound(_Position._Key_it + 1, _Data.keys.cend(), _Key, _Key_compare); - auto _Distance = _STD distance(_Data.keys.cbegin(), _Key_Position); - _Position = _Begin + _Distance; + _Insert_before_position = (_Position == _End) || _Key_compare(_Key, *(_Position._Key_it)); + _Insert_after_position_minus_1 = (_Position == _Begin) || _Key_compare(*(_Position._Key_it - 1), _Key); } + bool _Hint_is_accurate = _Insert_before_position && _Insert_after_position_minus_1; - bool _Should_insert = false; - if (_Position == _End) { - _Should_insert = true; - } else if (_Key_equal(*(_Position._Key_it), _Key)) { - _Should_insert = false; + if (_Hint_is_accurate) { + auto _Dist = _STD distance(_Begin._Key_it, _Position._Key_it); + _Insert_exact(_Position, value_type{piecewise_construct, forward_as_tuple(_STD forward<_K>(_Key)), + forward_as_tuple(_STD forward<_Mapped_args_t>(_Args)...)}); + return begin() + _Dist; } else { - _Should_insert = true; - } + if constexpr (_Overwrite_if_exists) { + if (_Key_equal(_Key, *(_Position._Key_it))) { + auto _Dist = _STD distance(_Begin._Key_it, _Position._Key_it); + auto _It = begin() + _Dist; + *(_It._Mapped_it) = mapped_type{_STD forward<_Mapped_args_t>(_Args)...}; + return _It; + } + } - auto _Distance = _STD distance(_Begin, _Position); - if (_Should_insert) { - _Insert_exact(_Position, value_type(_STD forward<_K>(_Key), _STD forward<_Mapped_args_t>(_Args)...)); - } else if constexpr (_Overwrite_if_exists) { - auto _It = begin() + _Distance; - *(_It._Mapped_it) = mapped_type(_STD forward<_Mapped_args_t>(_Args)...); + _Position = lower_bound(_Key); + if (_Overwrite_if_exists && _Position != _End && _Key_equal(_Key, *(_Position._Key_it))) { + auto _Dist = _STD distance(_Begin._Key_it, _Position._Key_it); + auto _It = begin() + _Dist; + *(_It._Mapped_it) = mapped_type{_STD forward<_Mapped_args_t>(_Args)...}; + return _It; + } else { + auto _Dist = _STD distance(_Begin._Key_it, _Position._Key_it); + _Insert_exact(_Position, value_type{piecewise_construct, forward_as_tuple(_STD forward<_K>(_Key)), + forward_as_tuple(_STD forward<_Mapped_args_t>(_Args)...)}); + return begin() + _Dist; + } } - // Consider _Position invalidated by the insert operation - return begin() + _Distance; } template From 2592b2b7502524ad71f6a2c9eb37987cdfae7b20 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Wed, 20 Sep 2023 15:21:40 +0800 Subject: [PATCH 072/100] Use hidden friend syntax --- stl/inc/flat_map | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index c7d8a5ff597..02e7c05e05b 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -199,7 +199,9 @@ public: return _Key_it - _Right._Key_it; } - friend type operator+(difference_type _Off, const type& _Right); + friend type operator+(difference_type _Off, const type& _Right) { + return _Right + _Off; + } template = 0> operator typename _Flat_map_iterator_Impl<_KeyContainer, _MappedContainer, true>::type() const { @@ -214,13 +216,6 @@ public: static_assert(swappable); }; -template -_EXPORT_STD typename _Flat_map_iterator_Impl<_KeyContainer, _MappedContainer, _IsConst>::type operator+( - typename _Flat_map_iterator_Impl<_KeyContainer, _MappedContainer, _IsConst>::type::difference_type _Off, - const typename _Flat_map_iterator_Impl<_KeyContainer, _MappedContainer, _IsConst>::type& _Right) { - return _Right + _Off; -} - _EXPORT_STD template requires same_as && same_as From 3cbbfded89ed64c7de370b157d92fbe80f576116 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Mon, 25 Sep 2023 15:13:36 +0800 Subject: [PATCH 073/100] Add == and <=> --- stl/inc/flat_map | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 02e7c05e05b..1fbbe1545a9 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -744,6 +744,24 @@ public: return {lower_bound(_X), upper_bound(_X)}; } + friend bool operator==(const flat_map& _X, const flat_map& _Y) { + return _RANGES equal(_X._Data.keys, _Y._Data.keys) && _RANGES equal(_X._Data.values, _Y._Data.values); + } + + friend _STD weak_ordering operator<=>(const flat_map& _X, const flat_map& _Y) { + if (_X.size() != _Y.size()) { + return _X.size() <=> _Y.size(); + } + + if (_RANGES lexicographical_compare(_X.cbegin(), _X.cend(), _Y.cbegin(), _Y.cend())) { + return _STD weak_ordering::less; + } else if (_RANGES lexicographical_compare(_Y.cbegin(), _Y.cend(), _X.cbegin(), _X.cend())) { + return _STD weak_ordering::greater; + } else { + return _STD weak_ordering::equivalent; + } + } + private: key_compare _Key_compare; @@ -873,7 +891,7 @@ private: _Guard._Clearable = nullptr; } -}; +} _STD_END From 45e23895918041a1729d1fd6539fa630a989bb01 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Mon, 25 Sep 2023 15:14:23 +0800 Subject: [PATCH 074/100] Add swap (non-member) --- stl/inc/flat_map | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 1fbbe1545a9..47e6466bebf 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -762,6 +762,10 @@ public: } } + friend void swap(flat_map& _X, flat_map& _Y) noexcept { + _X.swap(_Y); + } + private: key_compare _Key_compare; From 0a7f153b496c57373b8c469383dc46df0483367d Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Mon, 25 Sep 2023 15:47:56 +0800 Subject: [PATCH 075/100] Remove unnecessary default functions --- stl/inc/flat_map | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 47e6466bebf..35121151ffa 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -97,15 +97,6 @@ public: friend class flat_map; type() = default; type(_Key_iterator_t _Key_it, _Mapped_iterator_t _Mapped_it) : _Key_it(_Key_it), _Mapped_it(_Mapped_it) {} - // Copy-constructible - type(const type&) = default; - // Copy-assignable - type& operator=(const type&) = default; - // Move-assignable - type& operator=(type&&) = default; - // Swappable - // Destructible - ~type() = default; using iterator_category = input_iterator_tag; using iterator_concept = random_access_iterator_tag; @@ -895,7 +886,15 @@ private: _Guard._Clearable = nullptr; } -} +}; + +template +flat_map(_KeyContainer, _MappedContainer) -> flat_map, _KeyContainer, _MappedContainer>; + +template +flat_map(_KeyContainer, _MappedContainer, _Allocator) -> flat_map, _KeyContainer, _MappedContainer>; _STD_END From a69bd93c5ffdd5c08b35c740be457d06a4456713 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Mon, 25 Sep 2023 16:47:13 +0800 Subject: [PATCH 076/100] Add copy & move constructor; Also implement the allocator-extended versions (LWG-3884) --- stl/inc/flat_map | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 35121151ffa..55dd078e244 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -347,6 +347,29 @@ public: flat_map(sorted_unique_t _S, initializer_list _I, const Allocator& _Alloc) : flat_map(_S, _I, key_compare(), _Alloc) {} + // Copy constructors + flat_map(const flat_map& _Other) : _Key_compare(_Other._Key_compare), _Data(_Other._Data) {} + + template <_Valid_Allocator_for_flat_map _Allocator> + flat_map(const flat_map& _Other, const _Allocator& _Alloc) + : _Key_compare(_Other._Key_compare), + _Data{.keys = _STD make_obj_using_allocator(_Alloc, _Other._Data.keys), + .values = _STD make_obj_using_allocator(_Alloc, _Other._Data.values)} {} + + // Move constructors + flat_map(flat_map&& _Other) noexcept( + _STD is_nothrow_move_constructible_v&& _STD is_nothrow_move_constructible_v&& + _STD is_nothrow_move_constructible_v) + : _Key_compare(move(_Other._Key_compare)), _Data(move(_Other).extract()) {} + + template <_Valid_Allocator_for_flat_map _Allocator> + flat_map(flat_map&& _Other, const _Allocator& _Alloc) noexcept( + _STD is_nothrow_move_constructible_v&& _STD is_nothrow_move_constructible_v&& + _STD is_nothrow_move_constructible_v) + : _Key_compare(move(_Other._Key_compare)), + _Data{.keys = _STD make_obj_using_allocator(_Alloc, move(_Other._Data.keys)), + .values = _STD make_obj_using_allocator(_Alloc, move(_Other._Data.values))} {} + flat_map& operator=(initializer_list _I) { clear(); insert(_I.begin(), _I.end()); From 5652d60c013c691a48e02fe93a56ee20683456a4 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Mon, 25 Sep 2023 18:22:58 +0800 Subject: [PATCH 077/100] Add 4 more deduction guides --- stl/inc/flat_map | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 55dd078e244..6bcf5df40a8 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -919,6 +919,24 @@ template flat_map(_KeyContainer, _MappedContainer, _Allocator) -> flat_map, _KeyContainer, _MappedContainer>; +template +flat_map(sorted_unique_t, _KeyContainer, _MappedContainer) -> flat_map, _KeyContainer, _MappedContainer>; + +template +flat_map(sorted_unique_t, _KeyContainer, _MappedContainer, _Allocator) -> flat_map, _KeyContainer, _MappedContainer>; + +template ::first_type>> +flat_map(_InputIterator, _InputIterator, _Compare = _Compare()) + -> flat_map::first_type, typename iter_value_t<_InputIterator>::second_type, + _Compare>; + +template ::first_type>> +flat_map(sorted_unique_t, _InputIterator, _InputIterator, _Compare = _Compare()) + -> flat_map::first_type, typename iter_value_t<_InputIterator>::second_type, + _Compare>; + _STD_END #pragma pop_macro("new") From d0588ed18f385bb05182b6f8a8055057efa1f671 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Tue, 26 Sep 2023 11:35:09 +0800 Subject: [PATCH 078/100] Fix operator <=> --- stl/inc/flat_map | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 6bcf5df40a8..8045e21003a 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -762,18 +762,9 @@ public: return _RANGES equal(_X._Data.keys, _Y._Data.keys) && _RANGES equal(_X._Data.values, _Y._Data.values); } - friend _STD weak_ordering operator<=>(const flat_map& _X, const flat_map& _Y) { - if (_X.size() != _Y.size()) { - return _X.size() <=> _Y.size(); - } - - if (_RANGES lexicographical_compare(_X.cbegin(), _X.cend(), _Y.cbegin(), _Y.cend())) { - return _STD weak_ordering::less; - } else if (_RANGES lexicographical_compare(_Y.cbegin(), _Y.cend(), _X.cbegin(), _X.cend())) { - return _STD weak_ordering::greater; - } else { - return _STD weak_ordering::equivalent; - } + friend auto operator<=>(const flat_map& _X, const flat_map& _Y) { + return _STD lexicographical_compare_three_way( + _X.cbegin(), _X.cend(), _Y.cbegin(), _Y.cend(), _Synth_three_way{}); } friend void swap(flat_map& _X, flat_map& _Y) noexcept { From cf28719a7b05fa98627db23d72604be244ac90cb Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Wed, 27 Sep 2023 11:12:17 +0800 Subject: [PATCH 079/100] Remove unused _Maybe_const_iterator_t --- stl/inc/flat_map | 6 ------ 1 file changed, 6 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 8045e21003a..531e791272e 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -233,12 +233,6 @@ public: using value_compare = _Flat_value_compare::value_compare; using containers = _Flat_Container::container; -private: - template - requires same_as, flat_map> - using _Maybe_const_iterator_t = - _STD conditional_t<_STD is_const_v<_STD remove_reference_t>, const_iterator, iterator>; - public: // [flat.map.cons] Constructors explicit flat_map(const key_compare& _Comp) : _Key_compare(_Comp), _Data() {} From a67b9f838622944c3bb83a5cac2a5383c909ccaa Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Wed, 27 Sep 2023 11:12:43 +0800 Subject: [PATCH 080/100] Add remaining template deduction guides and specialization of std::uses_allocator --- stl/inc/flat_map | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 531e791272e..b70d233a37a 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -922,6 +922,27 @@ flat_map(sorted_unique_t, _InputIterator, _InputIterator, _Compare = _Compare()) -> flat_map::first_type, typename iter_value_t<_InputIterator>::second_type, _Compare>; +template <_RANGES input_range _R, class _Compare = less::first_type>, + class _Allocator> +flat_map(from_range_t, _R&&, _Compare = _Compare(), _Allocator = _Allocator()) + -> flat_map::first_type, typename _RANGES range_value_t<_R>::second_type, + _Compare>; + +template <_RANGES input_range _R, class _Allocator> +flat_map(from_range_t, _R&&, _Allocator) + -> flat_map::first_type, typename _RANGES range_value_t<_R>::second_type>; + +template > +flat_map(initializer_list>, _Compare = _Compare()) -> flat_map<_Key, _T, _Compare>; + +template > +flat_map(sorted_unique_t, initializer_list>, _Compare = _Compare()) -> flat_map<_Key, _T, _Compare>; + +// Specialization of uses_allocator +template +struct uses_allocator, _Allocator> + : bool_constant && uses_allocator_v<_MappedContainer, _Allocator>> {}; + _STD_END #pragma pop_macro("new") From a89a6bae4a6d10a427b4932c845f1482379e1a43 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Wed, 27 Sep 2023 11:15:45 +0800 Subject: [PATCH 081/100] Fix compile errors in clang-cl --- stl/inc/flat_map | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index b70d233a37a..7b2fc47184b 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -257,12 +257,12 @@ public: _SortAndDedup(); } - flat_map(sorted_unique_t _Sorted_unique, key_container_type _Key_cont, mapped_container_type _Mapped_cont) + flat_map(sorted_unique_t, key_container_type _Key_cont, mapped_container_type _Mapped_cont) : _Key_compare(key_compare()), _Data{.keys = _STD move(_Key_cont), .values = _STD move(_Mapped_cont)} {} template <_Valid_Allocator_for_flat_map Allocator> - flat_map(sorted_unique_t _Sorted_unique, const key_container_type& _Key_cont, - const mapped_container_type& _Mapped_cont, const Allocator& _Alloc) + flat_map(sorted_unique_t, const key_container_type& _Key_cont, const mapped_container_type& _Mapped_cont, + const Allocator& _Alloc) : _Key_compare(key_compare()), _Data{.keys = _STD make_obj_using_allocator(_Alloc, _Key_cont), .values = _STD make_obj_using_allocator(_Alloc, _Mapped_cont)} {} @@ -289,14 +289,13 @@ public: : flat_map(_From_range, _STD forward(_Range), key_compare(), _Alloc) {} template <_Container_compatible_range R> - flat_map(from_range_t _From_range, R&& _Range, const key_compare& _Comp) : flat_map(_Comp) { + flat_map(from_range_t, R&& _Range, const key_compare& _Comp) : flat_map(_Comp) { insert_range(_STD forward(_Range)); } template <_Container_compatible_range R, _Valid_Allocator_for_flat_map Allocator> - flat_map(from_range_t _From_range, R&& _Range, const key_compare& _Comp, const Allocator& _Alloc) - : flat_map(_Comp, _Alloc) { + flat_map(from_range_t, R&& _Range, const key_compare& _Comp, const Allocator& _Alloc) : flat_map(_Comp, _Alloc) { insert_range(_STD forward(_Range)); } From 562b2778284397e14b45daa84ed22a7aad7e15e0 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Wed, 27 Sep 2023 11:58:47 +0800 Subject: [PATCH 082/100] Fix SFINAE on clang; Add a simple test --- stl/inc/flat_map | 5 +++-- tests/std/tests/P0429R9_flat_map/test.cpp | 25 +++++++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 7b2fc47184b..8e7753a5199 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -194,8 +194,9 @@ public: return _Right + _Off; } - template = 0> - operator typename _Flat_map_iterator_Impl<_KeyContainer, _MappedContainer, true>::type() const { + template > + operator typename _Flat_map_iterator_Impl, + enable_if_t, true>::type() const { return typename _Flat_map_iterator_Impl<_KeyContainer, _MappedContainer, true>::type{_Key_it, _Mapped_it}; } diff --git a/tests/std/tests/P0429R9_flat_map/test.cpp b/tests/std/tests/P0429R9_flat_map/test.cpp index 114b223c67a..61d6d091b94 100644 --- a/tests/std/tests/P0429R9_flat_map/test.cpp +++ b/tests/std/tests/P0429R9_flat_map/test.cpp @@ -1,10 +1,35 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#include #include +#include using namespace std; +template +consteval bool check_reversible_container_requirements(T&& obj) + requires _Is_specialization_v, flat_map> +{ + using map_t = remove_cvref_t; + bool result = true; + result &= is_same_v, typename map_t::reverse_iterator>; + result &= is_same_v, typename map_t::const_reverse_iterator>; + result &= is_same_v; + result &= is_same_v; + result &= is_same_v; + result &= is_same_v; + result &= is_same_v; + result &= is_same_v; + result &= is_same_v; + result &= is_same_v; + result &= is_convertible_v; + result &= is_convertible_v; + return result; +} + int main() { + flat_map m; + assert(check_reversible_container_requirements(m)); return 0; } From 49e8bb39f6eb21defd986fbcd00d047202fc4d3b Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Wed, 27 Sep 2023 16:46:06 +0800 Subject: [PATCH 083/100] Add more tests. 1 of the configurations is failing. --- tests/std/tests/P0429R9_flat_map/test.cpp | 54 ++++++++++++++++++----- 1 file changed, 43 insertions(+), 11 deletions(-) diff --git a/tests/std/tests/P0429R9_flat_map/test.cpp b/tests/std/tests/P0429R9_flat_map/test.cpp index 61d6d091b94..975799441e6 100644 --- a/tests/std/tests/P0429R9_flat_map/test.cpp +++ b/tests/std/tests/P0429R9_flat_map/test.cpp @@ -8,28 +8,60 @@ using namespace std; template -consteval bool check_reversible_container_requirements(T&& obj) +bool check_container_requirements(T&&) requires _Is_specialization_v, flat_map> { - using map_t = remove_cvref_t; + return true; +} + +template +consteval bool check_reversible_container_requirements() + requires _Is_specialization_v, flat_map> +{ + using map_t = remove_cvref_t; bool result = true; result &= is_same_v, typename map_t::reverse_iterator>; result &= is_same_v, typename map_t::const_reverse_iterator>; - result &= is_same_v; - result &= is_same_v; - result &= is_same_v; - result &= is_same_v; - result &= is_same_v; - result &= is_same_v; - result &= is_same_v; - result &= is_same_v; + result &= is_same_v().begin()), typename map_t::iterator>; + result &= is_same_v().end()), typename map_t::iterator>; + result &= is_same_v().cbegin()), typename map_t::const_iterator>; + result &= is_same_v().cend()), typename map_t::const_iterator>; + result &= is_same_v().rbegin()), typename map_t::reverse_iterator>; + result &= is_same_v().rend()), typename map_t::reverse_iterator>; + result &= is_same_v().crbegin()), typename map_t::const_reverse_iterator>; + result &= is_same_v().crend()), typename map_t::const_reverse_iterator>; result &= is_convertible_v; result &= is_convertible_v; return result; } +template +constexpr bool check_reversible_container_requirements(T&&) + requires _Is_specialization_v, flat_map> +{ + return check_reversible_container_requirements(); +} + +template +bool check_requirements(T&& obj) { + return check_container_requirements(forward(obj)) && check_reversible_container_requirements(forward(obj)); +} + +void test_construction() { + { + std::flat_map map; + check_requirements(map); + } + { + std::vector keys = {0, 1, 2, 3, 4, 2}; + std::vector vals = {44, 2324, 635462, 433, 5, 7}; + std::flat_map map(keys, vals); + check_requirements(map); + } +} + int main() { flat_map m; - assert(check_reversible_container_requirements(m)); + assert(check_reversible_container_requirements<>(m)); return 0; } From f7ef6db47cdc4a6b172aafdad1465d612b5a1ac9 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Thu, 28 Sep 2023 15:18:08 +0800 Subject: [PATCH 084/100] Use strict test matrix Co-authored-by: A. Jiang --- tests/std/tests/P0429R9_flat_map/env.lst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/std/tests/P0429R9_flat_map/env.lst b/tests/std/tests/P0429R9_flat_map/env.lst index 18e2d7c71ec..8ac7033b206 100644 --- a/tests/std/tests/P0429R9_flat_map/env.lst +++ b/tests/std/tests/P0429R9_flat_map/env.lst @@ -1,4 +1,4 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -RUNALL_INCLUDE ..\concepts_latest_matrix.lst +RUNALL_INCLUDE ..\strict_concepts_latest_matrix.lst From f7512d601c25c9fb6c84a778b824c432ba990613 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Sun, 8 Oct 2023 14:40:13 +0800 Subject: [PATCH 085/100] Add more test cases on construction --- tests/std/tests/P0429R9_flat_map/test.cpp | 197 ++++++++++++++++++++-- 1 file changed, 187 insertions(+), 10 deletions(-) diff --git a/tests/std/tests/P0429R9_flat_map/test.cpp b/tests/std/tests/P0429R9_flat_map/test.cpp index 975799441e6..ae90743e6ea 100644 --- a/tests/std/tests/P0429R9_flat_map/test.cpp +++ b/tests/std/tests/P0429R9_flat_map/test.cpp @@ -1,20 +1,26 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#include #include +#include #include +#include +#include #include +#include using namespace std; template -bool check_container_requirements(T&&) - requires _Is_specialization_v, flat_map> -{ +concept IsFlatMap = _Is_specialization_v, flat_map>; + +template +bool check_container_requirements(T&&) { return true; } -template +template consteval bool check_reversible_container_requirements() requires _Is_specialization_v, flat_map> { @@ -35,33 +41,204 @@ consteval bool check_reversible_container_requirements() return result; } -template +template constexpr bool check_reversible_container_requirements(T&&) requires _Is_specialization_v, flat_map> { return check_reversible_container_requirements(); } -template +template bool check_requirements(T&& obj) { return check_container_requirements(forward(obj)) && check_reversible_container_requirements(forward(obj)); } +template +bool check_key_content(const T& obj, const typename T::key_container_type& expected) { + const auto& actual = obj.keys(); + if (actual.size() != expected.size()) { + return false; + } + return std::ranges::equal(actual, expected); +} + +template +bool check_value_content(const T& obj, const typename T::mapped_container_type& expected) { + const auto& actual = obj.values(); + if (actual.size() != expected.size()) { + return false; + } + return std::ranges::equal(actual, expected); +} + +template +class MyAllocator : public std::allocator { +public: + using value_type = T; + using std::allocator::allocator; + + static size_t getActiveAllocationCount() { + return s_allocations.load(); + } + + T* allocate(size_t n) { + ++s_allocations; + return std::allocator::allocate(n); + } + + T* allocate_at_least(size_t n) { + ++s_allocations; + return std::allocator::allocate_at_least(n); + } + + void deallocate(T* p, size_t n) noexcept { + --s_allocations; + std::allocator::deallocate(p, n); + } + +private: + static std::atomic s_allocations; +}; + +template +class Packaged { +private: + T value; + +public: + Packaged() : value() {} + template + Packaged(U&& u) : value(std::forward(u)) {} + + T get() const { + return value; + } + + void set(T t) { + value = t; + } + + friend bool operator==(const Packaged& lhs, const Packaged& rhs) { + return lhs.value == rhs.value; + } + + friend bool operator==(const Packaged& lhs, const T& rhs) { + return lhs.value == rhs; + } + + friend bool operator==(const T& lhs, const Packaged& rhs) { + return lhs == rhs.value; + } +}; + +template +class PackagedCompare : public std::less> { +public: + using std::less>::less; +}; + +template +class TransparentPackagedCompare : public PackagedCompare { +public: + using PackagedCompare::PackagedCompare; + using is_transparent = void; + + bool operator()(const T& lhs, const Packaged& rhs) const { + return lhs < rhs.get(); + } + + bool operator()(const Packaged& lhs, const T& rhs) const { + return lhs.get() < rhs; + } +}; + +template +std::atomic MyAllocator::s_allocations = 0; + void test_construction() { { std::flat_map map; - check_requirements(map); + assert(check_requirements(map)); + assert(check_key_content(map, {})); + assert(check_value_content(map, {})); } { std::vector keys = {0, 1, 2, 3, 4, 2}; std::vector vals = {44, 2324, 635462, 433, 5, 7}; std::flat_map map(keys, vals); - check_requirements(map); + assert(check_requirements(map)); + assert(check_key_content(map, {0, 1, 2, 3, 4})); + assert(check_value_content(map, {44, 2324, 635462, 433, 5})); } + { + std::vector> keys = {0, 1, 2, 3, 4, 2}; + std::vector> vals = {44, 2324, 635462, 433, 5, 7}; + size_t activeAllocations = MyAllocator::getActiveAllocationCount(); + std::flat_map map(keys, vals, MyAllocator()); + assert(check_key_content(map, {0, 1, 2, 3, 4})); + assert(check_value_content(map, {44, 2324, 635462, 433, 5})); + assert(MyAllocator::getActiveAllocationCount() > activeAllocations); + } + { + std::vector keys = {0, 1, 2, 3, 38, 242}; + std::vector vals = {44, 2324, 635462, 433, 5, 7}; + std::flat_map map(std::sorted_unique, keys, vals); + assert(check_requirements(map)); + assert(check_key_content(map, {0, 1, 2, 3, 38, 242})); + assert(check_value_content(map, {44, 2324, 635462, 433, 5, 7})); + } + { + PackagedCompare comp; + std::flat_map, int, PackagedCompare> map(comp); + assert(check_requirements(map)); + assert(check_key_content(map, {})); + assert(check_value_content(map, {})); + } + { + PackagedCompare comp; + MyAllocator> alloc; + std::flat_map, Packaged, PackagedCompare, + std::vector, MyAllocator>>, + std::vector, MyAllocator>>> + map(comp, alloc); + assert(check_requirements(map)); + assert(check_key_content(map, {})); + assert(check_value_content(map, {})); + } + { + MyAllocator> alloc; + std::flat_map, Packaged, PackagedCompare, + std::vector, MyAllocator>>, + std::vector, MyAllocator>>> + map(alloc); + assert(check_requirements(map)); + assert(check_key_content(map, {})); + assert(check_value_content(map, {})); + } + { + PackagedCompare comp; + MyAllocator> alloc; + std::vector, MyAllocator>> keys = {0, 1, 2, 3, 4, 2}; + std::vector, MyAllocator>> vals = {44, 2324, 635462, 433, 5, 7}; + std::flat_map, Packaged, PackagedCompare, + std::vector, MyAllocator>>, + std::vector, MyAllocator>>> + map(comp, alloc); + assert(check_requirements(map)); + assert(check_key_content(map, {})); + assert(check_value_content(map, {})); + } +} + +void test_pointer_to_incomplete_type() { + struct Test { + std::unique_ptr> ptr; + }; + + Test t; } int main() { - flat_map m; - assert(check_reversible_container_requirements<>(m)); + test_construction(); return 0; } From 8b7691dc29ef421c74e31bc421171c7d2d462e2f Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Sun, 8 Oct 2023 14:40:35 +0800 Subject: [PATCH 086/100] Implement LWG-3786 --- stl/inc/flat_map | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 8e7753a5199..e9a5e51952f 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -923,14 +923,22 @@ flat_map(sorted_unique_t, _InputIterator, _InputIterator, _Compare = _Compare()) _Compare>; template <_RANGES input_range _R, class _Compare = less::first_type>, - class _Allocator> + class _Allocator = allocator> flat_map(from_range_t, _R&&, _Compare = _Compare(), _Allocator = _Allocator()) -> flat_map::first_type, typename _RANGES range_value_t<_R>::second_type, - _Compare>; + _Compare, + vector::first_type, + _Rebind_alloc_t<_Allocator, typename _RANGES range_value_t<_R>::first_type>>, + vector::second_type, + _Rebind_alloc_t<_Allocator, typename _RANGES range_value_t<_R>::second_type>>>; template <_RANGES input_range _R, class _Allocator> -flat_map(from_range_t, _R&&, _Allocator) - -> flat_map::first_type, typename _RANGES range_value_t<_R>::second_type>; +flat_map(from_range_t, _R&&, _Allocator) -> flat_map::first_type, + typename _RANGES range_value_t<_R>::second_type, less::first_type>, + vector::first_type, + _Rebind_alloc_t<_Allocator, typename _RANGES range_value_t<_R>::first_type>>, + vector::second_type, + _Rebind_alloc_t<_Allocator, typename _RANGES range_value_t<_R>::second_type>>>; template > flat_map(initializer_list>, _Compare = _Compare()) -> flat_map<_Key, _T, _Compare>; From fddf5f22d282106299290858f5dcb51d0d838267 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Sun, 8 Oct 2023 14:46:06 +0800 Subject: [PATCH 087/100] Add _HAS_CXX23 guard check --- stl/inc/flat_map | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index e9a5e51952f..5ee94e55160 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -7,6 +7,9 @@ #define _FLAT_MAP_ #include #if _STL_COMPILER_PREPROCESSOR +#if !_HAS_CXX23 || !defined(__cpp_lib_concepts) // TRANSITION, GH-395 +_EMIT_STL_WARNING(STL4038, "The contents of are available only with C++23 or later."); +#else // ^^^ not supported / supported language mode vvv #include #include @@ -957,5 +960,6 @@ _STD_END _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) #pragma pack(pop) +#endif // ^^^ supported language mode ^^^ #endif // _STL_COMPILER_PREPROCESSOR #endif // _FLAT_MAP_ From 7284bac3f7f7856cedc5716260e65c6a47d1b1ed Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Sun, 8 Oct 2023 15:28:59 +0800 Subject: [PATCH 088/100] Implement LWG-3803 and add tests accordingly --- stl/inc/flat_map | 59 ++++++++++++++++++----- tests/std/tests/P0429R9_flat_map/test.cpp | 15 +++--- 2 files changed, 56 insertions(+), 18 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 5ee94e55160..6e75b05e6fa 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -47,6 +47,10 @@ template concept _Valid_Allocator_for_flat_map = uses_allocator_v<_Key_container, _Alloc> && uses_allocator_v<_Mapped_container, _Alloc>; +template +concept _Valid_Compare_for_container = is_invocable_v; + template concept _Compare_is_transparent = requires { typename _Compare::is_transparent; }; @@ -250,8 +254,8 @@ public: : _Key_compare(_Comp), _Data{.keys = _STD make_obj_using_allocator(_Alloc), .values = _STD make_obj_using_allocator(_Alloc)} {} - flat_map(key_container_type _Key_cont, mapped_container_type _Mapped_cont) - : flat_map(sorted_unique_t(), _Key_cont, _Mapped_cont) { + flat_map(key_container_type _Key_cont, mapped_container_type _Mapped_cont, const key_compare& _Comp = key_compare()) + : flat_map(sorted_unique_t(), _Key_cont, _Mapped_cont, _Comp) { _SortAndDedup(); } @@ -261,8 +265,16 @@ public: _SortAndDedup(); } - flat_map(sorted_unique_t, key_container_type _Key_cont, mapped_container_type _Mapped_cont) - : _Key_compare(key_compare()), _Data{.keys = _STD move(_Key_cont), .values = _STD move(_Mapped_cont)} {} + template <_Valid_Allocator_for_flat_map Allocator> + flat_map(const key_container_type& _Key_cont, const mapped_container_type& _Mapped_cont, const key_compare& _Comp, + const Allocator& _Alloc) + : flat_map(sorted_unique_t(), _Key_cont, _Mapped_cont, _Comp, _Alloc) { + _SortAndDedup(); + } + + flat_map(sorted_unique_t, key_container_type _Key_cont, mapped_container_type _Mapped_cont, + const key_compare& _Comp = key_compare()) + : _Key_compare(_Comp), _Data{.keys = _STD move(_Key_cont), .values = _STD move(_Mapped_cont)} {} template <_Valid_Allocator_for_flat_map Allocator> flat_map(sorted_unique_t, const key_container_type& _Key_cont, const mapped_container_type& _Mapped_cont, @@ -271,6 +283,13 @@ public: _Data{.keys = _STD make_obj_using_allocator(_Alloc, _Key_cont), .values = _STD make_obj_using_allocator(_Alloc, _Mapped_cont)} {} + template <_Valid_Allocator_for_flat_map Allocator> + flat_map(sorted_unique_t, const key_container_type& _Key_cont, const mapped_container_type& _Mapped_cont, + const key_compare& _Comp, const Allocator& _Alloc) + : _Key_compare(_Comp), + _Data{.keys = _STD make_obj_using_allocator(_Alloc, _Key_cont), + .values = _STD make_obj_using_allocator(_Alloc, _Mapped_cont)} {} + template requires _Is_iterator_v<_InputIterator> flat_map(_InputIterator _First, _InputIterator _Last, const key_compare& _Comp = key_compare()) : flat_map(_Comp) { @@ -899,22 +918,38 @@ private: } }; -template -flat_map(_KeyContainer, _MappedContainer) -> flat_map, _KeyContainer, _MappedContainer>; +template _Compare = less> +flat_map(_KeyContainer, _MappedContainer, _Compare = _Compare()) -> flat_map; -template +template _Allocator> flat_map(_KeyContainer, _MappedContainer, _Allocator) -> flat_map, _KeyContainer, _MappedContainer>; -template -flat_map(sorted_unique_t, _KeyContainer, _MappedContainer) -> flat_map, _KeyContainer, _MappedContainer>; +template _Compare, + _Valid_Allocator_for_flat_map<_KeyContainer, _MappedContainer> _Allocator> +flat_map(_KeyContainer, _MappedContainer, _Compare, _Allocator) -> flat_map; + +template _Compare = less> +flat_map(sorted_unique_t, _KeyContainer, _MappedContainer, _Compare = _Compare()) + -> flat_map; -template +template _Allocator> flat_map(sorted_unique_t, _KeyContainer, _MappedContainer, _Allocator) -> flat_map, _KeyContainer, _MappedContainer>; +template _Compare, + _Valid_Allocator_for_flat_map<_KeyContainer, _MappedContainer> _Allocator> +flat_map(sorted_unique_t, _KeyContainer, _MappedContainer, _Compare, _Allocator) + -> flat_map; + template ::first_type>> flat_map(_InputIterator, _InputIterator, _Compare = _Compare()) -> flat_map::first_type, typename iter_value_t<_InputIterator>::second_type, diff --git a/tests/std/tests/P0429R9_flat_map/test.cpp b/tests/std/tests/P0429R9_flat_map/test.cpp index ae90743e6ea..f65090d01e2 100644 --- a/tests/std/tests/P0429R9_flat_map/test.cpp +++ b/tests/std/tests/P0429R9_flat_map/test.cpp @@ -108,6 +108,7 @@ class Packaged { public: Packaged() : value() {} template + requires std::constructible_from Packaged(U&& u) : value(std::forward(u)) {} T get() const { @@ -129,6 +130,10 @@ class Packaged { friend bool operator==(const T& lhs, const Packaged& rhs) { return lhs == rhs.value; } + + friend auto operator<=>(const Packaged& lhs, const Packaged& rhs) { + return lhs.value <=> rhs.value; + } }; template @@ -220,13 +225,10 @@ void test_construction() { MyAllocator> alloc; std::vector, MyAllocator>> keys = {0, 1, 2, 3, 4, 2}; std::vector, MyAllocator>> vals = {44, 2324, 635462, 433, 5, 7}; - std::flat_map, Packaged, PackagedCompare, - std::vector, MyAllocator>>, - std::vector, MyAllocator>>> - map(comp, alloc); + std::flat_map map(keys, vals, comp, alloc); assert(check_requirements(map)); - assert(check_key_content(map, {})); - assert(check_value_content(map, {})); + assert(check_key_content(map, {0, 1, 2, 3, 4})); + assert(check_value_content(map, {44, 2324, 635462, 433, 5})); } } @@ -240,5 +242,6 @@ void test_pointer_to_incomplete_type() { int main() { test_construction(); + test_pointer_to_incomplete_type(); return 0; } From 1f4feec3c1c3a32c37c48041ccd5e5553f8e1878 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Sun, 8 Oct 2023 16:47:09 +0800 Subject: [PATCH 089/100] Improve tests --- tests/std/tests/P0429R9_flat_map/test.cpp | 27 +++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/tests/std/tests/P0429R9_flat_map/test.cpp b/tests/std/tests/P0429R9_flat_map/test.cpp index f65090d01e2..6631438ce2b 100644 --- a/tests/std/tests/P0429R9_flat_map/test.cpp +++ b/tests/std/tests/P0429R9_flat_map/test.cpp @@ -148,6 +148,10 @@ class TransparentPackagedCompare : public PackagedCompare { using PackagedCompare::PackagedCompare; using is_transparent = void; + bool operator()(const Packaged& lhs, const Packaged& rhs) const { + return PackagedCompare::operator()(lhs, rhs); + } + bool operator()(const T& lhs, const Packaged& rhs) const { return lhs < rhs.get(); } @@ -221,10 +225,29 @@ void test_construction() { assert(check_value_content(map, {})); } { - PackagedCompare comp; MyAllocator> alloc; + std::flat_map, int, PackagedCompare, std::vector, MyAllocator>>, + std::vector>> + map(alloc); + assert(check_requirements(map)); + assert(check_key_content(map, {})); + assert(check_value_content(map, {})); + } + { + PackagedCompare comp; + MyAllocator alloc; + std::vector, MyAllocator>> keys = {0, 1, 2, 3, 4, 2}; + std::vector> vals = {44, 2324, 635462, 433, 5, 7}; + std::flat_map map(keys, vals, comp, alloc); + assert(check_requirements(map)); + assert(check_key_content(map, {0, 1, 2, 3, 4})); + assert(check_value_content(map, {44, 2324, 635462, 433, 5})); + } + { + TransparentPackagedCompare comp; + MyAllocator alloc; std::vector, MyAllocator>> keys = {0, 1, 2, 3, 4, 2}; - std::vector, MyAllocator>> vals = {44, 2324, 635462, 433, 5, 7}; + std::vector> vals = {44, 2324, 635462, 433, 5, 7}; std::flat_map map(keys, vals, comp, alloc); assert(check_requirements(map)); assert(check_key_content(map, {0, 1, 2, 3, 4})); From 21459c73331a3433805730b5ad93ee8084a6af56 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Sun, 8 Oct 2023 17:10:38 +0800 Subject: [PATCH 090/100] Fix header test --- tests/std/include/test_header_units_and_modules.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/std/include/test_header_units_and_modules.hpp b/tests/std/include/test_header_units_and_modules.hpp index c268b02dde7..41ff2b0627c 100644 --- a/tests/std/include/test_header_units_and_modules.hpp +++ b/tests/std/include/test_header_units_and_modules.hpp @@ -236,12 +236,14 @@ void test_filesystem() { assert(info.capacity != static_cast(-1)); } +#if TEST_STANDARD >= 23 void test_flatmap() { using namespace std; - puts("Testing ."); + puts("Testing ."); // FIXME! ADD TEST COVERAGE HERE! } +#endif // TEST_STANDARD >= 23 void test_format() { using namespace std; From 1c08c84a2db3135b670561b9f9dcacc8f7ffa753 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Mon, 9 Oct 2023 16:01:04 +0800 Subject: [PATCH 091/100] Take review comments and change the signature of _Insert_exact --- stl/inc/flat_map | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 6e75b05e6fa..0bb3369c892 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -571,11 +571,9 @@ public: return {begin() + _STD distance(_Data.keys.begin(), _Key_It), false}; } else { // Need to insert - value_type _Val{piecewise_construct, - forward_as_tuple(_STD forward<_Key_constructible_t>(_Key_constructible)), - forward_as_tuple(_STD forward<_Args_t>(_Args)...)}; auto _Index = _STD distance(_Data.keys.begin(), _Key_It); - _Insert_exact(begin() + _Index, _STD move(_Val)); + _Insert_exact(cbegin() + _Index, key_type{_STD forward<_Key_constructible_t>(_Key_constructible)}, + mapped_type{_STD forward<_Args_t>(_Args)...}); return {begin() + _Index, true}; } } @@ -824,10 +822,10 @@ private: _Guard._Clearable = nullptr; } - void _Insert_exact(const_iterator _Position, value_type&& _Val) { + void _Insert_exact(const_iterator _Position, key_type&& _Key, mapped_type&& _Mapped) { _Clear_flat_map_scope_guard _Guard{this}; - _Data.keys.insert(_Position._Key_it, _STD move(_Val.first)); - _Data.values.insert(_Position._Mapped_it, _STD move(_Val.second)); + _Data.keys.insert(_Position._Key_it, _STD move(_Key)); + _Data.values.insert(_Position._Mapped_it, _STD move(_Mapped)); _Guard._Clearable = nullptr; } @@ -855,8 +853,8 @@ private: if (_Hint_is_accurate) { auto _Dist = _STD distance(_Begin._Key_it, _Position._Key_it); - _Insert_exact(_Position, value_type{piecewise_construct, forward_as_tuple(_STD forward<_K>(_Key)), - forward_as_tuple(_STD forward<_Mapped_args_t>(_Args)...)}); + _Insert_exact( + _Position, key_type{_STD forward<_K>(_Key)}, mapped_type{_STD forward<_Mapped_args_t>(_Args)...}); return begin() + _Dist; } else { if constexpr (_Overwrite_if_exists) { @@ -876,8 +874,8 @@ private: return _It; } else { auto _Dist = _STD distance(_Begin._Key_it, _Position._Key_it); - _Insert_exact(_Position, value_type{piecewise_construct, forward_as_tuple(_STD forward<_K>(_Key)), - forward_as_tuple(_STD forward<_Mapped_args_t>(_Args)...)}); + _Insert_exact( + _Position, key_type{_STD forward<_K>(_Key)}, mapped_type{_STD forward<_Mapped_args_t>(_Args)...}); return begin() + _Dist; } } From 213b4481294f3902bf469bedeb15b6434749fb74 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Mon, 9 Oct 2023 16:32:45 +0800 Subject: [PATCH 092/100] Use _Ugly style --- stl/inc/flat_map | 109 +++++++++++++++++++++++++---------------------- 1 file changed, 57 insertions(+), 52 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 0bb3369c892..bf770727564 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -33,9 +33,10 @@ _STL_DISABLE_CLANG_WARNINGS _STD_BEGIN -template , class KeyContainer = vector, - class MappedContainer = vector> - requires same_as && same_as +template , + class _FlatMap_KeyContainer = vector<_FlatMap_Key>, class _FlatMap_MappedContainer = vector<_FlatMap_T>> + requires same_as<_FlatMap_Key, typename _FlatMap_KeyContainer::value_type> + && same_as<_FlatMap_T, typename _FlatMap_MappedContainer::value_type> class flat_map; struct sorted_unique_t { @@ -99,8 +100,10 @@ public: conditional_t<_IsConst, typename _MappedContainer::const_iterator, typename _MappedContainer::iterator>; class type { public: - template - requires same_as && same_as + template + requires same_as<_FlatMap_Key, typename _FlatMap_KeyContainer::value_type> + && same_as<_FlatMap_T, typename _FlatMap_MappedContainer::value_type> friend class flat_map; type() = default; type(_Key_iterator_t _Key_it, _Mapped_iterator_t _Mapped_it) : _Key_it(_Key_it), _Mapped_it(_Mapped_it) {} @@ -216,20 +219,22 @@ public: }; _EXPORT_STD -template - requires same_as && same_as +template + requires same_as<_FlatMap_Key, typename _FlatMap_KeyContainer::value_type> + && same_as<_FlatMap_T, typename _FlatMap_MappedContainer::value_type> class flat_map { public: - using key_type = Key; - using mapped_type = T; + using key_type = _FlatMap_Key; + using mapped_type = _FlatMap_T; using value_type = pair; - using key_compare = Compare; + using key_compare = _FlatMap_Compare; using reference = pair; using const_reference = pair; using size_type = size_t; using difference_type = ptrdiff_t; - using key_container_type = KeyContainer; - using mapped_container_type = MappedContainer; + using key_container_type = _FlatMap_KeyContainer; + using mapped_container_type = _FlatMap_MappedContainer; using iterator = _Flat_map_iterator_Impl::type; using const_iterator = _Flat_map_iterator_Impl::type; using reverse_iterator = _STD reverse_iterator; @@ -468,18 +473,18 @@ public: // [flat.map.access] Access template - _NODISCARD mapped_type& operator[](_K&& _Key) + _NODISCARD mapped_type& operator[](_K&& _Key_val) requires same_as, key_type> || (_Compare_is_transparent && constructible_from) { - return try_emplace(_STD forward<_K>(_Key)).first->second; + return try_emplace(_STD forward<_K>(_Key_val)).first->second; } template - _NODISCARD mapped_type& at(const _K& _Key) + _NODISCARD mapped_type& at(const _K& _Key_val) requires same_as<_K, key_type> || _Compare_is_transparent { - iterator _Position = find(_Key); + iterator _Position = find(_Key_val); if (_Position == end()) { _Xout_of_range("std::flat_map::at: the specified key does not exist."); } else { @@ -488,10 +493,10 @@ public: } template - _NODISCARD const mapped_type& at(const _K& _Key) const + _NODISCARD const mapped_type& at(const _K& _Key_val) const requires same_as<_K, key_type> || _Compare_is_transparent { - const_iterator _Position = find(_Key); + const_iterator _Position = find(_Key_val); if (_Position == cend()) { _Xout_of_range("std::flat_map::at: the specified key does not exist."); } else { @@ -579,21 +584,21 @@ public: } template - iterator try_emplace(const_iterator _Position, _K&& _Key, _Args_t&&... _Args) + iterator try_emplace(const_iterator _Position, _K&& _Key_val, _Args_t&&... _Args) requires constructible_from && (same_as, key_type> || (constructible_from && _Compare_is_transparent) ) { - return _Emplace_hint(_Position, _STD forward<_K>(_Key), _STD forward<_Args_t>(_Args)...); + return _Emplace_hint(_Position, _STD forward<_K>(_Key_val), _STD forward<_Args_t>(_Args)...); } template - pair insert_or_assign(_K&& _Key, _M&& _Obj) + pair insert_or_assign(_K&& _Key_val, _M&& _Obj) requires assignable_from && constructible_from && (same_as, key_type> || (constructible_from && _Compare_is_transparent) ) { - auto _Res = try_emplace(_STD forward<_K>(_Key), _STD forward<_M>(_Obj)); + auto _Res = try_emplace(_STD forward<_K>(_Key_val), _STD forward<_M>(_Obj)); if (_Res.second) { // Insertion took place return _Res; @@ -605,12 +610,12 @@ public: } template - iterator insert_or_assign(const_iterator _Position, _K&& _Key, _M&& _Obj) + iterator insert_or_assign(const_iterator _Position, _K&& _Key_val, _M&& _Obj) requires assignable_from && constructible_from && (same_as, key_type> || (constructible_from && _Compare_is_transparent) ) { - return _Emplace_hint(_Position, _STD forward<_K>(_Key), _STD forward<_M>(_Obj)); + return _Emplace_hint(_Position, _STD forward<_K>(_Key_val), _STD forward<_M>(_Obj)); } iterator erase(iterator _Position) { @@ -634,13 +639,13 @@ public: } template - size_type erase(_K&& _Key) + size_type erase(_K&& _Key_val) requires convertible_to<_K&&, const key_type&> || (_Compare_is_transparent && !convertible_to<_K &&, iterator> && !convertible_to<_K &&, const_iterator>) { - const_iterator _Pos_begin = lower_bound(_STD forward<_K>(_Key)); - const_iterator _Pos_end = upper_bound(_STD forward<_K>(_Key)); + const_iterator _Pos_begin = lower_bound(_STD forward<_K>(_Key_val)); + const_iterator _Pos_end = upper_bound(_STD forward<_K>(_Key_val)); size_type _Count = _Pos_end - _Pos_begin; erase(_Pos_begin, _Pos_end); return _Count; @@ -718,10 +723,10 @@ public: iterator lower_bound(const _K& _X) requires same_as<_K, key_type> || _Compare_is_transparent { - typename KeyContainer::const_iterator _Key_it = + typename key_container_type::const_iterator _Key_it = _STD lower_bound(_Data.keys.cbegin(), _Data.keys.cend(), _X, _Key_compare); - auto _Dist = _STD distance(_Data.keys.cbegin(), _Key_it); - typename MappedContainer::iterator _Val_it = _Data.values.begin() + _Dist; + auto _Dist = _STD distance(_Data.keys.cbegin(), _Key_it); + typename mapped_container_type::iterator _Val_it = _Data.values.begin() + _Dist; return iterator{_STD move(_Key_it), _STD move(_Val_it)}; } @@ -729,10 +734,10 @@ public: const_iterator lower_bound(const _K& _X) const requires same_as<_K, key_type> || _Compare_is_transparent { - typename KeyContainer::const_iterator _Key_it = + typename key_container_type::const_iterator _Key_it = _STD lower_bound(_Data.keys.cbegin(), _Data.keys.cend(), _X, _Key_compare); - auto _Dist = _STD distance(_Data.keys.cbegin(), _Key_it); - typename MappedContainer::const_iterator _Val_it = _Data.values.cbegin() + _Dist; + auto _Dist = _STD distance(_Data.keys.cbegin(), _Key_it); + typename mapped_container_type::const_iterator _Val_it = _Data.values.cbegin() + _Dist; return const_iterator{_STD move(_Key_it), _STD move(_Val_it)}; } @@ -740,10 +745,10 @@ public: iterator upper_bound(const _K& _X) requires same_as<_K, key_type> || _Compare_is_transparent { - typename KeyContainer::const_iterator _Key_it = + typename key_container_type::const_iterator _Key_it = _STD upper_bound(_Data.keys.cbegin(), _Data.keys.cend(), _X, _Key_compare); - auto _Dist = _STD distance(_Data.keys.cbegin(), _Key_it); - typename MappedContainer::iterator _Val_it = _Data.values.begin() + _Dist; + auto _Dist = _STD distance(_Data.keys.cbegin(), _Key_it); + typename mapped_container_type::iterator _Val_it = _Data.values.begin() + _Dist; return iterator{_STD move(_Key_it), _STD move(_Val_it)}; } @@ -751,10 +756,10 @@ public: const_iterator upper_bound(const _K& _X) const requires same_as<_K, key_type> || _Compare_is_transparent { - typename KeyContainer::const_iterator _Key_it = + typename key_container_type::const_iterator _Key_it = _STD upper_bound(_Data.keys.cbegin(), _Data.keys.cend(), _X, _Key_compare); - auto _Dist = _STD distance(_Data.keys.cbegin(), _Key_it); - typename MappedContainer::const_iterator _Val_it = _Data.values.cbegin() + _Dist; + auto _Dist = _STD distance(_Data.keys.cbegin(), _Key_it); + typename mapped_container_type::const_iterator _Val_it = _Data.values.cbegin() + _Dist; return const_iterator{_STD move(_Key_it), _STD move(_Val_it)}; } @@ -822,15 +827,15 @@ private: _Guard._Clearable = nullptr; } - void _Insert_exact(const_iterator _Position, key_type&& _Key, mapped_type&& _Mapped) { + void _Insert_exact(const_iterator _Position, key_type&& _Key_val, mapped_type&& _Mapped) { _Clear_flat_map_scope_guard _Guard{this}; - _Data.keys.insert(_Position._Key_it, _STD move(_Key)); + _Data.keys.insert(_Position._Key_it, _STD move(_Key_val)); _Data.values.insert(_Position._Mapped_it, _STD move(_Mapped)); _Guard._Clearable = nullptr; } template - iterator _Emplace_hint(const_iterator _Position, _K&& _Key, _Mapped_args_t&&... _Args) + iterator _Emplace_hint(const_iterator _Position, _K&& _Key_val, _Mapped_args_t&&... _Args) requires is_constructible_v && (same_as, key_type> || (constructible_from && _Compare_is_transparent) ) @@ -843,22 +848,22 @@ private: bool _Insert_before_position = false; bool _Insert_after_position_minus_1 = false; if constexpr (_Multi) { - _Insert_before_position = (_Position == _End) || !_Key_compare(*(_Position._Key_it), _Key); - _Insert_after_position_minus_1 = (_Position == _Begin) || !_Key_compare(_Key, *(_Position._Key_it - 1)); + _Insert_before_position = (_Position == _End) || !_Key_compare(*(_Position._Key_it), _Key_val); + _Insert_after_position_minus_1 = (_Position == _Begin) || !_Key_compare(_Key_val, *(_Position._Key_it - 1)); } else { - _Insert_before_position = (_Position == _End) || _Key_compare(_Key, *(_Position._Key_it)); - _Insert_after_position_minus_1 = (_Position == _Begin) || _Key_compare(*(_Position._Key_it - 1), _Key); + _Insert_before_position = (_Position == _End) || _Key_compare(_Key_val, *(_Position._Key_it)); + _Insert_after_position_minus_1 = (_Position == _Begin) || _Key_compare(*(_Position._Key_it - 1), _Key_val); } bool _Hint_is_accurate = _Insert_before_position && _Insert_after_position_minus_1; if (_Hint_is_accurate) { auto _Dist = _STD distance(_Begin._Key_it, _Position._Key_it); _Insert_exact( - _Position, key_type{_STD forward<_K>(_Key)}, mapped_type{_STD forward<_Mapped_args_t>(_Args)...}); + _Position, key_type{_STD forward<_K>(_Key_val)}, mapped_type{_STD forward<_Mapped_args_t>(_Args)...}); return begin() + _Dist; } else { if constexpr (_Overwrite_if_exists) { - if (_Key_equal(_Key, *(_Position._Key_it))) { + if (_Key_equal(_Key_val, *(_Position._Key_it))) { auto _Dist = _STD distance(_Begin._Key_it, _Position._Key_it); auto _It = begin() + _Dist; *(_It._Mapped_it) = mapped_type{_STD forward<_Mapped_args_t>(_Args)...}; @@ -866,16 +871,16 @@ private: } } - _Position = lower_bound(_Key); - if (_Overwrite_if_exists && _Position != _End && _Key_equal(_Key, *(_Position._Key_it))) { + _Position = lower_bound(_Key_val); + if (_Overwrite_if_exists && _Position != _End && _Key_equal(_Key_val, *(_Position._Key_it))) { auto _Dist = _STD distance(_Begin._Key_it, _Position._Key_it); auto _It = begin() + _Dist; *(_It._Mapped_it) = mapped_type{_STD forward<_Mapped_args_t>(_Args)...}; return _It; } else { auto _Dist = _STD distance(_Begin._Key_it, _Position._Key_it); - _Insert_exact( - _Position, key_type{_STD forward<_K>(_Key)}, mapped_type{_STD forward<_Mapped_args_t>(_Args)...}); + _Insert_exact(_Position, key_type{_STD forward<_K>(_Key_val)}, + mapped_type{_STD forward<_Mapped_args_t>(_Args)...}); return begin() + _Dist; } } From 49d5dd6114a40727ede5e7554bd63263c654c53f Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Tue, 10 Oct 2023 13:08:03 +0800 Subject: [PATCH 093/100] Use concept instead of enable_if_t --- stl/inc/flat_map | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index bf770727564..014fc1cb6ea 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -204,9 +204,9 @@ public: return _Right + _Off; } - template > - operator typename _Flat_map_iterator_Impl, - enable_if_t, true>::type() const { + operator typename _Flat_map_iterator_Impl<_KeyContainer, _MappedContainer, true>::type() const + requires (!_IsConst) + { return typename _Flat_map_iterator_Impl<_KeyContainer, _MappedContainer, true>::type{_Key_it, _Mapped_it}; } From 4e3dc8df2586aa532f69ca7d0549fd0d5c177e0e Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Tue, 10 Oct 2023 13:33:51 +0800 Subject: [PATCH 094/100] Use _Is_transparent_v from instead of inventing a new concept --- stl/inc/flat_map | 43 ++++++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 014fc1cb6ea..d2e9a7a86a6 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -52,9 +52,6 @@ template concept _Valid_Compare_for_container = is_invocable_v; -template -concept _Compare_is_transparent = requires { typename _Compare::is_transparent; }; - template struct _Flat_value_compare { struct value_compare { @@ -475,14 +472,14 @@ public: template _NODISCARD mapped_type& operator[](_K&& _Key_val) requires same_as, key_type> - || (_Compare_is_transparent && constructible_from) + || (_Is_transparent_v && constructible_from) { return try_emplace(_STD forward<_K>(_Key_val)).first->second; } template _NODISCARD mapped_type& at(const _K& _Key_val) - requires same_as<_K, key_type> || _Compare_is_transparent + requires same_as<_K, key_type> || _Is_transparent_v { iterator _Position = find(_Key_val); if (_Position == end()) { @@ -494,7 +491,7 @@ public: template _NODISCARD const mapped_type& at(const _K& _Key_val) const - requires same_as<_K, key_type> || _Compare_is_transparent + requires same_as<_K, key_type> || _Is_transparent_v { const_iterator _Position = find(_Key_val); if (_Position == cend()) { @@ -565,7 +562,7 @@ public: pair try_emplace(_Key_constructible_t&& _Key_constructible, _Args_t&&... _Args) requires constructible_from && (same_as, key_type> - || (constructible_from && _Compare_is_transparent + || (constructible_from && _Is_transparent_v && !convertible_to<_Key_constructible_t&&, const_iterator> && !convertible_to<_Key_constructible_t&&, iterator>) ) { @@ -587,7 +584,7 @@ public: iterator try_emplace(const_iterator _Position, _K&& _Key_val, _Args_t&&... _Args) requires constructible_from && (same_as, key_type> - || (constructible_from && _Compare_is_transparent) ) + || (constructible_from && _Is_transparent_v) ) { return _Emplace_hint(_Position, _STD forward<_K>(_Key_val), _STD forward<_Args_t>(_Args)...); } @@ -596,7 +593,7 @@ public: pair insert_or_assign(_K&& _Key_val, _M&& _Obj) requires assignable_from && constructible_from && (same_as, key_type> - || (constructible_from && _Compare_is_transparent) ) + || (constructible_from && _Is_transparent_v) ) { auto _Res = try_emplace(_STD forward<_K>(_Key_val), _STD forward<_M>(_Obj)); if (_Res.second) { @@ -613,7 +610,7 @@ public: iterator insert_or_assign(const_iterator _Position, _K&& _Key_val, _M&& _Obj) requires assignable_from && constructible_from && (same_as, key_type> - || (constructible_from && _Compare_is_transparent) ) + || (constructible_from && _Is_transparent_v) ) { return _Emplace_hint(_Position, _STD forward<_K>(_Key_val), _STD forward<_M>(_Obj)); } @@ -641,7 +638,7 @@ public: template size_type erase(_K&& _Key_val) requires convertible_to<_K&&, const key_type&> - || (_Compare_is_transparent && !convertible_to<_K &&, iterator> + || (_Is_transparent_v && !convertible_to<_K &&, iterator> && !convertible_to<_K &&, const_iterator>) { const_iterator _Pos_begin = lower_bound(_STD forward<_K>(_Key_val)); @@ -683,7 +680,7 @@ public: // map operations template iterator find(const _K& _X) - requires same_as<_K, key_type> || _Compare_is_transparent + requires same_as<_K, key_type> || _Is_transparent_v { iterator _Position = lower_bound(_X); if (_Position != end() && _Key_equal(_Position->first, _X)) { @@ -695,7 +692,7 @@ public: template const_iterator find(const _K& _X) const - requires same_as<_K, key_type> || _Compare_is_transparent + requires same_as<_K, key_type> || _Is_transparent_v { const_iterator _Position = lower_bound(_X); if (_Position != cend() && _Key_equal(_Position->first, _X)) { @@ -707,21 +704,21 @@ public: template size_type count(const _K& _X) const - requires same_as<_K, key_type> || _Compare_is_transparent + requires same_as<_K, key_type> || _Is_transparent_v { return upper_bound(_X) - lower_bound(_X); } template bool contains(const _K& _X) const - requires same_as<_K, key_type> || _Compare_is_transparent + requires same_as<_K, key_type> || _Is_transparent_v { return find(_X) != cend(); } template iterator lower_bound(const _K& _X) - requires same_as<_K, key_type> || _Compare_is_transparent + requires same_as<_K, key_type> || _Is_transparent_v { typename key_container_type::const_iterator _Key_it = _STD lower_bound(_Data.keys.cbegin(), _Data.keys.cend(), _X, _Key_compare); @@ -732,7 +729,7 @@ public: template const_iterator lower_bound(const _K& _X) const - requires same_as<_K, key_type> || _Compare_is_transparent + requires same_as<_K, key_type> || _Is_transparent_v { typename key_container_type::const_iterator _Key_it = _STD lower_bound(_Data.keys.cbegin(), _Data.keys.cend(), _X, _Key_compare); @@ -743,7 +740,7 @@ public: template iterator upper_bound(const _K& _X) - requires same_as<_K, key_type> || _Compare_is_transparent + requires same_as<_K, key_type> || _Is_transparent_v { typename key_container_type::const_iterator _Key_it = _STD upper_bound(_Data.keys.cbegin(), _Data.keys.cend(), _X, _Key_compare); @@ -754,7 +751,7 @@ public: template const_iterator upper_bound(const _K& _X) const - requires same_as<_K, key_type> || _Compare_is_transparent + requires same_as<_K, key_type> || _Is_transparent_v { typename key_container_type::const_iterator _Key_it = _STD upper_bound(_Data.keys.cbegin(), _Data.keys.cend(), _X, _Key_compare); @@ -765,14 +762,14 @@ public: template pair equal_range(const _K& _X) - requires same_as<_K, key_type> || _Compare_is_transparent + requires same_as<_K, key_type> || _Is_transparent_v { return {lower_bound(_X), upper_bound(_X)}; } template pair equal_range(const _K& _X) const - requires same_as<_K, key_type> || _Compare_is_transparent + requires same_as<_K, key_type> || _Is_transparent_v { return {lower_bound(_X), upper_bound(_X)}; } @@ -798,7 +795,7 @@ private: template requires (same_as, key_type> && same_as, key_type>) || (constructible_from && constructible_from - && _Compare_is_transparent) + && _Is_transparent_v) bool _Key_equal(_K1&& _X, _K2&& _Y) const { return !_Key_compare(_STD forward<_K1>(_X), _STD forward<_K2>(_Y)) && !_Key_compare(_STD forward<_K2>(_Y), _STD forward<_K1>(_X)); @@ -838,7 +835,7 @@ private: iterator _Emplace_hint(const_iterator _Position, _K&& _Key_val, _Mapped_args_t&&... _Args) requires is_constructible_v && (same_as, key_type> - || (constructible_from && _Compare_is_transparent) ) + || (constructible_from && _Is_transparent_v) ) { static_assert(!(_Multi && _Overwrite_if_exists), "Overwriting is not supported when the container allows multiple copies of a key."); From 4d0d81ff45c3761748d03b9c2bbb08a96169e3d8 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Tue, 10 Oct 2023 13:36:07 +0800 Subject: [PATCH 095/100] Add definition of sorted_equivalent_t --- stl/inc/flat_map | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index d2e9a7a86a6..5cc03e0b2a4 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -44,6 +44,11 @@ struct sorted_unique_t { }; inline constexpr sorted_unique_t sorted_unique{}; +struct sorted_equivalent_t { + explicit sorted_equivalent_t() = default; +}; +inline constexpr sorted_equivalent_t sorted_equivalent{}; + template concept _Valid_Allocator_for_flat_map = uses_allocator_v<_Key_container, _Alloc> && uses_allocator_v<_Mapped_container, _Alloc>; From 945ef18db4f29539962b4cad446d79a064a8dfb7 Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Tue, 10 Oct 2023 14:36:41 +0800 Subject: [PATCH 096/100] Add definition of flat_multimap --- stl/inc/flat_map | 185 ++++++++++++++++++++++++++++++----------------- 1 file changed, 117 insertions(+), 68 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index 5cc03e0b2a4..a682ebec459 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -33,12 +33,20 @@ _STL_DISABLE_CLANG_WARNINGS _STD_BEGIN -template , - class _FlatMap_KeyContainer = vector<_FlatMap_Key>, class _FlatMap_MappedContainer = vector<_FlatMap_T>> +template requires same_as<_FlatMap_Key, typename _FlatMap_KeyContainer::value_type> && same_as<_FlatMap_T, typename _FlatMap_MappedContainer::value_type> +class _Flat_Map_Base; + +template , class _KeyContainer = vector<_Key>, + class _MappedContainer = vector<_Mapped>> class flat_map; +template , class _KeyContainer = vector<_Key>, + class _MappedContainer = vector<_Mapped>> +class flat_multimap; + struct sorted_unique_t { explicit sorted_unique_t() = default; }; @@ -103,10 +111,10 @@ public: class type { public: template + class _FlatMap_MappedContainer, bool _Is_Multi, class _Derived> requires same_as<_FlatMap_Key, typename _FlatMap_KeyContainer::value_type> && same_as<_FlatMap_T, typename _FlatMap_MappedContainer::value_type> - friend class flat_map; + friend class _Flat_Map_Base; type() = default; type(_Key_iterator_t _Key_it, _Mapped_iterator_t _Mapped_it) : _Key_it(_Key_it), _Mapped_it(_Mapped_it) {} @@ -222,10 +230,13 @@ public: _EXPORT_STD template + class _FlatMap_MappedContainer, bool _Is_Multi, class _Derived> requires same_as<_FlatMap_Key, typename _FlatMap_KeyContainer::value_type> && same_as<_FlatMap_T, typename _FlatMap_MappedContainer::value_type> -class flat_map { +class _Flat_Map_Base { +private: + using _Sorted_t = conditional_t<_Is_Multi, sorted_equivalent_t, sorted_unique_t>; + public: using key_type = _FlatMap_Key; using mapped_type = _FlatMap_T; @@ -250,48 +261,59 @@ public: public: // [flat.map.cons] Constructors - explicit flat_map(const key_compare& _Comp) : _Key_compare(_Comp), _Data() {} - flat_map() : flat_map(key_compare()) {} + explicit _Flat_Map_Base(const key_compare& _Comp) : _Key_compare(_Comp), _Data() {} + _Flat_Map_Base() : _Flat_Map_Base(key_compare()) {} template <_Valid_Allocator_for_flat_map Allocator> - explicit flat_map(const Allocator& _Alloc) : flat_map(key_compare(), _Alloc) {} + explicit _Flat_Map_Base(const Allocator& _Alloc) : _Flat_Map_Base(key_compare(), _Alloc) {} template <_Valid_Allocator_for_flat_map Allocator> - explicit flat_map(const key_compare& _Comp, const Allocator& _Alloc) + explicit _Flat_Map_Base(const key_compare& _Comp, const Allocator& _Alloc) : _Key_compare(_Comp), _Data{.keys = _STD make_obj_using_allocator(_Alloc), .values = _STD make_obj_using_allocator(_Alloc)} {} - flat_map(key_container_type _Key_cont, mapped_container_type _Mapped_cont, const key_compare& _Comp = key_compare()) - : flat_map(sorted_unique_t(), _Key_cont, _Mapped_cont, _Comp) { - _SortAndDedup(); + _Flat_Map_Base( + key_container_type _Key_cont, mapped_container_type _Mapped_cont, const key_compare& _Comp = key_compare()) + : _Flat_Map_Base(_Sorted_t(), _Key_cont, _Mapped_cont, _Comp) { + _Sort(); + if constexpr (!_Is_Multi) { + _Dedup(); + } } template <_Valid_Allocator_for_flat_map Allocator> - flat_map(const key_container_type& _Key_cont, const mapped_container_type& _Mapped_cont, const Allocator& _Alloc) - : flat_map(sorted_unique_t(), _Key_cont, _Mapped_cont, _Alloc) { - _SortAndDedup(); + _Flat_Map_Base( + const key_container_type& _Key_cont, const mapped_container_type& _Mapped_cont, const Allocator& _Alloc) + : _Flat_Map_Base(_Sorted_t(), _Key_cont, _Mapped_cont, _Alloc) { + _Sort(); + if constexpr (!_Is_Multi) { + _Dedup(); + } } template <_Valid_Allocator_for_flat_map Allocator> - flat_map(const key_container_type& _Key_cont, const mapped_container_type& _Mapped_cont, const key_compare& _Comp, - const Allocator& _Alloc) - : flat_map(sorted_unique_t(), _Key_cont, _Mapped_cont, _Comp, _Alloc) { - _SortAndDedup(); + _Flat_Map_Base(const key_container_type& _Key_cont, const mapped_container_type& _Mapped_cont, + const key_compare& _Comp, const Allocator& _Alloc) + : _Flat_Map_Base(_Sorted_t(), _Key_cont, _Mapped_cont, _Comp, _Alloc) { + _Sort(); + if constexpr (!_Is_Multi) { + _Dedup(); + } } - flat_map(sorted_unique_t, key_container_type _Key_cont, mapped_container_type _Mapped_cont, + _Flat_Map_Base(_Sorted_t, key_container_type _Key_cont, mapped_container_type _Mapped_cont, const key_compare& _Comp = key_compare()) : _Key_compare(_Comp), _Data{.keys = _STD move(_Key_cont), .values = _STD move(_Mapped_cont)} {} template <_Valid_Allocator_for_flat_map Allocator> - flat_map(sorted_unique_t, const key_container_type& _Key_cont, const mapped_container_type& _Mapped_cont, + _Flat_Map_Base(_Sorted_t, const key_container_type& _Key_cont, const mapped_container_type& _Mapped_cont, const Allocator& _Alloc) : _Key_compare(key_compare()), _Data{.keys = _STD make_obj_using_allocator(_Alloc, _Key_cont), .values = _STD make_obj_using_allocator(_Alloc, _Mapped_cont)} {} template <_Valid_Allocator_for_flat_map Allocator> - flat_map(sorted_unique_t, const key_container_type& _Key_cont, const mapped_container_type& _Mapped_cont, + _Flat_Map_Base(_Sorted_t, const key_container_type& _Key_cont, const mapped_container_type& _Mapped_cont, const key_compare& _Comp, const Allocator& _Alloc) : _Key_compare(_Comp), _Data{.keys = _STD make_obj_using_allocator(_Alloc, _Key_cont), @@ -299,104 +321,108 @@ public: template requires _Is_iterator_v<_InputIterator> - flat_map(_InputIterator _First, _InputIterator _Last, const key_compare& _Comp = key_compare()) : flat_map(_Comp) { + _Flat_Map_Base(_InputIterator _First, _InputIterator _Last, const key_compare& _Comp = key_compare()) + : _Flat_Map_Base(_Comp) { insert(_First, _Last); } template Allocator> requires _Is_iterator_v<_InputIterator> - flat_map(_InputIterator _First, _InputIterator _Last, const key_compare& _Comp, const Allocator& _Alloc) - : flat_map(_Comp, _Alloc) { + _Flat_Map_Base(_InputIterator _First, _InputIterator _Last, const key_compare& _Comp, const Allocator& _Alloc) + : _Flat_Map_Base(_Comp, _Alloc) { insert(_First, _Last); } template <_Container_compatible_range R> - flat_map(from_range_t _From_range, R&& _Range) : flat_map(_From_range, _STD forward(_Range), key_compare()) {} + _Flat_Map_Base(from_range_t _From_range, R&& _Range) + : _Flat_Map_Base(_From_range, _STD forward(_Range), key_compare()) {} template <_Container_compatible_range R, _Valid_Allocator_for_flat_map Allocator> - flat_map(from_range_t _From_range, R&& _Range, const Allocator& _Alloc) - : flat_map(_From_range, _STD forward(_Range), key_compare(), _Alloc) {} + _Flat_Map_Base(from_range_t _From_range, R&& _Range, const Allocator& _Alloc) + : _Flat_Map_Base(_From_range, _STD forward(_Range), key_compare(), _Alloc) {} template <_Container_compatible_range R> - flat_map(from_range_t, R&& _Range, const key_compare& _Comp) : flat_map(_Comp) { + _Flat_Map_Base(from_range_t, R&& _Range, const key_compare& _Comp) : _Flat_Map_Base(_Comp) { insert_range(_STD forward(_Range)); } template <_Container_compatible_range R, _Valid_Allocator_for_flat_map Allocator> - flat_map(from_range_t, R&& _Range, const key_compare& _Comp, const Allocator& _Alloc) : flat_map(_Comp, _Alloc) { + _Flat_Map_Base(from_range_t, R&& _Range, const key_compare& _Comp, const Allocator& _Alloc) + : _Flat_Map_Base(_Comp, _Alloc) { insert_range(_STD forward(_Range)); } template requires _Is_iterator_v<_InputIterator> - flat_map(sorted_unique_t _S, _InputIterator _First, _InputIterator _Last, const key_compare& _Comp = key_compare()) - : flat_map(_Comp) { + _Flat_Map_Base(_Sorted_t _S, _InputIterator _First, _InputIterator _Last, const key_compare& _Comp = key_compare()) + : _Flat_Map_Base(_Comp) { insert(_S, _First, _Last); } template Allocator> requires _Is_iterator_v<_InputIterator> - flat_map(sorted_unique_t _S, _InputIterator _First, _InputIterator _Last, const key_compare& _Comp, - const Allocator& _Alloc) - : flat_map(_Comp, _Alloc) { + _Flat_Map_Base( + _Sorted_t _S, _InputIterator _First, _InputIterator _Last, const key_compare& _Comp, const Allocator& _Alloc) + : _Flat_Map_Base(_Comp, _Alloc) { insert(_S, _First, _Last); } template Allocator> requires _Is_iterator_v<_InputIterator> - flat_map(sorted_unique_t _S, _InputIterator _First, _InputIterator _Last, const Allocator& _Alloc) - : flat_map(_S, _First, _Last, key_compare(), _Alloc) {} + _Flat_Map_Base(_Sorted_t _S, _InputIterator _First, _InputIterator _Last, const Allocator& _Alloc) + : _Flat_Map_Base(_S, _First, _Last, key_compare(), _Alloc) {} - flat_map(initializer_list _I, const key_compare& _Comp = key_compare()) - : flat_map(_I.begin(), _I.end(), _Comp) {} + _Flat_Map_Base(initializer_list _I, const key_compare& _Comp = key_compare()) + : _Flat_Map_Base(_I.begin(), _I.end(), _Comp) {} template <_Valid_Allocator_for_flat_map Allocator> - flat_map(initializer_list _I, const key_compare& _Comp, const Allocator& _Alloc) - : flat_map(_I.begin(), _I.end(), _Comp, _Alloc) {} + _Flat_Map_Base(initializer_list _I, const key_compare& _Comp, const Allocator& _Alloc) + : _Flat_Map_Base(_I.begin(), _I.end(), _Comp, _Alloc) {} template <_Valid_Allocator_for_flat_map Allocator> - flat_map(initializer_list _I, const Allocator& _Alloc) : flat_map(_I, key_compare(), _Alloc) {} + _Flat_Map_Base(initializer_list _I, const Allocator& _Alloc) + : _Flat_Map_Base(_I, key_compare(), _Alloc) {} - flat_map(sorted_unique_t _S, initializer_list _I, const key_compare& _Comp = key_compare()) - : flat_map(_S, _I.begin(), _I.end(), _Comp) {} + _Flat_Map_Base(_Sorted_t _S, initializer_list _I, const key_compare& _Comp = key_compare()) + : _Flat_Map_Base(_S, _I.begin(), _I.end(), _Comp) {} template <_Valid_Allocator_for_flat_map Allocator> - flat_map(sorted_unique_t _S, initializer_list _I, const key_compare& _Comp, const Allocator& _Alloc) - : flat_map(_S, _I.begin(), _I.end(), _Comp, _Alloc) {} + _Flat_Map_Base(_Sorted_t _S, initializer_list _I, const key_compare& _Comp, const Allocator& _Alloc) + : _Flat_Map_Base(_S, _I.begin(), _I.end(), _Comp, _Alloc) {} template <_Valid_Allocator_for_flat_map Allocator> - flat_map(sorted_unique_t _S, initializer_list _I, const Allocator& _Alloc) - : flat_map(_S, _I, key_compare(), _Alloc) {} + _Flat_Map_Base(_Sorted_t _S, initializer_list _I, const Allocator& _Alloc) + : _Flat_Map_Base(_S, _I, key_compare(), _Alloc) {} // Copy constructors - flat_map(const flat_map& _Other) : _Key_compare(_Other._Key_compare), _Data(_Other._Data) {} + _Flat_Map_Base(const _Derived& _Other) : _Key_compare(_Other._Key_compare), _Data(_Other._Data) {} template <_Valid_Allocator_for_flat_map _Allocator> - flat_map(const flat_map& _Other, const _Allocator& _Alloc) + _Flat_Map_Base(const _Derived& _Other, const _Allocator& _Alloc) : _Key_compare(_Other._Key_compare), _Data{.keys = _STD make_obj_using_allocator(_Alloc, _Other._Data.keys), .values = _STD make_obj_using_allocator(_Alloc, _Other._Data.values)} {} // Move constructors - flat_map(flat_map&& _Other) noexcept( + _Flat_Map_Base(_Derived&& _Other) noexcept( _STD is_nothrow_move_constructible_v&& _STD is_nothrow_move_constructible_v&& _STD is_nothrow_move_constructible_v) : _Key_compare(move(_Other._Key_compare)), _Data(move(_Other).extract()) {} template <_Valid_Allocator_for_flat_map _Allocator> - flat_map(flat_map&& _Other, const _Allocator& _Alloc) noexcept( + _Flat_Map_Base(_Derived&& _Other, const _Allocator& _Alloc) noexcept( _STD is_nothrow_move_constructible_v&& _STD is_nothrow_move_constructible_v&& _STD is_nothrow_move_constructible_v) : _Key_compare(move(_Other._Key_compare)), _Data{.keys = _STD make_obj_using_allocator(_Alloc, move(_Other._Data.keys)), .values = _STD make_obj_using_allocator(_Alloc, move(_Other._Data.values))} {} - flat_map& operator=(initializer_list _I) { + _Derived& operator=(initializer_list _I) { clear(); insert(_I.begin(), _I.end()); - return *this; + return static_cast<_Derived&>(*this); // Use "deducing this" when it is supported } // [container.reqmts] iterators @@ -448,7 +474,7 @@ public: return _STD make_reverse_iterator(cbegin()); } - void swap(flat_map& _Other) noexcept { + void swap(_Derived& _Other) noexcept { _RANGES swap(_Key_compare, _Other._Key_compare); _RANGES swap(_Data.keys, _Other._Data.keys); _RANGES swap(_Data.values, _Other._Data.values); @@ -541,13 +567,13 @@ public: template requires _Is_iterator_v<_InputIterator> void insert(_InputIterator _First, _InputIterator _Last) { - _Insert_range(_First, _Last); + _Insert_range(_First, _Last); } template requires _Is_iterator_v<_InputIterator> - void insert(sorted_unique_t, _InputIterator _First, _InputIterator _Last) { - _Insert_range(_First, _Last); + void insert(_Sorted_t, _InputIterator _First, _InputIterator _Last) { + _Insert_range(_First, _Last); } template <_Container_compatible_range R> @@ -559,7 +585,7 @@ public: insert(_I.begin(), _I.end()); } - void insert(sorted_unique_t _S, initializer_list _I) { + void insert(_Sorted_t _S, initializer_list _I) { insert(_S, _I.begin(), _I.end()); } @@ -779,16 +805,16 @@ public: return {lower_bound(_X), upper_bound(_X)}; } - friend bool operator==(const flat_map& _X, const flat_map& _Y) { + friend bool operator==(const _Derived& _X, const _Derived& _Y) { return _RANGES equal(_X._Data.keys, _Y._Data.keys) && _RANGES equal(_X._Data.values, _Y._Data.values); } - friend auto operator<=>(const flat_map& _X, const flat_map& _Y) { + friend auto operator<=>(const _Derived& _X, const _Derived& _Y) { return _STD lexicographical_compare_three_way( _X.cbegin(), _X.cend(), _Y.cbegin(), _Y.cend(), _Synth_three_way{}); } - friend void swap(flat_map& _X, flat_map& _Y) noexcept { + friend void swap(_Derived& _X, _Derived& _Y) noexcept { _X.swap(_Y); } @@ -806,11 +832,6 @@ private: && !_Key_compare(_STD forward<_K2>(_Y), _STD forward<_K1>(_X)); } - void _SortAndDedup() { - _Sort(); - _Dedup(); - } - void _Sort() { _Clear_flat_map_scope_guard _Guard{this}; auto _Zip_view = _RANGES views::zip(_Data.keys, _Data.values); @@ -923,6 +944,30 @@ private: } }; +template +class flat_map : public _Flat_Map_Base<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer, false, + flat_map<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer>> { +private: + using _MyBase = _Flat_Map_Base<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer, false, + flat_map<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer>>; + +public: + using _MyBase::_MyBase; + using _MyBase::operator=; +}; + +template +class flat_multimap : public _Flat_Map_Base<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer, true, + flat_multimap<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer>> { +private: + using _MyBase = _Flat_Map_Base<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer, true, + flat_multimap<_Key, _Mapped, _Compare, _KeyContainer, _MappedContainer>>; + +public: + using _MyBase::_MyBase; + using _MyBase::operator=; +}; + template _Compare = less> flat_map(_KeyContainer, _MappedContainer, _Compare = _Compare()) -> flat_map, _Allocator> : bool_constant && uses_allocator_v<_MappedContainer, _Allocator>> {}; +template +struct uses_allocator, _Allocator> + : bool_constant && uses_allocator_v<_MappedContainer, _Allocator>> {}; + _STD_END #pragma pop_macro("new") From aabc8cac83b1603f89967aa956e1cf459d41d19c Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Tue, 10 Oct 2023 15:17:49 +0800 Subject: [PATCH 097/100] Add a test of incomplete type --- tests/std/tests/P0429R9_flat_map/test.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/std/tests/P0429R9_flat_map/test.cpp b/tests/std/tests/P0429R9_flat_map/test.cpp index 6631438ce2b..d3d10569eab 100644 --- a/tests/std/tests/P0429R9_flat_map/test.cpp +++ b/tests/std/tests/P0429R9_flat_map/test.cpp @@ -255,12 +255,23 @@ void test_construction() { } } + +struct Incomplete; +template +struct MyType { + T* ptr; + + bool operator==(const MyType&) const = default; + auto operator<=>(const MyType&) const = default; +}; + void test_pointer_to_incomplete_type() { struct Test { std::unique_ptr> ptr; }; Test t; + std::flat_map, std::shared_ptr>> map; } int main() { From 858ff8a0e21f40a0a6f2722d15ebab96a990a3bd Mon Sep 17 00:00:00 2001 From: Qingnan Duan Date: Fri, 15 Dec 2023 18:00:56 +0800 Subject: [PATCH 098/100] Separate function overloads that take 'const key_type&' from 'const K&' (the latter requires a transparent comparator) --- stl/inc/flat_map | 245 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 183 insertions(+), 62 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index a682ebec459..b50be85183d 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -508,28 +508,16 @@ public: return try_emplace(_STD forward<_K>(_Key_val)).first->second; } - template - _NODISCARD mapped_type& at(const _K& _Key_val) - requires same_as<_K, key_type> || _Is_transparent_v + _NODISCARD mapped_type& at(const key_type& _Key_val) { - iterator _Position = find(_Key_val); - if (_Position == end()) { - _Xout_of_range("std::flat_map::at: the specified key does not exist."); - } else { - return _Position->second; - } + return _At(_Key_val); } template _NODISCARD const mapped_type& at(const _K& _Key_val) const - requires same_as<_K, key_type> || _Is_transparent_v + requires _Is_transparent_v { - const_iterator _Position = find(_Key_val); - if (_Position == cend()) { - _Xout_of_range("std::flat_map::at: the specified key does not exist."); - } else { - return _Position->second; - } + return _At(_Key_val); } // [flat.map.modifiers] Modifiers @@ -709,100 +697,124 @@ public: } // map operations + iterator find(const key_type& _X) + { + return _Find(_X); + } + template iterator find(const _K& _X) - requires same_as<_K, key_type> || _Is_transparent_v + requires _Is_transparent_v { - iterator _Position = lower_bound(_X); - if (_Position != end() && _Key_equal(_Position->first, _X)) { - return _Position; - } else { - return end(); - } + return _Find(_X); + } + + const_iterator find(const key_type& _X) const + { + return _Find(_X); } template const_iterator find(const _K& _X) const - requires same_as<_K, key_type> || _Is_transparent_v + requires _Is_transparent_v { - const_iterator _Position = lower_bound(_X); - if (_Position != cend() && _Key_equal(_Position->first, _X)) { - return _Position; - } else { - return cend(); - } + return _Find(_X); + } + + size_type count(const key_type& _X) const + { + return _Count(_X); } template size_type count(const _K& _X) const - requires same_as<_K, key_type> || _Is_transparent_v + requires _Is_transparent_v { - return upper_bound(_X) - lower_bound(_X); + return _Count(_X); + } + + bool contains(const key_type& _X) const + { + return _Contains(_X); } template bool contains(const _K& _X) const - requires same_as<_K, key_type> || _Is_transparent_v + requires _Is_transparent_v { - return find(_X) != cend(); + return _Contains(_X); + } + + iterator lower_bound(const key_type& _X) + { + return _Lower_bound(_X); } template iterator lower_bound(const _K& _X) - requires same_as<_K, key_type> || _Is_transparent_v + requires _Is_transparent_v { - typename key_container_type::const_iterator _Key_it = - _STD lower_bound(_Data.keys.cbegin(), _Data.keys.cend(), _X, _Key_compare); - auto _Dist = _STD distance(_Data.keys.cbegin(), _Key_it); - typename mapped_container_type::iterator _Val_it = _Data.values.begin() + _Dist; - return iterator{_STD move(_Key_it), _STD move(_Val_it)}; + return _Lower_bound(_X); + } + + const_iterator lower_bound(const key_type& _X) const + { + return _Lower_bound(_X); } template const_iterator lower_bound(const _K& _X) const - requires same_as<_K, key_type> || _Is_transparent_v + requires _Is_transparent_v { - typename key_container_type::const_iterator _Key_it = - _STD lower_bound(_Data.keys.cbegin(), _Data.keys.cend(), _X, _Key_compare); - auto _Dist = _STD distance(_Data.keys.cbegin(), _Key_it); - typename mapped_container_type::const_iterator _Val_it = _Data.values.cbegin() + _Dist; - return const_iterator{_STD move(_Key_it), _STD move(_Val_it)}; + return _Lower_bound(_X); + } + + iterator upper_bound(const key_type& _X) + { + return _Upper_bound(_X); } template iterator upper_bound(const _K& _X) - requires same_as<_K, key_type> || _Is_transparent_v + requires _Is_transparent_v { - typename key_container_type::const_iterator _Key_it = - _STD upper_bound(_Data.keys.cbegin(), _Data.keys.cend(), _X, _Key_compare); - auto _Dist = _STD distance(_Data.keys.cbegin(), _Key_it); - typename mapped_container_type::iterator _Val_it = _Data.values.begin() + _Dist; - return iterator{_STD move(_Key_it), _STD move(_Val_it)}; + return _Upper_bound(_X); + } + + const_iterator upper_bound(const key_type& _X) const + { + return _Upper_bound(_X); } template const_iterator upper_bound(const _K& _X) const - requires same_as<_K, key_type> || _Is_transparent_v + requires _Is_transparent_v { - typename key_container_type::const_iterator _Key_it = - _STD upper_bound(_Data.keys.cbegin(), _Data.keys.cend(), _X, _Key_compare); - auto _Dist = _STD distance(_Data.keys.cbegin(), _Key_it); - typename mapped_container_type::const_iterator _Val_it = _Data.values.cbegin() + _Dist; - return const_iterator{_STD move(_Key_it), _STD move(_Val_it)}; + return _Upper_bound(_X); + } + + pair equal_range(const key_type& _X) + { + return _Equal_range(_X); } template pair equal_range(const _K& _X) - requires same_as<_K, key_type> || _Is_transparent_v + requires _Is_transparent_v { - return {lower_bound(_X), upper_bound(_X)}; + return _Equal_range(_X); + } + + pair equal_range(const key_type& _X) const + { + return _Equal_range(_X); } template pair equal_range(const _K& _X) const - requires same_as<_K, key_type> || _Is_transparent_v + requires _Is_transparent_v { - return {lower_bound(_X), upper_bound(_X)}; + return _Equal_range(_X); } friend bool operator==(const _Derived& _X, const _Derived& _Y) { @@ -942,6 +954,115 @@ private: _Guard._Clearable = nullptr; } + + template + _NODISCARD mapped_type& _At(const _K& _Key_val) + requires same_as<_K, key_type> || _Is_transparent_v + { + iterator _Position = find(_Key_val); + if (_Position == end()) { + _Xout_of_range("std::flat_map::at: the specified key does not exist."); + } else { + return _Position->second; + } + } + + template + iterator _Find(const _K& _X) + requires same_as<_K, key_type> || _Is_transparent_v + { + iterator _Position = lower_bound(_X); + if (_Position != end() && _Key_equal(_Position->first, _X)) { + return _Position; + } else { + return end(); + } + } + + template + const_iterator _Find(const _K& _X) const + requires same_as<_K, key_type> || _Is_transparent_v + { + const_iterator _Position = lower_bound(_X); + if (_Position != cend() && _Key_equal(_Position->first, _X)) { + return _Position; + } else { + return cend(); + } + } + + template + size_type _Count(const _K& _X) const + requires same_as<_K, key_type> || _Is_transparent_v + { + return upper_bound(_X) - lower_bound(_X); + } + + template + bool _Contains(const _K& _X) const + requires same_as<_K, key_type> || _Is_transparent_v + { + return find(_X) != cend(); + } + + template + iterator _Lower_bound(const _K& _X) + requires same_as<_K, key_type> || _Is_transparent_v + { + typename key_container_type::const_iterator _Key_it = + _STD lower_bound(_Data.keys.cbegin(), _Data.keys.cend(), _X, _Key_compare); + auto _Dist = _STD distance(_Data.keys.cbegin(), _Key_it); + typename mapped_container_type::iterator _Val_it = _Data.values.begin() + _Dist; + return iterator{_STD move(_Key_it), _STD move(_Val_it)}; + } + + template + const_iterator _Lower_bound(const _K& _X) const + requires same_as<_K, key_type> || _Is_transparent_v + { + typename key_container_type::const_iterator _Key_it = + _STD lower_bound(_Data.keys.cbegin(), _Data.keys.cend(), _X, _Key_compare); + auto _Dist = _STD distance(_Data.keys.cbegin(), _Key_it); + typename mapped_container_type::const_iterator _Val_it = _Data.values.cbegin() + _Dist; + return const_iterator{_STD move(_Key_it), _STD move(_Val_it)}; + } + + template + iterator _Upper_bound(const _K& _X) + requires same_as<_K, key_type> || _Is_transparent_v + { + typename key_container_type::const_iterator _Key_it = + _STD upper_bound(_Data.keys.cbegin(), _Data.keys.cend(), _X, _Key_compare); + auto _Dist = _STD distance(_Data.keys.cbegin(), _Key_it); + typename mapped_container_type::iterator _Val_it = _Data.values.begin() + _Dist; + return iterator{_STD move(_Key_it), _STD move(_Val_it)}; + } + + template + const_iterator _Upper_bound(const _K& _X) const + requires same_as<_K, key_type> || _Is_transparent_v + { + typename key_container_type::const_iterator _Key_it = + _STD upper_bound(_Data.keys.cbegin(), _Data.keys.cend(), _X, _Key_compare); + auto _Dist = _STD distance(_Data.keys.cbegin(), _Key_it); + typename mapped_container_type::const_iterator _Val_it = _Data.values.cbegin() + _Dist; + return const_iterator{_STD move(_Key_it), _STD move(_Val_it)}; + } + + template + pair _Equal_range(const _K& _X) + requires same_as<_K, key_type> || _Is_transparent_v + { + return {lower_bound(_X), upper_bound(_X)}; + } + + template + pair _Equal_range(const _K& _X) const + requires same_as<_K, key_type> || _Is_transparent_v + { + return {lower_bound(_X), upper_bound(_X)}; + } + }; template From 1f603992ca2f4fa9d1a6b7b03086a7ff1d731b76 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 11 Jan 2024 18:58:26 -0800 Subject: [PATCH 099/100] clang-format, no manual changes. --- stl/inc/flat_map | 58 +++++++++++++++++++----------------------------- 1 file changed, 23 insertions(+), 35 deletions(-) diff --git a/stl/inc/flat_map b/stl/inc/flat_map index b50be85183d..52e35f8a7bf 100644 --- a/stl/inc/flat_map +++ b/stl/inc/flat_map @@ -406,15 +406,15 @@ public: .values = _STD make_obj_using_allocator(_Alloc, _Other._Data.values)} {} // Move constructors - _Flat_Map_Base(_Derived&& _Other) noexcept( - _STD is_nothrow_move_constructible_v&& _STD is_nothrow_move_constructible_v&& - _STD is_nothrow_move_constructible_v) + _Flat_Map_Base(_Derived&& _Other) noexcept(_STD is_nothrow_move_constructible_v + && _STD is_nothrow_move_constructible_v + && _STD is_nothrow_move_constructible_v) : _Key_compare(move(_Other._Key_compare)), _Data(move(_Other).extract()) {} template <_Valid_Allocator_for_flat_map _Allocator> _Flat_Map_Base(_Derived&& _Other, const _Allocator& _Alloc) noexcept( - _STD is_nothrow_move_constructible_v&& _STD is_nothrow_move_constructible_v&& - _STD is_nothrow_move_constructible_v) + _STD is_nothrow_move_constructible_v && _STD is_nothrow_move_constructible_v + && _STD is_nothrow_move_constructible_v) : _Key_compare(move(_Other._Key_compare)), _Data{.keys = _STD make_obj_using_allocator(_Alloc, move(_Other._Data.keys)), .values = _STD make_obj_using_allocator(_Alloc, move(_Other._Data.values))} {} @@ -508,8 +508,7 @@ public: return try_emplace(_STD forward<_K>(_Key_val)).first->second; } - _NODISCARD mapped_type& at(const key_type& _Key_val) - { + _NODISCARD mapped_type& at(const key_type& _Key_val) { return _At(_Key_val); } @@ -581,9 +580,9 @@ public: pair try_emplace(_Key_constructible_t&& _Key_constructible, _Args_t&&... _Args) requires constructible_from && (same_as, key_type> - || (constructible_from && _Is_transparent_v - && !convertible_to<_Key_constructible_t&&, const_iterator> - && !convertible_to<_Key_constructible_t&&, iterator>) ) + || (constructible_from && _Is_transparent_v + && !convertible_to<_Key_constructible_t &&, const_iterator> + && !convertible_to<_Key_constructible_t &&, iterator>) ) { auto _Key_It = _STD lower_bound(_Data.keys.begin(), _Data.keys.end(), _Key_constructible, _Key_compare); if (_Key_It != _Data.keys.end() @@ -603,7 +602,7 @@ public: iterator try_emplace(const_iterator _Position, _K&& _Key_val, _Args_t&&... _Args) requires constructible_from && (same_as, key_type> - || (constructible_from && _Is_transparent_v) ) + || (constructible_from && _Is_transparent_v) ) { return _Emplace_hint(_Position, _STD forward<_K>(_Key_val), _STD forward<_Args_t>(_Args)...); } @@ -612,7 +611,7 @@ public: pair insert_or_assign(_K&& _Key_val, _M&& _Obj) requires assignable_from && constructible_from && (same_as, key_type> - || (constructible_from && _Is_transparent_v) ) + || (constructible_from && _Is_transparent_v) ) { auto _Res = try_emplace(_STD forward<_K>(_Key_val), _STD forward<_M>(_Obj)); if (_Res.second) { @@ -629,7 +628,7 @@ public: iterator insert_or_assign(const_iterator _Position, _K&& _Key_val, _M&& _Obj) requires assignable_from && constructible_from && (same_as, key_type> - || (constructible_from && _Is_transparent_v) ) + || (constructible_from && _Is_transparent_v) ) { return _Emplace_hint(_Position, _STD forward<_K>(_Key_val), _STD forward<_M>(_Obj)); } @@ -697,8 +696,7 @@ public: } // map operations - iterator find(const key_type& _X) - { + iterator find(const key_type& _X) { return _Find(_X); } @@ -709,8 +707,7 @@ public: return _Find(_X); } - const_iterator find(const key_type& _X) const - { + const_iterator find(const key_type& _X) const { return _Find(_X); } @@ -721,8 +718,7 @@ public: return _Find(_X); } - size_type count(const key_type& _X) const - { + size_type count(const key_type& _X) const { return _Count(_X); } @@ -733,8 +729,7 @@ public: return _Count(_X); } - bool contains(const key_type& _X) const - { + bool contains(const key_type& _X) const { return _Contains(_X); } @@ -745,8 +740,7 @@ public: return _Contains(_X); } - iterator lower_bound(const key_type& _X) - { + iterator lower_bound(const key_type& _X) { return _Lower_bound(_X); } @@ -757,8 +751,7 @@ public: return _Lower_bound(_X); } - const_iterator lower_bound(const key_type& _X) const - { + const_iterator lower_bound(const key_type& _X) const { return _Lower_bound(_X); } @@ -769,8 +762,7 @@ public: return _Lower_bound(_X); } - iterator upper_bound(const key_type& _X) - { + iterator upper_bound(const key_type& _X) { return _Upper_bound(_X); } @@ -781,8 +773,7 @@ public: return _Upper_bound(_X); } - const_iterator upper_bound(const key_type& _X) const - { + const_iterator upper_bound(const key_type& _X) const { return _Upper_bound(_X); } @@ -793,8 +784,7 @@ public: return _Upper_bound(_X); } - pair equal_range(const key_type& _X) - { + pair equal_range(const key_type& _X) { return _Equal_range(_X); } @@ -805,8 +795,7 @@ public: return _Equal_range(_X); } - pair equal_range(const key_type& _X) const - { + pair equal_range(const key_type& _X) const { return _Equal_range(_X); } @@ -873,7 +862,7 @@ private: iterator _Emplace_hint(const_iterator _Position, _K&& _Key_val, _Mapped_args_t&&... _Args) requires is_constructible_v && (same_as, key_type> - || (constructible_from && _Is_transparent_v) ) + || (constructible_from && _Is_transparent_v) ) { static_assert(!(_Multi && _Overwrite_if_exists), "Overwriting is not supported when the container allows multiple copies of a key."); @@ -1062,7 +1051,6 @@ private: { return {lower_bound(_X), upper_bound(_X)}; } - }; template From 279049d4306cef97fd59c36e3a564b578ed81c58 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 11 Jan 2024 21:08:52 -0800 Subject: [PATCH 100/100] Fix errors in test_header_units_and_modules.hpp. --- tests/std/include/test_header_units_and_modules.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/std/include/test_header_units_and_modules.hpp b/tests/std/include/test_header_units_and_modules.hpp index 41ff2b0627c..da06e630897 100644 --- a/tests/std/include/test_header_units_and_modules.hpp +++ b/tests/std/include/test_header_units_and_modules.hpp @@ -237,7 +237,7 @@ void test_filesystem() { } #if TEST_STANDARD >= 23 -void test_flatmap() { +void test_flat_map() { using namespace std; puts("Testing ."); @@ -1149,7 +1149,9 @@ void all_cpp_header_tests() { test_expected(); #endif // TEST_STANDARD >= 23 test_filesystem(); +#if TEST_STANDARD >= 23 test_flat_map(); +#endif // TEST_STANDARD >= 23 test_format(); test_forward_list(); test_fstream();