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 | // UNSUPPORTED: c++03, no-exceptions |
12 | |
13 | // TODO: |
14 | // - throwing upon moving; |
15 | // - initializer lists; |
16 | // - throwing when constructing the element in place. |
17 | |
18 | // forward_list(size_type n, const value_type& v); |
19 | // forward_list(size_type n, const value_type& v, const allocator_type& a); |
20 | // template <class InputIterator> |
21 | // forward_list(InputIterator first, InputIterator last); |
22 | // template <class InputIterator> |
23 | // forward_list(InputIterator first, InputIterator last, const allocator_type& a); |
24 | // forward_list(const forward_list& x); |
25 | // forward_list(const forward_list& x, const allocator_type& a); |
26 | // template<container-compatible-range<T> R> |
27 | // forward_list(from_range_t, R&& rg, const Allocator& = Allocator()); // C++23 |
28 | // |
29 | // forward_list& operator=(const forward_list& x); |
30 | // |
31 | // template <class InputIterator> |
32 | // void assign(InputIterator first, InputIterator last); |
33 | // void assign(size_type n, const value_type& v); |
34 | // template<container-compatible-range<T> R> |
35 | // void assign_range(R&& rg); // C++23 |
36 | // |
37 | // void push_front(const value_type& v); |
38 | // template<container-compatible-range<T> R> |
39 | // void prepend_range(R&& rg); // C++23 |
40 | // |
41 | // iterator insert_after(const_iterator p, const value_type& v); |
42 | // iterator insert_after(const_iterator p, size_type n, const value_type& v); |
43 | // template <class InputIterator> |
44 | // iterator insert_after(const_iterator p, |
45 | // InputIterator first, InputIterator last); |
46 | // template<container-compatible-range<T> R> |
47 | // iterator insert_range_after(const_iterator position, R&& rg); // C++23 |
48 | // |
49 | // void resize(size_type n, const value_type& v); |
50 | |
51 | #include <forward_list> |
52 | |
53 | #include <cassert> |
54 | #include "../../exception_safety_helpers.h" |
55 | #include "test_macros.h" |
56 | |
57 | #if TEST_STD_VER >= 23 |
58 | #include <ranges> |
59 | #endif |
60 | |
61 | int main(int, char**) { |
62 | { |
63 | constexpr int ThrowOn = 1; |
64 | constexpr int Size = 1; |
65 | using T = ThrowingCopy<ThrowOn>; |
66 | |
67 | // void push_front(const value_type& v); |
68 | test_exception_safety_throwing_copy<ThrowOn, Size>(func: [](T* from, T*){ |
69 | std::forward_list<T> c; |
70 | c.push_front(val: *from); |
71 | }); |
72 | |
73 | // iterator insert_after(const_iterator p, const value_type& v); |
74 | test_exception_safety_throwing_copy</*ThrowOn=*/1, Size>(func: [](T* from, T*){ |
75 | std::forward_list<T> c; |
76 | c.insert_after(pos: c.before_begin(), val: *from); |
77 | }); |
78 | } |
79 | |
80 | { |
81 | constexpr int ThrowOn = 3; |
82 | constexpr int Size = 5; |
83 | using T = ThrowingCopy<ThrowOn>; |
84 | using C = std::forward_list<T>; |
85 | using Alloc = std::allocator<T>; |
86 | |
87 | // forward_list(size_type n, const value_type& v); |
88 | test_exception_safety_throwing_copy<ThrowOn, Size>(func: [](T* from, T*){ |
89 | std::forward_list<T> c(Size, *from); |
90 | (void)c; |
91 | }); |
92 | |
93 | // forward_list(size_type n, const value_type& v, const allocator_type& a); |
94 | test_exception_safety_throwing_copy<ThrowOn, Size>(func: [](T* from, T*){ |
95 | std::forward_list<T> c(Size, *from, Alloc()); |
96 | (void)c; |
97 | }); |
98 | |
99 | // template <class InputIterator> |
100 | // forward_list(InputIterator first, InputIterator last); |
101 | test_exception_safety_throwing_copy<ThrowOn, Size>(func: [](T* from, T* to){ |
102 | std::forward_list<T> c(from, to); |
103 | (void)c; |
104 | }); |
105 | |
106 | #if TEST_STD_VER >= 23 |
107 | // template<container-compatible-range<T> R> |
108 | // forward_list(from_range_t, R&& rg, const Allocator& = Allocator()); // C++23 |
109 | test_exception_safety_throwing_copy<ThrowOn, Size>([](T* from, T* to){ |
110 | { |
111 | std::forward_list<T> c(std::from_range, std::ranges::subrange(from, to)); |
112 | (void)c; |
113 | } |
114 | |
115 | { |
116 | std::forward_list<T> c(std::from_range, std::ranges::subrange(from, to), Alloc()); |
117 | (void)c; |
118 | } |
119 | }); |
120 | #endif |
121 | |
122 | // template <class InputIterator> |
123 | // forward_list(InputIterator first, InputIterator last, const allocator_type& a); |
124 | test_exception_safety_throwing_copy<ThrowOn, Size>(func: [](T* from, T* to){ |
125 | std::forward_list<T> c(from, to, Alloc()); |
126 | (void)c; |
127 | }); |
128 | |
129 | // forward_list(const forward_list& x); |
130 | test_exception_safety_throwing_copy_container<C, ThrowOn, Size>(func: [](C&& in) { |
131 | std::forward_list<T> c(in); |
132 | (void)c; |
133 | }); |
134 | |
135 | // forward_list(const forward_list& x, const allocator_type& a); |
136 | test_exception_safety_throwing_copy_container<C, ThrowOn, Size>(func: [](C&& in) { |
137 | std::forward_list<T> c(in, Alloc()); |
138 | (void)c; |
139 | }); |
140 | |
141 | // forward_list& operator=(const forward_list& x); |
142 | test_exception_safety_throwing_copy_container<C, ThrowOn, Size>(func: [](C&& in) { |
143 | std::forward_list<T> c; |
144 | c = in; |
145 | }); |
146 | |
147 | // template <class InputIterator> |
148 | // void assign(InputIterator first, InputIterator last); |
149 | test_exception_safety_throwing_copy<ThrowOn, Size>(func: [](T* from, T* to) { |
150 | std::forward_list<T> c; |
151 | c.assign(first: from, last: to); |
152 | }); |
153 | |
154 | #if TEST_STD_VER >= 23 |
155 | // template<container-compatible-range<T> R> |
156 | // void assign_range(R&& rg); // C++23 |
157 | test_exception_safety_throwing_copy<ThrowOn, Size>([](T* from, T* to) { |
158 | std::forward_list<T> c; |
159 | c.assign_range(std::ranges::subrange(from, to)); |
160 | }); |
161 | #endif |
162 | |
163 | // void assign(size_type n, const value_type& v); |
164 | test_exception_safety_throwing_copy<ThrowOn, Size>(func: [](T* from, T*) { |
165 | std::forward_list<T> c; |
166 | c.assign(n: Size, val: *from); |
167 | }); |
168 | |
169 | #if TEST_STD_VER >= 23 |
170 | // template<container-compatible-range<T> R> |
171 | // void prepend_range(R&& rg); // C++23 |
172 | test_exception_safety_throwing_copy<ThrowOn, Size>([](T* from, T* to) { |
173 | std::forward_list<T> c; |
174 | c.prepend_range(std::ranges::subrange(from, to)); |
175 | }); |
176 | #endif |
177 | |
178 | // iterator insert_after(const_iterator p, size_type n, const value_type& v); |
179 | test_exception_safety_throwing_copy<ThrowOn, Size>(func: [](T* from, T*) { |
180 | std::forward_list<T> c; |
181 | c.insert_after(pos: c.before_begin(), n: Size, val: *from); |
182 | }); |
183 | |
184 | // template <class InputIterator> |
185 | // iterator insert_after(const_iterator p, |
186 | // InputIterator first, InputIterator last); |
187 | test_exception_safety_throwing_copy<ThrowOn, Size>(func: [](T* from, T* to) { |
188 | std::forward_list<T> c; |
189 | c.insert_after(pos: c.before_begin(), first: from, last: to); |
190 | }); |
191 | |
192 | #if TEST_STD_VER >= 23 |
193 | // template<container-compatible-range<T> R> |
194 | // iterator insert_range_after(const_iterator position, R&& rg); // C++23 |
195 | test_exception_safety_throwing_copy<ThrowOn, Size>([](T* from, T* to) { |
196 | std::forward_list<T> c; |
197 | c.insert_range_after(c.before_begin(), std::ranges::subrange(from, to)); |
198 | }); |
199 | #endif |
200 | |
201 | // void resize(size_type n, const value_type& v); |
202 | test_exception_safety_throwing_copy<ThrowOn, Size>(func: [](T* from, T*) { |
203 | std::forward_list<T> c; |
204 | c.resize(sz: Size, val: *from); |
205 | }); |
206 | } |
207 | |
208 | return 0; |
209 | } |
210 | |