From: Tomasz Kamiński Date: Wed, 19 Mar 2025 10:42:50 +0000 (+0100) Subject: libstdc++: Support maps deduction from_range of tuples. X-Git-Tag: basepoints/gcc-16~1257 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=r15-8296-gd50171bc07006d;p=thirdparty%2Fgcc.git libstdc++: Support maps deduction from_range of tuples. This implements part of LWG4223 that enables deduction for maps types (map, unordered_map, flat_map and non-unique equivalent) from (from_range, rg, ...) arguments, where rg is range of tuple or other pair-like. libstdc++-v3/ChangeLog: * include/bits/ranges_base.h (__detail::__range_key_type): Replace RV::first_type with tuple_element_t<0, RV>. (__detail::__range_mapped_type) Replace RV::second_type with tuple_element_t<1, RV>. * testsuite/23_containers/flat_map/1.cc: New tests. * testsuite/23_containers/flat_multimap/1.cc: New tests. * testsuite/23_containers/map/cons/from_range.cc: New tests. * testsuite/23_containers/multimap/cons/from_range.cc: New tests. * testsuite/23_containers/unordered_map/cons/from_range.cc: New tests. * testsuite/23_containers/unordered_multimap/cons/from_range.cc: New tests. Reviewed-by: Jonathan Wakely Signed-off-by: Tomasz Kamiński --- diff --git a/libstdc++-v3/include/bits/ranges_base.h b/libstdc++-v3/include/bits/ranges_base.h index c9687c256e9..13bfbb3795b 100644 --- a/libstdc++-v3/include/bits/ranges_base.h +++ b/libstdc++-v3/include/bits/ranges_base.h @@ -41,6 +41,10 @@ #include #include +#if __glibcxx_ranges_to_container // C++ >= 23 +# include // for tuple_element_t +#endif + #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpedantic" // __int128 @@ -1093,13 +1097,15 @@ namespace __detail = ranges::input_range<_Rg> && convertible_to, _Tp>; + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4223. Deduction guides for maps are mishandling tuples and references template using __range_key_type - = remove_const_t::first_type>; + = remove_const_t>>; template using __range_mapped_type - = typename ranges::range_value_t<_Range>::second_type; + = tuple_element_t<1, ranges::range_value_t<_Range>>; // The allocator's value_type for map-like containers. template diff --git a/libstdc++-v3/testsuite/23_containers/flat_map/1.cc b/libstdc++-v3/testsuite/23_containers/flat_map/1.cc index 00254dc2ee6..d9d88c4df6e 100644 --- a/libstdc++-v3/testsuite/23_containers/flat_map/1.cc +++ b/libstdc++-v3/testsuite/23_containers/flat_map/1.cc @@ -11,6 +11,67 @@ #include #include #include +#include +#include + +struct Gt { + template + bool operator()(T const& l, U const & r) const + { return l > r; } +}; + +void +test_deduction_guide() +{ + __gnu_test::test_input_range> r(0, 0); + std::flat_map it1(r.begin(), r.begin()); + static_assert(std::is_same_v>); + std::flat_map fr1(std::from_range, r); + static_assert(std::is_same_v>); + + Gt cmp; + std::flat_map it2(r.begin(), r.begin(), cmp); + static_assert(std::is_same_v>); + std::flat_map fr2(std::from_range, r, cmp); + static_assert(std::is_same_v>); + + using Alloc = __gnu_test::SimpleAllocator>; + Alloc alloc; + // No matching deduction guide + // std::flat_map it3(r.begin(), r.begin(), alloc); + std::flat_map fr3(std::from_range, r, alloc); + static_assert(std::is_same_v< + decltype(fr3), + std::flat_map, + std::vector>, + std::vector>>>); + + // No matching deduction guide + // std::flat_map it4(r.begin(), r.begin(), cmp, alloc); + std::flat_map fr4(std::from_range, r, cmp, alloc); + static_assert(std::is_same_v< + decltype(fr4), + std::flat_map>, + std::vector>>>); + + // LWG4223: deduces flat_map, which in turn instantiates + // std::vector that is ill-formed. + // __gnu_test::test_input_range> r2(0, 0); + // std::flat_map it5(r2.begin(), r2.begin()); + // std::flat_map fr5(std::from_range, r2); + + // LWG4223: deduces flat_map + //__gnu_test::test_input_range> r3(0, 0); + // std::flat_map it6(r3.begin(), r3.begin()); + // std::flat_map fr6(std::from_range, r3); + + __gnu_test::test_input_range> r4(0, 0); + std::flat_map it7(r4.begin(), r4.begin()); + static_assert(std::is_same_v>); + std::flat_map fr7(std::from_range, r4); + static_assert(std::is_same_v>); +} template class KeyContainer, template class MappedContainer> void diff --git a/libstdc++-v3/testsuite/23_containers/flat_multimap/1.cc b/libstdc++-v3/testsuite/23_containers/flat_multimap/1.cc index 38650a81bcf..ff180bf1bdf 100644 --- a/libstdc++-v3/testsuite/23_containers/flat_multimap/1.cc +++ b/libstdc++-v3/testsuite/23_containers/flat_multimap/1.cc @@ -5,6 +5,71 @@ #include #include #include +#include +#include + +struct Gt { + template + bool operator()(T const& l, U const & r) const + { return l > r; } +}; + +void +test_deduction_guide() +{ + __gnu_test::test_input_range> r(0, 0); + std::flat_multimap it1(r.begin(), r.begin()); + static_assert(std::is_same_v>); + std::flat_multimap fr1(std::from_range, r); + static_assert(std::is_same_v>); + + Gt cmp; + std::flat_multimap it2(r.begin(), r.begin(), cmp); + static_assert(std::is_same_v< + decltype(it2), + std::flat_multimap>); + std::flat_multimap fr2(std::from_range, r, cmp); + static_assert(std::is_same_v< + decltype(fr2), + std::flat_multimap>); + + using Alloc = __gnu_test::SimpleAllocator>; + Alloc alloc; + // No matching deduction guide + // std::flat_multimap it3(r.begin(), r.begin(), alloc); + std::flat_multimap fr3(std::from_range, r, alloc); + static_assert(std::is_same_v< + decltype(fr3), + std::flat_multimap, + std::vector>, + std::vector>>>); + + // No matching deduction guide + // std::flat_multimap it4(r.begin(), r.begin(), cmp, alloc); + std::flat_multimap fr4(std::from_range, r, cmp, alloc); + static_assert(std::is_same_v< + decltype(fr4), + std::flat_multimap>, + std::vector>>>); + + // LWG4223: deduces flat_multimap, which in turn instantiates + // std::vector that is ill-formed. + // __gnu_test::test_input_range> r2(0, 0); + // std::flat_multimap it5(r2.begin(), r2.begin()); + // std::flat_multimap fr5(std::from_range, r2); + + // LWG4223: deduces flat_multimap + //__gnu_test::test_input_range> r3(0, 0); + // std::flat_multimap it6(r3.begin(), r3.begin()); + // std::flat_multimap fr6(std::from_range, r3); + + __gnu_test::test_input_range> r4(0, 0); + std::flat_multimap it7(r4.begin(), r4.begin()); + static_assert(std::is_same_v>); + std::flat_multimap fr7(std::from_range, r4); + static_assert(std::is_same_v>); +} template class KeyContainer, template class MappedContainer> void 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 01e426fde3d..c740471f2da 100644 --- a/libstdc++-v3/testsuite/23_containers/map/cons/from_range.cc +++ b/libstdc++-v3/testsuite/23_containers/map/cons/from_range.cc @@ -44,9 +44,11 @@ test_deduction_guide() //__gnu_test::test_input_range> r3(0, 0); // std::map m6(std::from_range, r3); - // LWG4223: no deduction guide - // __gnu_test::test_input_range> r4(0, 0); - // std::map m7(std::from_range, r4); + __gnu_test::test_input_range> r4(0, 0); + std::map m7(std::from_range, r4); + static_assert(std::is_same_v>); + std::map it7(r4.begin(), r4.begin()); + static_assert(std::is_same_v>); } template 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 e0052e499ca..3e456f566cc 100644 --- a/libstdc++-v3/testsuite/23_containers/multimap/cons/from_range.cc +++ b/libstdc++-v3/testsuite/23_containers/multimap/cons/from_range.cc @@ -44,9 +44,11 @@ test_deduction_guide() //__gnu_test::test_input_range> r3(0, 0); // std::multimap m6(std::from_range, r3); - // LWG4223: no deduction guide - // __gnu_test::test_input_range> r4(0, 0); - // std::multimap m7(std::from_range, r4); + __gnu_test::test_input_range> r4(0, 0); + std::multimap m7(std::from_range, r4); + static_assert(std::is_same_v>); + std::multimap it7(r4.begin(), r4.begin()); + static_assert(std::is_same_v>); } template 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 51f8538669a..6d1da5bf5d1 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 @@ -81,9 +81,11 @@ test_deduction_guide() // __gnu_test::test_input_range> r3(0, 0); // std::unordered_map m10(std::from_range, r3); - // LWG4223: no deduction guide - // __gnu_test::test_input_range> r4(0, 0); - // std::unordered_map m11(std::from_range, r4); + __gnu_test::test_input_range> r4(0, 0); + std::unordered_map m11(std::from_range, r4); + static_assert(std::is_same_v>); + std::unordered_map it11(r4.begin(), r4.begin()); + static_assert(std::is_same_v>); } template 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 1baf7305c84..2ca93d344e9 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 @@ -87,9 +87,15 @@ test_deduction_guide() // __gnu_test::test_input_range> r3(0, 0); // std::unordered_multimap m10(std::from_range, r3); - // LWG4223: no deduction guide - // __gnu_test::test_input_range> r4(0, 0); - // std::unordered_multimap m11(std::from_range, r4); + __gnu_test::test_input_range> r4(0, 0); + std::unordered_multimap m11(std::from_range, r4); + static_assert(std::is_same_v< + decltype(m11), + std::unordered_multimap>); + std::unordered_multimap it11(r4.begin(), r4.begin()); + static_assert(std::is_same_v< + decltype(it11), + std::unordered_multimap>); } template