Skip to content

Commit 84fad2d

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

File tree

2 files changed

+138
-0
lines changed

2 files changed

+138
-0
lines changed

libcxx/include/__iterator/iterator_traits.h

Lines changed: 15 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,19 @@ 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 =
473+
__remove_const_t<tuple_element_t<0, __iter_value_type<_InputIterator>>>;
474+
475+
template <class _InputIterator>
476+
using __iter_mapped_type _LIBCPP_NODEBUG = tuple_element_t<1, __iter_value_type<_InputIterator>>;
477+
478+
template <class _InputIterator>
479+
using __iter_to_alloc_type _LIBCPP_NODEBUG =
480+
pair<const tuple_element_t<0, __iter_value_type<_InputIterator>>,
481+
tuple_element_t<1, __iter_value_type<_InputIterator>>>;
482+
#else
469483
template <class _InputIterator>
470484
using __iter_key_type _LIBCPP_NODEBUG =
471485
__remove_const_t<typename iterator_traits<_InputIterator>::value_type::first_type>;
@@ -477,6 +491,7 @@ template <class _InputIterator>
477491
using __iter_to_alloc_type _LIBCPP_NODEBUG =
478492
pair<const typename iterator_traits<_InputIterator>::value_type::first_type,
479493
typename iterator_traits<_InputIterator>::value_type::second_type>;
494+
#endif // _LIBCPP_STD_VER >= 23
480495

481496
template <class _Iter>
482497
using __iterator_category_type _LIBCPP_NODEBUG = typename iterator_traits<_Iter>::iterator_category;
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
9+
10+
#include <array>
11+
#include <flat_map>
12+
#include <iostream>
13+
#include <map>
14+
#include <set>
15+
#include <string>
16+
#include <tuple>
17+
#include <type_traits>
18+
#include <unordered_map>
19+
#include <utility>
20+
#include <vector>
21+
22+
#include "test_macros.h"
23+
24+
int main(int, char**) {
25+
#if TEST_STD_VER >= 23
26+
// --- Input Data ---
27+
// 1. Vector of std::pair
28+
std::vector<std::pair<const int, std::string>> pair_vec = {{1, "apple"}, {2, "banana"}, {3, "cherry"}};
29+
30+
// 2. Vector of std::tuple
31+
std::vector<std::tuple<int, double>> tuple_vec = {{10, 1.1}, {20, 2.2}, {30, 3.3}};
32+
33+
// 3. Vector of std::array
34+
std::vector<std::array<long, 2>> array_vec = {{100L, 101L}, {200L, 201L}, {300L, 301L}};
35+
36+
// 4. Vector of std::pair with non-const key (for testing const addition in iter_to_alloc_type)
37+
std::vector<std::pair<int, std::string>> non_const_key_pair_vec = {{5, "grape"}, {6, "kiwi"}};
38+
39+
40+
// --- CTAD Tests ---
41+
42+
// map
43+
std::map m1(pair_vec.begin(), pair_vec.end());
44+
static_assert(std::is_same_v<decltype(m1), std::map<int, std::string>>);
45+
46+
// multimap
47+
std::multimap mm1(pair_vec.begin(), pair_vec.end());
48+
static_assert(std::is_same_v<decltype(mm1), std::multimap<int, std::string>>);
49+
50+
// unordered_map
51+
std::unordered_map um1(pair_vec.begin(), pair_vec.end());
52+
static_assert(std::is_same_v<decltype(um1), std::unordered_map<int, std::string>>);
53+
54+
// unordered_multimap
55+
std::unordered_multimap umm1(pair_vec.begin(), pair_vec.end());
56+
static_assert(std::is_same_v<decltype(umm1), std::unordered_multimap<int, std::string>>);
57+
58+
// flat_map
59+
std::flat_map fm1(pair_vec.begin(), pair_vec.end());
60+
static_assert(std::is_same_v<decltype(fm1), std::flat_map<int, std::string>>);
61+
62+
// flat_multimap
63+
std::flat_multimap fmm1(pair_vec.begin(), pair_vec.end());
64+
static_assert(std::is_same_v<decltype(fmm1), std::flat_multimap<int, std::string>>);
65+
66+
// map
67+
std::map m2(tuple_vec.begin(), tuple_vec.end());
68+
static_assert(std::is_same_v<decltype(m2), std::map<int, double>>);
69+
70+
// multimap
71+
std::multimap mm2(tuple_vec.begin(), tuple_vec.end());
72+
static_assert(std::is_same_v<decltype(mm2), std::multimap<int, double>>);
73+
74+
// unordered_map
75+
std::unordered_map um2(tuple_vec.begin(), tuple_vec.end());
76+
// Note: std::tuple needs a hash specialization to be used as a key in unordered containers.
77+
// CTAD itself should work, but compilation/runtime might fail without a hash.
78+
// This static_assert checks the deduced type. A hash specialization would be needed for actual use.
79+
static_assert(std::is_same_v<decltype(um2), std::unordered_map<int, double>>);
80+
81+
// unordered_multimap
82+
std::unordered_multimap umm2(tuple_vec.begin(), tuple_vec.end());
83+
static_assert(std::is_same_v<decltype(umm2), std::unordered_multimap<int, double>>);
84+
85+
// flat_map
86+
std::flat_map fm2(tuple_vec.begin(), tuple_vec.end());
87+
static_assert(std::is_same_v<decltype(fm2), std::flat_map<int, double>>);
88+
89+
// flat_multimap
90+
std::flat_multimap fmm2(tuple_vec.begin(), tuple_vec.end());
91+
static_assert(std::is_same_v<decltype(fmm2), std::flat_multimap<int, double>>);
92+
93+
// map
94+
std::map m3(array_vec.begin(), array_vec.end());
95+
static_assert(std::is_same_v<decltype(m3), std::map<long, long>>);
96+
97+
// multimap
98+
std::multimap mm3(array_vec.begin(), array_vec.end());
99+
static_assert(std::is_same_v<decltype(mm3), std::multimap<long, long>>);
100+
101+
// unordered_map
102+
std::unordered_map um3(array_vec.begin(), array_vec.end());
103+
// Note: std::array needs a hash specialization.
104+
static_assert(std::is_same_v<decltype(um3), std::unordered_map<long, long>>);
105+
106+
// unordered_multimap
107+
std::unordered_multimap umm3(array_vec.begin(), array_vec.end());
108+
static_assert(std::is_same_v<decltype(umm3), std::unordered_multimap<long, long>>);
109+
110+
// flat_map
111+
std::flat_map fm3(array_vec.begin(), array_vec.end());
112+
static_assert(std::is_same_v<decltype(fm3), std::flat_map<long, long>>);
113+
114+
// flat_multimap
115+
std::flat_multimap fmm3(array_vec.begin(), array_vec.end());
116+
static_assert(std::is_same_v<decltype(fmm3), std::flat_multimap<long, long>>);
117+
118+
// map
119+
std::map m4(non_const_key_pair_vec.begin(), non_const_key_pair_vec.end());
120+
static_assert(std::is_same_v<decltype(m4), std::map<int, std::string>>);
121+
#endif
122+
return 0;
123+
}

0 commit comments

Comments
 (0)