https://gcc.gnu.org/g:4794340cd257ece0d197f041812c34c5ac5d50a1

commit r16-182-g4794340cd257ece0d197f041812c34c5ac5d50a1
Author: Tomasz Kamiński <tkami...@redhat.com>
Date:   Thu Mar 20 09:02:03 2025 +0100

    libstdc++: Strip reference and cv-qual in range deduction guides for maps.
    
    This implements part of LWG4223 that adjust the deduction guides for maps 
types
    (map, unordered_map, flat_map and non-unique equivalent) from "range"
    (std::from_range, iterator pair), such that referience and cv qualification 
are
    stripped from the element of the pair-like value_type.
    
    In combination with r15-8296-gd50171bc07006d, the LWG4223 is fully 
implemented now.
    
    libstdc++-v3/ChangeLog:
    
            * include/bits/ranges_base.h (__detail::__range_key_type):
            Replace remove_const_t with remove_cvref_t.
            (__detail::__range_mapped_type): Apply remove_cvref_t.
            * include/bits/stl_iterator.h: (__detail::__iter_key_t):
            Replace remove_const_t with __remove_cvref_t.
            (__detail::__iter_val_t): Apply __remove_cvref_t.
            * testsuite/23_containers/flat_map/1.cc: New tests.
            * testsuite/23_containers/flat_multimap/1.cc: New tests.
            * testsuite/23_containers/map/cons/deduction.cc: New tests.
            * testsuite/23_containers/map/cons/from_range.cc: New tests.
            * testsuite/23_containers/multimap/cons/deduction.cc: New tests.
            * testsuite/23_containers/multimap/cons/from_range.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/deduction.cc:
            New tests.
            * testsuite/23_containers/unordered_multimap/cons/from_range.cc:
            New tests.
    
    Reviewed-by: Jonathan Wakely <jwak...@redhat.com>
    Signed-off-by: Tomasz Kamiński <tkami...@redhat.com>

Diff:
---
 libstdc++-v3/include/bits/ranges_base.h            |  4 +-
 libstdc++-v3/include/bits/stl_iterator.h           | 11 ++--
 libstdc++-v3/testsuite/23_containers/flat_map/1.cc | 21 +++----
 .../testsuite/23_containers/flat_multimap/1.cc     | 21 +++----
 .../testsuite/23_containers/map/cons/deduction.cc  | 46 +++++++++++++++
 .../testsuite/23_containers/map/cons/from_range.cc |  8 +--
 .../23_containers/multimap/cons/deduction.cc       | 46 +++++++++++++++
 .../23_containers/multimap/cons/from_range.cc      |  8 +--
 .../23_containers/unordered_map/cons/deduction.cc  | 69 ++++++++++++++++++++++
 .../23_containers/unordered_map/cons/from_range.cc | 10 ++--
 .../unordered_multimap/cons/deduction.cc           | 69 ++++++++++++++++++++++
 .../unordered_multimap/cons/from_range.cc          | 10 ++--
 12 files changed, 279 insertions(+), 44 deletions(-)

diff --git a/libstdc++-v3/include/bits/ranges_base.h 
b/libstdc++-v3/include/bits/ranges_base.h
index 488907da4466..dde164988569 100644
--- a/libstdc++-v3/include/bits/ranges_base.h
+++ b/libstdc++-v3/include/bits/ranges_base.h
@@ -1103,11 +1103,11 @@ namespace __detail
   // 4223. Deduction guides for maps are mishandling tuples and references
   template<ranges::input_range _Range>
     using __range_key_type
-      = remove_const_t<tuple_element_t<0, ranges::range_value_t<_Range>>>;
+      = remove_cvref_t<tuple_element_t<0, ranges::range_value_t<_Range>>>;
 
   template<ranges::input_range _Range>
     using __range_mapped_type
-      = tuple_element_t<1, ranges::range_value_t<_Range>>;
+      = remove_cvref_t<tuple_element_t<1, ranges::range_value_t<_Range>>>;
 
   // The allocator's value_type for map-like containers.
   template<ranges::input_range _Range>
