1*c3648f37Svarconst //===----------------------------------------------------------------------===//
2*c3648f37Svarconst //
3*c3648f37Svarconst // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*c3648f37Svarconst // See https://llvm.org/LICENSE.txt for license information.
5*c3648f37Svarconst // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*c3648f37Svarconst //
7*c3648f37Svarconst //===----------------------------------------------------------------------===//
8*c3648f37Svarconst
9*c3648f37Svarconst // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
10*c3648f37Svarconst
11*c3648f37Svarconst // Test that `ranges::to` can be used to convert between arbitrary standard containers.
12*c3648f37Svarconst
13*c3648f37Svarconst #include <ranges>
14*c3648f37Svarconst
15*c3648f37Svarconst #include <algorithm>
16*c3648f37Svarconst #include <cassert>
17*c3648f37Svarconst #include <deque>
18*c3648f37Svarconst #include <forward_list>
19*c3648f37Svarconst #include <list>
20*c3648f37Svarconst #include <map>
21*c3648f37Svarconst #include <queue>
22*c3648f37Svarconst #include <set>
23*c3648f37Svarconst #include <stack>
24*c3648f37Svarconst #include <string>
25*c3648f37Svarconst #include <unordered_map>
26*c3648f37Svarconst #include <unordered_set>
27*c3648f37Svarconst #include <vector>
28*c3648f37Svarconst
29*c3648f37Svarconst #include "test_iterators.h"
30*c3648f37Svarconst #include "test_range.h"
31*c3648f37Svarconst #include "type_algorithms.h"
32*c3648f37Svarconst #include "unwrap_container_adaptor.h"
33*c3648f37Svarconst
34*c3648f37Svarconst std::vector<std::vector<int>> ints = {
35*c3648f37Svarconst {5, 1, 3, 4, 2},
36*c3648f37Svarconst {3},
37*c3648f37Svarconst {}
38*c3648f37Svarconst };
39*c3648f37Svarconst
40*c3648f37Svarconst std::vector<std::vector<char>> chars = {
41*c3648f37Svarconst {'a', 'b', 'c'},
42*c3648f37Svarconst {'a'},
43*c3648f37Svarconst {}
44*c3648f37Svarconst };
45*c3648f37Svarconst
46*c3648f37Svarconst std::vector<std::vector<std::pair<const int, int>>> pairs = {
47*c3648f37Svarconst {{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 0}},
48*c3648f37Svarconst {{1, 2}},
49*c3648f37Svarconst {}
50*c3648f37Svarconst };
51*c3648f37Svarconst
52*c3648f37Svarconst template <class From, class To>
test_is_equal(std::vector<std::vector<typename From::value_type>> inputs)53*c3648f37Svarconst void test_is_equal(std::vector<std::vector<typename From::value_type>> inputs) {
54*c3648f37Svarconst for (const auto& in : inputs) {
55*c3648f37Svarconst From from(in.begin(), in.end());
56*c3648f37Svarconst std::same_as<To> decltype(auto) result = std::ranges::to<To>(from);
57*c3648f37Svarconst assert(std::ranges::equal(in, result));
58*c3648f37Svarconst }
59*c3648f37Svarconst }
60*c3648f37Svarconst
61*c3648f37Svarconst template <class From, class To>
test_is_permutation(std::vector<std::vector<typename From::value_type>> inputs)62*c3648f37Svarconst void test_is_permutation(std::vector<std::vector<typename From::value_type>> inputs) {
63*c3648f37Svarconst for (const auto& in : inputs) {
64*c3648f37Svarconst From from(in.begin(), in.end());
65*c3648f37Svarconst std::same_as<To> decltype(auto) result = std::ranges::to<To>(in);
66*c3648f37Svarconst assert(std::ranges::is_permutation(in, result));
67*c3648f37Svarconst }
68*c3648f37Svarconst }
69*c3648f37Svarconst
70*c3648f37Svarconst template <class From, class To>
test_is_equal_for_adaptors(std::vector<std::vector<typename From::value_type>> inputs)71*c3648f37Svarconst void test_is_equal_for_adaptors(std::vector<std::vector<typename From::value_type>> inputs) {
72*c3648f37Svarconst for (const auto& in : inputs) {
73*c3648f37Svarconst From from(in.begin(), in.end());
74*c3648f37Svarconst std::same_as<To> decltype(auto) result = std::ranges::to<To>(in);
75*c3648f37Svarconst
76*c3648f37Svarconst UnwrapAdaptor<From> unwrap_from(std::move(from));
77*c3648f37Svarconst UnwrapAdaptor<To> unwrap_to(std::move(result));
78*c3648f37Svarconst assert(std::ranges::is_permutation(unwrap_from.get_container(), unwrap_to.get_container()));
79*c3648f37Svarconst }
80*c3648f37Svarconst }
81*c3648f37Svarconst
82*c3648f37Svarconst template <class T>
83*c3648f37Svarconst using sequence_containers = types::type_list<
84*c3648f37Svarconst std::vector<T>,
85*c3648f37Svarconst std::deque<T>,
86*c3648f37Svarconst std::list<T>,
87*c3648f37Svarconst std::forward_list<T>
88*c3648f37Svarconst >;
89*c3648f37Svarconst
90*c3648f37Svarconst template <class T>
91*c3648f37Svarconst using associative_sets = types::type_list<
92*c3648f37Svarconst std::set<T>,
93*c3648f37Svarconst std::multiset<T>
94*c3648f37Svarconst >;
95*c3648f37Svarconst
96*c3648f37Svarconst template <class K, class V>
97*c3648f37Svarconst using associative_maps = types::type_list<
98*c3648f37Svarconst std::map<K, V>,
99*c3648f37Svarconst std::multimap<K, V>
100*c3648f37Svarconst >;
101*c3648f37Svarconst
102*c3648f37Svarconst template <class T>
103*c3648f37Svarconst using unordered_sets = types::type_list<
104*c3648f37Svarconst std::unordered_set<T>,
105*c3648f37Svarconst std::unordered_multiset<T>
106*c3648f37Svarconst >;
107*c3648f37Svarconst
108*c3648f37Svarconst template <class K, class V>
109*c3648f37Svarconst using unordered_maps = types::type_list<
110*c3648f37Svarconst std::unordered_map<K, V>,
111*c3648f37Svarconst std::unordered_multimap<K, V>
112*c3648f37Svarconst >;
113*c3648f37Svarconst
114*c3648f37Svarconst template <class T>
115*c3648f37Svarconst using container_adaptors = types::type_list<
116*c3648f37Svarconst std::stack<T>,
117*c3648f37Svarconst std::queue<T>,
118*c3648f37Svarconst std::priority_queue<T>
119*c3648f37Svarconst >;
120*c3648f37Svarconst
121*c3648f37Svarconst template <class T>
122*c3648f37Svarconst using sequences_and_sets = types::concatenate_t<sequence_containers<T>, associative_sets<T>, unordered_sets<T>>;
123*c3648f37Svarconst
124*c3648f37Svarconst template <class K, class V>
125*c3648f37Svarconst using all_containers = types::concatenate_t<
126*c3648f37Svarconst sequence_containers<std::pair<const K, V>>,
127*c3648f37Svarconst associative_sets<std::pair<const K, V>>,
128*c3648f37Svarconst associative_maps<K, V>,
129*c3648f37Svarconst unordered_sets<std::pair<const K, V>>,
130*c3648f37Svarconst unordered_maps<K, V>>;
131*c3648f37Svarconst
132*c3648f37Svarconst // This is necessary to be able to use `pair`s with unordered sets.
133*c3648f37Svarconst template <class K, class V>
134*c3648f37Svarconst struct std::hash<std::pair<const K, V>> {
operator ()std::hash135*c3648f37Svarconst std::size_t operator()(const std::pair<const K, V>& p) const {
136*c3648f37Svarconst std::size_t h1 = std::hash<K>{}(p.first);
137*c3648f37Svarconst std::size_t h2 = std::hash<V>{}(p.second);
138*c3648f37Svarconst return h1 ^ (h2 << 1);
139*c3648f37Svarconst }
140*c3648f37Svarconst };
141*c3648f37Svarconst
test()142*c3648f37Svarconst void test() {
143*c3648f37Svarconst { // Conversions always preserving equality.
144*c3648f37Svarconst { // sequences <-> sequences
145*c3648f37Svarconst types::for_each(sequence_containers<int>{}, []<class From>() {
146*c3648f37Svarconst types::for_each(sequence_containers<int>{}, []<class To>() {
147*c3648f37Svarconst test_is_equal<From, To>(ints);
148*c3648f37Svarconst });
149*c3648f37Svarconst });
150*c3648f37Svarconst
151*c3648f37Svarconst types::for_each(sequence_containers<int>{}, []<class From>() {
152*c3648f37Svarconst types::for_each(sequence_containers<double>{}, []<class To>() {
153*c3648f37Svarconst test_is_equal<From, To>(ints);
154*c3648f37Svarconst });
155*c3648f37Svarconst });
156*c3648f37Svarconst }
157*c3648f37Svarconst
158*c3648f37Svarconst { // sequences <-> string
159*c3648f37Svarconst types::for_each(sequence_containers<char>{}, []<class Seq>() {
160*c3648f37Svarconst test_is_equal<Seq, std::basic_string<char>>(chars);
161*c3648f37Svarconst test_is_equal<std::basic_string<char>, Seq>(chars);
162*c3648f37Svarconst });
163*c3648f37Svarconst }
164*c3648f37Svarconst }
165*c3648f37Svarconst
166*c3648f37Svarconst { // sequences/sets <-> sequences/sets
167*c3648f37Svarconst types::for_each(sequences_and_sets<int>{}, []<class From>() {
168*c3648f37Svarconst types::for_each(sequences_and_sets<int>{}, []<class To>() {
169*c3648f37Svarconst test_is_permutation<From, To>(ints);
170*c3648f37Svarconst });
171*c3648f37Svarconst });
172*c3648f37Svarconst
173*c3648f37Svarconst types::for_each(sequences_and_sets<int>{}, []<class From>() {
174*c3648f37Svarconst types::for_each(sequences_and_sets<double>{}, []<class To>() {
175*c3648f37Svarconst test_is_permutation<From, To>(ints);
176*c3648f37Svarconst });
177*c3648f37Svarconst });
178*c3648f37Svarconst }
179*c3648f37Svarconst
180*c3648f37Svarconst { // sequences/sets/maps <-> sequences/sets/maps. Uses `pair` for non-map containers to allow mutual conversion with
181*c3648f37Svarconst // map types.
182*c3648f37Svarconst types::for_each(all_containers<int, int>{}, []<class From>() {
183*c3648f37Svarconst types::for_each(all_containers<int, int>{}, []<class To>() {
184*c3648f37Svarconst test_is_permutation<From, To>(pairs);
185*c3648f37Svarconst });
186*c3648f37Svarconst });
187*c3648f37Svarconst
188*c3648f37Svarconst types::for_each(all_containers<int, int>{}, []<class From>() {
189*c3648f37Svarconst types::for_each(all_containers<long, double>{}, []<class To>() {
190*c3648f37Svarconst test_is_permutation<From, To>(pairs);
191*c3648f37Svarconst });
192*c3648f37Svarconst });
193*c3648f37Svarconst }
194*c3648f37Svarconst
195*c3648f37Svarconst { // adaptors <-> adaptors
196*c3648f37Svarconst types::for_each(container_adaptors<int>{}, []<class From>() {
197*c3648f37Svarconst types::for_each(container_adaptors<int>{}, []<class To>() {
198*c3648f37Svarconst test_is_equal_for_adaptors<From, To>(ints);
199*c3648f37Svarconst });
200*c3648f37Svarconst });
201*c3648f37Svarconst
202*c3648f37Svarconst types::for_each(container_adaptors<int>{}, []<class From>() {
203*c3648f37Svarconst types::for_each(container_adaptors<double>{}, []<class To>() {
204*c3648f37Svarconst test_is_equal_for_adaptors<From, To>(ints);
205*c3648f37Svarconst });
206*c3648f37Svarconst });
207*c3648f37Svarconst }
208*c3648f37Svarconst }
209*c3648f37Svarconst
main(int,char **)210*c3648f37Svarconst int main(int, char**) {
211*c3648f37Svarconst test();
212*c3648f37Svarconst
213*c3648f37Svarconst return 0;
214*c3648f37Svarconst }
215