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