diff --git a/libstdc++-v3/include/bits/stl_iterator.h 
b/libstdc++-v3/include/bits/stl_iterator.h
index 9203a66b2ff0..bed72955d0c4 100644
--- a/libstdc++-v3/include/bits/stl_iterator.h
+++ b/libstdc++-v3/include/bits/stl_iterator.h
@@ -3086,8 +3086,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #if __cpp_deduction_guides >= 201606
   // These helper traits are used for deduction guides
   // of associative containers.
+
+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+  // 4223. Deduction guides for maps are mishandling tuples and references
   template<typename _InputIterator>
-    using __iter_key_t = remove_const_t<
+    using __iter_key_t = __remove_cvref_t<
 #ifdef __glibcxx_tuple_like // >= C++23
       tuple_element_t<0, typename 
iterator_traits<_InputIterator>::value_type>>;
 #else
@@ -3095,11 +3098,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #endif
 
   template<typename _InputIterator>
-    using __iter_val_t
+    using __iter_val_t = __remove_cvref_t<
 #ifdef __glibcxx_tuple_like // >= C++23
-      = tuple_element_t<1, typename 
iterator_traits<_InputIterator>::value_type>;
+      tuple_element_t<1, typename 
iterator_traits<_InputIterator>::value_type>>;
 #else
-      = typename iterator_traits<_InputIterator>::value_type::second_type;
+      typename iterator_traits<_InputIterator>::value_type::second_type>;
 #endif
 
   template<typename _T1, typename _T2>
diff --git a/libstdc++-v3/testsuite/23_containers/flat_map/1.cc 
b/libstdc++-v3/testsuite/23_containers/flat_map/1.cc
index 4fd33f616f78..a4e0d867c936 100644
--- a/libstdc++-v3/testsuite/23_containers/flat_map/1.cc
+++ b/libstdc++-v3/testsuite/23_containers/flat_map/1.cc
@@ -56,16 +56,17 @@ test_deduction_guide()
                   std::vector<long, __gnu_test::SimpleAllocator<long>>,
                   std::vector<float, __gnu_test::SimpleAllocator<float>>>>);
 
-  // LWG4223: deduces flat_map<long, float const>, which in turn instantiates
-  // std::vector<cosnt float> that is ill-formed.
-  // __gnu_test::test_input_range<std::pair<const long, const float>> r2(0, 0);
-  // std::flat_map it5(r2.begin(), r2.begin());
-  // std::flat_map fr5(std::from_range, r2);
-
-  // LWG4223: deduces flat_map<const long&, float&>
-  //__gnu_test::test_input_range<std::pair<const long&, float&>> r3(0, 0);
-  // std::flat_map it6(r3.begin(), r3.begin());
-  // std::flat_map fr6(std::from_range, r3);
+  __gnu_test::test_input_range<std::pair<const long, const float>> r2(0, 0);
+  std::flat_map it5(r2.begin(), r2.begin());
+  static_assert(std::is_same_v<decltype(it5), std::flat_map<long, float>>);
+  std::flat_map fr5(std::from_range, r2);
+  static_assert(std::is_same_v<decltype(fr5), std::flat_map<long, float>>);
+
+  __gnu_test::test_input_range<std::pair<const long&, float&>> r3(0, 0);
+  std::flat_map it6(r3.begin(), r3.begin());
+  static_assert(std::is_same_v<decltype(it6), std::flat_map<long, float>>);
+  std::flat_map fr6(std::from_range, r3);
+  static_assert(std::is_same_v<decltype(fr6), std::flat_map<long, float>>);
 
   __gnu_test::test_input_range<std::tuple<long, float>> r4(0, 0);
   std::flat_map it7(r4.begin(), r4.begin());
diff --git a/libstdc++-v3/testsuite/23_containers/flat_multimap/1.cc 
b/libstdc++-v3/testsuite/23_containers/flat_multimap/1.cc
index ea0d4b41e9fb..1e70535286a4 100644
--- a/libstdc++-v3/testsuite/23_containers/flat_multimap/1.cc
+++ b/libstdc++-v3/testsuite/23_containers/flat_multimap/1.cc
@@ -54,16 +54,17 @@ test_deduction_guide()
                   std::vector<long, __gnu_test::SimpleAllocator<long>>,
                   std::vector<float, __gnu_test::SimpleAllocator<float>>>>);
 
