diff --git a/libcxx/include/__iterator/iterator_traits.h b/libcxx/include/__iterator/iterator_traits.h index c08d72971ec3e..8256580acb291 100644 --- a/libcxx/include/__iterator/iterator_traits.h +++ b/libcxx/include/__iterator/iterator_traits.h @@ -22,6 +22,7 @@ #include <__fwd/pair.h> #include <__iterator/incrementable_traits.h> #include <__iterator/readable_traits.h> +#include <__tuple/tuple_element.h> #include <__type_traits/common_reference.h> #include <__type_traits/conditional.h> #include <__type_traits/detected_or.h> @@ -466,6 +467,18 @@ using __has_exactly_bidirectional_iterator_category _LIBCPP_NODEBUG = template using __iter_value_type _LIBCPP_NODEBUG = typename iterator_traits<_InputIterator>::value_type; +#if _LIBCPP_STD_VER >= 23 +template +using __iter_key_type _LIBCPP_NODEBUG = remove_const_t>>; + +template +using __iter_mapped_type _LIBCPP_NODEBUG = tuple_element_t<1, __iter_value_type<_InputIterator>>; + +template +using __iter_to_alloc_type _LIBCPP_NODEBUG = + pair>, + tuple_element_t<1, __iter_value_type<_InputIterator>>>; +#else template using __iter_key_type _LIBCPP_NODEBUG = __remove_const_t::value_type::first_type>; @@ -477,6 +490,7 @@ template using __iter_to_alloc_type _LIBCPP_NODEBUG = pair::value_type::first_type, typename iterator_traits<_InputIterator>::value_type::second_type>; +#endif // _LIBCPP_STD_VER >= 23 template using __iterator_category_type _LIBCPP_NODEBUG = typename iterator_traits<_Iter>::iterator_category; diff --git a/libcxx/test/std/containers/associative/map/map.cons/deduct.pass.cpp b/libcxx/test/std/containers/associative/map/map.cons/deduct.pass.cpp index c91fe4b23566a..5cefb6f361a53 100644 --- a/libcxx/test/std/containers/associative/map/map.cons/deduct.pass.cpp +++ b/libcxx/test/std/containers/associative/map/map.cons/deduct.pass.cpp @@ -40,7 +40,10 @@ #include // INT_MAX #include #include +#include +#include #include +#include #include "deduction_guides_sfinae_checks.h" #include "test_allocator.h" @@ -189,6 +192,23 @@ int main(int, char**) { static_assert(std::is_same_v>); } } + { + std::vector> pair_vec = {{1, 1.1f}, {2, 2.2f}, {3, 3.3f}}; + std::map m1(pair_vec.begin(), pair_vec.end()); + ASSERT_SAME_TYPE(decltype(m1), std::map); + + std::vector> tuple_vec = {{10, 1.1}, {20, 2.2}, {30, 3.3}}; + std::map m2(tuple_vec.begin(), tuple_vec.end()); + ASSERT_SAME_TYPE(decltype(m2), std::map); + + std::vector> array_vec = {{100L, 101L}, {200L, 201L}, {300L, 301L}}; + std::map m3(array_vec.begin(), array_vec.end()); + ASSERT_SAME_TYPE(decltype(m3), std::map); + + std::vector> non_const_key_pair_vec = {{5, 'a'}, {6, 'b'}}; + std::map m4(non_const_key_pair_vec.begin(), non_const_key_pair_vec.end()); + ASSERT_SAME_TYPE(decltype(m4), std::map); + } #endif AssociativeContainerDeductionGuidesSfinaeAway>(); diff --git a/libcxx/test/std/containers/associative/map/map.cons/deduct.verify.cpp b/libcxx/test/std/containers/associative/map/map.cons/deduct.verify.cpp index c8c0e1e538db2..8c00adca4f446 100644 --- a/libcxx/test/std/containers/associative/map/map.cons/deduct.verify.cpp +++ b/libcxx/test/std/containers/associative/map/map.cons/deduct.verify.cpp @@ -26,9 +26,11 @@ // map(initializer_list, Allocator) // -> map, Allocator>; +#include #include // INT_MAX #include #include +#include #include struct NotAnAllocator { @@ -101,6 +103,17 @@ int main(int, char**) { std::map m(PC{1, 1L}); // expected-error-re@-1{{no viable constructor or deduction guide for deduction of template arguments of '{{(std::)?}}map'}} } - + { + // cannot deduce from tuple-like objects without proper iterator + std::tuple t{1, 2.0}; + std::map m(t); + // expected-error-re@-1{{no viable constructor or deduction guide for deduction of template arguments of '{{(std::)?}}map'}} + } + { + // cannot deduce from array-like objects without proper iterator + std::array arr{1, 2}; + std::map m(arr); + // expected-error-re@-1{{no viable constructor or deduction guide for deduction of template arguments of '{{(std::)?}}map'}} + } return 0; } diff --git a/libcxx/test/std/containers/associative/multimap/multimap.cons/deduct.pass.cpp b/libcxx/test/std/containers/associative/multimap/multimap.cons/deduct.pass.cpp index 2f3db7f0de992..1e318890e58ac 100644 --- a/libcxx/test/std/containers/associative/multimap/multimap.cons/deduct.pass.cpp +++ b/libcxx/test/std/containers/associative/multimap/multimap.cons/deduct.pass.cpp @@ -40,7 +40,10 @@ #include // INT_MAX #include #include +#include #include +#include +#include #include "deduction_guides_sfinae_checks.h" #include "test_allocator.h" @@ -189,6 +192,24 @@ int main(int, char**) { static_assert(std::is_same_v>); } } + { + std::vector> pair_vec = {{1, 1.1f}, {2, 2.2f}, {3, 3.3f}}; + std::multimap mm1(pair_vec.begin(), pair_vec.end()); + ASSERT_SAME_TYPE(decltype(mm1), std::multimap); + + std::vector> tuple_vec = {{10, 1.1}, {20, 2.2}, {30, 3.3}}; + std::multimap mm2(tuple_vec.begin(), tuple_vec.end()); + ASSERT_SAME_TYPE(decltype(mm2), std::multimap); + + std::vector> array_vec = {{100L, 101L}, {200L, 201L}, {300L, 301L}}; + std::multimap mm3(array_vec.begin(), array_vec.end()); + ASSERT_SAME_TYPE(decltype(mm3), std::multimap); + + // Check deduction with non-const key in input pair + std::vector> non_const_key_pair_vec = {{5, 'a'}, {6, 'b'}}; + std::multimap mm4(non_const_key_pair_vec.begin(), non_const_key_pair_vec.end()); + ASSERT_SAME_TYPE(decltype(mm4), std::multimap); + } #endif AssociativeContainerDeductionGuidesSfinaeAway>(); diff --git a/libcxx/test/std/containers/associative/multimap/multimap.cons/deduct.verify.cpp b/libcxx/test/std/containers/associative/multimap/multimap.cons/deduct.verify.cpp index 03ac8ebf92716..aa642e39bec17 100644 --- a/libcxx/test/std/containers/associative/multimap/multimap.cons/deduct.verify.cpp +++ b/libcxx/test/std/containers/associative/multimap/multimap.cons/deduct.verify.cpp @@ -26,9 +26,11 @@ // multimap(initializer_list, Allocator) // -> multimap, Allocator>; +#include #include // INT_MAX #include #include +#include #include struct NotAnAllocator { @@ -101,6 +103,18 @@ int main(int, char**) { std::multimap m(PC{1, 1L}); // expected-error-re@-1{{no viable constructor or deduction guide for deduction of template arguments of '{{(std::)?}}multimap'}} } + { + // cannot deduce from tuple-like objects without proper iterator + std::tuple t{1, 2.0}; + std::multimap m(t); + // expected-error-re@-1{{no viable constructor or deduction guide for deduction of template arguments of '{{(std::)?}}multimap'}} + } + { + // cannot deduce from array-like objects without proper iterator + std::array arr{1, 2}; + std::multimap m(arr); + // expected-error-re@-1{{no viable constructor or deduction guide for deduction of template arguments of '{{(std::)?}}multimap'}} + } return 0; } diff --git a/libcxx/test/std/containers/container.adaptors/flat.map/flat.map.cons/deduct.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.map/flat.map.cons/deduct.pass.cpp index 009392feb3862..21166361b014b 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.map/flat.map.cons/deduct.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.map/flat.map.cons/deduct.pass.cpp @@ -11,6 +11,7 @@ // #include +#include #include #include #include @@ -19,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -335,6 +337,24 @@ int main(int, char**) { test_from_range(); test_from_range_compare(); +#if TEST_STD_VER >= 23 + std::vector> pair_vec = {{1, 1.1f}, {2, 2.2f}, {3, 3.3f}}; + std::flat_map fm1(pair_vec.begin(), pair_vec.end()); + ASSERT_SAME_TYPE(decltype(fm1), std::flat_map); + + std::vector> tuple_vec = {{10, 1.1}, {20, 2.2}, {30, 3.3}}; + std::flat_map fm2(tuple_vec.begin(), tuple_vec.end()); + ASSERT_SAME_TYPE(decltype(fm2), std::flat_map); + + std::vector> array_vec = {{100L, 101L}, {200L, 201L}, {300L, 301L}}; + std::flat_map fm3(array_vec.begin(), array_vec.end()); + ASSERT_SAME_TYPE(decltype(fm3), std::flat_map); + + std::vector> non_const_key_pair_vec = {{5, 'a'}, {6, 'b'}}; + std::flat_map fm4(non_const_key_pair_vec.begin(), non_const_key_pair_vec.end()); + ASSERT_SAME_TYPE(decltype(fm4), std::flat_map); +#endif + AssociativeContainerDeductionGuidesSfinaeAway>(); return 0; diff --git a/libcxx/test/std/containers/container.adaptors/flat.map/flat.map.cons/deduct.verify.cpp b/libcxx/test/std/containers/container.adaptors/flat.map/flat.map.cons/deduct.verify.cpp index ed20c1ae715b8..6f0d802e8e236 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.map/flat.map.cons/deduct.verify.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.map/flat.map.cons/deduct.verify.cpp @@ -12,9 +12,11 @@ // Test CTAD on cases where deduction should fail. +#include #include #include #include +#include using P = std::pair; using PC = std::pair; @@ -50,4 +52,16 @@ void test() { std::flat_map m(PC{1, 1L}); // expected-error-re@-1{{{{no viable constructor or deduction guide for deduction of template arguments of '.*flat_map'}}}} } + { + // cannot deduce from tuple-like objects without proper iterator + std::tuple t{1, 2.0}; + std::flat_map m(t); + // expected-error-re@-1{{no viable constructor or deduction guide for deduction of template arguments of '{{(std::)?}}flat_map'}} + } + { + // cannot deduce from array-like objects without proper iterator + std::array arr{1, 2}; + std::flat_map m(arr); + // expected-error-re@-1{{no viable constructor or deduction guide for deduction of template arguments of '{{(std::)?}}flat_map'}} + } } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/deduct.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/deduct.pass.cpp index a718d9cfad5b7..23ef312a5c67c 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/deduct.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/deduct.pass.cpp @@ -11,6 +11,7 @@ // #include +#include #include #include #include @@ -325,6 +326,24 @@ void test_from_range_compare() { } } +void test_tuple_like_deduction() { + std::vector> pair_vec = {{1, 1.1f}, {2, 2.2f}, {3, 3.3f}}; + std::flat_multimap fmm1(pair_vec.begin(), pair_vec.end()); + ASSERT_SAME_TYPE(decltype(fmm1), std::flat_multimap); + + std::vector> tuple_vec = {{10, 1.1}, {20, 2.2}, {30, 3.3}}; + std::flat_multimap fmm2(tuple_vec.begin(), tuple_vec.end()); + ASSERT_SAME_TYPE(decltype(fmm2), std::flat_multimap); + + std::vector> array_vec = {{100L, 101L}, {200L, 201L}, {300L, 301L}}; + std::flat_multimap fmm3(array_vec.begin(), array_vec.end()); + ASSERT_SAME_TYPE(decltype(fmm3), std::flat_multimap); + + std::vector> non_const_key_pair_vec = {{5, 'a'}, {6, 'b'}}; + std::flat_multimap fmm4(non_const_key_pair_vec.begin(), non_const_key_pair_vec.end()); + ASSERT_SAME_TYPE(decltype(fmm4), std::flat_multimap); +} + int main(int, char**) { // Each test function also tests the sorted_equivalent-prefixed and allocator-suffixed overloads. test_copy(); @@ -336,6 +355,7 @@ int main(int, char**) { test_initializer_list_compare(); test_from_range(); test_from_range_compare(); + test_tuple_like_deduction(); AssociativeContainerDeductionGuidesSfinaeAway>(); diff --git a/libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/deduct.verify.cpp b/libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/deduct.verify.cpp index c25218e890f21..415e9ee29e73a 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/deduct.verify.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/deduct.verify.cpp @@ -12,8 +12,10 @@ // Test CTAD on cases where deduction should fail. +#include #include #include +#include #include struct NotAnAllocator { @@ -54,4 +56,16 @@ void test() { std::flat_multimap m(PC{1, 1L}); // expected-error-re@-1{{{{no viable constructor or deduction guide for deduction of template arguments of '.*flat_multimap'}}}} } + { + // cannot deduce from tuple-like objects without proper iterator + std::tuple t{1, 2.0}; + std::flat_multimap m(t); + // expected-error-re@-1{{no viable constructor or deduction guide for deduction of template arguments of '{{(std::)?}}flat_multimap'}} + } + { + // cannot deduce from array-like objects without proper iterator + std::array arr{1, 2}; + std::flat_multimap m(arr); + // expected-error-re@-1{{no viable constructor or deduction guide for deduction of template arguments of '{{(std::)?}}flat_multimap'}} + } } diff --git a/libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/deduct.pass.cpp b/libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/deduct.pass.cpp index b2ef6be5523a5..2396fbd1002c3 100644 --- a/libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/deduct.pass.cpp +++ b/libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/deduct.pass.cpp @@ -82,8 +82,11 @@ #include #include // INT_MAX #include +#include #include #include +#include +#include #include "../../../test_compare.h" #include "../../../test_hash.h" @@ -311,6 +314,26 @@ int main(int, char**) { static_assert(std::is_same_v>); } } + { + std::vector> pair_vec = {{1, 1.1f}, {2, 2.2f}, {3, 3.3f}}; + std::unordered_map um1(pair_vec.begin(), pair_vec.end()); + ASSERT_SAME_TYPE(decltype(um1), std::unordered_map); + + std::vector> tuple_vec = {{10, 1.1}, {20, 2.2}, {30, 3.3}}; + // Note: std::tuple needs a hash specialization to be used as a key in unordered containers. + // This static_assert only checks the deduced type. + std::unordered_map um2(tuple_vec.begin(), tuple_vec.end()); + ASSERT_SAME_TYPE(decltype(um2), std::unordered_map); + + std::vector> array_vec = {{100L, 101L}, {200L, 201L}, {300L, 301L}}; + // Note: std::array needs a hash specialization. + std::unordered_map um3(array_vec.begin(), array_vec.end()); + ASSERT_SAME_TYPE(decltype(um3), std::unordered_map); + + std::vector> non_const_key_pair_vec = {{5, 'a'}, {6, 'b'}}; + std::unordered_map um4(non_const_key_pair_vec.begin(), non_const_key_pair_vec.end()); + ASSERT_SAME_TYPE(decltype(um4), std::unordered_map); + } #endif UnorderedContainerDeductionGuidesSfinaeAway>(); diff --git a/libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/deduct.verify.cpp b/libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/deduct.verify.cpp index 5bb2b28fa09f5..017bf122c7230 100644 --- a/libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/deduct.verify.cpp +++ b/libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/deduct.verify.cpp @@ -56,7 +56,9 @@ // Allocator) // -> unordered_map, Allocator>; +#include #include +#include #include int main(int, char**) { @@ -101,6 +103,18 @@ int main(int, char**) { std::unordered_map m(42, std::hash(), std::allocator

