[libcxx-commits] [libcxx] [libc++] P2165R4: Update deduction guides for map containers and container adaptors (PR #136011)
via libcxx-commits
libcxx-commits at lists.llvm.org
Tue May 27 11:08:39 PDT 2025
https://github.com/KSARK updated https://github.com/llvm/llvm-project/pull/136011
>From cd6c7989879ed9b9d798551ce279be329bf27a2c Mon Sep 17 00:00:00 2001
From: KSARK <hcwenyc at hotmail.com>
Date: Tue, 27 May 2025 18:05:56 +0000
Subject: [PATCH] [libc++] P2165R4: Update deduction guides for map containers
and container adaptors
---
libcxx/include/__iterator/iterator_traits.h | 14 +++++++++++
.../associative/map/map.cons/deduct.pass.cpp | 20 ++++++++++++++++
.../map/map.cons/deduct.verify.cpp | 15 +++++++++++-
.../multimap/multimap.cons/deduct.pass.cpp | 21 +++++++++++++++++
.../multimap/multimap.cons/deduct.verify.cpp | 14 +++++++++++
.../flat.map/flat.map.cons/deduct.pass.cpp | 20 ++++++++++++++++
.../flat.map/flat.map.cons/deduct.verify.cpp | 14 +++++++++++
.../flat.multimap.cons/deduct.pass.cpp | 20 ++++++++++++++++
.../flat.multimap.cons/deduct.verify.cpp | 15 ++++++++++++
.../unord.map/unord.map.cnstr/deduct.pass.cpp | 23 +++++++++++++++++++
.../unord.map.cnstr/deduct.verify.cpp | 14 +++++++++++
.../unord.multimap.cnstr/deduct.pass.cpp | 21 +++++++++++++++++
.../unord.multimap.cnstr/deduct.verify.cpp | 14 +++++++++++
13 files changed, 224 insertions(+), 1 deletion(-)
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 <class _InputIterator>
using __iter_value_type _LIBCPP_NODEBUG = typename iterator_traits<_InputIterator>::value_type;
+#if _LIBCPP_STD_VER >= 23
+template <class _InputIterator>
+using __iter_key_type _LIBCPP_NODEBUG = remove_const_t<tuple_element_t<0, __iter_value_type<_InputIterator>>>;
+
+template <class _InputIterator>
+using __iter_mapped_type _LIBCPP_NODEBUG = tuple_element_t<1, __iter_value_type<_InputIterator>>;
+
+template <class _InputIterator>
+using __iter_to_alloc_type _LIBCPP_NODEBUG =
+ pair<const tuple_element_t<0, __iter_value_type<_InputIterator>>,
+ tuple_element_t<1, __iter_value_type<_InputIterator>>>;
+#else
template <class _InputIterator>
using __iter_key_type _LIBCPP_NODEBUG =
__remove_const_t<typename iterator_traits<_InputIterator>::value_type::first_type>;
@@ -477,6 +490,7 @@ template <class _InputIterator>
using __iter_to_alloc_type _LIBCPP_NODEBUG =
pair<const typename iterator_traits<_InputIterator>::value_type::first_type,
typename iterator_traits<_InputIterator>::value_type::second_type>;
+#endif // _LIBCPP_STD_VER >= 23
template <class _Iter>
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 <climits> // INT_MAX
#include <functional>
#include <map>
+#include <utility>
+#include <tuple>
#include <type_traits>
+#include <vector>
#include "deduction_guides_sfinae_checks.h"
#include "test_allocator.h"
@@ -189,6 +192,23 @@ int main(int, char**) {
static_assert(std::is_same_v<decltype(c), std::map<int, long, DefaultComp, Alloc>>);
}
}
+ {
+ std::vector<std::pair<const int, float>> 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<int, float>);
+
+ std::vector<std::tuple<int, double>> 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<int, double>);
+
+ std::vector<std::array<long, 2>> array_vec = {{100L, 101L}, {200L, 201L}, {300L, 301L}};
+ std::map m3(array_vec.begin(), array_vec.end());
+ ASSERT_SAME_TYPE(decltype(m3), std::map<long, long>);
+
+ std::vector<std::pair<int, char>> 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<int, char>);
+ }
#endif
AssociativeContainerDeductionGuidesSfinaeAway<std::map, std::map<int, long>>();
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<Key>, Allocator)
// -> map<Key, less<Key>, Allocator>;
+#include <array>
#include <climits> // INT_MAX
#include <functional>
#include <map>
+#include <tuple>
#include <type_traits>
struct NotAnAllocator {
@@ -101,6 +103,17 @@ int main(int, char**) {
std::map m(PC{1, 1L});
// expected-error-re at -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<int, double> t{1, 2.0};
+ std::map m(t);
+ // expected-error-re at -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<int, 2> arr{1, 2};
+ std::map m(arr);
+ // expected-error-re at -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 <climits> // INT_MAX
#include <functional>
#include <map>
+#include <tuple>
#include <type_traits>
+#include <utility>
+#include <vector>
#include "deduction_guides_sfinae_checks.h"
#include "test_allocator.h"
@@ -189,6 +192,24 @@ int main(int, char**) {
static_assert(std::is_same_v<decltype(c), std::multimap<int, long, DefaultComp, Alloc>>);
}
}
+ {
+ std::vector<std::pair<const int, float>> 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<int, float>);
+
+ std::vector<std::tuple<int, double>> 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<int, double>);
+
+ std::vector<std::array<long, 2>> array_vec = {{100L, 101L}, {200L, 201L}, {300L, 301L}};
+ std::multimap mm3(array_vec.begin(), array_vec.end());
+ ASSERT_SAME_TYPE(decltype(mm3), std::multimap<long, long>);
+
+ // Check deduction with non-const key in input pair
+ std::vector<std::pair<int, char>> 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<int, char>);
+ }
#endif
AssociativeContainerDeductionGuidesSfinaeAway<std::multimap, std::multimap<int, long>>();
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<Key>, Allocator)
// -> multimap<Key, less<Key>, Allocator>;
+#include <array>
#include <climits> // INT_MAX
#include <functional>
#include <map>
+#include <tuple>
#include <type_traits>
struct NotAnAllocator {
@@ -101,6 +103,18 @@ int main(int, char**) {
std::multimap m(PC{1, 1L});
// expected-error-re at -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<int, double> t{1, 2.0};
+ std::multimap m(t);
+ // expected-error-re at -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<int, 2> arr{1, 2};
+ std::multimap m(arr);
+ // expected-error-re at -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 @@
// <flat_map>
#include <algorithm>
+#include <array>
#include <cassert>
#include <climits>
#include <deque>
@@ -19,6 +20,7 @@
#include <flat_map>
#include <functional>
#include <ranges>
+#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>
@@ -335,6 +337,24 @@ int main(int, char**) {
test_from_range();
test_from_range_compare();
+#if TEST_STD_VER >= 23
+ std::vector<std::pair<const int, float>> 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<int, float>);
+
+ std::vector<std::tuple<int, double>> 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<int, double>);
+
+ std::vector<std::array<long, 2>> 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<long, long>);
+
+ std::vector<std::pair<int, char>> 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<int, char>);
+#endif
+
AssociativeContainerDeductionGuidesSfinaeAway<std::flat_map, std::flat_map<int, short>>();
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 <array>
#include <flat_map>
#include <functional>
#include <utility>
+#include <tuple>
using P = std::pair<int, long>;
using PC = std::pair<const int, long>;
@@ -50,4 +52,16 @@ void test() {
std::flat_map m(PC{1, 1L});
// expected-error-re at -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<int, double> t{1, 2.0};
+ std::flat_map m(t);
+ // expected-error-re at -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<int, 2> arr{1, 2};
+ std::flat_map m(arr);
+ // expected-error-re at -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 @@
// <flat_map>
#include <algorithm>
+#include <array>
#include <cassert>
#include <climits>
#include <deque>
@@ -325,6 +326,24 @@ void test_from_range_compare() {
}
}
+void test_tuple_like_deduction() {
+ std::vector<std::pair<const int, float>> 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<int, float>);
+
+ std::vector<std::tuple<int, double>> 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<int, double>);
+
+ std::vector<std::array<long, 2>> 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<long, long>);
+
+ std::vector<std::pair<int, char>> 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, char>);
+}
+
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<std::flat_multimap, std::flat_multimap<int, short>>();
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..316c73075fcc1 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 <array>
#include <flat_map>
#include <functional>
+#include <tuple>
#include <utility>
struct NotAnAllocator {
@@ -54,4 +56,17 @@ void test() {
std::flat_multimap m(PC{1, 1L});
// expected-error-re at -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<int, double> t{1, 2.0};
+ std::flat_multimap m(t);
+ // expected-error-re at -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<int, 2> arr{1, 2};
+ std::flat_multimap m(arr);
+ // expected-error-re at -1{{no viable constructor or deduction guide for deduction of template arguments of '{{(std::)?}}flat_multimap'}}
+ }
+ return 0;
}
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 <cassert>
#include <climits> // INT_MAX
#include <iterator>
+#include <tuple>
#include <type_traits>
#include <unordered_map>
+#include <utility>
+#include <vector>
#include "../../../test_compare.h"
#include "../../../test_hash.h"
@@ -311,6 +314,26 @@ int main(int, char**) {
static_assert(std::is_same_v<decltype(c), std::unordered_map<int, long, Hash, DefaultPred, Alloc>>);
}
}
+ {
+ std::vector<std::pair<const int, float>> 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<int, float>);
+
+ std::vector<std::tuple<int, double>> 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<int, double>);
+
+ std::vector<std::array<long, 2>> 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<long, long>);
+
+ std::vector<std::pair<int, char>> 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<int, char>);
+ }
#endif
UnorderedContainerDeductionGuidesSfinaeAway<std::unordered_map, std::unordered_map<int, long>>();
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<Key, T, Hash, equal_to<Key>, Allocator>;
+#include <array>
#include <functional>
+#include <tuple>
#include <unordered_map>
int main(int, char**) {
@@ -101,6 +103,18 @@ int main(int, char**) {
std::unordered_map m(42, std::hash<int>(), std::allocator<P>());
// expected-error-re at -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<int, double> t{1, 2.0};
+ std::unordered_map m(t);
+ // expected-error-re at -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<int, 2> arr{1, 2};
+ std::unordered_map m(arr);
+ // expected-error-re at -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 <array>
#include <cassert>
#include <climits> // INT_MAX
+#include <tuple>
#include <type_traits>
#include <unordered_map>
+#include <utility>
+#include <vector>
#include "../../../test_compare.h"
#include "../../../test_hash.h"
@@ -307,6 +310,24 @@ int main(int, char**) {
static_assert(std::is_same_v<decltype(c), std::unordered_multimap<int, long, Hash, DefaultPred, Alloc>>);
}
}
+
+ {
+ std::vector<std::pair<const int, float>> 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<int, float>);
+
+ std::vector<std::tuple<int, double>> 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<int, double>);
+
+ std::vector<std::array<long, 2>> 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<long, long>);
+
+ std::vector<std::pair<int, char>> 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<int, char>);
+ }
#endif
UnorderedContainerDeductionGuidesSfinaeAway<std::unordered_multimap, std::unordered_multimap<int, long>>();
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<Key, T, Hash, equal_to<Key>, Allocator>;
+#include <array>
#include <functional>
+#include <tuple>
#include <unordered_map>
int main(int, char**) {
@@ -101,6 +103,18 @@ int main(int, char**) {
std::unordered_multimap m(42, std::hash<int>(), std::allocator<P>());
// expected-error-re at -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<int, double> t{1, 2.0};
+ std::unordered_multimap m(t);
+ // expected-error-re at -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<int, 2> arr{1, 2};
+ std::unordered_multimap m(arr);
+ // expected-error-re at -1{{no viable constructor or deduction guide for deduction of template arguments of '{{(std::)?}}unordered_multimap'}}
+ }
return 0;
}
More information about the libcxx-commits
mailing list