-  // LWG4223: deduces flat_multimap<long, float const>, which in turn 
instantiates
-  // std::vector<cosnt float> that is ill-formed.
-  // __gnu_test::test_input_range<std::pair<const long, const float>> r2(0, 0);
-  // std::flat_multimap it5(r2.begin(), r2.begin());
-  // std::flat_multimap fr5(std::from_range, r2);
-
-  // LWG4223: deduces flat_multimap<const long&, float&>
-  //__gnu_test::test_input_range<std::pair<const long&, float&>> r3(0, 0);
-  // std::flat_multimap it6(r3.begin(), r3.begin());
-  // std::flat_multimap fr6(std::from_range, r3);
+  __gnu_test::test_input_range<std::pair<const long, const float>> r2(0, 0);
+  std::flat_multimap it5(r2.begin(), r2.begin());
+  static_assert(std::is_same_v<decltype(it5), std::flat_multimap<long, 
float>>);
+  std::flat_multimap fr5(std::from_range, r2);
+  static_assert(std::is_same_v<decltype(fr5), std::flat_multimap<long, 
float>>);
+
+  __gnu_test::test_input_range<std::pair<const long&, float&>> r3(0, 0);
+  std::flat_multimap it6(r3.begin(), r3.begin());
+  static_assert(std::is_same_v<decltype(it6), std::flat_multimap<long, 
float>>);
+  std::flat_multimap fr6(std::from_range, r3);
+  static_assert(std::is_same_v<decltype(fr6), std::flat_multimap<long, 
float>>);
 
   __gnu_test::test_input_range<std::tuple<long, float>> r4(0, 0);
   std::flat_multimap it7(r4.begin(), r4.begin());
diff --git a/libstdc++-v3/testsuite/23_containers/map/cons/deduction.cc 
b/libstdc++-v3/testsuite/23_containers/map/cons/deduction.cc
index f8e6e6e8b994..864598879b06 100644
--- a/libstdc++-v3/testsuite/23_containers/map/cons/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/map/cons/deduction.cc
@@ -258,3 +258,49 @@ test_p1518r2()
   std::map s2(std::move(m), p);
   check_type<Map>(s2);
 }
+
+struct MyPred
+{
+  template<typename T, typename U>
+  bool operator()(T const&, U const&) const;
+};
+
+template<typename K, typename V>
+constexpr bool test_lwg4223()
+{
+  using KD = std::remove_cv_t<std::remove_reference_t<K>>;
+  using VD = std::remove_cv_t<std::remove_reference_t<V>>;
+  using Alloc = __gnu_test::SimpleAllocator<std::pair<const KD, VD>>;
+
+  std::initializer_list<std::pair<K, V>> il = {};
+  Alloc a;
+  MyPred p;
+
+  // The remove_cvref_t is not applied here.
+  // static_assert(std::is_same_v<
+  //   decltype(std::map(il)),
+  //   std::map<KD, VD>>);
+
+  static_assert(std::is_same_v<
+    decltype(std::map(il.begin(), il.end())),
+    std::map<KD, VD>>);
+
+  static_assert(std::is_same_v<
+    decltype(std::map(il.begin(), il.end(), p)),
+    std::map<KD, VD, MyPred>>);
+
+  static_assert(std::is_same_v<
+    decltype(std::map(il.begin(), il.end(), a)),
+    std::map<KD, VD, std::less<KD>, Alloc>>);
+
+  static_assert(std::is_same_v<
+    decltype(std::map(il.begin(), il.end(), p, a)),
+    std::map<KD, VD, MyPred, Alloc>>);
+
+  return true;
+}
+
+static_assert(test_lwg4223<const int, const float>());
+static_assert(test_lwg4223<int&, float&>());
+static_assert(test_lwg4223<int&&, float&&>());
+static_assert(test_lwg4223<const int&, const float&>());
diff --git a/libstdc++-v3/testsuite/23_containers/map/cons/from_range.cc 
b/libstdc++-v3/testsuite/23_containers/map/cons/from_range.cc
index 9935f44aa0f9..3a9fede04348 100644
--- a/libstdc++-v3/testsuite/23_containers/map/cons/from_range.cc
+++ b/libstdc++-v3/testsuite/23_containers/map/cons/from_range.cc
@@ -43,11 +43,11 @@ test_deduction_guide()
 
   __gnu_test::test_input_range<std::pair<const long, const float>> r2(0, 0);
   std::map m5(std::from_range, r2);
