Skip to content

Commit 9bb102a

Browse files
committed
[libc++] P2165R4: Update deduction guides for map containers and container adaptors
1 parent 51fa6cd commit 9bb102a

File tree

13 files changed

+224
-1
lines changed

13 files changed

+224
-1
lines changed

libcxx/include/__iterator/iterator_traits.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <__fwd/pair.h>
2323
#include <__iterator/incrementable_traits.h>
2424
#include <__iterator/readable_traits.h>
25+
#include <__tuple/tuple_element.h>
2526
#include <__type_traits/common_reference.h>
2627
#include <__type_traits/conditional.h>
2728
#include <__type_traits/detected_or.h>
@@ -466,6 +467,18 @@ using __has_exactly_bidirectional_iterator_category _LIBCPP_NODEBUG =
466467
template <class _InputIterator>
467468
using __iter_value_type _LIBCPP_NODEBUG = typename iterator_traits<_InputIterator>::value_type;
468469

470+
#if _LIBCPP_STD_VER >= 23
471+
template <class _InputIterator>
472+
using __iter_key_type _LIBCPP_NODEBUG = remove_const_t<tuple_element_t<0, __iter_value_type<_InputIterator>>>;
473+
474+
template <class _InputIterator>
475+
using __iter_mapped_type _LIBCPP_NODEBUG = tuple_element_t<1, __iter_value_type<_InputIterator>>;
476+
477+
template <class _InputIterator>
478+
using __iter_to_alloc_type _LIBCPP_NODEBUG =
479+
pair<const tuple_element_t<0, __iter_value_type<_InputIterator>>,
480+
tuple_element_t<1, __iter_value_type<_InputIterator>>>;
481+
#else
469482
template <class _InputIterator>
470483
using __iter_key_type _LIBCPP_NODEBUG =
471484
__remove_const_t<typename iterator_traits<_InputIterator>::value_type::first_type>;
@@ -477,6 +490,7 @@ template <class _InputIterator>
477490
using __iter_to_alloc_type _LIBCPP_NODEBUG =
478491
pair<const typename iterator_traits<_InputIterator>::value_type::first_type,
479492
typename iterator_traits<_InputIterator>::value_type::second_type>;
493+
#endif // _LIBCPP_STD_VER >= 23
480494

481495
template <class _Iter>
482496
using __iterator_category_type _LIBCPP_NODEBUG = typename iterator_traits<_Iter>::iterator_category;

libcxx/test/std/containers/associative/map/map.cons/deduct.pass.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@
4040
#include <climits> // INT_MAX
4141
#include <functional>
4242
#include <map>
43+
#include <utility>
44+
#include <tuple>
4345
#include <type_traits>
46+
#include <vector>
4447

4548
#include "deduction_guides_sfinae_checks.h"
4649
#include "test_allocator.h"
@@ -189,6 +192,23 @@ int main(int, char**) {
189192
static_assert(std::is_same_v<decltype(c), std::map<int, long, DefaultComp, Alloc>>);
190193
}
191194
}
195+
{
196+
std::vector<std::pair<const int, float>> pair_vec = {{1, 1.1f}, {2, 2.2f}, {3, 3.3f}};
197+
std::map m1(pair_vec.begin(), pair_vec.end());
198+
ASSERT_SAME_TYPE(decltype(m1), std::map<int, float>);
199+
200+
std::vector<std::tuple<int, double>> tuple_vec = {{10, 1.1}, {20, 2.2}, {30, 3.3}};
201+
std::map m2(tuple_vec.begin(), tuple_vec.end());
202+
ASSERT_SAME_TYPE(decltype(m2), std::map<int, double>);
203+
204+
std::vector<std::array<long, 2>> array_vec = {{100L, 101L}, {200L, 201L}, {300L, 301L}};
205+
std::map m3(array_vec.begin(), array_vec.end());
206+
ASSERT_SAME_TYPE(decltype(m3), std::map<long, long>);
207+
208+
std::vector<std::pair<int, char>> non_const_key_pair_vec = {{5, 'a'}, {6, 'b'}};
209+
std::map m4(non_const_key_pair_vec.begin(), non_const_key_pair_vec.end());
210+
ASSERT_SAME_TYPE(decltype(m4), std::map<int, char>);
211+
}
192212
#endif
193213

