[libcxx-commits] [libcxx] [libc++] Move out `flat_map::iterator` (for reusing it in flat_multimap) (PR #117445)

via libcxx-commits libcxx-commits at lists.llvm.org
Sun Nov 24 05:41:27 PST 2024


https://github.com/huixie90 updated https://github.com/llvm/llvm-project/pull/117445

>From 02ca7a67d7aaa1769b3450e7bdf701c722f8435c Mon Sep 17 00:00:00 2001
From: Hui Xie <huixie at Mac.broadband>
Date: Sat, 23 Nov 2024 18:54:14 +0000
Subject: [PATCH] [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 0ae031e5365aef..b37b00165fd6ac 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 58b362ad7a706f..1d1b16e9947919 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 _Key,
           class _KeyContainer    = vector<_Key>,
           class _MappedContainer = vector<_Tp>>
 class flat_map {
-  template <bool _Const>
-  struct __iterator;
-
   template <class, class, class, class, class>
   friend class flat_map;
 
@@ -93,6 +89,9 @@ class flat_map {
   static_assert(!is_same_v<_KeyContainer, std::vector<bool>>, "vector<bool> is not a sequence container");
   static_assert(!is_same_v<_MappedContainer, std::vector<bool>>, "vector<bool> is not a sequence container");
 
+  template <bool _Const>
+  using __iterator = __key_value_iterator<flat_map, _KeyContainer, _MappedContainer, _Const>;
+
 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 <bool _Const>
-  struct __iterator {
-  private:
-    using __key_iterator    = ranges::iterator_t<const key_container_type>;
-    using __mapped_iterator = ranges::iterator_t<__maybe_const<_Const, mapped_container_type>>;
-    using __reference       = pair<iter_reference_t<__key_iterator>, 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<!_Const> __i)
-      requires _Const && convertible_to<ranges::iterator_t<key_container_type>, __key_iterator> &&
-                   convertible_to<ranges::iterator_t<mapped_container_type>, __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 <ranges::input_range _Range,
           class _Allocator = allocator<byte>,
           class            = __enable_if_t<!__is_allocator<_Compare>::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 <ranges::input_range _Range, class _Allocator, class = __enable_if_t<__is_allocator<_Allocator>::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 00000000000000..a36a8fdc424c2a
--- /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 <class _Owner, class _KeyContainer, class _MappedContainer, bool _Const>
+struct __key_value_iterator {
+private:
+  using __key_iterator    = ranges::iterator_t<const _KeyContainer>;
+  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 <class, class, class, bool>
+  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<ranges::iterator_t<_KeyContainer>, __key_iterator> &&
+                 convertible_to<ranges::iterator_t<_MappedContainer>, __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 15d79dd1ddca34..e96af677a7eed9 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 <version>
 
diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index 4e06a68c6a6b61..52e13aebc2187c 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -1229,6 +1229,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 1ce859f6c737ea..14189840ce6605 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 <flat_map>
 #include <random>
 #include <map>
+#include <vector>
 
 #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 09e18986a7e813..fc3949d70745fc 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 <deque>
 #include <flat_map>
 #include <functional>
-#include <string>
+#include <vector>
 
 #include <iterator>
 
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 81c590ba73a157..76461951f0d3d8 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 <flat_map>
+#include <vector>
 
 struct A {
   using Map = std::flat_map<A, A>;



More information about the libcxx-commits mailing list