-  static_assert(std::is_same_v<decltype(m5), std::map<long, const float>>);
+  static_assert(std::is_same_v<decltype(m5), std::map<long, float>>);
 
-  // LWG4223: deduces map<const long&, float&>
-  //__gnu_test::test_input_range<std::pair<const long&, float&>> r3(0, 0);
-  // std::map m6(std::from_range, r3);
+  __gnu_test::test_input_range<std::pair<const long&, float&>> r3(0, 0);
+  std::map m6(std::from_range, r3);
+  static_assert(std::is_same_v<decltype(m6), std::map<long, float>>);
 
   __gnu_test::test_input_range<std::tuple<long, float>> r4(0, 0);
   std::map m7(std::from_range, r4);
diff --git a/libstdc++-v3/testsuite/23_containers/multimap/cons/deduction.cc 
b/libstdc++-v3/testsuite/23_containers/multimap/cons/deduction.cc
index f0699e2eefc3..de5e6acb4f24 100644
--- a/libstdc++-v3/testsuite/23_containers/multimap/cons/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/multimap/cons/deduction.cc
@@ -210,3 +210,49 @@ test_p1518r2()
   std::multimap s2(std::move(m), p);
   check_type<MMap>(s2);
 }
+
+struct MyPred
+{
+  template<typename T, typename U>
+  bool operator()(T const&, U const&) const;
+};
+
+template<typename K, typename V>
+constexpr bool test_lwg4223()
+{
+  using KD = std::remove_cv_t<std::remove_reference_t<K>>;
+  using VD = std::remove_cv_t<std::remove_reference_t<V>>;
+  using Alloc = __gnu_test::SimpleAllocator<std::pair<const KD, VD>>;
+
+  std::initializer_list<std::pair<K, V>> il = {};
+  Alloc a;
+  MyPred p;
+
+  // The remove_cvref_t is not applied here.
+  // static_assert(std::is_same_v<
+  //   decltype(std::multimap(il)),
+  //   std::multimap<KD, VD>>);
+
+  static_assert(std::is_same_v<
+    decltype(std::multimap(il.begin(), il.end())),
+    std::multimap<KD, VD>>);
+
+  static_assert(std::is_same_v<
+    decltype(std::multimap(il.begin(), il.end(), p)),
+    std::multimap<KD, VD, MyPred>>);
+
+  static_assert(std::is_same_v<
+    decltype(std::multimap(il.begin(), il.end(), a)),
+    std::multimap<KD, VD, std::less<KD>, Alloc>>);
+
+  static_assert(std::is_same_v<
+    decltype(std::multimap(il.begin(), il.end(), p, a)),
+    std::multimap<KD, VD, MyPred, Alloc>>);
+
+  return true;
+}
+
+static_assert(test_lwg4223<const int, const float>());
+static_assert(test_lwg4223<int&, float&>());
+static_assert(test_lwg4223<int&&, float&&>());
+static_assert(test_lwg4223<const int&, const float&>());
diff --git a/libstdc++-v3/testsuite/23_containers/multimap/cons/from_range.cc 
b/libstdc++-v3/testsuite/23_containers/multimap/cons/from_range.cc
index 4a8ea9fec7d7..5907bab9878c 100644
--- a/libstdc++-v3/testsuite/23_containers/multimap/cons/from_range.cc
+++ b/libstdc++-v3/testsuite/23_containers/multimap/cons/from_range.cc
@@ -43,11 +43,11 @@ test_deduction_guide()
 
   __gnu_test::test_input_range<std::pair<const long, const float>> r2(0, 0);
   std::multimap m5(std::from_range, r2);
-  static_assert(std::is_same_v<decltype(m5), std::multimap<long, const 
float>>);
+  static_assert(std::is_same_v<decltype(m5), std::multimap<long, float>>);
 
