diff options
author | Tomasz Kamiński <tkaminsk@redhat.com> | 2025-03-18 16:10:48 +0100 |
---|---|---|
committer | Tomasz Kamiński <tkaminsk@redhat.com> | 2025-03-19 13:52:32 +0100 |
commit | 64f5c854597759fd11648b7d9e3884b8c69f218f (patch) | |
tree | 8a5845931797757d92905e108908c44e0d5e068b /libstdc++-v3 | |
parent | 73987e69d1b24e3807b94ec7cf5d859b93b9ae78 (diff) | |
download | gcc-64f5c854597759fd11648b7d9e3884b8c69f218f.zip gcc-64f5c854597759fd11648b7d9e3884b8c69f218f.tar.gz gcc-64f5c854597759fd11648b7d9e3884b8c69f218f.tar.bz2 |
libstdc++-v3: Implement allocator-aware from_range_t constructors for unordered containers.
This patch implements part of LWG2713 covering the from_range
constructors, which makes std::ranges::to<std::unordered_set>(alloc)
well-formed. Likewise for rest of unordered containers.
As this consturctors were added to v15, this has no impact
on code that compiled with previous versions.
libstdc++-v3/ChangeLog:
* include/bits/unordered_map.h
(unordered_map(from_range_t, _Rg&&, const allocator_type&))
(unordered_multimap(from_range_t, _Rg&&, const allocator_type&)):
Define.
* include/bits/unordered_set.h
(unordered_set(from_range_t, _Rg&&, const allocator_type&))
(unordered_multiset(from_range_t, _Rg&&, const allocator_type&)):
Define.
* testsuite/23_containers/unordered_map/cons/from_range.cc: New tests.
New tests.
* testsuite/23_containers/unordered_multimap/cons/from_range.cc:
New tests.
* testsuite/23_containers/unordered_multiset/cons/from_range.cc:
New tests.
* testsuite/23_containers/unordered_set/cons/from_range.cc: New tests.
* testsuite/std/ranges/conv/1.cc: New tests.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
Diffstat (limited to 'libstdc++-v3')
7 files changed, 93 insertions, 50 deletions
diff --git a/libstdc++-v3/include/bits/unordered_map.h b/libstdc++-v3/include/bits/unordered_map.h index 4a0527c..49e97e2 100644 --- a/libstdc++-v3/include/bits/unordered_map.h +++ b/libstdc++-v3/include/bits/unordered_map.h @@ -300,6 +300,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) @@ -1546,6 +1553,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 cfa8ee2..4bc256c 100644 --- a/libstdc++-v3/include/bits/unordered_set.h +++ b/libstdc++-v3/include/bits/unordered_set.h @@ -294,6 +294,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) @@ -1265,6 +1272,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) 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 b3cbb2e..51f8538 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/from_range.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/from_range.cc index 381302b..1baf730 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 @@ -54,12 +54,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< @@ -160,13 +159,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/from_range.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/from_range.cc index cb522b0..45c3848 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 @@ -50,11 +50,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< @@ -137,13 +136,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/from_range.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/cons/from_range.cc index c1acf14..0806045 100644 --- a/libstdc++-v3/testsuite/23_containers/unordered_set/cons/from_range.cc +++ b/libstdc++-v3/testsuite/23_containers/unordered_set/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_set s5(std::from_range, r, alloc); - // static_assert(std::is_same_v< - // decltype(s5), - // std::unordered_set<long, std::hash<long>, std::equal_to<long>, Alloc>>); + std::unordered_set s5(std::from_range, r, alloc); + static_assert(std::is_same_v< + decltype(s5), + std::unordered_set<long, std::hash<long>, std::equal_to<long>, Alloc>>); std::unordered_set 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_set<V, Hash, Equal, Alloc> - // sa(std::from_range, Range(a, a+14), alloc); - // VERIFY( eq(sa1, {a, 9}) ); - // VERIFY( is_equal(sa1.hash_function(), Hash()) ); - // VERIFY( is_equal(sa1.key_eq(), Equal()) ); - // VERIFY( sa1.get_allocator() == alloc ); + std::unordered_set<V, Hash, Equal, Alloc> + sa1(std::from_range, Range(a, a+14), alloc); + VERIFY( eq(sa1, {a, 9}) ); + VERIFY( is_equal(sa1.hash_function(), Hash()) ); + VERIFY( is_equal(sa1.key_eq(), Equal()) ); + VERIFY( sa1.get_allocator() == alloc ); std::unordered_set<V, Hash, Equal, Alloc> sa2(std::from_range, Range(a, a+14), 2, alloc); diff --git a/libstdc++-v3/testsuite/std/ranges/conv/1.cc b/libstdc++-v3/testsuite/std/ranges/conv/1.cc index 231cb9d..2caa1b8 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(); |