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 | |
9 | // UNSUPPORTED: c++03 |
10 | |
11 | // <forward_list> |
12 | |
13 | // void merge(forward_list&& x); |
14 | |
15 | #include <forward_list> |
16 | #include <functional> |
17 | #include <iterator> |
18 | #include <vector> |
19 | #include <cassert> |
20 | |
21 | #include "test_macros.h" |
22 | #include "min_allocator.h" |
23 | |
24 | /// Helper for testing a stable sort. |
25 | /// |
26 | /// The relation operator uses \ref a. |
27 | /// The equality operator uses \ref a and \ref b. |
28 | struct value { |
29 | int a; |
30 | int b; |
31 | |
32 | friend bool operator<(const value& lhs, const value& rhs) { return lhs.a < rhs.a; } |
33 | friend bool operator==(const value& lhs, const value& rhs) { return lhs.a == rhs.a && lhs.b == rhs.b; } |
34 | }; |
35 | |
36 | int main(int, char**) { |
37 | { // Basic merge operation. |
38 | typedef int T; |
39 | typedef std::forward_list<T> C; |
40 | const T t1[] = {3, 5, 6, 7, 12, 13}; |
41 | const T t2[] = {0, 1, 2, 4, 8, 9, 10, 11, 14, 15}; |
42 | const T t3[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; |
43 | |
44 | C c1(std::begin(arr: t1), std::end(arr: t1)); |
45 | C c2(std::begin(arr: t2), std::end(arr: t2)); |
46 | c1.merge(list: std::move(c2)); |
47 | assert(c2.empty()); |
48 | |
49 | C c3(std::begin(arr: t3), std::end(arr: t3)); |
50 | assert(c1 == c3); |
51 | } |
52 | { // Pointers, references, and iterators should remain valid after merging. |
53 | typedef int T; |
54 | typedef std::forward_list<T> C; |
55 | typedef T* P; |
56 | typedef typename C::iterator I; |
57 | const T to[3] = {0, 1, 2}; |
58 | |
59 | C c2(std::begin(arr: to), std::end(arr: to)); |
60 | I io[3] = {c2.begin(), ++c2.begin(), ++ ++c2.begin()}; |
61 | std::reference_wrapper<T> ro[3] = {*io[0], *io[1], *io[2]}; |
62 | P po[3] = {&*io[0], &*io[1], &*io[2]}; |
63 | |
64 | C c1; |
65 | c1.merge(list: std::move(c2)); |
66 | assert(c2.empty()); |
67 | |
68 | for (std::size_t i = 0; i < 3; ++i) { |
69 | assert(to[i] == *io[i]); |
70 | assert(to[i] == ro[i].get()); |
71 | assert(to[i] == *po[i]); |
72 | } |
73 | } |
74 | { // Sorting is stable. |
75 | typedef value T; |
76 | typedef std::forward_list<T> C; |
77 | const T t1[] = {{.a: 0, .b: 0}, {.a: 2, .b: 0}, {.a: 3, .b: 0}}; |
78 | const T t2[] = {{.a: 0, .b: 1}, {.a: 1, .b: 1}, {.a: 2, .b: 1}, {.a: 4, .b: 1}}; |
79 | const T t3[] = {{.a: 0, .b: 0}, {.a: 0, .b: 1}, {.a: 1, .b: 1}, {.a: 2, .b: 0}, {.a: 2, .b: 1}, {.a: 3, .b: 0}, {.a: 4, .b: 1}}; |
80 | |
81 | C c1(std::begin(arr: t1), std::end(arr: t1)); |
82 | C c2(std::begin(arr: t2), std::end(arr: t2)); |
83 | c1.merge(list: std::move(c2)); |
84 | assert(c2.empty()); |
85 | |
86 | C c3(std::begin(arr: t3), std::end(arr: t3)); |
87 | assert(c1 == c3); |
88 | } |
89 | { // Test with a different allocator. |
90 | typedef int T; |
91 | typedef std::forward_list<T, min_allocator<T>> C; |
92 | const T t1[] = {3, 5, 6, 7, 12, 13}; |
93 | const T t2[] = {0, 1, 2, 4, 8, 9, 10, 11, 14, 15}; |
94 | const T t3[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; |
95 | |
96 | C c1(std::begin(arr: t1), std::end(arr: t1)); |
97 | C c2(std::begin(arr: t2), std::end(arr: t2)); |
98 | c1.merge(std::move(c2)); |
99 | assert(c2.empty()); |
100 | |
101 | C c3(std::begin(arr: t3), std::end(arr: t3)); |
102 | assert(c1 == c3); |
103 | } |
104 | |
105 | return 0; |
106 | } |
107 | |