194214
AssociativeContainerDeductionGuidesSfinaeAway<std::map, std::map<int, long>>();

libcxx/test/std/containers/associative/map/map.cons/deduct.verify.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@
2626
// map(initializer_list<Key>, Allocator)
2727
// -> map<Key, less<Key>, Allocator>;
2828

29+
#include <array>
2930
#include <climits> // INT_MAX
3031
#include <functional>
3132
#include <map>
33+
#include <tuple>
3234
#include <type_traits>
3335

3436
struct NotAnAllocator {
@@ -101,6 +103,18 @@ int main(int, char**) {
101103
std::map m(PC{1, 1L});
102104
// expected-error-re@-1{{no viable constructor or deduction guide for deduction of template arguments of '{{(std::)?}}map'}}
103105
}
104-
106+
{
107+
// cannot deduce from tuple-like objects without proper iterator
108+
std::tuple<int, double> t{1, 2.0};
109+
std::map m(t);
110+
// expected-error-re@-1{{no viable constructor or deduction guide for deduction of template arguments of '{{(std::)?}}map'}}
111+
}
112+
{
113+
// cannot deduce from array-like objects without proper iterator
114+
std::array<int, 2> arr{1, 2};
115+
std::map m(arr);
116+
// expected-error-re@-1{{no viable constructor or deduction guide for deduction of template arguments of '{{(std::)?}}map'}}
117+
}
118+
105119
return 0;
106120
}

libcxx/test/std/containers/associative/multimap/multimap.cons/deduct.pass.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@
4040
#include <climits> // INT_MAX
4141
#include <functional>
4242
#include <map>
43+
#include <tuple>
4344
#include <type_traits>
45+
#include <utility>
46+
#include <vector>
4447

4548
#include "deduction_guides_sfinae_checks.h"
4649
#include "test_allocator.h"
@@ -189,6 +192,24 @@ int main(int, char**) {
189192
static_assert(std::is_same_v<decltype(c), std::multimap<int, long, DefaultComp, Alloc>>);
190193
}
191194
}
195+
{
196+
std::vector<std::pair<const int, float>> pair_vec = {{1, 1.1f}, {2, 2.2f}, {3, 3.3f}};
197+
std::multimap mm1(pair_vec.begin(), pair_vec.end());
198+
ASSERT_SAME_TYPE(decltype(mm1), std::multimap<int, float>);
199+
200+
std::vector<std::tuple<int, double>> tuple_vec = {{10, 1.1}, {20, 2.2}, {30, 3.3}};
201+
std::multimap mm2(tuple_vec.begin(), tuple_vec.end());
202+
ASSERT_SAME_TYPE(decltype(mm2), std::multimap<int, double>);
203+
204+
std::vector<std::array<long, 2>> array_vec = {{100L, 101L}, {200L, 201L}, {300L, 301L}};
205+
std::multimap mm3(array_vec.begin(), array_vec.end());
206+
ASSERT_SAME_TYPE(decltype(mm3), std::multimap<long, long>);
207+
208+
// Check deduction with non-const key in input pair
209+
std::vector<std::pair<int, char>> non_const_key_pair_vec = {{5, 'a'}, {6, 'b'}};
210+
std::multimap mm4(non_const_key_pair_vec.begin(), non_const_key_pair_vec.end());
211+
ASSERT_SAME_TYPE(decltype(mm4), std::multimap<int, char>);
212+
}
192213
#endif
193214

194215
AssociativeContainerDeductionGuidesSfinaeAway<std::multimap, std::multimap<int, long>>();

