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

Reply via email to