-  // LWG4223: deduces multimap<const long&, float&>
-  //__gnu_test::test_input_range<std::pair<const long&, float&>> r3(0, 0);
-  // std::multimap m6(std::from_range, r3);
+  __gnu_test::test_input_range<std::pair<const long&, float&>> r3(0, 0);
+  std::multimap m6(std::from_range, r3);
+  static_assert(std::is_same_v<decltype(m6), std::multimap<long, float>>);
 
   __gnu_test::test_input_range<std::tuple<long, float>> r4(0, 0);
   std::multimap m7(std::from_range, r4);
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 fa182f5866d3..26013da15c2f 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_map/cons/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/cons/deduction.cc
@@ -190,3 +190,72 @@ test_p1518r2()
   std::unordered_map s2(std::move(m), p);
   check_type<UMap>(s2);
 }
+
+struct MyHash
+{
+  template<typename T>
+  std::size_t operator()(T const&) const;
+};
+
+struct MyPred
+{
+  template<typename T, typename U>
+  bool operator()(T const&, U const&) const;
+};
+
+template<typename K, typename V>
+constexpr bool test_lwg4223()
+{
+  using KD = std::remove_cv_t<std::remove_reference_t<K>>;
+  using VD = std::remove_cv_t<std::remove_reference_t<V>>;
+  using Alloc = __gnu_test::SimpleAllocator<std::pair<const KD, VD>>;
+
+  std::initializer_list<std::pair<K, V>> il = {};
+  Alloc a;
+  MyHash h;
+  MyPred p;
+
+  // The remove_cvref_t is not applied here.
+  // static_assert(std::is_same_v<
+  //   decltype(std::unordered_map(il)),
+  //   std::unordered_map<KD, VD>>);
+
+  static_assert(std::is_same_v<
+    decltype(std::unordered_map(il.begin(), il.end())),
+    std::unordered_map<KD, VD>>);
+
+  static_assert(std::is_same_v<
+    decltype(std::unordered_map(il.begin(), il.end(), 0)),
+    std::unordered_map<KD, VD>>);
+
+  static_assert(std::is_same_v<
+    decltype(std::unordered_map(il.begin(), il.end(), 0, h)),
+    std::unordered_map<KD, VD, MyHash>>);
+
+  static_assert(std::is_same_v<
+    decltype(std::unordered_map(il.begin(), il.end(), 0, h, p)),
+    std::unordered_map<KD, VD, MyHash, MyPred>>);
+
+  static_assert(std::is_same_v<
+    decltype(std::unordered_map(il.begin(), il.end(), a)),
+    std::unordered_map<KD, VD, std::hash<KD>, std::equal_to<KD>, Alloc>>);
+
+  static_assert(std::is_same_v<
+    decltype(std::unordered_map(il.begin(), il.end(), 0, a)),
+    std::unordered_map<KD, VD, std::hash<KD>, std::equal_to<KD>, Alloc>>);
+
+  static_assert(std::is_same_v<
+    decltype(std::unordered_map(il.begin(), il.end(), 0, h, a)),
+    std::unordered_map<KD, VD, MyHash, std::equal_to<KD>, Alloc>>);
+
+  static_assert(std::is_same_v<
+    decltype(std::unordered_map(il.begin(), il.end(), 0, h, p, a)),
+    std::unordered_map<KD, VD, MyHash, MyPred, Alloc>>);
+
+  return true;
+}
+
+static_assert(test_lwg4223<const int, const float>());
+static_assert(test_lwg4223<int&, float&>());
+static_assert(test_lwg4223<int&&, float&&>());
+static_assert(test_lwg4223<const int&, const float&>());
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 36efc2de5a39..04479a5e54d8 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
@@ -78,13 +78,11 @@ test_deduction_guide()
 
   __gnu_test::test_input_range<std::pair<const long, const float>> r2(0, 0);
   std::unordered_map m9(std::from_range, r2);
-  static_assert(std::is_same_v<
-    decltype(m9),
-    std::unordered_map<long, const float>>);
+  static_assert(std::is_same_v<decltype(m9), std::unordered_map<long, float>>);
 
-  // LWG4223: deduces map<const long&, float&>
-  // __gnu_test::test_input_range<std::pair<const long&, float&>> r3(0, 0);
-  // std::unordered_map m10(std::from_range, r3);
+  __gnu_test::test_input_range<std::pair<const long&, float&>> r3(0, 0);
+  std::unordered_map m10(std::from_range, r3);
+  static_assert(std::is_same_v<decltype(m10), std::unordered_map<long, 
float>>);
 
   __gnu_test::test_input_range<std::tuple<long, float>> r4(0, 0);
   std::unordered_map m11(std::from_range, r4);
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 4de23fe3e791..1db58a04abf8 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/deduction.cc
@@ -205,3 +205,72 @@ test_p1518r2()
   std::unordered_multimap s2(std::move(m), p);
   check_type<UMMap>(s2);
 }