libcxx/test/std/containers/associative/multimap/multimap.cons/deduct.verify.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@
2626
// multimap(initializer_list<Key>, Allocator)
2727
// -> multimap<Key, less<Key>, Allocator>;
2828

29+
#include <array>
2930
#include <climits> // INT_MAX
3031
#include <functional>
3132
#include <map>
33+
#include <tuple>
3234
#include <type_traits>
3335

3436
struct NotAnAllocator {
@@ -101,6 +103,18 @@ int main(int, char**) {
101103
std::multimap m(PC{1, 1L});
102104
// expected-error-re@-1{{no viable constructor or deduction guide for deduction of template arguments of '{{(std::)?}}multimap'}}
103105
}
106+
{
107+
// cannot deduce from tuple-like objects without proper iterator
108+
std::tuple<int, double> t{1, 2.0};
109+
std::multimap m(t);
110+
// expected-error-re@-1{{no viable constructor or deduction guide for deduction of template arguments of '{{(std::)?}}multimap'}}
111+
}
112+
{
113+
// cannot deduce from array-like objects without proper iterator
114+
std::array<int, 2> arr{1, 2};
115+
std::multimap m(arr);
116+
// expected-error-re@-1{{no viable constructor or deduction guide for deduction of template arguments of '{{(std::)?}}multimap'}}
117+
}
104118

105119
return 0;
106120
}

libcxx/test/std/containers/container.adaptors/flat.map/flat.map.cons/deduct.pass.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
// <flat_map>
1212

1313
#include <algorithm>
14+
#include <array>
1415
#include <cassert>
1516
#include <climits>
1617
#include <deque>
@@ -19,6 +20,7 @@
1920
#include <flat_map>
2021
#include <functional>
2122
#include <ranges>
23+
#include <tuple>
2224
#include <type_traits>
2325
#include <utility>
2426
#include <vector>
@@ -335,6 +337,24 @@ int main(int, char**) {
335337
test_from_range();
336338
test_from_range_compare();
337339

340+
#if TEST_STD_VER >= 23
341+
std::vector<std::pair<const int, float>> pair_vec = {{1, 1.1f}, {2, 2.2f}, {3, 3.3f}};
342+
std::flat_map fm1(pair_vec.begin(), pair_vec.end());
343+
ASSERT_SAME_TYPE(decltype(fm1), std::flat_map<int, float>);
344+
345+
std::vector<std::tuple<int, double>> tuple_vec = {{10, 1.1}, {20, 2.2}, {30, 3.3}};
346+
std::flat_map fm2(tuple_vec.begin(), tuple_vec.end());
347+
ASSERT_SAME_TYPE(decltype(fm2), std::flat_map<int, double>);
348+
349+
std::vector<std::array<long, 2>> array_vec = {{100L, 101L}, {200L, 201L}, {300L, 301L}};
350+
std::flat_map fm3(array_vec.begin(), array_vec.end());
351+
ASSERT_SAME_TYPE(decltype(fm3), std::flat_map<long, long>);
352+
353+
std::vector<std::pair<int, char>> non_const_key_pair_vec = {{5, 'a'}, {6, 'b'}};
354+
std::flat_map fm4(non_const_key_pair_vec.begin(), non_const_key_pair_vec.end());
355+
ASSERT_SAME_TYPE(decltype(fm4), std::flat_map<int, char>);
356+
#endif
357+
338358
AssociativeContainerDeductionGuidesSfinaeAway<std::flat_map, std::flat_map<int, short>>();
339359

340360
return 0;

libcxx/test/std/containers/container.adaptors/flat.map/flat.map.cons/deduct.verify.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212

1313
// Test CTAD on cases where deduction should fail.
1414

15+
#include <array>
1516
#include <flat_map>
1617
#include <functional>
1718
#include <utility>
19+
#include <tuple>
1820

1921
using P = std::pair<int, long>;
2022
using PC = std::pair<const int, long>;
@@ -50,4 +52,16 @@ void test() {
5052
std::flat_map m(PC{1, 1L});
5153
// expected-error-re@-1{{{{no viable constructor or deduction guide for deduction of template arguments of '.*flat_map'}}}}
5254
}
55+
{
56+
// cannot deduce from tuple-like objects without proper iterator
57+
std::tuple<int, double> t{1, 2.0};
58+
std::flat_map m(t);
59+
// expected-error-re@-1{{no viable constructor or deduction guide for deduction of template arguments of '{{(std::)?}}flat_map'}}
60+
}
61+
{
62+
// cannot deduce from array-like objects without proper iterator
63+
std::array<int, 2> arr{1, 2};
64+
std::flat_map m(arr);
65+
// expected-error-re@-1{{no viable constructor or deduction guide for deduction of template arguments of '{{(std::)?}}flat_map'}}
66+
}
5367
}

libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/deduct.pass.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
// <flat_map>
1212

1313
#include <algorithm>
14+
#include <array>
1415
#include <cassert>
1516
#include <climits>
1617
#include <deque>
@@ -325,6 +326,24 @@ void test_from_range_compare() {
325326
}
326327
}
327328

329+
void test_tuple_like_deduction() {
330+
std::vector<std::pair<const int, float>> pair_vec = {{1, 1.1f}, {2, 2.2f}, {3, 3.3f}};
331+
std::flat_multimap fmm1(pair_vec.begin(), pair_vec.end());
332+
ASSERT_SAME_TYPE(decltype(fmm1), std::flat_multimap<int, float>);
333+
334+
std::vector<std::tuple<int, double>> tuple_vec = {{10, 1.1}, {20, 2.2}, {30, 3.3}};
335+
std::flat_multimap fmm2(tuple_vec.begin(), tuple_vec.end());
336+
ASSERT_SAME_TYPE(decltype(fmm2), std::flat_multimap<int, double>);
337+
338+
std::vector<std::array<long, 2>> array_vec = {{100L, 101L}, {200L, 201L}, {300L, 301L}};
339+
std::flat_multimap fmm3(array_vec.begin(), array_vec.end());
340+
ASSERT_SAME_TYPE(decltype(fmm3), std::flat_multimap<long, long>);
341+
342+
std::vector<std::pair<int, char>> non_const_key_pair_vec = {{5, 'a'}, {6, 'b'}};
343+
std::flat_multimap fmm4(non_const_key_pair_vec.begin(), non_const_key_pair_vec.end());
344+
ASSERT_SAME_TYPE(decltype(fmm4), std::flat_multimap<int, char>);
345+
}
346+
328347
int main(int, char**) {
329348
// Each test function also tests the sorted_equivalent-prefixed and allocator-suffixed overloads.
330349
test_copy();
@@ -336,6 +355,7 @@ int main(int, char**) {
336355
test_initializer_list_compare();
337356
test_from_range();
338357
test_from_range_compare();
358+
test_tuple_like_deduction();
339359

340360
AssociativeContainerDeductionGuidesSfinaeAway<std::flat_multimap, std::flat_multimap<int, short>>();
341361

libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/deduct.verify.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@
1212

1313
// Test CTAD on cases where deduction should fail.
1414

15+
#include <array>
1516
#include <flat_map>
1617
#include <functional>
18+
#include <tuple>
1719
#include <utility>
1820

1921
struct NotAnAllocator {
@@ -54,4 +56,16 @@ void test() {
5456
std::flat_multimap m(PC{1, 1L});
5557
// expected-error-re@-1{{{{no viable constructor or deduction guide for deduction of template arguments of '.*flat_multimap'}}}}
5658
}
59+
{
60+
// cannot deduce from tuple-like objects without proper iterator
61+
std::tuple<int, double> t{1, 2.0};
62+
std::flat_multimap m(t);
63+
// expected-error-re@-1{{no viable constructor or deduction guide for deduction of template arguments of '{{(std::)?}}flat_multimap'}}
64+
}
65+
{
66+
// cannot deduce from array-like objects without proper iterator
67+
std::array<int, 2> arr{1, 2};
68+
std::flat_multimap m(arr);
69+
// expected-error-re@-1{{no viable constructor or deduction guide for deduction of template arguments of '{{(std::)?}}flat_multimap'}}
70+
}
5771
}

libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/deduct.pass.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,11 @@
8282
#include <cassert>
8383
#include <climits> // INT_MAX
8484
#include <iterator>
85+
#include <tuple>
8586
#include <type_traits>
8687
#include <unordered_map>
88+
#include <utility>
89+
#include <vector>
8790

8891
#include "../../../test_compare.h"
8992
#include "../../../test_hash.h"
@@ -311,6 +314,26 @@ int main(int, char**) {
311314
static_assert(std::is_same_v<decltype(c), std::unordered_map<int, long, Hash, DefaultPred, Alloc>>);
312315
}
313316
}
317+
{
318+
std::vector<std::pair<const int, float>> pair_vec = {{1, 1.1f}, {2, 2.2f}, {3, 3.3f}};
319+
std::unordered_map um1(pair_vec.begin(), pair_vec.end());
320+
ASSERT_SAME_TYPE(decltype(um1), std::unordered_map<int, float>);
321+
322+
std::vector<std::tuple<int, double>> tuple_vec = {{10, 1.1}, {20, 2.2}, {30, 3.3}};
323+
// Note: std::tuple needs a hash specialization to be used as a key in unordered containers.
324+
// This static_assert only checks the deduced type.
325+
std::unordered_map um2(tuple_vec.begin(), tuple_vec.end());
326+
ASSERT_SAME_TYPE(decltype(um2), std::unordered_map<int, double>);
327+
328+
std::vector<std::array<long, 2>> array_vec = {{100L, 101L}, {200L, 201L}, {300L, 301L}};
329+
// Note: std::array needs a hash specialization.
330+
std::unordered_map um3(array_vec.begin(), array_vec.end());
331+
ASSERT_SAME_TYPE(decltype(um3), std::unordered_map<long, long>);
332+
333+
std::vector<std::pair<int, char>> non_const_key_pair_vec = {{5, 'a'}, {6, 'b'}};
334+
std::unordered_map um4(non_const_key_pair_vec.begin(), non_const_key_pair_vec.end());
335+
ASSERT_SAME_TYPE(decltype(um4), std::unordered_map<int, char>);
336+
}
314337
#endif
315338

316339
UnorderedContainerDeductionGuidesSfinaeAway<std::unordered_map, std::unordered_map<int, long>>();

libcxx/test/std/containers/unord/unord.map/unord.map.cnstr/deduct.verify.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@
5656
// Allocator)
5757
// -> unordered_map<Key, T, Hash, equal_to<Key>, Allocator>;
5858

59+
#include <array>
5960
#include <functional>
61+
#include <tuple>
6062
#include <unordered_map>
6163

6264
int main(int, char**) {
@@ -101,6 +103,18 @@ int main(int, char**) {
101103
std::unordered_map m(42, std::hash<int>(), std::allocator<P>());
102104
// expected-error-re@-1{{no viable constructor or deduction guide for deduction of template arguments of '{{(std::)?}}unordered_map'}}
103105
}
106+
{
107+
// cannot deduce from tuple-like objects without proper iterator
108+
std::tuple<int, double> t{1, 2.0};
109+
std::unordered_map m(t);
110+
// expected-error-re@-1{{no viable constructor or deduction guide for deduction of template arguments of '{{(std::)?}}unordered_map'}}
111+
}
112+
{
113+
// cannot deduce from array-like objects without proper iterator
114+
std::array<int, 2> arr{1, 2};
115+
std::unordered_map m(arr);
116+
// expected-error-re@-1{{no viable constructor or deduction guide for deduction of template arguments of '{{(std::)?}}unordered_map'}}
117+
}
104118

105119
return 0;
106120
}

0 commit comments

Comments
 (0)