On 17/03/2025 09:21, Tomasz Kamiński wrote:
This is another piece of P1206R7, adding new members to std::set
and std::multiset.

        PR libstdc++/111055

libstdc++-v3/ChangeLog:

        * include/bits/stl_multiset.h: (inser_range)
        (multiset(from_range_t, _Rg&&, const _Compare&, const _Alloc&))
        (multiset(from_range_t, _Rg&&, const _Alloc&)):     Define.
        * include/bits/stl_set.h: (set(from_range_t, _Rg&&, const _Alloc&))
        (set(from_range_t, _Rg&&, const _Compare&, const _Alloc&), 
insert_range):
        Define.
        * testsuite/23_containers/multiset/cons/from_range.cc: New test.
        * testsuite/23_containers/multiset/modifiers/insert/insert_range.cc: 
New test.
        * testsuite/23_containers/set/cons/from_range.cc: New test.
        * testsuite/23_containers/set/modifiers/insert/insert_range.cc: New 
test.
---
  Added missing includes, replaced spaces with tabs.
  Tested on x86_64-linux without PCH. OK for trunk?

  libstdc++-v3/include/bits/stl_multiset.h      |  52 ++++++++
  libstdc++-v3/include/bits/stl_set.h           |  55 ++++++++
  .../23_containers/multiset/cons/from_range.cc | 118 ++++++++++++++++++
  .../multiset/modifiers/insert/insert_range.cc |  76 +++++++++++
  .../23_containers/set/cons/from_range.cc      | 117 +++++++++++++++++
  .../set/modifiers/insert/insert_range.cc      |  79 ++++++++++++
  6 files changed, 497 insertions(+)
  create mode 100644 
libstdc++-v3/testsuite/23_containers/multiset/cons/from_range.cc
  create mode 100644 
libstdc++-v3/testsuite/23_containers/multiset/modifiers/insert/insert_range.cc
  create mode 100644 libstdc++-v3/testsuite/23_containers/set/cons/from_range.cc
  create mode 100644 
libstdc++-v3/testsuite/23_containers/set/modifiers/insert/insert_range.cc

diff --git a/libstdc++-v3/include/bits/stl_multiset.h 
b/libstdc++-v3/include/bits/stl_multiset.h
index 57caf6e8cc4..1d40ae01de3 100644
--- a/libstdc++-v3/include/bits/stl_multiset.h
+++ b/libstdc++-v3/include/bits/stl_multiset.h
@@ -60,6 +60,9 @@
  #if __cplusplus >= 201103L
  #include <initializer_list>
  #endif