+
+struct MyHash
+{
+  template<typename T>
+  std::size_t operator()(T const&) const;
+};
+
+struct MyPred
+{
+  template<typename T, typename U>
+  bool operator()(T const&, U const&) const;
+};
+
+template<typename K, typename V>
+constexpr bool test_lwg4223()
+{
+  using KD = std::remove_cv_t<std::remove_reference_t<K>>;
+  using VD = std::remove_cv_t<std::remove_reference_t<V>>;
+  using Alloc = __gnu_test::SimpleAllocator<std::pair<const KD, VD>>;
+
+  std::initializer_list<std::pair<K, V>> il = {};
+  Alloc a;
+  MyHash h;
+  MyPred p;
+
+  // The remove_cvref_t is not applied here.
+  // static_assert(std::is_same_v<
+  //   decltype(std::unordered_multimap(il)),
+  //   std::unordered_multimap<KD, VD>>);
+
+  static_assert(std::is_same_v<
+    decltype(std::unordered_multimap(il.begin(), il.end())),
+    std::unordered_multimap<KD, VD>>);
+
+  static_assert(std::is_same_v<
+    decltype(std::unordered_multimap(il.begin(), il.end(), 0)),
+    std::unordered_multimap<KD, VD>>);
+
+  static_assert(std::is_same_v<
+    decltype(std::unordered_multimap(il.begin(), il.end(), 0, h)),
+    std::unordered_multimap<KD, VD, MyHash>>);
+
+  static_assert(std::is_same_v<
+    decltype(std::unordered_multimap(il.begin(), il.end(), 0, h, p)),
+    std::unordered_multimap<KD, VD, MyHash, MyPred>>);
+
+  static_assert(std::is_same_v<
+    decltype(std::unordered_multimap(il.begin(), il.end(), a)),
+    std::unordered_multimap<KD, VD, std::hash<KD>, std::equal_to<KD>, Alloc>>);
+
+  static_assert(std::is_same_v<
+    decltype(std::unordered_multimap(il.begin(), il.end(), 0, a)),
+    std::unordered_multimap<KD, VD, std::hash<KD>, std::equal_to<KD>, Alloc>>);
+
+  static_assert(std::is_same_v<
+    decltype(std::unordered_multimap(il.begin(), il.end(), 0, h, a)),
+    std::unordered_multimap<KD, VD, MyHash, std::equal_to<KD>, Alloc>>);
+
+  static_assert(std::is_same_v<
+    decltype(std::unordered_multimap(il.begin(), il.end(), 0, h, p, a)),
+    std::unordered_multimap<KD, VD, MyHash, MyPred, Alloc>>);
+
+  return true;
+}
+
+static_assert(test_lwg4223<const int, const float>());
+static_assert(test_lwg4223<int&, float&>());
+static_assert(test_lwg4223<int&&, float&&>());
+static_assert(test_lwg4223<const int&, const float&>());
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 b551df49f3e7..4567bd8aa914 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
@@ -86,11 +86,13 @@ test_deduction_guide()
   std::unordered_multimap m9(std::from_range, r2);
   static_assert(std::is_same_v<
     decltype(m9),
-    std::unordered_multimap<long, const float>>);
+    std::unordered_multimap<long, float>>);
 
-  // LWG4223: deduces map<const long&, float&>
-  // __gnu_test::test_input_range<std::pair<const long&, float&>> r3(0, 0);
-  // std::unordered_multimap m10(std::from_range, r3);
+  __gnu_test::test_input_range<std::pair<const long&, float&>> r3(0, 0);
+  std::unordered_multimap m10(std::from_range, r3);
+  static_assert(std::is_same_v<
+    decltype(m10),
+    std::unordered_multimap<long, float>>);
 
   __gnu_test::test_input_range<std::tuple<long, float>> r4(0, 0);
   std::unordered_multimap m11(std::from_range, r4);

Reply via email to