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// void remove(const value_type& v); // C++17 and before
12// size_type remove(const value_type& v); // C++20 and after; // constexpr since C++26
13
14#include <forward_list>
15#include <iterator>
16#include <cassert>
17
18#include "test_macros.h"
19#include "min_allocator.h"
20
21template <class L>
22TEST_CONSTEXPR_CXX26 void do_remove(L& l, const typename L::value_type& value, typename L::size_type expected) {
23 typename L::size_type old_size = std::distance(l.begin(), l.end());
24#if TEST_STD_VER > 17
25 ASSERT_SAME_TYPE(decltype(l.remove(value)), typename L::size_type);
26 assert(l.remove(value) == expected);
27#else
28 ASSERT_SAME_TYPE(decltype(l.remove(value)), void);
29 l.remove(value);
30#endif
31 assert(old_size - std::distance(l.begin(), l.end()) == expected);
32}
33
34struct S {
35 TEST_CONSTEXPR_CXX20 S(int i) : i_(new int(i)) {}
36 TEST_CONSTEXPR_CXX20 S(const S& rhs) : i_(new int(*rhs.i_)) {}
37 TEST_CONSTEXPR_CXX20 S& operator=(const S& rhs) {
38 *i_ = *rhs.i_;
39 return *this;
40 }
41 TEST_CONSTEXPR_CXX20 ~S() {
42 delete i_;
43 i_ = NULL;
44 }
45 TEST_CONSTEXPR bool operator==(const S& rhs) const { return *i_ == *rhs.i_; }
46 TEST_CONSTEXPR int get() const { return *i_; }
47 int* i_;
48};
49
50TEST_CONSTEXPR_CXX26 bool test() {
51 {
52 typedef int T;
53 typedef std::forward_list<T> C;
54 const T t1[] = {0, 5, 5, 0, 0, 0, 5};
55 const T t2[] = {5, 5, 5};
56 C c1(std::begin(arr: t1), std::end(arr: t1));
57 C c2(std::begin(arr: t2), std::end(arr: t2));
58 do_remove(c1, 0, 4);
59 assert(c1 == c2);
60 }
61 {
62 typedef int T;
63 typedef std::forward_list<T> C;
64 const T t1[] = {0, 0, 0, 0};
65 C c1(std::begin(arr: t1), std::end(arr: t1));
66 C c2;
67 do_remove(c1, 0, 4);
68 assert(c1 == c2);
69 }
70 {
71 typedef int T;
72 typedef std::forward_list<T> C;
73 const T t1[] = {5, 5, 5};
74 const T t2[] = {5, 5, 5};
75 C c1(std::begin(arr: t1), std::end(arr: t1));
76 C c2(std::begin(arr: t2), std::end(arr: t2));
77 do_remove(c1, 0, 0);
78 assert(c1 == c2);
79 }
80 {
81 typedef int T;
82 typedef std::forward_list<T> C;
83 C c1;
84 C c2;
85 do_remove(c1, 0, 0);
86 assert(c1 == c2);
87 }
88 {
89 typedef int T;
90 typedef std::forward_list<T> C;
91 const T t1[] = {5, 5, 5, 0};
92 const T t2[] = {5, 5, 5};
93 C c1(std::begin(arr: t1), std::end(arr: t1));
94 C c2(std::begin(arr: t2), std::end(arr: t2));
95 do_remove(c1, 0, 1);
96 assert(c1 == c2);
97 }
98 { // LWG issue #526
99 typedef int T;
100 typedef std::forward_list<T> C;
101 int t1[] = {1, 2, 1, 3, 5, 8, 11};
102 int t2[] = {2, 3, 5, 8, 11};
103 C c1(std::begin(arr&: t1), std::end(arr&: t1));
104 C c2(std::begin(arr&: t2), std::end(arr&: t2));
105 do_remove(c1, c1.front(), 2);
106 assert(c1 == c2);
107 }
108 {
109 typedef S T;
110 typedef std::forward_list<T> C;
111 int t1[] = {1, 2, 1, 3, 5, 8, 11, 1};
112 int t2[] = {2, 3, 5, 8, 11};
113 C c;
114 for (int* ip = std::end(arr&: t1); ip != std::begin(arr&: t1);)
115 c.push_front(val: S(*--ip));
116 do_remove(c, c.front(), 3);
117 C::const_iterator it = c.begin();
118 for (int* ip = std::begin(arr&: t2); ip != std::end(arr&: t2); ++ip, ++it) {
119 assert(it != c.end());
120 assert(*ip == it->get());
121 }
122 assert(it == c.end());
123 }
124#if TEST_STD_VER >= 11
125 {
126 typedef int T;
127 typedef std::forward_list<T, min_allocator<T>> C;
128 const T t1[] = {0, 5, 5, 0, 0, 0, 5};
129 const T t2[] = {5, 5, 5};
130 C c1(std::begin(t1), std::end(t1));
131 C c2(std::begin(t2), std::end(t2));
132 do_remove(c1, 0, 4);
133 assert(c1 == c2);
134 }
135 {
136 typedef int T;
137 typedef std::forward_list<T, min_allocator<T>> C;
138 const T t1[] = {0, 0, 0, 0};
139 C c1(std::begin(t1), std::end(t1));
140 C c2;
141 do_remove(c1, 0, 4);
142 assert(c1 == c2);
143 }
144 {
145 typedef int T;
146 typedef std::forward_list<T, min_allocator<T>> C;
147 const T t1[] = {5, 5, 5};
148 const T t2[] = {5, 5, 5};
149 C c1(std::begin(t1), std::end(t1));
150 C c2(std::begin(t2), std::end(t2));
151 do_remove(c1, 0, 0);
152 assert(c1 == c2);
153 }
154 {
155 typedef int T;
156 typedef std::forward_list<T, min_allocator<T>> C;
157 C c1;
158 C c2;
159 do_remove(c1, 0, 0);
160 assert(c1 == c2);
161 }
162 {
163 typedef int T;
164 typedef std::forward_list<T, min_allocator<T>> C;
165 const T t1[] = {5, 5, 5, 0};
166 const T t2[] = {5, 5, 5};
167 C c1(std::begin(t1), std::end(t1));
168 C c2(std::begin(t2), std::end(t2));
169 do_remove(c1, 0, 1);
170 assert(c1 == c2);
171 }
172#endif
173
174 return true;
175}
176
177int main(int, char**) {
178 assert(test());
179#if TEST_STD_VER >= 26
180 static_assert(test());
181#endif
182
183 return 0;
184}
185

source code of libcxx/test/std/containers/sequences/forwardlist/forwardlist.ops/remove.pass.cpp