+#if __glibcxx_ranges_to_container // C++ >= 23
+# include <bits/ranges_base.h> // ranges::begin, ranges::distance etc.
+#endif
namespace std _GLIBCXX_VISIBILITY(default)
  {
@@ -271,6 +274,25 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        : _M_t(_Key_alloc_type(__a))
        { _M_t._M_insert_range_equal(__first, __last); }
+#if __glibcxx_ranges_to_container // C++ >= 23
+      /**
+       * @brief Builds a %set from a range.
+       * @since C++23
+       */
+      template<__detail::__container_compatible_range<_Key> _Rg>
+       multiset(from_range_t, _Rg&& __rg,
+                const _Compare& __comp,
+                const _Alloc& __a = _Alloc())
+       : _M_t(__comp, _Key_alloc_type(__a))
+       { insert_range(std::forward<_Rg>(__rg)); }
+
+      /// Allocator-extended range constructor.
+      template<__detail::__container_compatible_range<_Key> _Rg>
+       multiset(from_range_t, _Rg&& __rg, const _Alloc& __a = _Alloc())
+       : _M_t(_Key_alloc_type(__a))
+       { insert_range(std::forward<_Rg>(__rg)); }
+#endif
+
        /**
         *  The dtor only erases the elements, and note that if the elements
         *  themselves are pointers, the pointed-to memory is not touched in any
@@ -566,6 +588,25 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        { this->insert(__l.begin(), __l.end()); }
  #endif
+#if __glibcxx_ranges_to_container // C++ >= 23
+      /**
+       *  @brief Inserts a range of elements.
+       *  @since C++23
+       *  @param  __rg An input range of elements that can be converted to
+       *               the list's value type.
Looks like a copy/paste, this comment should adapted to the current context.
+       */
+      template<__detail::__container_compatible_range<_Key> _Rg>
+       void
+       insert_range(_Rg&& __rg)
+       {
+         auto __first = ranges::begin(__rg);
+         const auto __last = ranges::end(__rg);
+         for (; __first != __last; ++__first)
+           _M_t._M_emplace_equal(*__first);
+       }
+#endif
+
+
  #ifdef __glibcxx_node_extract // >= C++17
        /// Extract a node.
        node_type
@@ -955,6 +996,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
      multiset(initializer_list<_Key>, _Allocator)
      -> multiset<_Key, less<_Key>, _Allocator>;
+#if __glibcxx_ranges_to_container // C++ >= 23
+  template<ranges::input_range _Rg,
+          __not_allocator_like _Compare = less<ranges::range_value_t<_Rg>>,
+          __allocator_like _Alloc = std::allocator<ranges::range_value_t<_Rg>>>
+    multiset(from_range_t, _Rg&&, _Compare = _Compare(), _Alloc = _Alloc())
+      -> multiset<ranges::range_value_t<_Rg>, _Compare, _Alloc>;
+
+  template<ranges::input_range _Rg, __allocator_like _Alloc>
+    multiset(from_range_t, _Rg&&, _Alloc)
+      -> multiset<ranges::range_value_t<_Rg>, less<ranges::range_value_t<_Rg>>, 
_Alloc>;
+#endif
  #endif // deduction guides
/**
diff --git a/libstdc++-v3/include/bits/stl_set.h 
b/libstdc++-v3/include/bits/stl_set.h
index f32323db368..2f9b2bbfb5f 100644
--- a/libstdc++-v3/include/bits/stl_set.h
+++ b/libstdc++-v3/include/bits/stl_set.h
@@ -60,6 +60,9 @@
  #if __cplusplus >= 201103L
  #include <initializer_list>
  #endif
+#if __glibcxx_ranges_to_container // C++ >= 23
+# include <bits/ranges_base.h> // ranges::begin, ranges::distance etc.
+#endif
namespace std _GLIBCXX_VISIBILITY(default)
  {
@@ -275,6 +278,25 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        : _M_t(_Key_alloc_type(__a))
        { _M_t._M_insert_range_unique(__first, __last); }
+#if __glibcxx_ranges_to_container // C++ >= 23
+      /**
+       * @brief Builds a %set from a range.
+       * @since C++23
+       */
+      template<__detail::__container_compatible_range<_Key> _Rg>
+       set(from_range_t, _Rg&& __rg,
+           const _Compare& __comp,
+           const _Alloc& __a = _Alloc())
+       : _M_t(__comp, _Key_alloc_type(__a))
+       { insert_range(std::forward<_Rg>(__rg)); }
+
+      /// Allocator-extended range constructor.
+      template<__detail::__container_compatible_range<_Key> _Rg>
+       set(from_range_t, _Rg&& __rg, const _Alloc& __a = _Alloc())
+       : _M_t(_Key_alloc_type(__a))
+       { insert_range(std::forward<_Rg>(__rg)); }
+#endif
+
        /**
         *  The dtor only erases the elements, and note that if the elements
         *  themselves are pointers, the pointed-to memory is not touched in any
@@ -581,6 +603,28 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        { this->insert(__l.begin(), __l.end()); }
  #endif
+#if __glibcxx_ranges_to_container // C++ >= 23
+      /**
+       *  @brief Inserts a range of elements.
+       *  @since C++23
+       *  @param  __rg An input range of elements that can be converted to
+       *               the list's value type.
+       */
+      template<__detail::__container_compatible_range<_Key> _Rg>
+       void
+       insert_range(_Rg&& __rg)
+       {
+         auto __first = ranges::begin(__rg);
+         const auto __last = ranges::end(__rg);
+         using _Rv = __remove_cvref_t<ranges::range_value_t<_Rg>>;
+         for (; __first != __last; ++__first)
+           if constexpr (is_same_v<_Rv, _Key>)
+             _M_t._M_insert_unique(*__first);
+           else
+             _M_t._M_emplace_unique(*__first);

I hope it's not a too naive question but why not always call _M_emplace_unique ?


Reply via email to