On Wed, Mar 19, 2025 at 12:36 PM Jonathan Wakely <jwak...@redhat.com> wrote:

> On 19/03/25 09:32 +0100, Tomasz Kamiński wrote:
> >This patch implements LWG2713 by adding missing allocator aware version of
> >unordered associative containers constructors accepting only "range"
> >(pair of iterators, initializer_list, or from_range), and corresponding
> >deduction guides.
> >
> >In addition the std::ranges::to<std::unordered_set>(alloc) is well-formed,
> >likewise for rest of unordered containers.
> >
> >libstdc++-v3/ChangeLog:
> >
> >       * include/bits/unordered_map.h (unordered_map):
> >       Define constructors accepting:
> >       (_InputIterator, _InputIterator, const allocator_type&),
> >       (initializer_list<value_type>, const allocator_type&),
> >       (from_range_t, _Rg&&, const allocator_type&)
> >       (unordered_multimap): Likewise.
> >       * include/bits/unordered_set.h (unordered_set):
> >       Define constructors and deduction guide accepting:
> >       (_InputIterator, _InputIterator, const allocator_type&),
> >       (initializer_list<value_type>, const allocator_type&).
> >       Define constructor (from_range_t, _Rg&&, const allocator_type&).
> >       (unordered_multiset): Likewise.
> >       * testsuite/23_containers/unordered_map/cons/66055.cc: New tests.
> >       * testsuite/23_containers/unordered_map/cons/deduction.cc: New
> tests.
> >       * testsuite/23_containers/unordered_map/cons/from_range.cc: New
> tests.
> >       * testsuite/23_containers/unordered_multimap/cons/66055.cc: New
> tests.
> >       * testsuite/23_containers/unordered_multimap/cons/deduction.cc:
> >       New tests.
> >       * testsuite/23_containers/unordered_multimap/cons/from_range.cc:
> >       New tests.
> >       * testsuite/23_containers/unordered_multiset/cons/66055.cc: New
> tests.
> >       * testsuite/23_containers/unordered_multiset/cons/deduction.cc:
> >       New tests.
> >       * testsuite/23_containers/unordered_multiset/cons/from_range.cc:
> >       New tests.
> >       * testsuite/23_containers/unordered_set/cons/66055.cc: New tests.
> >       * testsuite/23_containers/unordered_set/cons/deduction.cc: New
> tests.
> >       * testsuite/23_containers/unordered_set/cons/from_range.cc: New
> tests.
> >       * testsuite/std/ranges/conv/1.cc: New tests.
> >---
> >I have added ranges::to test, as they provide additional motivation.
> >Tested on x86_64-linux. OK for trunk?
>
> I think we should be a little cautious here, because we're very close
> to the GCC 15 release and this is changing C++11/14/17 code as well.
> We don't want a last-minute regression this close to the release.
>
> Although these constructors all look correct, they introduce the
> possibility of new ambiguities just by changing the overload set.
>
> The C++23 from_range_t constructors are OK to add now. For the rest of
> them, I think I'd prefer to guard them with #if __cplusplus >= 202002L
> for now, and open a bugzilla bug reminding us to remove those #if
> guards for GCC 16.
>
I think it would be better to just reduce the GCC15 patch to only new
from_range constructors. I think if we are concerned with new ambiguities
for old constructors we should not add them conditionally.
Otherwise we are risking breaking old code when compiled with new standard.

I will prepare a partial patch.

