From e95ebf222dba99dd21e40c57c7be69bd668d7d34 Mon Sep 17 00:00:00 2001 From: Hui Xie Date: Sat, 23 Nov 2024 18:54:14 +0000 Subject: [PATCH 1/2] [libc++] Move out (for reusing it in flat_multimap) --- libcxx/include/CMakeLists.txt | 1 + libcxx/include/__flat_map/flat_map.h | 132 +------------- .../include/__flat_map/key_value_iterator.h | 171 ++++++++++++++++++ libcxx/include/flat_map | 1 + libcxx/include/module.modulemap | 1 + .../iter_iter_stability.pass.cpp | 1 + .../reverse_iterator.pass.cpp | 2 +- .../flat.map/incomplete_type.pass.cpp | 1 + 8 files changed, 184 insertions(+), 126 deletions(-) create mode 100644 libcxx/include/__flat_map/key_value_iterator.h diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index 2bb6d263340d3..9bbbf436f97ce 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -358,6 +358,7 @@ set(files __filesystem/space_info.h __filesystem/u8path.h __flat_map/flat_map.h + __flat_map/key_value_iterator.h __flat_map/sorted_unique.h __format/buffer.h __format/concepts.h diff --git a/libcxx/include/__flat_map/flat_map.h b/libcxx/include/__flat_map/flat_map.h index 58b362ad7a706..1d1b16e994791 100644 --- a/libcxx/include/__flat_map/flat_map.h +++ b/libcxx/include/__flat_map/flat_map.h @@ -23,11 +23,11 @@ #include <__algorithm/remove_if.h> #include <__assert> #include <__compare/synth_three_way.h> -#include <__concepts/convertible_to.h> #include <__concepts/swappable.h> #include <__config> #include <__cstddef/byte.h> #include <__cstddef/ptrdiff_t.h> +#include <__flat_map/key_value_iterator.h> #include <__flat_map/sorted_unique.h> #include <__functional/invoke.h> #include <__functional/is_transparent.h> @@ -38,7 +38,6 @@ #include <__iterator/next.h> #include <__iterator/ranges_iterator_traits.h> #include <__iterator/reverse_iterator.h> -#include <__memory/addressof.h> #include <__memory/allocator_traits.h> #include <__memory/uses_allocator.h> #include <__memory/uses_allocator_construction.h> @@ -57,8 +56,8 @@ #include <__type_traits/is_allocator.h> #include <__type_traits/is_nothrow_constructible.h> #include <__type_traits/is_same.h> -#include <__type_traits/maybe_const.h> #include <__utility/exception_guard.h> +#include <__utility/move.h> #include <__utility/pair.h> #include <__utility/scope_guard.h> #include <__vector/vector.h> @@ -82,9 +81,6 @@ template , class _MappedContainer = vector<_Tp>> class flat_map { - template - struct __iterator; - template friend class flat_map; @@ -93,6 +89,9 @@ class flat_map { static_assert(!is_same_v<_KeyContainer, std::vector>, "vector is not a sequence container"); static_assert(!is_same_v<_MappedContainer, std::vector>, "vector is not a sequence container"); + template + using __iterator = __key_value_iterator; + public: // types using key_type = _Key; @@ -134,123 +133,6 @@ class flat_map { _LIBCPP_HIDE_FROM_ABI static constexpr bool __is_compare_transparent = __is_transparent_v<_Compare, _Compare>; - template - struct __iterator { - private: - using __key_iterator = ranges::iterator_t; - using __mapped_iterator = ranges::iterator_t<__maybe_const<_Const, mapped_container_type>>; - using __reference = pair, iter_reference_t<__mapped_iterator>>; - - struct __arrow_proxy { - __reference __ref_; - _LIBCPP_HIDE_FROM_ABI __reference* operator->() { return std::addressof(__ref_); } - }; - - __key_iterator __key_iter_; - __mapped_iterator __mapped_iter_; - - friend flat_map; - - public: - using iterator_concept = random_access_iterator_tag; - // `flat_map::iterator` only satisfy "Cpp17InputIterator" named requirements, because - // its `reference` is not a reference type. - // However, to avoid surprising runtime behaviour when it is used with the - // Cpp17 algorithms or operations, iterator_category is set to random_access_iterator_tag. - using iterator_category = random_access_iterator_tag; - using value_type = flat_map::value_type; - using difference_type = flat_map::difference_type; - - _LIBCPP_HIDE_FROM_ABI __iterator() = default; - - _LIBCPP_HIDE_FROM_ABI __iterator(__iterator __i) - requires _Const && convertible_to, __key_iterator> && - convertible_to, __mapped_iterator> - : __key_iter_(std::move(__i.__key_iter_)), __mapped_iter_(std::move(__i.__mapped_iter_)) {} - - _LIBCPP_HIDE_FROM_ABI __iterator(__key_iterator __key_iter, __mapped_iterator __mapped_iter) - : __key_iter_(std::move(__key_iter)), __mapped_iter_(std::move(__mapped_iter)) {} - - _LIBCPP_HIDE_FROM_ABI __reference operator*() const { return __reference(*__key_iter_, *__mapped_iter_); } - _LIBCPP_HIDE_FROM_ABI __arrow_proxy operator->() const { return __arrow_proxy{**this}; } - - _LIBCPP_HIDE_FROM_ABI __iterator& operator++() { - ++__key_iter_; - ++__mapped_iter_; - return *this; - } - - _LIBCPP_HIDE_FROM_ABI __iterator operator++(int) { - __iterator __tmp(*this); - ++*this; - return __tmp; - } - - _LIBCPP_HIDE_FROM_ABI __iterator& operator--() { - --__key_iter_; - --__mapped_iter_; - return *this; - } - - _LIBCPP_HIDE_FROM_ABI __iterator operator--(int) { - __iterator __tmp(*this); - --*this; - return __tmp; - } - - _LIBCPP_HIDE_FROM_ABI __iterator& operator+=(difference_type __x) { - __key_iter_ += __x; - __mapped_iter_ += __x; - return *this; - } - - _LIBCPP_HIDE_FROM_ABI __iterator& operator-=(difference_type __x) { - __key_iter_ -= __x; - __mapped_iter_ -= __x; - return *this; - } - - _LIBCPP_HIDE_FROM_ABI __reference operator[](difference_type __n) const { return *(*this + __n); } - - _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) { - return __x.__key_iter_ == __y.__key_iter_; - } - - _LIBCPP_HIDE_FROM_ABI friend bool operator<(const __iterator& __x, const __iterator& __y) { - return __x.__key_iter_ < __y.__key_iter_; - } - - _LIBCPP_HIDE_FROM_ABI friend bool operator>(const __iterator& __x, const __iterator& __y) { return __y < __x; } - - _LIBCPP_HIDE_FROM_ABI friend bool operator<=(const __iterator& __x, const __iterator& __y) { return !(__y < __x); } - - _LIBCPP_HIDE_FROM_ABI friend bool operator>=(const __iterator& __x, const __iterator& __y) { return !(__x < __y); } - - _LIBCPP_HIDE_FROM_ABI friend auto operator<=>(const __iterator& __x, const __iterator& __y) - requires three_way_comparable<__key_iterator> - { - return __x.__key_iter_ <=> __y.__key_iter_; - } - - _LIBCPP_HIDE_FROM_ABI friend __iterator operator+(const __iterator& __i, difference_type __n) { - auto __tmp = __i; - __tmp += __n; - return __tmp; - } - - _LIBCPP_HIDE_FROM_ABI friend __iterator operator+(difference_type __n, const __iterator& __i) { return __i + __n; } - - _LIBCPP_HIDE_FROM_ABI friend __iterator operator-(const __iterator& __i, difference_type __n) { - auto __tmp = __i; - __tmp -= __n; - return __tmp; - } - - _LIBCPP_HIDE_FROM_ABI friend difference_type operator-(const __iterator& __x, const __iterator& __y) { - return difference_type(__x.__key_iter_ - __y.__key_iter_); - } - }; - public: // [flat.map.cons], construct/copy/destroy _LIBCPP_HIDE_FROM_ABI flat_map() noexcept( @@ -1308,7 +1190,7 @@ template , class = __enable_if_t::value && __is_allocator<_Allocator>::value>> flat_map(from_range_t, _Range&&, _Compare = _Compare(), _Allocator = _Allocator()) - -> flat_map< + ->flat_map< __range_key_type<_Range>, __range_mapped_type<_Range>, _Compare, @@ -1317,7 +1199,7 @@ flat_map(from_range_t, _Range&&, _Compare = _Compare(), _Allocator = _Allocator( template ::value>> flat_map(from_range_t, _Range&&, _Allocator) - -> flat_map< + ->flat_map< __range_key_type<_Range>, __range_mapped_type<_Range>, less<__range_key_type<_Range>>, diff --git a/libcxx/include/__flat_map/key_value_iterator.h b/libcxx/include/__flat_map/key_value_iterator.h new file mode 100644 index 0000000000000..a36a8fdc424c2 --- /dev/null +++ b/libcxx/include/__flat_map/key_value_iterator.h @@ -0,0 +1,171 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FLAT_MAP_KEY_VALUE_ITERATOR_H +#define _LIBCPP___FLAT_MAP_KEY_VALUE_ITERATOR_H + +#include <__compare/three_way_comparable.h> +#include <__concepts/convertible_to.h> +#include <__config> +#include <__iterator/iterator_traits.h> +#include <__memory/addressof.h> +#include <__ranges/access.h> +#include <__type_traits/conditional.h> +#include <__type_traits/maybe_const.h> +#include <__utility/move.h> +#include <__utility/pair.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +#if _LIBCPP_STD_VER >= 23 + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +struct __key_value_iterator { +private: + using __key_iterator = ranges::iterator_t; + using __mapped_iterator = ranges::iterator_t<__maybe_const<_Const, _MappedContainer>>; + using __reference = _If<_Const, typename _Owner::const_reference, typename _Owner::reference>; + + struct __arrow_proxy { + __reference __ref_; + _LIBCPP_HIDE_FROM_ABI __reference* operator->() { return std::addressof(__ref_); } + }; + + __key_iterator __key_iter_; + __mapped_iterator __mapped_iter_; + + friend _Owner; + + template + friend struct __key_value_iterator; + +public: + using iterator_concept = random_access_iterator_tag; + // `flat_map::iterator` only satisfy "Cpp17InputIterator" named requirements, because + // its `reference` is not a reference type. + // However, to avoid surprising runtime behaviour when it is used with the + // Cpp17 algorithms or operations, iterator_category is set to random_access_iterator_tag. + using iterator_category = random_access_iterator_tag; + using value_type = typename _Owner::value_type; + using difference_type = typename _Owner::difference_type; + + _LIBCPP_HIDE_FROM_ABI __key_value_iterator() = default; + + _LIBCPP_HIDE_FROM_ABI __key_value_iterator(__key_value_iterator<_Owner, _KeyContainer, _MappedContainer, !_Const> __i) + requires _Const && convertible_to, __key_iterator> && + convertible_to, __mapped_iterator> + : __key_iter_(std::move(__i.__key_iter_)), __mapped_iter_(std::move(__i.__mapped_iter_)) {} + + _LIBCPP_HIDE_FROM_ABI __key_value_iterator(__key_iterator __key_iter, __mapped_iterator __mapped_iter) + : __key_iter_(std::move(__key_iter)), __mapped_iter_(std::move(__mapped_iter)) {} + + _LIBCPP_HIDE_FROM_ABI __reference operator*() const { return __reference(*__key_iter_, *__mapped_iter_); } + _LIBCPP_HIDE_FROM_ABI __arrow_proxy operator->() const { return __arrow_proxy{**this}; } + + _LIBCPP_HIDE_FROM_ABI __key_value_iterator& operator++() { + ++__key_iter_; + ++__mapped_iter_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI __key_value_iterator operator++(int) { + __key_value_iterator __tmp(*this); + ++*this; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI __key_value_iterator& operator--() { + --__key_iter_; + --__mapped_iter_; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI __key_value_iterator operator--(int) { + __key_value_iterator __tmp(*this); + --*this; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI __key_value_iterator& operator+=(difference_type __x) { + __key_iter_ += __x; + __mapped_iter_ += __x; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI __key_value_iterator& operator-=(difference_type __x) { + __key_iter_ -= __x; + __mapped_iter_ -= __x; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI __reference operator[](difference_type __n) const { return *(*this + __n); } + + _LIBCPP_HIDE_FROM_ABI friend constexpr bool + operator==(const __key_value_iterator& __x, const __key_value_iterator& __y) { + return __x.__key_iter_ == __y.__key_iter_; + } + + _LIBCPP_HIDE_FROM_ABI friend bool operator<(const __key_value_iterator& __x, const __key_value_iterator& __y) { + return __x.__key_iter_ < __y.__key_iter_; + } + + _LIBCPP_HIDE_FROM_ABI friend bool operator>(const __key_value_iterator& __x, const __key_value_iterator& __y) { + return __y < __x; + } + + _LIBCPP_HIDE_FROM_ABI friend bool operator<=(const __key_value_iterator& __x, const __key_value_iterator& __y) { + return !(__y < __x); + } + + _LIBCPP_HIDE_FROM_ABI friend bool operator>=(const __key_value_iterator& __x, const __key_value_iterator& __y) { + return !(__x < __y); + } + + _LIBCPP_HIDE_FROM_ABI friend auto operator<=>(const __key_value_iterator& __x, const __key_value_iterator& __y) + requires three_way_comparable<__key_iterator> + { + return __x.__key_iter_ <=> __y.__key_iter_; + } + + _LIBCPP_HIDE_FROM_ABI friend __key_value_iterator operator+(const __key_value_iterator& __i, difference_type __n) { + auto __tmp = __i; + __tmp += __n; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI friend __key_value_iterator operator+(difference_type __n, const __key_value_iterator& __i) { + return __i + __n; + } + + _LIBCPP_HIDE_FROM_ABI friend __key_value_iterator operator-(const __key_value_iterator& __i, difference_type __n) { + auto __tmp = __i; + __tmp -= __n; + return __tmp; + } + + _LIBCPP_HIDE_FROM_ABI friend difference_type + operator-(const __key_value_iterator& __x, const __key_value_iterator& __y) { + return difference_type(__x.__key_iter_ - __y.__key_iter_); + } +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 23 + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___FLAT_MAP_KEY_VALUE_ITERATOR_H diff --git a/libcxx/include/flat_map b/libcxx/include/flat_map index 15d79dd1ddca3..e96af677a7eed 100644 --- a/libcxx/include/flat_map +++ b/libcxx/include/flat_map @@ -40,6 +40,7 @@ namespace std { #include <__assert> // all public C++ headers provide the assertion handler #include <__config> #include <__flat_map/flat_map.h> +#include <__flat_map/key_value_iterator.h> #include <__flat_map/sorted_unique.h> #include diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap index ed2b7fb192164..15fdc8d2e2a53 100644 --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -1230,6 +1230,7 @@ module std [system] { module flat_map { module flat_map { header "__flat_map/flat_map.h" } + module key_value_iterator { header "__flat_map/key_value_iterator.h" } module sorted_unique { header "__flat_map/sorted_unique.h" } header "flat_map" diff --git a/libcxx/test/std/containers/container.adaptors/flat.map/flat.map.cons/iter_iter_stability.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.map/flat.map.cons/iter_iter_stability.pass.cpp index 1ce859f6c737e..14189840ce660 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.map/flat.map.cons/iter_iter_stability.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.map/flat.map.cons/iter_iter_stability.pass.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include "test_macros.h" diff --git a/libcxx/test/std/containers/container.adaptors/flat.map/flat.map.iterators/reverse_iterator.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.map/flat.map.iterators/reverse_iterator.pass.cpp index 09e18986a7e81..fc3949d70745f 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.map/flat.map.iterators/reverse_iterator.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.map/flat.map.iterators/reverse_iterator.pass.cpp @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include diff --git a/libcxx/test/std/containers/container.adaptors/flat.map/incomplete_type.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.map/incomplete_type.pass.cpp index 81c590ba73a15..76461951f0d3d 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.map/incomplete_type.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.map/incomplete_type.pass.cpp @@ -14,6 +14,7 @@ // type. #include +#include struct A { using Map = std::flat_map; From a1ae892ee2c674969ac41a0e268fff5b4fdd574c Mon Sep 17 00:00:00 2001 From: Hui Xie Date: Sun, 1 Dec 2024 13:32:38 +0000 Subject: [PATCH 2/2] review comments --- libcxx/include/__flat_map/flat_map.h | 4 ++-- libcxx/include/__flat_map/key_value_iterator.h | 8 +++++++- libcxx/include/flat_map | 1 - 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/libcxx/include/__flat_map/flat_map.h b/libcxx/include/__flat_map/flat_map.h index 1d1b16e994791..b66bc1cb66fc1 100644 --- a/libcxx/include/__flat_map/flat_map.h +++ b/libcxx/include/__flat_map/flat_map.h @@ -1190,7 +1190,7 @@ template , class = __enable_if_t::value && __is_allocator<_Allocator>::value>> flat_map(from_range_t, _Range&&, _Compare = _Compare(), _Allocator = _Allocator()) - ->flat_map< + -> flat_map< __range_key_type<_Range>, __range_mapped_type<_Range>, _Compare, @@ -1199,7 +1199,7 @@ flat_map(from_range_t, _Range&&, _Compare = _Compare(), _Allocator = _Allocator( template ::value>> flat_map(from_range_t, _Range&&, _Allocator) - ->flat_map< + -> flat_map< __range_key_type<_Range>, __range_mapped_type<_Range>, less<__range_key_type<_Range>>, diff --git a/libcxx/include/__flat_map/key_value_iterator.h b/libcxx/include/__flat_map/key_value_iterator.h index a36a8fdc424c2..987ac677a4130 100644 --- a/libcxx/include/__flat_map/key_value_iterator.h +++ b/libcxx/include/__flat_map/key_value_iterator.h @@ -32,6 +32,12 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD +/** + * __key_value_iterator is a proxy iterator which zips the underlying + * _KeyContainer::iterator and the underlying _MappedContainer::iterator. + * The two underlying iterators will be incremented/decremented together. + * And the reference is a pair of the const key reference and the value reference. + */ template struct __key_value_iterator { private: @@ -54,7 +60,7 @@ struct __key_value_iterator { public: using iterator_concept = random_access_iterator_tag; - // `flat_map::iterator` only satisfy "Cpp17InputIterator" named requirements, because + // `__key_value_iterator` only satisfy "Cpp17InputIterator" named requirements, because // its `reference` is not a reference type. // However, to avoid surprising runtime behaviour when it is used with the // Cpp17 algorithms or operations, iterator_category is set to random_access_iterator_tag. diff --git a/libcxx/include/flat_map b/libcxx/include/flat_map index e96af677a7eed..15d79dd1ddca3 100644 --- a/libcxx/include/flat_map +++ b/libcxx/include/flat_map @@ -40,7 +40,6 @@ namespace std { #include <__assert> // all public C++ headers provide the assertion handler #include <__config> #include <__flat_map/flat_map.h> -#include <__flat_map/key_value_iterator.h> #include <__flat_map/sorted_unique.h> #include