On Tue, 22 Apr 2025 at 08:13, Tomasz Kaminski <tkami...@redhat.com> wrote: > > The test cover constructors introduced in [PATCH v2] libstdc++-v3: Implement > missing allocator-aware constructors for unordered containers, > so I will merge that after.
This change is OK for trunk now too. > > On Fri, Apr 18, 2025 at 5:18 PM Jonathan Wakely <jwakely....@gmail.com> wrote: >> >> >> >> On Fri, 18 Apr 2025, 12:55 Tomasz Kamiński, <tkami...@redhat.com> wrote: >>> >>> This implements part of LWG4223 that adjust the deduction guides for maps >>> types >>> (map, unordered_map, flat_map and non-unique equivalent) from "range", 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. >>> --- >>> Desipite there being some discussion about this on reflector, I think we >>> should go ahead with this, to avoid creating maps of references/const types. >>> As we are at the begining of development of 16, this seems like a good time >>> to do it. >>> OK for trunk? >> >> >> OK for trunk. >> >> >>> >>> >>> libstdc++-v3/include/bits/ranges_base.h | 4 +- >>> libstdc++-v3/include/bits/stl_iterator.h | 11 +-- >>> .../testsuite/23_containers/flat_map/1.cc | 21 +++--- >>> .../23_containers/flat_multimap/1.cc | 21 +++--- >>> .../23_containers/map/cons/deduction.cc | 46 +++++++++++++ >>> .../23_containers/map/cons/from_range.cc | 8 +-- >>> .../23_containers/multimap/cons/deduction.cc | 46 +++++++++++++ >>> .../23_containers/multimap/cons/from_range.cc | 8 +-- >>> .../unordered_map/cons/deduction.cc | 69 +++++++++++++++++++ >>> .../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 488907da446..dde16498856 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 9203a66b2ff..bed72955d0c 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 d9d88c4df6e..6105a2865c9 100644 >>> --- a/libstdc++-v3/testsuite/23_containers/flat_map/1.cc >>> +++ b/libstdc++-v3/testsuite/23_containers/flat_map/1.cc >>> @@ -55,16 +55,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 ff180bf1bdf..ac8b0e0d7d9 100644 >>> --- a/libstdc++-v3/testsuite/23_containers/flat_multimap/1.cc >>> +++ b/libstdc++-v3/testsuite/23_containers/flat_multimap/1.cc >>> @@ -53,16 +53,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 f8e6e6e8b99..194bff5bf78 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_cvref_t<K>; >>> + using VD = std::remove_cvref_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 9935f44aa0f..3a9fede0434 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 f0699e2eefc..84754f3f561 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_cvref_t<K>; >>> + using VD = std::remove_cvref_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 4a8ea9fec7d..5907bab9878 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 8b69af896a2..e806de2045c 100644 >>> --- a/libstdc++-v3/testsuite/23_containers/unordered_map/cons/deduction.cc >>> +++ b/libstdc++-v3/testsuite/23_containers/unordered_map/cons/deduction.cc >>> @@ -162,3 +162,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_cvref_t<K>; >>> + using VD = std::remove_cvref_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 36efc2de5a3..04479a5e54d 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 e7e535b527a..786e5030bb2 100644 >>> --- >>> a/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/deduction.cc >>> +++ >>> b/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/deduction.cc >>> @@ -171,3 +171,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_cvref_t<K>; >>> + using VD = std::remove_cvref_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 b551df49f3e..4567bd8aa91 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); >>> -- >>> 2.49.0 >>>