>
> Does that seem reasonable?
>
>
> > libstdc++-v3/include/bits/unordered_map.h     | 44 ++++++++++
> > libstdc++-v3/include/bits/unordered_set.h     | 86 +++++++++++++++++++
> > .../23_containers/unordered_map/cons/66055.cc | 11 ++-
> > .../unordered_map/cons/deduction.cc           | 29 +++++++
> > .../unordered_map/cons/from_range.cc          | 24 +++---
> > .../unordered_multimap/cons/66055.cc          | 10 ++-
> > .../unordered_multimap/cons/deduction.cc      | 34 ++++++++
> > .../unordered_multimap/cons/from_range.cc     | 24 +++---
> > .../unordered_multiset/cons/66055.cc          | 10 ++-
> > .../unordered_multiset/cons/deduction.cc      | 28 ++++++
> > .../unordered_multiset/cons/from_range.cc     | 22 +++--
> > .../23_containers/unordered_set/cons/66055.cc | 10 ++-
> > .../unordered_set/cons/deduction.cc           | 28 ++++++
> > libstdc++-v3/testsuite/std/ranges/conv/1.cc   | 22 +++++
> > 14 files changed, 328 insertions(+), 54 deletions(-)
> >
> >diff --git a/libstdc++-v3/include/bits/unordered_map.h
> b/libstdc++-v3/include/bits/unordered_map.h
> >index 5c930487190..2d85da3f29d 100644
> >--- a/libstdc++-v3/include/bits/unordered_map.h
> >+++ b/libstdc++-v3/include/bits/unordered_map.h
> >@@ -251,6 +251,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
> >       : unordered_map(__n, __hf, key_equal(), __a)
> >       { }
> >
> >+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
> >+      // 2713. More missing allocator-extended constructors for
> unordered containers
> >+      template<typename _InputIterator>
> >+      unordered_map(_InputIterator __first, _InputIterator __last,
> >+                    const allocator_type& __a)
> >+      : unordered_map(__first, __last, 0, hasher(), key_equal(), __a)
> >+      { }
> >+
> >       template<typename _InputIterator>
> >       unordered_map(_InputIterator __first, _InputIterator __last,
> >                     size_type __n,
> >@@ -271,6 +279,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
> >       : unordered_map(__l, __n, hasher(), key_equal(), __a)
> >       { }
> >
> >+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
> >+      // 2713. More missing allocator-extended constructors for
> unordered containers
> >+      unordered_map(initializer_list<value_type> __l,
> >+                  const allocator_type& __a)
> >+      : unordered_map(__l, 0, hasher(), key_equal(), __a)
> >+      { }
> >+
> >       unordered_map(initializer_list<value_type> __l,
> >                   size_type __n, const hasher& __hf,
> >                   const allocator_type& __a)
> >@@ -300,6 +315,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
> >         : _M_h(__n, __hf, __eql, __a)
> >         { insert_range(std::forward<_Rg>(__rg)); }
> >
> >+       // _GLIBCXX_RESOLVE_LIB_DEFECTS
> >+       // 2713. More missing allocator-extended constructors for
> unordered containers
> >+       template<__detail::__container_compatible_range<value_type> _Rg>
> >+       unordered_map(from_range_t, _Rg&& __rg, const allocator_type& __a)
> >+        : _M_h(0, hasher(), key_equal(), __a)
> >+        { insert_range(std::forward<_Rg>(__rg)); }
> >+
> >        template<__detail::__container_compatible_range<value_type> _Rg>
> >        unordered_map(from_range_t, _Rg&& __rg, size_type __n,
> >                      const allocator_type& __a)
> >@@ -1497,6 +1519,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
> >       : unordered_multimap(__n, __hf, key_equal(), __a)
> >       { }
> >
> >+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
> >+      // 2713. More missing allocator-extended constructors for
> unordered containers
> >+      template<typename _InputIterator>
> >+      unordered_multimap(_InputIterator __first, _InputIterator __last,
> >+                         const allocator_type& __a)
> >+      : unordered_multimap(__first, __last, 0, hasher(), key_equal(),
> __a)
> >+      { }
> >+
> >       template<typename _InputIterator>
> >       unordered_multimap(_InputIterator __first, _InputIterator __last,
> >                          size_type __n,
> >@@ -1511,6 +1541,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
> >       : unordered_multimap(__first, __last, __n, __hf, key_equal(), __a)
> >       { }
> >
> >+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
> >+      // 2713. More missing allocator-extended constructors for
> unordered containers
> >+      unordered_multimap(initializer_list<value_type> __l,
> >+                       const allocator_type& __a)
> >+      : unordered_multimap(__l, 0, hasher(), key_equal(), __a)
> >+      { }
> >+
> >       unordered_multimap(initializer_list<value_type> __l,
> >                        size_type __n,
> >                        const allocator_type& __a)
> >@@ -1546,6 +1583,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
> >         : _M_h(__n, __hf, __eql, __a)
> >         { insert_range(std::forward<_Rg>(__rg)); }
> >
> >+       // _GLIBCXX_RESOLVE_LIB_DEFECTS
> >+       // 2713. More missing allocator-extended constructors for
> unordered containers
> >+       template<__detail::__container_compatible_range<value_type> _Rg>
> >+       unordered_multimap(from_range_t, _Rg&& __rg, const
> allocator_type& __a)
> >+        : _M_h(0, hasher(), key_equal(), __a)
> >+        { insert_range(std::forward<_Rg>(__rg)); }
> >+
> >        template<__detail::__container_compatible_range<value_type> _Rg>
> >        unordered_multimap(from_range_t, _Rg&& __rg, size_type __n,
> >                           const allocator_type& __a)
> >diff --git a/libstdc++-v3/include/bits/unordered_set.h
> b/libstdc++-v3/include/bits/unordered_set.h
> >index 21ffdaf50a0..d81e66065f0 100644
> >--- a/libstdc++-v3/include/bits/unordered_set.h
> >+++ b/libstdc++-v3/include/bits/unordered_set.h
> >@@ -245,6 +245,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
> >       : unordered_set(__n, __hf, key_equal(), __a)
> >       { }
> >
> >+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
> >+      // 2713. More missing allocator-extended constructors for
> unordered container
> >+      template<typename _InputIterator>
> >+      unordered_set(_InputIterator __first, _InputIterator __last,
> >+                    const allocator_type& __a)
> >+      : unordered_set(__first, __last, 0, hasher(), key_equal(), __a)
> >+      { }
> >+
> >       template<typename _InputIterator>
> >       unordered_set(_InputIterator __first, _InputIterator __last,
> >                     size_type __n,
> >@@ -259,6 +267,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
> >       : unordered_set(__first, __last, __n, __hf, key_equal(), __a)
> >       { }
> >
> >+
> >+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
> >+      // 2713. More missing allocator-extended constructors for
> unordered container
> >+      unordered_set(initializer_list<value_type> __l,
> >+                  const allocator_type& __a)
> >+      : unordered_set(__l, 0, hasher(), key_equal(), __a)
> >+      { }
> >+
> >       unordered_set(initializer_list<value_type> __l,
> >                   size_type __n,
> >                   const allocator_type& __a)
> >@@ -294,6 +310,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
> >         : _M_h(__n, __hf, __eql, __a)
> >         { insert_range(std::forward<_Rg>(__rg)); }
> >
> >+       // _GLIBCXX_RESOLVE_LIB_DEFECTS
> >+       // 2713. More missing allocator-extended constructors for
> unordered container
> >+       template<__detail::__container_compatible_range<_Value> _Rg>
> >+       unordered_set(from_range_t, _Rg&& __rg, const allocator_type& __a)
> >+        : _M_h(0, hasher(), key_equal(), __a)
> >+        { insert_range(std::forward<_Rg>(__rg)); }
> >+
> >        template<__detail::__container_compatible_range<_Value> _Rg>
> >        unordered_set(from_range_t, _Rg&& __rg, size_type __n,
> >                      const allocator_type& __a)
> >@@ -980,6 +1003,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
> >                      typename
> iterator_traits<_InputIterator>::value_type>,
> >                    _Allocator>;
> >
> >+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
> >+  // 2713. More missing allocator-extended constructors for unordered
> container
> >+  template<typename _InputIterator, typename _Allocator,
> >+         typename = _RequireInputIter<_InputIterator>,
> >+         typename = _RequireAllocator<_Allocator>>
> >+    unordered_set(_InputIterator, _InputIterator, _Allocator)
> >+    -> unordered_set<typename
> iterator_traits<_InputIterator>::value_type,
> >+                   hash<
> >+                     typename
> iterator_traits<_InputIterator>::value_type>,
> >+                   equal_to<
> >+                     typename
> iterator_traits<_InputIterator>::value_type>,
> >+                   _Allocator>;
> >+
> >   template<typename _InputIterator, typename _Hash, typename _Allocator,
> >          typename = _RequireInputIter<_InputIterator>,
> >          typename = _RequireNotAllocatorOrIntegral<_Hash>,
> >@@ -999,6 +1035,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
> >                 unordered_set<int>::size_type, _Allocator)
> >     -> unordered_set<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>;
> >
> >+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
> >+  // 2713. More missing allocator-extended constructors for unordered
> container
> >+  template<typename _Tp, typename _Allocator,
> >+         typename = _RequireAllocator<_Allocator>>
> >+    unordered_set(initializer_list<_Tp>, _Allocator)
> >+    -> unordered_set<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>;
> >+
> >   template<typename _Tp, typename _Hash, typename _Allocator,
> >          typename = _RequireNotAllocatorOrIntegral<_Hash>,
> >          typename = _RequireAllocator<_Allocator>>
> >@@ -1216,6 +1259,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
> >       : unordered_multiset(__n, __hf, key_equal(), __a)
> >       { }
> >
> >+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
> >+      // 2713. More missing allocator-extended constructors for
> unordered container
> >+      template<typename _InputIterator>
> >+      unordered_multiset(_InputIterator __first, _InputIterator __last,
> >+                         const allocator_type& __a)
> >+      : unordered_multiset(__first, __last, 0, hasher(), key_equal(),
> __a)
> >+      { }
> >+
> >       template<typename _InputIterator>
> >       unordered_multiset(_InputIterator __first, _InputIterator __last,
> >                          size_type __n,
> >@@ -1230,6 +1281,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
> >       : unordered_multiset(__first, __last, __n, __hf, key_equal(), __a)
> >       { }
> >
> >+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
> >+      // 2713. More missing allocator-extended constructors for
> unordered container
> >+      unordered_multiset(initializer_list<value_type> __l,
> >+                       const allocator_type& __a)
> >+      : unordered_multiset(__l, 0, hasher(), key_equal(), __a)
> >+      { }
> >+
> >       unordered_multiset(initializer_list<value_type> __l,
> >                        size_type __n,
> >                        const allocator_type& __a)
> >@@ -1265,6 +1323,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
> >         : _M_h(__n, __hf, __eql, __a)
> >         { insert_range(std::forward<_Rg>(__rg)); }
> >
> >+
> >+       // _GLIBCXX_RESOLVE_LIB_DEFECTS
> >+       // 2713. More missing allocator-extended constructors for
> unordered container
> >+       template<__detail::__container_compatible_range<_Value> _Rg>
> >+       unordered_multiset(from_range_t, _Rg&& __rg, const
> allocator_type& __a)
> >+        : _M_h(0, hasher(), key_equal(), __a)
> >+        { insert_range(std::forward<_Rg>(__rg)); }
> >+
> >        template<__detail::__container_compatible_range<_Value> _Rg>
> >        unordered_multiset(from_range_t, _Rg&& __rg, size_type __n,
> >                           const allocator_type& __a)
> >@@ -1934,6 +2000,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
> >
> iterator_traits<_InputIterator>::value_type>,
> >                         _Allocator>;
> >
> >+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
> >+  // 2713. More missing allocator-extended constructors for unordered
> container
> >+  template<typename _InputIterator, typename _Allocator,
> >+         typename = _RequireInputIter<_InputIterator>,
> >+         typename = _RequireAllocator<_Allocator>>
> >+    unordered_multiset(_InputIterator, _InputIterator, _Allocator)
> >+    -> unordered_multiset<typename
> iterator_traits<_InputIterator>::value_type,
> >+                        hash<typename
> >+
>  iterator_traits<_InputIterator>::value_type>,
> >+                        equal_to<typename
> >+
>  iterator_traits<_InputIterator>::value_type>,
> >+                        _Allocator>;
> >+
> >   template<typename _InputIterator, typename _Hash, typename _Allocator,
> >          typename = _RequireInputIter<_InputIterator>,
> >          typename = _RequireNotAllocatorOrIntegral<_Hash>,
> >@@ -1955,6 +2034,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
> >                      unordered_multiset<int>::size_type, _Allocator)
> >     -> unordered_multiset<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>;
> >
> >+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
> >+  // 2713. More missing allocator-extended constructors for unordered
> container
> >+  template<typename _Tp, typename _Allocator,
> >+         typename = _RequireAllocator<_Allocator>>
> >+    unordered_multiset(initializer_list<_Tp>, _Allocator)
> >+    -> unordered_multiset<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>;
> >+
> >   template<typename _Tp, typename _Hash, typename _Allocator,
> >          typename = _RequireNotAllocatorOrIntegral<_Hash>,
> >          typename = _RequireAllocator<_Allocator>>
> >diff --git
> a/libstdc++-v3/testsuite/23_containers/unordered_map/cons/66055.cc
> b/libstdc++-v3/testsuite/23_containers/unordered_map/cons/66055.cc
> >index c7a12c14425..0f959760713 100644
> >--- a/libstdc++-v3/testsuite/23_containers/unordered_map/cons/66055.cc
> >+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/cons/66055.cc
> >@@ -27,7 +27,10 @@ using alloc_type = test_type::allocator_type;
> >
> > test_type h1(10, alloc_type());
> > test_type h2(10, hasher_type(), alloc_type());
> >-test_type h3(h1.begin(), h1.end(), 10, alloc_type());
> >-test_type h4(h1.begin(), h1.end(), 10, hasher_type(), alloc_type());
> >-test_type h5({ { 1, 1 } }, 10, alloc_type());
> >-test_type h6({ { 1, 1 } }, 10, hasher_type(), alloc_type());
> >+test_type h3(h1.begin(), h1.end(), alloc_type());
> >+test_type h4(h1.begin(), h1.end(), 10, alloc_type());
> >+test_type h5(h1.begin(), h1.end(), 10, hasher_type(), alloc_type());
> >+test_type h6({ { 1, 1 } }, alloc_type());
> >+test_type h7({ { 1, 1 } }, 10, alloc_type());
> >+test_type h8({ { 1, 1 } }, 10, hasher_type(), alloc_type());
> >+
> >diff --git
> a/libstdc++-v3/testsuite/23_containers/unordered_map/cons/deduction.cc
> b/libstdc++-v3/testsuite/23_containers/unordered_map/cons/deduction.cc
> >index 8b69af896a2..61ef71330bb 100644
> >--- a/libstdc++-v3/testsuite/23_containers/unordered_map/cons/deduction.cc
> >+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/cons/deduction.cc
> >@@ -15,12 +15,28 @@ static_assert(std::is_same_v<
> >                     {2, 3.0}, {3, 4.0}}}),
> >             std::unordered_map<int, double>>);
> >
> >+static_assert(std::is_same_v<
> >+            decltype(std::unordered_map{{std::pair{1, 2.0},
> >+                    {2, 3.0}, {3, 4.0}},
> >+                  SimpleAllocator<std::pair<const int, double>>{}}),
> >+            std::unordered_map<int, double, std::hash<int>,
> >+            std::equal_to<int>,
> >+            SimpleAllocator<std::pair<const int, double>>>>);
> >+
> > static_assert(std::is_same_v<
> >             decltype(std::unordered_map{
> >               {std::pair{1, 2.0}, {2, 3.0}, {3, 4.0}},
> >               1}),
> >             std::unordered_map<int, double>>);
> >
> >+static_assert(std::is_same_v<
> >+            decltype(std::unordered_map{
> >+              {std::pair{1, 2.0}, {2, 3.0}, {3, 4.0}},
> >+              1, SimpleAllocator<std::pair<const int, double>>{}}),
> >+            std::unordered_map<int, double, std::hash<int>,
> >+            std::equal_to<int>,
> >+            SimpleAllocator<std::pair<const int, double>>>>);
> >+
> > static_assert(std::is_same_v<
> >             decltype(std::unordered_map{{std::pair{1, 2.0},
> >                     {2, 3.0}, {3, 4.0}},
> >@@ -96,12 +112,25 @@ void f()
> >               std::equal_to<int>,
> >               SimpleAllocator<std::pair<const int, double>>>>);
> >
> >+  static_assert(std::is_same_v<
> >+              decltype(std::unordered_map{x.begin(), x.end(),
> >+                    std::allocator<std::pair<const int, double>>{}}),
> >+              std::unordered_map<int, double>>);
> >+
> >+  static_assert(std::is_same_v<
> >+              decltype(std::unordered_map{x.begin(), x.end(),
> >+                    SimpleAllocator<std::pair<const int, double>>{}}),
> >+              std::unordered_map<int, double, std::hash<int>,
> >+              std::equal_to<int>,
> >+              SimpleAllocator<std::pair<const int, double>>>>);
> >+
> >   static_assert(std::is_same_v<
> >               decltype(std::unordered_map{x.begin(), x.end(),
> >                     1, std::hash<int>{},
> >                     std::allocator<std::pair<const int, double>>{}}),
> >               std::unordered_map<int, double>>);
> >
> >+
> >   static_assert(std::is_same_v<
> >               decltype(std::unordered_map{x.begin(), x.end(),
> >                     1, std::hash<int>{},
> >diff --git
> a/libstdc++-v3/testsuite/23_containers/unordered_map/cons/from_range.cc
> b/libstdc++-v3/testsuite/23_containers/unordered_map/cons/from_range.cc
> >index b3cbb2e6062..51f8538669a 100644
> >---
> a/libstdc++-v3/testsuite/23_containers/unordered_map/cons/from_range.cc
> >+++
> b/libstdc++-v3/testsuite/23_containers/unordered_map/cons/from_range.cc
> >@@ -49,12 +49,11 @@ test_deduction_guide()
> >
> >   using Alloc = __gnu_test::SimpleAllocator<std::pair<const long,
> float>>;
> >   Alloc alloc;
> >-  // LWG2713: there is no matching constructor
> >-  // std::unordered_map m5(std::from_range, r, alloc);
> >-  // static_assert(std::is_same_v<
> >-  //   decltype(m5),
> >-  //   std::unordered_map<long, float,
> >-  //                      std::hash<long>, std::equal_to<long>, Alloc>>);
> >+  std::unordered_map m5(std::from_range, r, alloc);
> >+  static_assert(std::is_same_v<
> >+    decltype(m5),
> >+    std::unordered_map<long, float,
> >+                     std::hash<long>, std::equal_to<long>, Alloc>>);
> >
> >   std::unordered_map m6(std::from_range, r, 0, alloc);
> >   static_assert(std::is_same_v<
> >@@ -154,13 +153,12 @@ do_test(Alloc alloc, Hash hf, Equal eqf)
> >   VERIFY( is_equal(m9.hash_function(), hf) );
> >   VERIFY( is_equal(m9.key_eq(), eqf) );
> >
> >-  // LWG2713: there is no matching constructor
> >-  // std::unordered_map<K, V, Hash, Equal, Alloc>
> >-  //   ma1(std::from_range, Range(a, a+14), alloc);
> >-  // VERIFY( eq(ma1, {a, 9}) );
> >-  // VERIFY( is_equal(ma1.hash_function(), Hash()) );
> >-  // VERIFY( is_equal(ma1.key_eq(), Equal()) );
> >-  // VERIFY( ma1.get_allocator() == alloc );
> >+  std::unordered_map<K, V, Hash, Equal, Alloc>
> >+    ma1(std::from_range, Range(a, a+14), alloc);
> >+  VERIFY( eq(ma1, {a, 9}) );
> >+  VERIFY( is_equal(ma1.hash_function(), Hash()) );
> >+  VERIFY( is_equal(ma1.key_eq(), Equal()) );
> >+  VERIFY( ma1.get_allocator() == alloc );
> >
> >   std::unordered_map<K, V, Hash, Equal, Alloc>
> >     ma2(std::from_range, Range(a, a+14), 2, alloc);
> >diff --git
> a/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/66055.cc
> b/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/66055.cc
> >index dc0a65196c8..eecc60024fe 100644
> >---
> a/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/66055.cc
> >+++
> b/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/66055.cc
> >@@ -27,7 +27,9 @@ using alloc_type = test_type::allocator_type;
> >
> > test_type h1(10, alloc_type());
> > test_type h2(10, hasher_type(), alloc_type());
> >-test_type h3(h1.begin(), h1.end(), 10, alloc_type());
> >-test_type h4(h1.begin(), h1.end(), 10, hasher_type(), alloc_type());
> >-test_type h5({ { 1, 1 } }, 10, alloc_type());
> >-test_type h6({ { 1, 1 } }, 10, hasher_type(), alloc_type());
> >+test_type h3(h1.begin(), h1.end(), alloc_type());
> >+test_type h4(h1.begin(), h1.end(), 10, alloc_type());
> >+test_type h5(h1.begin(), h1.end(), 10, hasher_type(), alloc_type());
> >+test_type h6({ { 1, 1 } }, alloc_type());
> >+test_type h7({ { 1, 1 } }, 10, alloc_type());
> >+test_type h8({ { 1, 1 } }, 10, hasher_type(), alloc_type());
> >diff --git
> a/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/deduction.cc
> b/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/deduction.cc
> >index e7e535b527a..4de23fe3e79 100644
> >---
> a/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/deduction.cc
> >+++
> b/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/deduction.cc
> >@@ -15,6 +15,28 @@ static_assert(std::is_same_v<
> >                     {2, 3.0}, {3, 4.0}}}),
> >             std::unordered_multimap<int, double>>);
> >
> >+static_assert(std::is_same_v<
> >+            decltype(std::unordered_multimap{
> >+              {std::pair{1, 2.0}, {2, 3.0}, {3, 4.0}},
> >+              SimpleAllocator<std::pair<const int, double>>{}}),
> >+            std::unordered_multimap<int, double, std::hash<int>,
> >+            std::equal_to<int>,
> >+            SimpleAllocator<std::pair<const int, double>>>>);
> >+
> >+static_assert(std::is_same_v<
> >+            decltype(std::unordered_multimap{
> >+              {std::pair{1, 2.0}, {2, 3.0}, {3, 4.0}},
> >+              1}),
> >+            std::unordered_multimap<int, double>>);
> >+
> >+static_assert(std::is_same_v<
> >+            decltype(std::unordered_multimap{
> >+              {std::pair{1, 2.0}, {2, 3.0}, {3, 4.0}},
> >+              1, SimpleAllocator<std::pair<const int, double>>{}}),
> >+            std::unordered_multimap<int, double, std::hash<int>,
> >+            std::equal_to<int>,
> >+            SimpleAllocator<std::pair<const int, double>>>>);
> >+
> > static_assert(std::is_same_v<
> >             decltype(std::unordered_multimap{{std::pair{1, 2.0},
> >                     {2, 3.0}, {3, 4.0}},
> >@@ -105,6 +127,18 @@ void f()
> >               std::equal_to<int>,
> >               SimpleAllocator<std::pair<const int, double>>>>);
> >
> >+  static_assert(std::is_same_v<
> >+              decltype(std::unordered_multimap{x.begin(), x.end(),
> >+                    std::allocator<std::pair<const int, double>>{}}),
> >+              std::unordered_multimap<int, double>>);
> >+
> >+  static_assert(std::is_same_v<
> >+              decltype(std::unordered_multimap{x.begin(), x.end(),
> >+                    SimpleAllocator<std::pair<const int, double>>{}}),
> >+              std::unordered_multimap<int, double, std::hash<int>,
> >+              std::equal_to<int>,
> >+              SimpleAllocator<std::pair<const int, double>>>>);
> >+
> >   static_assert(std::is_same_v<
> >               decltype(std::unordered_multimap{x.begin(), x.end(),
> >                     1, std::hash<int>{},
> >diff --git
> a/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/from_range.cc
> b/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/from_range.cc
> >index 9273ef0d57a..2e26cd2d201 100644
> >---
> a/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/from_range.cc
> >+++
> b/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/from_range.cc
> >@@ -53,12 +53,11 @@ test_deduction_guide()
> >
> >   using Alloc = __gnu_test::SimpleAllocator<std::pair<const long,
> float>>;
> >   Alloc alloc;
> >-  // LWG2713: there is no matching constructor
> >-  // std::unordered_multimap m5(std::from_range, r, alloc);
> >-  // static_assert(std::is_same_v<
> >-  //   decltype(m5),
> >-  //   std::unordered_multimap<long, float,
> >-  //                           std::hash<long>, std::equal_to<long>,
> Alloc>>);
> >+  std::unordered_multimap m5(std::from_range, r, alloc);
> >+  static_assert(std::is_same_v<
> >+    decltype(m5),
> >+    std::unordered_multimap<long, float,
> >+                          std::hash<long>, std::equal_to<long>, Alloc>>);
> >
> >   std::unordered_multimap m6(std::from_range, r, 0, alloc);
> >   static_assert(std::is_same_v<
> >@@ -159,13 +158,12 @@ do_test(Alloc alloc, Hash hf, Equal eqf)
> >   VERIFY( is_equal(m9.hash_function(), hf) );
> >   VERIFY( is_equal(m9.key_eq(), eqf) );
> >
> >-  // LWG2713: there is no matching constructor
> >-  // std::unordered_multimap<K, V, Hash, Equal, Alloc>
> >-  //   ma1(std::from_range, Range(a, a+14), alloc);
> >-  // VERIFY( eq(ma1, {a, 14}) );
> >-  // VERIFY( is_equal(ma1.hash_function(), Hash()) );
> >-  // VERIFY( is_equal(ma1.key_eq(), Equal()) );
> >-  // VERIFY( ma1.get_allocator() == alloc );
> >+  std::unordered_multimap<K, V, Hash, Equal, Alloc>
> >+    ma1(std::from_range, Range(a, a+14), alloc);
> >+  VERIFY( eq(ma1, {a, 14}) );
> >+  VERIFY( is_equal(ma1.hash_function(), Hash()) );
> >+  VERIFY( is_equal(ma1.key_eq(), Equal()) );
> >+  VERIFY( ma1.get_allocator() == alloc );
> >
> >   std::unordered_multimap<K, V, Hash, Equal, Alloc>
> >     ma2(std::from_range, Range(a, a+14), 2, alloc);
> >diff --git
> a/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/66055.cc
> b/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/66055.cc
> >index 5c34b94c00d..3ba609fc449 100644
> >---
> a/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/66055.cc
> >+++
> b/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/66055.cc
> >@@ -27,7 +27,9 @@ using alloc_type = test_type::allocator_type;
> >
> > test_type h1(10, alloc_type());
> > test_type h2(10, hasher_type(), alloc_type());
> >-test_type h3(h1.begin(), h1.end(), 10, alloc_type());
> >-test_type h4(h1.begin(), h1.end(), 10, hasher_type(), alloc_type());
> >-test_type h5({ 1, 1 }, 10, alloc_type());
> >-test_type h6({ 1, 1 }, 10, hasher_type(), alloc_type());
> >+test_type h3(h1.begin(), h1.end(), alloc_type());
> >+test_type h4(h1.begin(), h1.end(), 10, alloc_type());
> >+test_type h5(h1.begin(), h1.end(), 10, hasher_type(), alloc_type());
> >+test_type h6({ 1, 1 }, alloc_type());
> >+test_type h7({ 1, 1 }, 10, alloc_type());
> >+test_type h9({ 1, 1 }, 10, hasher_type(), alloc_type());
> >diff --git
> a/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/deduction.cc
> b/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/deduction.cc
> >index 22b729749e2..46cd2105acc 100644
> >---
> a/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/deduction.cc
> >+++
> b/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/deduction.cc
> >@@ -19,6 +19,22 @@ static_assert(std::is_same_v<
> >                   0, std::hash<int>{}, std::allocator<int>{}}),
> >             std::unordered_multiset<int>>);
> >
> >+static_assert(std::is_same_v<
> >+            decltype(std::unordered_multiset{{1, 2, 3}}),
> >+            std::unordered_multiset<int>>);
> >+
> >+static_assert(std::is_same_v<
> >+            decltype(std::unordered_multiset{{1, 2, 3},
> >+                  std::allocator<int>{}}),
> >+            std::unordered_multiset<int>>);
> >+
> >+static_assert(std::is_same_v<
> >+            decltype(std::unordered_multiset{{1, 2, 3},
> >+                  SimpleAllocator<int>{}}),
> >+            std::unordered_multiset<int, std::hash<int>,
> >+            std::equal_to<int>,
> >+            SimpleAllocator<int>>>);
> >+
> > static_assert(std::is_same_v<
> >             decltype(std::unordered_multiset{{1, 2, 3},
> >                   {}}),
> >@@ -86,6 +102,18 @@ void f()
> >                     {}, std::hash<int>{}, std::equal_to<int>{}}),
> >               std::unordered_multiset<int>>);
> >
> >+  static_assert(std::is_same_v<
> >+              decltype(std::unordered_multiset{x.begin(), x.end(),
> >+                    std::allocator<int>{}}),
> >+              std::unordered_multiset<int>>);
> >+
> >+  static_assert(std::is_same_v<
> >+              decltype(std::unordered_multiset{x.begin(), x.end(),
> >+                    SimpleAllocator<int>{}}),
> >+              std::unordered_multiset<int, std::hash<int>,
> >+              std::equal_to<int>,
> >+              SimpleAllocator<int>>>);
> >+
> >   static_assert(std::is_same_v<
> >               decltype(std::unordered_multiset{x.begin(), x.end(),
> >                     {}, std::hash<int>{}, std::allocator<int>{}}),
> >diff --git
> a/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/from_range.cc
> b/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/from_range.cc
> >index fb388764423..ddbc7ff822f 100644
> >---
> a/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/from_range.cc
> >+++
> b/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/from_range.cc
> >@@ -49,11 +49,10 @@ test_deduction_guide(long* p)
> >
> >   using Alloc = __gnu_test::SimpleAllocator<long>;
> >   Alloc alloc;
> >-  // LWG2713: there is no matching constructor
> >-  // std::unordered_multiset s5(std::from_range, r, alloc);
> >-  // static_assert(std::is_same_v<
> >-  //   decltype(s5),
> >-  //   std::unordered_multiset<long, std::hash<long>,
> std::equal_to<long>, Alloc>>);
> >+  std::unordered_multiset s5(std::from_range, r, alloc);
> >+  static_assert(std::is_same_v<
> >+    decltype(s5),
> >+    std::unordered_multiset<long, std::hash<long>, std::equal_to<long>,
> Alloc>>);
> >
> >   std::unordered_multiset s6(std::from_range, r, 0, alloc);
> >   static_assert(std::is_same_v<
> >@@ -136,13 +135,12 @@ do_test(Alloc alloc, Hash hf, Equal eqf)
> >   VERIFY( is_equal(s9.hash_function(), hf) );
> >   VERIFY( is_equal(s9.key_eq(), eqf) );
> >
> >-  // LWG2713: there is no matching constructor
> >-  // std::unordered_multiset<V, Hash, Equal, Alloc>
> >-  //   sa(std::from_range, Range(a, a+14), alloc);
> >-  // VERIFY( eq(sa1, {a, 14}) );
> >-  // VERIFY( is_equal(sa1.hash_function(), Hash()) );
> >-  // VERIFY( is_equal(sa1.key_eq(), Equal()) );
> >-  // VERIFY( sa1.get_allocator() == alloc );
> >+  std::unordered_multiset<V, Hash, Equal, Alloc>
> >+    sa1(std::from_range, Range(a, a+14), alloc);
> >+  VERIFY( eq(sa1, {a, 14}) );
> >+  VERIFY( is_equal(sa1.hash_function(), Hash()) );
> >+  VERIFY( is_equal(sa1.key_eq(), Equal()) );
> >+  VERIFY( sa1.get_allocator() == alloc );
> >
> >   std::unordered_multiset<V, Hash, Equal, Alloc>
> >     sa2(std::from_range, Range(a, a+14), 2, alloc);
> >diff --git
> a/libstdc++-v3/testsuite/23_containers/unordered_set/cons/66055.cc
> b/libstdc++-v3/testsuite/23_containers/unordered_set/cons/66055.cc
> >index 0d318a04b2b..96c0ca3be53 100644
> >--- a/libstdc++-v3/testsuite/23_containers/unordered_set/cons/66055.cc
> >+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/cons/66055.cc
> >@@ -27,7 +27,9 @@ using alloc_type = test_type::allocator_type;
> >
> > test_type h1(10, alloc_type());
> > test_type h2(10, hasher_type(), alloc_type());
> >-test_type h3(h1.begin(), h1.end(), 10, alloc_type());
> >-test_type h4(h1.begin(), h1.end(), 10, hasher_type(), alloc_type());
> >-test_type h5({ 1, 1 }, 10, alloc_type());
> >-test_type h6({ 1, 1 }, 10, hasher_type(), alloc_type());
> >+test_type h3(h1.begin(), h1.end(), alloc_type());
> >+test_type h4(h1.begin(), h1.end(), 10, alloc_type());
> >+test_type h5(h1.begin(), h1.end(), 10, hasher_type(), alloc_type());
> >+test_type h6({ 1, 1 }, alloc_type());
> >+test_type h7({ 1, 1 }, 10, alloc_type());
> >+test_type h9({ 1, 1 }, 10, hasher_type(), alloc_type());
> >diff --git
> a/libstdc++-v3/testsuite/23_containers/unordered_set/cons/deduction.cc
> b/libstdc++-v3/testsuite/23_containers/unordered_set/cons/deduction.cc
> >index db5858132fc..9558d70505f 100644
> >--- a/libstdc++-v3/testsuite/23_containers/unordered_set/cons/deduction.cc
> >+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/cons/deduction.cc
> >@@ -19,6 +19,22 @@ static_assert(std::is_same_v<
> >                   0, std::hash<int>{}, std::allocator<int>{}}),
> >             std::unordered_set<int>>);
> >
> >+static_assert(std::is_same_v<
> >+            decltype(std::unordered_set{{1, 2, 3}}),
> >+            std::unordered_set<int>>);
> >+
> >+static_assert(std::is_same_v<
> >+            decltype(std::unordered_set{{1, 2, 3},
> >+                  std::allocator<int>{}}),
> >+            std::unordered_set<int>>);
> >+
> >+static_assert(std::is_same_v<
> >+            decltype(std::unordered_set{{1, 2, 3},
> >+                  SimpleAllocator<int>{}}),
> >+            std::unordered_set<int, std::hash<int>,
> >+            std::equal_to<int>,
> >+            SimpleAllocator<int>>>);
> >+
> > static_assert(std::is_same_v<
> >             decltype(std::unordered_set{{1, 2, 3},
> >                   {}}),
> >@@ -91,6 +107,18 @@ void f()
> >                     {})),
> >               std::unordered_set<int>>);
> >
> >+  static_assert(std::is_same_v<
> >+              decltype(std::unordered_set{x.begin(), x.end(),
> >+                    std::allocator<int>{}}),
> >+              std::unordered_set<int>>);
> >+
> >+  static_assert(std::is_same_v<
> >+              decltype(std::unordered_set{x.begin(), x.end(),
> >+                    SimpleAllocator<int>{}}),
> >+              std::unordered_set<int, std::hash<int>,
> >+              std::equal_to<int>,
> >+              SimpleAllocator<int>>>);
> >+
> >   static_assert(std::is_same_v<
> >               decltype(std::unordered_set{x.begin(), x.end(), 1}),
> >               std::unordered_set<int>>);
> >diff --git a/libstdc++-v3/testsuite/std/ranges/conv/1.cc
> b/libstdc++-v3/testsuite/std/ranges/conv/1.cc
> >index 231cb9d9934..2caa1b83f30 100644
> >--- a/libstdc++-v3/testsuite/std/ranges/conv/1.cc
> >+++ b/libstdc++-v3/testsuite/std/ranges/conv/1.cc
> >@@ -12,6 +12,7 @@
> > #include <testsuite_hooks.h>
> > #include <testsuite_allocator.h>
> > #include <testsuite_iterators.h>
> >+#include <unordered_map>
> >
> > void
> > test_p1206r7_examples()
> >@@ -478,6 +479,26 @@ test_pr119282()
> >   return true;
> > }
> >
> >+void
> >+test_lwg2713()
> >+{
> >+  using Alloc = __gnu_test::uneq_allocator<std::pair<const int, const
> char*>>;
> >+  const Alloc alloc(303);
> >+  const std::map<int, const char*> m{{1, "one"}, {2, "two"}, {3,
> "three"}};
> >+  namespace ranges = std::ranges;
> >+
> >+  // Call constructors with bucket count
> >+  auto m1 = m | ranges::to<std::unordered_map>(0, alloc);
> >+  VERIFY( m1.get_allocator() == alloc );
> >+  auto m2 = m | ranges::to<std::unordered_multimap>(0, alloc);
> >+  VERIFY( m2.get_allocator() == alloc );
> >+  // These call constructors added in lwg2713
> >+  auto m3 = m | ranges::to<std::unordered_map>(alloc);
> >+  VERIFY( m3.get_allocator() == alloc );
> >+  auto m4 = m | ranges::to<std::unordered_multimap>(alloc);
> >+  VERIFY( m4.get_allocator() == alloc );
> >+}
> >+
> > int main()
> > {
> >   test_p1206r7_examples();
> >@@ -487,6 +508,7 @@ int main()
> >   test_2_1_3();
> >   test_2_1_4();
> >   test_2_2();
> >+  test_lwg2713();
> >   test_lwg3984();
> >   test_nodiscard();
> >   test_constexpr();
> >--
> >2.48.1
> >
> >
>
>

Reply via email to