On Mon, Mar 17, 2025 at 7:49 PM François Dumont <[email protected]>
wrote:
>
> 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.
>
Indeed thank you.
> > + */
> > + 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>>;
>
This should use ranges::range_reference_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 ?
>
>
>