aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
authorTomasz Kamiński <tkaminsk@redhat.com>2025-03-18 16:10:48 +0100
committerTomasz Kamiński <tkaminsk@redhat.com>2025-03-19 13:52:32 +0100
commit64f5c854597759fd11648b7d9e3884b8c69f218f (patch)
tree8a5845931797757d92905e108908c44e0d5e068b /libstdc++-v3
parent73987e69d1b24e3807b94ec7cf5d859b93b9ae78 (diff)
downloadgcc-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')
-rw-r--r--libstdc++-v3/include/bits/unordered_map.h14
-rw-r--r--libstdc++-v3/include/bits/unordered_set.h15
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_map/cons/from_range.cc24
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/from_range.cc24
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/from_range.cc22
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_set/cons/from_range.cc22
-rw-r--r--libstdc++-v3/testsuite/std/ranges/conv/1.cc22
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();