This implements part of LWG2713 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 and 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. --- This implements non-controvesial part of LWG2713, which provides parity between iterator pair and from_range cosntructors. Testing on x86_64-linux (*map* tests passed). OK for trunk when test finishes? libstdc++-v3/include/bits/ranges_base.h | 8 ++- .../testsuite/23_containers/flat_map/1.cc | 61 +++++++++++++++++ .../23_containers/flat_multimap/1.cc | 65 +++++++++++++++++++ .../23_containers/map/cons/from_range.cc | 8 ++- .../23_containers/multimap/cons/from_range.cc | 8 ++- .../unordered_map/cons/from_range.cc | 8 ++- .../unordered_multimap/cons/from_range.cc | 12 +++- 7 files changed, 156 insertions(+), 14 deletions(-) diff --git a/libstdc++-v3/include/bits/ranges_base.h b/libstdc++-v3/include/bits/ranges_base.h index c9687c256e9..7d5aee9c430 100644 --- a/libstdc++-v3/include/bits/ranges_base.h +++ b/libstdc++-v3/include/bits/ranges_base.h @@ -41,6 +41,10 @@ #include <bits/max_size_type.h> #include <bits/version.h> +#if __glibcxx_ranges_to_container // C++ >= 23 +# include <bits/utility.h> // for tuple_element_t +#endif + #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpedantic" // __int128 @@ -1095,11 +1099,11 @@ namespace __detail template<ranges::input_range _Range> using __range_key_type - = remove_const_t<typename ranges::range_value_t<_Range>::first_type>; + = remove_const_t<tuple_element_t<0, ranges::range_value_t<_Range>>>; template<ranges::input_range _Range> 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<ranges::input_range _Range> diff --git a/libstdc++-v3/testsuite/23_containers/flat_map/1.cc b/libstdc++-v3/testsuite/23_containers/flat_map/1.cc index 00254dc2ee6..4e5ac9b62b7 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 <vector> #include <testsuite_allocator.h> #include <testsuite_hooks.h> +#include <testsuite_iterators.h> +#include <tuple> + +struct Gt { + template<typename T, typename U> + bool operator()(T const& l, U const & r) const + { return l > r; } +}; + +void +test_deduction_guide() +{ + __gnu_test::test_input_range<std::pair<long, float>> r(0, 0); + std::flat_map it1(std::from_range, r); + static_assert(std::is_same_v<decltype(it1), std::flat_map<long, float>>); + std::flat_map fr1(std::from_range, r); + static_assert(std::is_same_v<decltype(fr1), std::flat_map<long, float>>); + + Gt cmp; + std::flat_map it2(r.begin(), r.begin(), cmp); + static_assert(std::is_same_v<decltype(it2), std::flat_map<long, float, Gt>>); + std::flat_map fr2(std::from_range, r, cmp); + static_assert(std::is_same_v<decltype(fr2), std::flat_map<long, float, Gt>>); + + using Alloc = __gnu_test::SimpleAllocator<std::pair<const long, float>>; + 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<long, float, std::less<long>, + std::vector<long, __gnu_test::SimpleAllocator<long>>, + std::vector<float, __gnu_test::SimpleAllocator<float>>>>); + + // 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<long, float, Gt, + 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::tuple<long, float>> r4(0, 0); + std::flat_map it7(r4.begin(), r4.begin()); + static_assert(std::is_same_v<decltype(it7), std::flat_map<long, float>>); + std::flat_map fr7(std::from_range, r4); + static_assert(std::is_same_v<decltype(fr7), std::flat_map<long, float>>); +} template<template<typename> class KeyContainer, template<typename> 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..62bda65d79f 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 <vector> #include <testsuite_allocator.h> #include <testsuite_hooks.h> +#include <testsuite_iterators.h> +#include <tuple> + +struct Gt { + template<typename T, typename U> + bool operator()(T const& l, U const & r) const + { return l > r; } +}; + +void +test_deduction_guide() +{ + __gnu_test::test_input_range<std::pair<long, float>> r(0, 0); + std::flat_multimap it1(std::from_range, r); + static_assert(std::is_same_v<decltype(it1), std::flat_multimap<long, float>>); + std::flat_multimap fr1(std::from_range, r); + static_assert(std::is_same_v<decltype(fr1), std::flat_multimap<long, float>>); + + Gt cmp; + std::flat_multimap it2(r.begin(), r.begin(), cmp); + static_assert(std::is_same_v< + decltype(it2), + std::flat_multimap<long, float, Gt>>); + std::flat_multimap fr2(std::from_range, r, cmp); + static_assert(std::is_same_v< + decltype(fr2), + std::flat_multimap<long, float, Gt>>); + + using Alloc = __gnu_test::SimpleAllocator<std::pair<const long, float>>; + 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<long, float, std::less<long>, + std::vector<long, __gnu_test::SimpleAllocator<long>>, + std::vector<float, __gnu_test::SimpleAllocator<float>>>>); + + // 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<long, float, Gt, + 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::tuple<long, float>> r4(0, 0); + std::flat_multimap it7(r4.begin(), r4.begin()); + static_assert(std::is_same_v<decltype(it7), std::flat_multimap<long, float>>); + std::flat_multimap fr7(std::from_range, r4); + static_assert(std::is_same_v<decltype(fr7), std::flat_multimap<long, float>>); +} template<template<typename> class KeyContainer, template<typename> 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<std::pair<const long&, float&>> r3(0, 0); // std::map m6(std::from_range, r3); - // LWG4223: no deduction guide - // __gnu_test::test_input_range<std::tuple<long, float>> r4(0, 0); - // std::map m7(std::from_range, r4); + __gnu_test::test_input_range<std::tuple<long, float>> r4(0, 0); + std::map m7(std::from_range, r4); + static_assert(std::is_same_v<decltype(m7), std::map<long, float>>); + std::map it7(r4.begin(), r4.begin()); + static_assert(std::is_same_v<decltype(it7), std::map<long, float>>); } template<typename T, typename U> 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<std::pair<const long&, float&>> r3(0, 0); // std::multimap m6(std::from_range, r3); - // LWG4223: no deduction guide - // __gnu_test::test_input_range<std::tuple<long, float>> r4(0, 0); - // std::multimap m7(std::from_range, r4); + __gnu_test::test_input_range<std::tuple<long, float>> r4(0, 0); + std::multimap m7(std::from_range, r4); + static_assert(std::is_same_v<decltype(m7), std::multimap<long, float>>); + std::multimap it7(r4.begin(), r4.begin()); + static_assert(std::is_same_v<decltype(it7), std::multimap<long, float>>); } template<typename T, typename U> 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 b3cbb2e6062..a15bfaa48b3 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 @@ -82,9 +82,11 @@ test_deduction_guide() // __gnu_test::test_input_range<std::pair<const long&, float&>> r3(0, 0); // std::unordered_map m10(std::from_range, r3); - // LWG4223: no deduction guide - // __gnu_test::test_input_range<std::tuple<long, float>> r4(0, 0); - // std::unordered_map m11(std::from_range, r4); + __gnu_test::test_input_range<std::tuple<long, float>> r4(0, 0); + std::unordered_map m11(std::from_range, r4); + static_assert(std::is_same_v<decltype(m11), std::unordered_map<long, float>>); + std::unordered_map it11(r4.begin(), r4.begin()); + static_assert(std::is_same_v<decltype(it11), std::unordered_map<long, float>>); } template<typename T, typename U> 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 9273ef0d57a..416d9e08395 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<std::pair<const long&, float&>> r3(0, 0); // std::unordered_multimap m10(std::from_range, r3); - // LWG4223: no deduction guide - // __gnu_test::test_input_range<std::tuple<long, float>> r4(0, 0); - // std::unordered_multimap m11(std::from_range, r4); + __gnu_test::test_input_range<std::tuple<long, float>> r4(0, 0); + std::unordered_multimap m11(std::from_range, r4); + static_assert(std::is_same_v< + decltype(m11), + std::unordered_multimap<long, float>>); + std::unordered_multimap it11(r4.begin(), r4.begin()); + static_assert(std::is_same_v< + decltype(it11), + std::unordered_multimap<long, float>>); } template<typename T, typename U> -- 2.48.1