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 <class... Args> reference emplace_front(Args&&... args); // reference in C++17
39// template<container-compatible-range<T> R>
40// void prepend_range(R&& rg); // C++23
41//
42// iterator insert_after(const_iterator p, const value_type& v);
43// iterator insert_after(const_iterator p, value_type&& v);
44// iterator insert_after(const_iterator p, size_type n, const value_type& v);
45// iterator insert_after(const_iterator p, initializer_list<value_type> il);
46// template <class InputIterator>
47// iterator insert_after(const_iterator p,
48// InputIterator first, InputIterator last);
49// template<container-compatible-range<T> R>
50// iterator insert_range_after(const_iterator position, R&& rg); // C++23
51// template <class... Args>
52// iterator emplace_after(const_iterator p, Args&&... args);
53// void resize(size_type n, const value_type& v);
54// void resize(size_type n);
55
56#include <forward_list>
57
58#include <cassert>
59#include "../../exception_safety_helpers.h"
60#include "test_macros.h"
61
62#if TEST_STD_VER >= 23
63# include <ranges>
64#endif
65
66int main(int, char**) {
67 {
68 constexpr int ThrowOn = 1;
69 constexpr int Size = 1;
70 using T = ThrowingCopy<ThrowOn>;
71
72 // void push_front(const value_type& v);
73 test_strong_exception_safety_throwing_copy<ThrowOn, Size>(func: [](std::forward_list<T>& c, T* from, T*) {
74 c.push_front(val: *from);
75 });
76
77 // template <class... Args> reference emplace_front(Args&&... args);
78 test_strong_exception_safety_throwing_copy<ThrowOn, Size>(func: [](std::forward_list<T>& c, T* from, T*) {
79 c.push_front(val: *from);
80 });
81
82 // iterator insert_after(const_iterator p, const value_type& v);
83 test_strong_exception_safety_throwing_copy<ThrowOn, Size>(func: [](std::forward_list<T>& c, T* from, T*) {
84 c.insert_after(pos: c.before_begin(), val: *from);
85 });
86
87 // iterator insert_after(const_iterator p, value_type&& v);
88 test_strong_exception_safety_throwing_copy<ThrowOn, Size>(func: [](std::forward_list<T>& c, T* from, T*) {
89 c.insert_after(pos: c.before_begin(), val: std::move(*from));
90 });
91
92 // template <class... Args>
93 // iterator emplace_after(const_iterator p, Args&&... args);
94 test_strong_exception_safety_throwing_copy<ThrowOn, Size>(func: [](std::forward_list<T>& c, T* from, T*) {
95 c.emplace_after(pos: c.before_begin(), args&: *from);
96 });
97 test_strong_exception_safety_throwing_copy<ThrowOn, Size>(func: [](std::forward_list<T>& c, T* from, T*) {
98 c.emplace_after(pos: c.before_begin(), args: std::move(*from));
99 });
100 }
101
102 {
103 constexpr int ThrowOn = 3;
104 constexpr int Size = 5;
105 using T = ThrowingCopy<ThrowOn>;
106 using C = std::forward_list<T>;
107 using Alloc = std::allocator<T>;
108
109 // forward_list(size_type n, const value_type& v);
110 test_exception_safety_throwing_copy<ThrowOn, Size>(func: [](T* from, T*) {
111 std::forward_list<T> c(Size, *from);
112 (void)c;
113 });
114
115 // forward_list(size_type n, const value_type& v, const allocator_type& a);
116 test_exception_safety_throwing_copy<ThrowOn, Size>(func: [](T* from, T*) {
117 std::forward_list<T> c(Size, *from, Alloc());
118 (void)c;
119 });
120
121 // template <class InputIterator>
122 // forward_list(InputIterator first, InputIterator last);
123 test_exception_safety_throwing_copy<ThrowOn, Size>(func: [](T* from, T* to) {
124 std::forward_list<T> c(from, to);
125 (void)c;
126 });
127
128#if TEST_STD_VER >= 23
129 // template<container-compatible-range<T> R>
130 // forward_list(from_range_t, R&& rg, const Allocator& = Allocator()); // C++23
131 test_exception_safety_throwing_copy<ThrowOn, Size>([](T* from, T* to) {
132 {
133 std::forward_list<T> c(std::from_range, std::ranges::subrange(from, to));
134 (void)c;
135 }
136
137 {
138 std::forward_list<T> c(std::from_range, std::ranges::subrange(from, to), Alloc());
139 (void)c;
140 }
141 });
142#endif
143
144 // template <class InputIterator>
145 // forward_list(InputIterator first, InputIterator last, const allocator_type& a);
146 test_exception_safety_throwing_copy<ThrowOn, Size>(func: [](T* from, T* to) {
147 std::forward_list<T> c(from, to, Alloc());
148 (void)c;
149 });
150
151 // forward_list(const forward_list& x);
152 test_exception_safety_throwing_copy_container<C, ThrowOn, Size>(func: [](C&& in) {
153 std::forward_list<T> c(in);
154 (void)c;
155 });
156
157 // forward_list(const forward_list& x, const allocator_type& a);
158 test_exception_safety_throwing_copy_container<C, ThrowOn, Size>(func: [](C&& in) {
159 std::forward_list<T> c(in, Alloc());
160 (void)c;
161 });
162
163 // forward_list& operator=(const forward_list& x);
164 test_exception_safety_throwing_copy_container<C, ThrowOn, Size>(func: [](C&& in) {
165 std::forward_list<T> c;
166 c = in;
167 });
168
169 // template <class InputIterator>
170 // void assign(InputIterator first, InputIterator last);
171 test_exception_safety_throwing_copy<ThrowOn, Size>(func: [](T* from, T* to) {
172 std::forward_list<T> c;
173 c.assign(first: from, last: to);
174 });
175
176#if TEST_STD_VER >= 23
177 // template<container-compatible-range<T> R>
178 // void assign_range(R&& rg); // C++23
179 test_exception_safety_throwing_copy<ThrowOn, Size>([](T* from, T* to) {
180 std::forward_list<T> c;
181 c.assign_range(std::ranges::subrange(from, to));
182 });
183#endif
184
185 // void assign(size_type n, const value_type& v);
186 test_exception_safety_throwing_copy<ThrowOn, Size>(func: [](T* from, T*) {
187 std::forward_list<T> c;
188 c.assign(n: Size, val: *from);
189 });
190
191#if TEST_STD_VER >= 23
192 // template<container-compatible-range<T> R>
193 // void prepend_range(R&& rg); // C++23
194 test_strong_exception_safety_throwing_copy<ThrowOn, Size>([](std::forward_list<T>& c, T* from, T* to) {
195 c.prepend_range(std::ranges::subrange(from, to));
196 });
197#endif
198
199 // iterator insert_after(const_iterator p, size_type n, const value_type& v);
200 test_strong_exception_safety_throwing_copy<ThrowOn, Size>(func: [](std::forward_list<T>& c, T* from, T*) {
201 c.insert_after(pos: c.before_begin(), n: Size, val: *from);
202 });
203
204 // template <class InputIterator>
205 // iterator insert_after(const_iterator p,
206 // InputIterator first, InputIterator last);
207 test_strong_exception_safety_throwing_copy<ThrowOn, Size>(func: [](std::forward_list<T>& c, T* from, T* to) {
208 c.insert_after(pos: c.before_begin(), first: from, last: to);
209 });
210
211 // iterator insert_after(const_iterator p, initializer_list<value_type> il);
212 std::initializer_list<T> il{1, 2, 3, 4, 5};
213 test_strong_exception_safety_throwing_copy<ThrowOn, Size>(func: [&](std::forward_list<T>& c, T*, T*) {
214 c.insert_after(pos: c.before_begin(), il: il);
215 });
216
217#if TEST_STD_VER >= 23
218 // template<container-compatible-range<T> R>
219 // iterator insert_range_after(const_iterator position, R&& rg); // C++23
220 test_strong_exception_safety_throwing_copy<ThrowOn, Size>([](std::forward_list<T>& c, T* from, T* to) {
221 c.insert_range_after(c.before_begin(), std::ranges::subrange(from, to));
222 });
223#endif
224
225 // void resize(size_type n, const value_type& v);
226 test_strong_exception_safety_throwing_copy<ThrowOn, Size>(func: [](std::forward_list<T>& c, T* from, T*) {
227 c.resize(sz: Size * 3, val: *from);
228 });
229
230 { // void resize(size_type n);
231 using X = ThrowingDefault<ThrowOn>;
232 std::forward_list<X> c0{X{1}, X{2}, X{3}};
233 std::forward_list<X> c = c0;
234 try {
235 c.resize(sz: 3 * ThrowOn);
236 assert(false);
237 } catch (int) {
238 assert(c == c0);
239 }
240 }
241 }
242
243 return 0;
244}
245

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