1 | ////////////////////////////////////////////////////////////////////////////// |
2 | // |
3 | // (C) Copyright Ion Gaztanaga 2004-2013. Distributed under the Boost |
4 | // Software License, Version 1.0. (See accompanying file |
5 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
6 | // |
7 | // See http://www.boost.org/libs/container for documentation. |
8 | // |
9 | ////////////////////////////////////////////////////////////////////////////// |
10 | #include <boost/container/slist.hpp> |
11 | #include <boost/container/node_allocator.hpp> |
12 | |
13 | #include <memory> |
14 | #include "dummy_test_allocator.hpp" |
15 | #include "movable_int.hpp" |
16 | #include "list_test.hpp" |
17 | #include "propagate_allocator_test.hpp" |
18 | #include "emplace_test.hpp" |
19 | #include "../../intrusive/test/iterator_test.hpp" |
20 | |
21 | using namespace boost::container; |
22 | |
23 | class recursive_slist |
24 | { |
25 | public: |
26 | int id_; |
27 | slist<recursive_slist> slist_; |
28 | slist<recursive_slist>::iterator it_; |
29 | slist<recursive_slist>::const_iterator cit_; |
30 | |
31 | recursive_slist &operator=(const recursive_slist &o) |
32 | { slist_ = o.slist_; return *this; } |
33 | |
34 | recursive_slist (const recursive_slist &o) |
35 | : slist_(o.slist_) |
36 | {} |
37 | }; |
38 | |
39 | void recursive_slist_test()//Test for recursive types |
40 | { |
41 | slist<recursive_slist> recursive_list_list; |
42 | } |
43 | |
44 | template<class VoidAllocator> |
45 | struct GetAllocatorCont |
46 | { |
47 | template<class ValueType> |
48 | struct apply |
49 | { |
50 | typedef slist< ValueType |
51 | , typename allocator_traits<VoidAllocator> |
52 | ::template portable_rebind_alloc<ValueType>::type |
53 | > type; |
54 | }; |
55 | }; |
56 | |
57 | bool test_support_for_initializer_list() |
58 | { |
59 | #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) |
60 | const std::initializer_list<int> il = {5, 10, 15}; |
61 | const slist<int> expected_list(il.begin(), il.end()); |
62 | { |
63 | slist<int> sl = il; |
64 | if(sl != expected_list) |
65 | return false; |
66 | } |
67 | |
68 | { |
69 | slist<int> sl = {1, 2}; |
70 | sl = il; |
71 | if(sl != expected_list) |
72 | return false; |
73 | } |
74 | { |
75 | slist<int> sl({ 1, 2 }, slist<int>::allocator_type()); |
76 | sl = il; |
77 | if (sl != expected_list) |
78 | return false; |
79 | } |
80 | { |
81 | slist<int> sl = {4, 5}; |
82 | sl.assign(il); |
83 | if(sl != expected_list) |
84 | return false; |
85 | } |
86 | |
87 | { |
88 | slist<int> sl = {15}; |
89 | sl.insert(p: sl.cbegin(), il: {5, 10}); |
90 | if(sl != expected_list) |
91 | return false; |
92 | } |
93 | |
94 | { |
95 | slist<int> sl = {5}; |
96 | sl.insert_after(prev_p: sl.cbegin(), il: {10, 15}); |
97 | if(sl != expected_list) |
98 | return false; |
99 | } |
100 | return true; |
101 | #endif |
102 | return true; |
103 | } |
104 | |
105 | bool test_for_splice() |
106 | { |
107 | { |
108 | slist<int> list1; list1.push_front(x: 3); list1.push_front(x: 2); list1.push_front(x: 1); list1.push_front(x: 0); |
109 | slist<int> list2; |
110 | slist<int> expected1; expected1.push_front(x: 3); expected1.push_front(x: 2); expected1.push_front(x: 0); |
111 | slist<int> expected2; expected2.push_front(x: 1); |
112 | |
113 | list2.splice(p: list2.begin(), x&: list1, i: ++list1.begin()); |
114 | |
115 | if (!(expected1 == list1 && expected2 == list2)) |
116 | return false; |
117 | } |
118 | { |
119 | slist<int> list1; list1.push_front(x: 3); list1.push_front(x: 2); list1.push_front(x: 1); list1.push_front(x: 0); |
120 | slist<int> list2; |
121 | slist<int> expected1; |
122 | slist<int> expected2; expected2.push_front(x: 3); expected2.push_front(x: 2); expected2.push_front(x: 1); expected2.push_front(x: 0); |
123 | |
124 | list2.splice(p: list2.begin(), x&: list1, first: list1.begin(), last: list1.end()); |
125 | |
126 | if (!(expected1 == list1 && expected2 == list2)) |
127 | return false; |
128 | } |
129 | return true; |
130 | } |
131 | |
132 | struct boost_container_slist; |
133 | |
134 | namespace boost { |
135 | namespace container { |
136 | namespace test { |
137 | |
138 | template<> |
139 | struct alloc_propagate_base<boost_container_slist> |
140 | { |
141 | template <class T, class Allocator> |
142 | struct apply |
143 | { |
144 | typedef boost::container::slist<T, Allocator> type; |
145 | }; |
146 | }; |
147 | |
148 | }}} |
149 | |
150 | int main () |
151 | { |
152 | recursive_slist_test(); |
153 | { |
154 | //Now test move semantics |
155 | slist<recursive_slist> original; |
156 | slist<recursive_slist> move_ctor(boost::move(t&: original)); |
157 | slist<recursive_slist> move_assign; |
158 | move_assign = boost::move(t&: move_ctor); |
159 | move_assign.swap(x&: original); |
160 | { |
161 | slist<recursive_slist> recursive, copy; |
162 | //Test to test both move emulations |
163 | if(!copy.size()){ |
164 | copy = recursive; |
165 | } |
166 | } |
167 | } |
168 | //////////////////////////////////// |
169 | // Testing allocator implementations |
170 | //////////////////////////////////// |
171 | if (test::list_test<slist<int, std::allocator<int> >, false>()) |
172 | return 1; |
173 | if (test::list_test<slist<int>, false>()) |
174 | return 1; |
175 | if (test::list_test<slist<int, node_allocator<int> >, false>()) |
176 | return 1; |
177 | if (test::list_test<slist<test::movable_int>, false>()) |
178 | return 1; |
179 | if (test::list_test<slist<test::movable_and_copyable_int>, false>()) |
180 | return 1; |
181 | if (test::list_test<slist<test::copyable_int>, false>()) |
182 | return 1; |
183 | |
184 | //////////////////////////////////// |
185 | // Emplace testing |
186 | //////////////////////////////////// |
187 | const test::EmplaceOptions Options = (test::EmplaceOptions) |
188 | (test::EMPLACE_FRONT | test::EMPLACE_AFTER | test::EMPLACE_BEFORE | test::EMPLACE_AFTER); |
189 | |
190 | if(!boost::container::test::test_emplace |
191 | < slist<test::EmplaceInt>, Options>()) |
192 | return 1; |
193 | |
194 | //////////////////////////////////// |
195 | // Allocator propagation testing |
196 | //////////////////////////////////// |
197 | if(!boost::container::test::test_propagate_allocator<boost_container_slist>()) |
198 | return 1; |
199 | |
200 | //////////////////////////////////// |
201 | // Initializer lists |
202 | //////////////////////////////////// |
203 | if(!test_support_for_initializer_list()) |
204 | return 1; |
205 | |
206 | //////////////////////////////////// |
207 | // Splice testing |
208 | //////////////////////////////////// |
209 | if(!test_for_splice()) |
210 | return 1; |
211 | |
212 | //////////////////////////////////// |
213 | // Iterator testing |
214 | //////////////////////////////////// |
215 | { |
216 | typedef boost::container::slist<int> vector_int; |
217 | vector_int a; a.push_front(x: 2); a.push_front(x: 1); a.push_front(x: 0); |
218 | boost::intrusive::test::test_iterator_forward< boost::container::slist<int> >(c&: a); |
219 | if(boost::report_errors() != 0) { |
220 | return 1; |
221 | } |
222 | } |
223 | #ifndef BOOST_CONTAINER_NO_CXX17_CTAD |
224 | //////////////////////////////////// |
225 | // Constructor Template Auto Deduction Tests |
226 | //////////////////////////////////// |
227 | { |
228 | auto gold = std::list{ 1, 2, 3 }; |
229 | auto test = boost::container::slist(gold.begin(), gold.end()); |
230 | if (test.size() != 3) { |
231 | return 1; |
232 | } |
233 | if (test.front() != 1) |
234 | return 1; |
235 | test.pop_front(); |
236 | if (test.front() != 2) |
237 | return 1; |
238 | test.pop_front(); |
239 | if (test.front() != 3) |
240 | return 1; |
241 | test.pop_front(); |
242 | } |
243 | { |
244 | auto gold = std::list{ 1, 2, 3 }; |
245 | auto test = boost::container::slist(gold.begin(), gold.end(), new_allocator<int>()); |
246 | if (test.size() != 3) { |
247 | return 1; |
248 | } |
249 | if (test.front() != 1) |
250 | return 1; |
251 | test.pop_front(); |
252 | if (test.front() != 2) |
253 | return 1; |
254 | test.pop_front(); |
255 | if (test.front() != 3) |
256 | return 1; |
257 | test.pop_front(); |
258 | } |
259 | #endif |
260 | |
261 | //////////////////////////////////// |
262 | // has_trivial_destructor_after_move testing |
263 | //////////////////////////////////// |
264 | // default allocator |
265 | { |
266 | typedef boost::container::slist<int> cont; |
267 | typedef cont::allocator_type allocator_type; |
268 | typedef boost::container::allocator_traits<allocator_type>::pointer pointer; |
269 | BOOST_CONTAINER_STATIC_ASSERT_MSG( |
270 | !(boost::has_trivial_destructor_after_move<cont>::value != |
271 | boost::has_trivial_destructor_after_move<allocator_type>::value && |
272 | boost::has_trivial_destructor_after_move<pointer>::value) |
273 | , "has_trivial_destructor_after_move(default allocator) test failed" ); |
274 | } |
275 | // std::allocator |
276 | { |
277 | typedef boost::container::slist<int, std::allocator<int> > cont; |
278 | typedef cont::allocator_type allocator_type; |
279 | typedef boost::container::allocator_traits<allocator_type>::pointer pointer; |
280 | BOOST_CONTAINER_STATIC_ASSERT_MSG( |
281 | !(boost::has_trivial_destructor_after_move<cont>::value != |
282 | boost::has_trivial_destructor_after_move<allocator_type>::value && |
283 | boost::has_trivial_destructor_after_move<pointer>::value) |
284 | , "has_trivial_destructor_after_move(std::allocator) test failed" ); |
285 | } |
286 | |
287 | return 0; |
288 | } |
289 | |