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