On Mon, 17 Mar 2025, 18:49 François Dumont, <frs.dum...@gmail.com> 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. > > + */ > > + 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 ? > _M_emplace_unique always allocates a new node. _M_insert_unique is optimized to avoid that when inserting the value_type. > >