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 > > > > > >