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 | // <forward_list> |
10 | |
11 | // template <class BinaryPredicate> void unique(BinaryPredicate binary_pred); // C++17 and before |
12 | // template <class BinaryPredicate> size_type unique(BinaryPredicate binary_pred); // C++20 and after |
13 | |
14 | #include <cassert> |
15 | #include <forward_list> |
16 | #include <functional> |
17 | #include <iterator> |
18 | |
19 | #include "test_macros.h" |
20 | #include "min_allocator.h" |
21 | |
22 | template <class L, class Predicate> |
23 | void do_unique(L &l, Predicate pred, typename L::size_type expected) |
24 | { |
25 | typename L::size_type old_size = std::distance(l.begin(), l.end()); |
26 | #if TEST_STD_VER > 17 |
27 | ASSERT_SAME_TYPE(decltype(l.unique(pred)), typename L::size_type); |
28 | assert(l.unique(pred) == expected); |
29 | #else |
30 | ASSERT_SAME_TYPE(decltype(l.unique(pred)), void); |
31 | l.unique(pred); |
32 | #endif |
33 | assert(old_size - std::distance(l.begin(), l.end()) == expected); |
34 | } |
35 | |
36 | |
37 | struct PredLWG526 { |
38 | PredLWG526(int i) : i_(i) {} |
39 | ~PredLWG526() { i_ = -32767; } |
40 | bool operator()(const PredLWG526& lhs, const PredLWG526& rhs) const { return lhs.i_ == rhs.i_; } |
41 | |
42 | bool operator==(int i) const { return i == i_; } |
43 | int i_; |
44 | }; |
45 | |
46 | |
47 | bool g(int x, int y) |
48 | { |
49 | return x == y; |
50 | } |
51 | |
52 | int main(int, char**) |
53 | { |
54 | { |
55 | typedef int T; |
56 | typedef std::forward_list<T> C; |
57 | const T t1[] = {0, 5, 5, 0, 0, 0, 5}; |
58 | const T t2[] = {0, 5, 0, 5}; |
59 | C c1(std::begin(arr: t1), std::end(arr: t1)); |
60 | C c2(std::begin(arr: t2), std::end(arr: t2)); |
61 | do_unique(l&: c1, pred: g, expected: 3); |
62 | assert(c1 == c2); |
63 | } |
64 | { |
65 | typedef int T; |
66 | typedef std::forward_list<T> C; |
67 | const T t1[] = {0, 0, 0, 0}; |
68 | const T t2[] = {0}; |
69 | C c1(std::begin(arr: t1), std::end(arr: t1)); |
70 | C c2(std::begin(arr: t2), std::end(arr: t2)); |
71 | do_unique(l&: c1, pred: g, expected: 3); |
72 | assert(c1 == c2); |
73 | } |
74 | { |
75 | typedef int T; |
76 | typedef std::forward_list<T> C; |
77 | const T t1[] = {5, 5, 5}; |
78 | const T t2[] = {5}; |
79 | C c1(std::begin(arr: t1), std::end(arr: t1)); |
80 | C c2(std::begin(arr: t2), std::end(arr: t2)); |
81 | do_unique(l&: c1, pred: g, expected: 2); |
82 | assert(c1 == c2); |
83 | } |
84 | { |
85 | typedef int T; |
86 | typedef std::forward_list<T> C; |
87 | C c1; |
88 | C c2; |
89 | do_unique(l&: c1, pred: g, expected: 0); |
90 | assert(c1 == c2); |
91 | } |
92 | { |
93 | typedef int T; |
94 | typedef std::forward_list<T> C; |
95 | const T t1[] = {5, 5, 5, 0}; |
96 | const T t2[] = {5, 0}; |
97 | C c1(std::begin(arr: t1), std::end(arr: t1)); |
98 | C c2(std::begin(arr: t2), std::end(arr: t2)); |
99 | do_unique(l&: c1, pred: g, expected: 2); |
100 | assert(c1 == c2); |
101 | } |
102 | |
103 | { // LWG issue #526 |
104 | int a1[] = {1, 1, 1, 2, 3, 5, 2, 11}; |
105 | int a2[] = {1, 2, 3, 5, 2, 11}; |
106 | std::forward_list<PredLWG526> c1(a1, a1 + 8); |
107 | do_unique(l&: c1, pred: std::ref(t&: c1.front()), expected: 2); |
108 | for (std::size_t i = 0; i < 6; ++i) |
109 | { |
110 | assert(!c1.empty()); |
111 | assert(c1.front() == a2[i]); |
112 | c1.pop_front(); |
113 | } |
114 | assert(c1.empty()); |
115 | } |
116 | |
117 | #if TEST_STD_VER >= 11 |
118 | { |
119 | typedef int T; |
120 | typedef std::forward_list<T, min_allocator<T>> C; |
121 | const T t1[] = {0, 5, 5, 0, 0, 0, 5}; |
122 | const T t2[] = {0, 5, 0, 5}; |
123 | C c1(std::begin(t1), std::end(t1)); |
124 | C c2(std::begin(t2), std::end(t2)); |
125 | do_unique(c1, g, 3); |
126 | assert(c1 == c2); |
127 | } |
128 | { |
129 | typedef int T; |
130 | typedef std::forward_list<T, min_allocator<T>> C; |
131 | const T t1[] = {0, 0, 0, 0}; |
132 | const T t2[] = {0}; |
133 | C c1(std::begin(t1), std::end(t1)); |
134 | C c2(std::begin(t2), std::end(t2)); |
135 | do_unique(c1, g, 3); |
136 | assert(c1 == c2); |
137 | } |
138 | { |
139 | typedef int T; |
140 | typedef std::forward_list<T, min_allocator<T>> C; |
141 | const T t1[] = {5, 5, 5}; |
142 | const T t2[] = {5}; |
143 | C c1(std::begin(t1), std::end(t1)); |
144 | C c2(std::begin(t2), std::end(t2)); |
145 | do_unique(c1, g, 2); |
146 | assert(c1 == c2); |
147 | } |
148 | { |
149 | typedef int T; |
150 | typedef std::forward_list<T, min_allocator<T>> C; |
151 | C c1; |
152 | C c2; |
153 | do_unique(c1, g, 0); |
154 | assert(c1 == c2); |
155 | } |
156 | { |
157 | typedef int T; |
158 | typedef std::forward_list<T, min_allocator<T>> C; |
159 | const T t1[] = {5, 5, 5, 0}; |
160 | const T t2[] = {5, 0}; |
161 | C c1(std::begin(t1), std::end(t1)); |
162 | C c2(std::begin(t2), std::end(t2)); |
163 | do_unique(c1, g, 2); |
164 | assert(c1 == c2); |
165 | } |
166 | #endif |
167 | |
168 | return 0; |
169 | } |
170 | |