()); // expected-error-re@-1{{no viable constructor or deduction guide for deduction of template arguments of '{{(std::)?}}unordered_map'}} } + { + // cannot deduce from tuple-like objects without proper iterator + std::tuple t{1, 2.0}; + std::unordered_map m(t); + // expected-error-re@-1{{no viable constructor or deduction guide for deduction of template arguments of '{{(std::)?}}unordered_map'}} + } + { + // cannot deduce from array-like objects without proper iterator + std::array arr{1, 2}; + std::unordered_map m(arr); + // expected-error-re@-1{{no viable constructor or deduction guide for deduction of template arguments of '{{(std::)?}}unordered_map'}} + } return 0; } diff --git a/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/deduct.pass.cpp b/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/deduct.pass.cpp index 5d625a1deaab5..39896c6fe4ef1 100644 --- a/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/deduct.pass.cpp +++ b/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/deduct.pass.cpp @@ -81,8 +81,11 @@ #include #include #include // INT_MAX +#include #include #include +#include +#include #include "../../../test_compare.h" #include "../../../test_hash.h" @@ -307,6 +310,24 @@ int main(int, char**) { static_assert(std::is_same_v>); } } + + { + std::vector> pair_vec = {{1, 1.1f}, {2, 2.2f}, {3, 3.3f}}; + std::unordered_multimap umm1(pair_vec.begin(), pair_vec.end()); + ASSERT_SAME_TYPE(decltype(umm1), std::unordered_multimap); + + std::vector> tuple_vec = {{10, 1.1}, {20, 2.2}, {30, 3.3}}; + std::unordered_multimap umm2(tuple_vec.begin(), tuple_vec.end()); + ASSERT_SAME_TYPE(decltype(umm2), std::unordered_multimap); + + std::vector> array_vec = {{100L, 101L}, {200L, 201L}, {300L, 301L}}; + std::unordered_multimap umm3(array_vec.begin(), array_vec.end()); + ASSERT_SAME_TYPE(decltype(umm3), std::unordered_multimap); + + std::vector> non_const_key_pair_vec = {{5, 'a'}, {6, 'b'}}; + std::unordered_multimap umm4(non_const_key_pair_vec.begin(), non_const_key_pair_vec.end()); + ASSERT_SAME_TYPE(decltype(umm4), std::unordered_multimap); + } #endif UnorderedContainerDeductionGuidesSfinaeAway>(); diff --git a/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/deduct.verify.cpp b/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/deduct.verify.cpp index 11410ef2da9a4..dad8293b4b342 100644 --- a/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/deduct.verify.cpp +++ b/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/deduct.verify.cpp @@ -56,7 +56,9 @@ // Allocator) // -> unordered_multimap, Allocator>; +#include #include +#include #include int main(int, char**) { @@ -101,6 +103,18 @@ int main(int, char**) { std::unordered_multimap m(42, std::hash(), std::allocator

()); // expected-error-re@-1{{no viable constructor or deduction guide for deduction of template arguments of '{{(std::)?}}unordered_multimap'}} } + { + // cannot deduce from tuple-like objects without proper iterator + std::tuple t{1, 2.0}; + std::unordered_multimap m(t); + // expected-error-re@-1{{no viable constructor or deduction guide for deduction of template arguments of '{{(std::)?}}unordered_multimap'}} + } + { + // cannot deduce from array-like objects without proper iterator + std::array arr{1, 2}; + std::unordered_multimap m(arr); + // expected-error-re@-1{{no viable constructor or deduction guide for deduction of template arguments of '{{(std::)?}}unordered_multimap'}} + } return 0; }