]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | |
2 | // Copyright 2005-2009 Daniel James. | |
3 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
4 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
5 | ||
6 | #if defined(BOOST_MSVC) | |
7 | #pragma warning(push) | |
b32b8144 FG |
8 | #pragma warning(disable : 4100) // unreferenced formal parameter |
9 | #pragma warning(disable : 4610) // class can never be instantiated | |
10 | #pragma warning(disable : 4510) // default constructor could not be generated | |
7c673cae FG |
11 | #endif |
12 | ||
13 | #include <boost/concept_check.hpp> | |
14 | ||
15 | #if defined(BOOST_MSVC) | |
16 | #pragma warning(pop) | |
17 | #endif | |
18 | ||
b32b8144 | 19 | #include "../helpers/check_return_type.hpp" |
7c673cae FG |
20 | #include <boost/iterator/iterator_traits.hpp> |
21 | #include <boost/limits.hpp> | |
b32b8144 FG |
22 | #include <boost/predef.h> |
23 | #include <boost/static_assert.hpp> | |
24 | #include <boost/type_traits/cv_traits.hpp> | |
25 | #include <boost/type_traits/is_convertible.hpp> | |
26 | #include <boost/type_traits/is_same.hpp> | |
7c673cae | 27 | #include <boost/utility/swap.hpp> |
7c673cae FG |
28 | |
29 | typedef long double comparison_type; | |
30 | ||
31 | template <class T> void sink(T const&) {} | |
32 | template <class T> T rvalue(T const& v) { return v; } | |
33 | template <class T> T rvalue_default() { return T(); } | |
34 | ||
b32b8144 FG |
35 | #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) |
36 | template <class T> T implicit_construct() { return {}; } | |
37 | #else | |
38 | template <class T> int implicit_construct() | |
39 | { | |
40 | T x; | |
41 | sink(x); | |
42 | return 0; | |
43 | } | |
44 | #endif | |
45 | ||
46 | #if !defined(BOOST_NO_CXX11_NOEXCEPT) | |
47 | #define TEST_NOEXCEPT_EXPR(x) BOOST_STATIC_ASSERT((BOOST_NOEXCEPT_EXPR(x))); | |
48 | #else | |
49 | #define TEST_NOEXCEPT_EXPR(x) | |
50 | #endif | |
51 | ||
52 | template <class X, class T> void container_test(X& r, T const&) | |
7c673cae | 53 | { |
b32b8144 FG |
54 | typedef BOOST_DEDUCED_TYPENAME X::iterator iterator; |
55 | typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator; | |
56 | typedef BOOST_DEDUCED_TYPENAME X::difference_type difference_type; | |
57 | typedef BOOST_DEDUCED_TYPENAME X::size_type size_type; | |
58 | ||
59 | typedef BOOST_DEDUCED_TYPENAME boost::iterator_value<iterator>::type | |
60 | iterator_value_type; | |
61 | typedef BOOST_DEDUCED_TYPENAME boost::iterator_value<const_iterator>::type | |
62 | const_iterator_value_type; | |
63 | typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference<iterator>::type | |
64 | iterator_difference_type; | |
65 | typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference< | |
66 | const_iterator>::type const_iterator_difference_type; | |
67 | ||
68 | typedef BOOST_DEDUCED_TYPENAME X::value_type value_type; | |
69 | typedef BOOST_DEDUCED_TYPENAME X::reference reference; | |
70 | typedef BOOST_DEDUCED_TYPENAME X::const_reference const_reference; | |
71 | ||
72 | typedef BOOST_DEDUCED_TYPENAME X::node_type node_type; | |
7c673cae | 73 | |
b32b8144 | 74 | typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type; |
7c673cae | 75 | |
b32b8144 | 76 | // value_type |
7c673cae | 77 | |
b32b8144 FG |
78 | BOOST_STATIC_ASSERT((boost::is_same<T, value_type>::value)); |
79 | boost::function_requires<boost::CopyConstructibleConcept<X> >(); | |
7c673cae | 80 | |
b32b8144 | 81 | // reference_type / const_reference_type |
7c673cae | 82 | |
b32b8144 FG |
83 | BOOST_STATIC_ASSERT((boost::is_same<T&, reference>::value)); |
84 | BOOST_STATIC_ASSERT((boost::is_same<T const&, const_reference>::value)); | |
7c673cae | 85 | |
b32b8144 | 86 | // iterator |
7c673cae | 87 | |
b32b8144 FG |
88 | boost::function_requires<boost::InputIteratorConcept<iterator> >(); |
89 | BOOST_STATIC_ASSERT((boost::is_same<T, iterator_value_type>::value)); | |
90 | BOOST_STATIC_ASSERT((boost::is_convertible<iterator, const_iterator>::value)); | |
7c673cae | 91 | |
b32b8144 | 92 | // const_iterator |
7c673cae | 93 | |
b32b8144 FG |
94 | boost::function_requires<boost::InputIteratorConcept<const_iterator> >(); |
95 | BOOST_STATIC_ASSERT((boost::is_same<T, const_iterator_value_type>::value)); | |
7c673cae | 96 | |
b32b8144 | 97 | // node_type |
7c673cae | 98 | |
b32b8144 FG |
99 | BOOST_STATIC_ASSERT((boost::is_same<allocator_type, |
100 | BOOST_DEDUCED_TYPENAME node_type::allocator_type>::value)); | |
7c673cae | 101 | |
b32b8144 | 102 | // difference_type |
7c673cae | 103 | |
b32b8144 FG |
104 | BOOST_STATIC_ASSERT(std::numeric_limits<difference_type>::is_signed); |
105 | BOOST_STATIC_ASSERT(std::numeric_limits<difference_type>::is_integer); | |
106 | BOOST_STATIC_ASSERT( | |
107 | (boost::is_same<difference_type, iterator_difference_type>::value)); | |
108 | BOOST_STATIC_ASSERT( | |
109 | (boost::is_same<difference_type, const_iterator_difference_type>::value)); | |
7c673cae | 110 | |
b32b8144 | 111 | // size_type |
7c673cae | 112 | |
b32b8144 FG |
113 | BOOST_STATIC_ASSERT(!std::numeric_limits<size_type>::is_signed); |
114 | BOOST_STATIC_ASSERT(std::numeric_limits<size_type>::is_integer); | |
7c673cae | 115 | |
b32b8144 FG |
116 | // size_type can represent any non-negative value type of difference_type |
117 | // I'm not sure about either of these tests... | |
118 | size_type max_diff = | |
119 | static_cast<size_type>((std::numeric_limits<difference_type>::max)()); | |
120 | difference_type converted_diff(static_cast<difference_type>(max_diff)); | |
121 | BOOST_TEST((std::numeric_limits<difference_type>::max)() == converted_diff); | |
7c673cae | 122 | |
b32b8144 FG |
123 | BOOST_TEST( |
124 | static_cast<comparison_type>((std::numeric_limits<size_type>::max)()) > | |
125 | static_cast<comparison_type>( | |
126 | (std::numeric_limits<difference_type>::max)())); | |
7c673cae | 127 | |
b32b8144 FG |
128 | // Constructors |
129 | ||
130 | // I don't test the runtime post-conditions here. | |
7c673cae FG |
131 | |
132 | #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) | |
b32b8144 FG |
133 | // It isn't specified in the container requirements that the no argument |
134 | // constructor is implicit, but it is defined that way in the concrete | |
135 | // container specification. | |
136 | X u_implicit = {}; | |
137 | sink(u_implicit); | |
138 | #endif | |
139 | ||
140 | X u; | |
141 | BOOST_TEST(u.size() == 0); | |
142 | BOOST_TEST(X().size() == 0); | |
143 | ||
144 | X a, b; | |
145 | X a_const; | |
146 | ||
147 | sink(X(a)); | |
148 | X u2(a); | |
149 | X u3 = a; | |
150 | X u4(rvalue(a_const)); | |
151 | X u5 = rvalue(a_const); | |
152 | ||
153 | a.swap(b); | |
154 | boost::swap(a, b); | |
155 | test::check_return_type<X>::equals_ref(r = a); | |
156 | ||
157 | // Allocator | |
158 | ||
159 | test::check_return_type<allocator_type>::equals(a_const.get_allocator()); | |
160 | ||
161 | allocator_type m = a.get_allocator(); | |
162 | sink(X(m)); | |
163 | X c(m); | |
164 | sink(X(a_const, m)); | |
165 | X c2(a_const, m); | |
166 | sink(X(rvalue(a_const), m)); | |
167 | X c3(rvalue(a_const), m); | |
168 | ||
169 | // node_type | |
170 | ||
171 | implicit_construct<node_type const>(); | |
172 | #if !BOOST_COMP_GNUC || BOOST_COMP_GNUC >= BOOST_VERSION_NUMBER(4, 8, 0) | |
173 | TEST_NOEXCEPT_EXPR(node_type()); | |
7c673cae FG |
174 | #endif |
175 | ||
b32b8144 FG |
176 | node_type n1; |
177 | node_type n2(rvalue_default<node_type>()); | |
178 | #if !BOOST_COMP_GNUC || BOOST_COMP_GNUC >= BOOST_VERSION_NUMBER(4, 8, 0) | |
179 | TEST_NOEXCEPT_EXPR(node_type(boost::move(n1))); | |
180 | #endif | |
181 | node_type n3; | |
182 | n3 = boost::move(n2); | |
183 | n1.swap(n3); | |
184 | swap(n1, n3); | |
185 | // TODO: noexcept for swap? | |
186 | // value, key, mapped tests in map and set specific testing. | |
187 | ||
188 | node_type const n_const; | |
189 | BOOST_TEST(n_const ? 0 : 1); | |
190 | TEST_NOEXCEPT_EXPR(n_const ? 0 : 1); | |
191 | test::check_return_type<bool>::equals(!n_const); | |
192 | test::check_return_type<bool>::equals(n_const.empty()); | |
193 | TEST_NOEXCEPT_EXPR(!n_const); | |
194 | TEST_NOEXCEPT_EXPR(n_const.empty()); | |
195 | ||
196 | // Avoid unused variable warnings: | |
197 | ||
198 | sink(u); | |
199 | sink(u2); | |
200 | sink(u3); | |
201 | sink(u4); | |
202 | sink(u5); | |
203 | sink(c); | |
204 | sink(c2); | |
205 | sink(c3); | |
7c673cae FG |
206 | } |
207 | ||
b32b8144 | 208 | template <class X> void unordered_destructible_test(X&) |
7c673cae | 209 | { |
b32b8144 FG |
210 | typedef BOOST_DEDUCED_TYPENAME X::iterator iterator; |
211 | typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator; | |
212 | typedef BOOST_DEDUCED_TYPENAME X::size_type size_type; | |
7c673cae | 213 | |
b32b8144 | 214 | X x1; |
7c673cae FG |
215 | |
216 | #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) | |
b32b8144 FG |
217 | X x2(rvalue_default<X>()); |
218 | X x3 = rvalue_default<X>(); | |
219 | // This can only be done if propagate_on_container_move_assignment::value | |
220 | // is true. | |
221 | // x2 = rvalue_default<X>(); | |
7c673cae FG |
222 | #endif |
223 | ||
b32b8144 FG |
224 | X* ptr = new X(); |
225 | X& a1 = *ptr; | |
226 | (&a1)->~X(); | |
227 | ::operator delete((void*)(&a1)); | |
228 | ||
229 | X a, b; | |
230 | X const a_const; | |
231 | test::check_return_type<iterator>::equals(a.begin()); | |
232 | test::check_return_type<const_iterator>::equals(a_const.begin()); | |
233 | test::check_return_type<const_iterator>::equals(a.cbegin()); | |
234 | test::check_return_type<const_iterator>::equals(a_const.cbegin()); | |
235 | test::check_return_type<iterator>::equals(a.end()); | |
236 | test::check_return_type<const_iterator>::equals(a_const.end()); | |
237 | test::check_return_type<const_iterator>::equals(a.cend()); | |
238 | test::check_return_type<const_iterator>::equals(a_const.cend()); | |
239 | ||
240 | a.swap(b); | |
241 | boost::swap(a, b); | |
242 | ||
243 | test::check_return_type<size_type>::equals(a.size()); | |
244 | test::check_return_type<size_type>::equals(a.max_size()); | |
245 | test::check_return_type<bool>::convertible(a.empty()); | |
246 | ||
247 | // Allocator | |
248 | ||
249 | typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type; | |
250 | test::check_return_type<allocator_type>::equals(a_const.get_allocator()); | |
7c673cae FG |
251 | } |
252 | ||
b32b8144 | 253 | template <class X, class Key> void unordered_set_test(X& r, Key const&) |
7c673cae | 254 | { |
b32b8144 FG |
255 | typedef BOOST_DEDUCED_TYPENAME X::value_type value_type; |
256 | typedef BOOST_DEDUCED_TYPENAME X::key_type key_type; | |
257 | ||
258 | BOOST_STATIC_ASSERT((boost::is_same<value_type, key_type>::value)); | |
259 | ||
260 | // iterator pointer / const_pointer_type | |
261 | ||
262 | typedef BOOST_DEDUCED_TYPENAME X::iterator iterator; | |
263 | typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator; | |
264 | typedef BOOST_DEDUCED_TYPENAME X::local_iterator local_iterator; | |
265 | typedef BOOST_DEDUCED_TYPENAME X::const_local_iterator const_local_iterator; | |
266 | typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer<iterator>::type | |
267 | iterator_pointer; | |
268 | typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer<const_iterator>::type | |
269 | const_iterator_pointer; | |
270 | typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer<local_iterator>::type | |
271 | local_iterator_pointer; | |
272 | typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer< | |
273 | const_local_iterator>::type const_local_iterator_pointer; | |
274 | ||
275 | BOOST_STATIC_ASSERT( | |
276 | (boost::is_same<value_type const*, iterator_pointer>::value)); | |
277 | BOOST_STATIC_ASSERT( | |
278 | (boost::is_same<value_type const*, const_iterator_pointer>::value)); | |
279 | BOOST_STATIC_ASSERT( | |
280 | (boost::is_same<value_type const*, local_iterator_pointer>::value)); | |
281 | BOOST_STATIC_ASSERT( | |
282 | (boost::is_same<value_type const*, const_local_iterator_pointer>::value)); | |
283 | ||
284 | typedef BOOST_DEDUCED_TYPENAME X::node_type node_type; | |
285 | typedef BOOST_DEDUCED_TYPENAME node_type::value_type node_value_type; | |
286 | BOOST_STATIC_ASSERT((boost::is_same<value_type, node_value_type>::value)); | |
287 | ||
288 | // Call node_type functions. | |
289 | ||
290 | test::minimal::constructor_param v; | |
291 | Key k_lvalue(v); | |
292 | r.emplace(boost::move(k_lvalue)); | |
293 | node_type n1 = r.extract(r.begin()); | |
294 | test::check_return_type<value_type>::equals_ref(n1.value()); | |
7c673cae FG |
295 | } |
296 | ||
297 | template <class X, class Key, class T> | |
298 | void unordered_map_test(X& r, Key const& k, T const& v) | |
299 | { | |
b32b8144 FG |
300 | typedef BOOST_DEDUCED_TYPENAME X::value_type value_type; |
301 | typedef BOOST_DEDUCED_TYPENAME X::key_type key_type; | |
302 | ||
303 | BOOST_STATIC_ASSERT( | |
304 | (boost::is_same<value_type, std::pair<key_type const, T> >::value)); | |
305 | ||
306 | // iterator pointer / const_pointer_type | |
307 | ||
308 | typedef BOOST_DEDUCED_TYPENAME X::iterator iterator; | |
309 | typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator; | |
310 | typedef BOOST_DEDUCED_TYPENAME X::local_iterator local_iterator; | |
311 | typedef BOOST_DEDUCED_TYPENAME X::const_local_iterator const_local_iterator; | |
312 | typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer<iterator>::type | |
313 | iterator_pointer; | |
314 | typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer<const_iterator>::type | |
315 | const_iterator_pointer; | |
316 | typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer<local_iterator>::type | |
317 | local_iterator_pointer; | |
318 | typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer< | |
319 | const_local_iterator>::type const_local_iterator_pointer; | |
320 | ||
321 | BOOST_STATIC_ASSERT((boost::is_same<value_type*, iterator_pointer>::value)); | |
322 | BOOST_STATIC_ASSERT( | |
323 | (boost::is_same<value_type const*, const_iterator_pointer>::value)); | |
324 | BOOST_STATIC_ASSERT( | |
325 | (boost::is_same<value_type*, local_iterator_pointer>::value)); | |
326 | BOOST_STATIC_ASSERT( | |
327 | (boost::is_same<value_type const*, const_local_iterator_pointer>::value)); | |
328 | ||
329 | typedef BOOST_DEDUCED_TYPENAME X::node_type node_type; | |
330 | typedef BOOST_DEDUCED_TYPENAME node_type::key_type node_key_type; | |
331 | typedef BOOST_DEDUCED_TYPENAME node_type::mapped_type node_mapped_type; | |
332 | ||
333 | BOOST_STATIC_ASSERT((boost::is_same<Key, node_key_type>::value)); | |
334 | BOOST_STATIC_ASSERT((boost::is_same<T, node_mapped_type>::value)); | |
335 | // Superfluous,but just to make sure. | |
336 | BOOST_STATIC_ASSERT((!boost::is_const<node_key_type>::value)); | |
337 | ||
338 | // Calling functions | |
339 | ||
340 | r.insert(std::pair<Key const, T>(k, v)); | |
341 | r.insert(r.begin(), std::pair<Key const, T>(k, v)); | |
342 | std::pair<Key const, T> const value(k, v); | |
343 | r.insert(value); | |
344 | r.insert(r.end(), value); | |
345 | ||
346 | Key k_lvalue(k); | |
347 | T v_lvalue(v); | |
348 | ||
349 | // Emplace | |
350 | ||
351 | r.emplace(k, v); | |
352 | r.emplace(k_lvalue, v_lvalue); | |
353 | r.emplace(rvalue(k), rvalue(v)); | |
354 | ||
355 | r.emplace(boost::unordered::piecewise_construct, boost::make_tuple(k), | |
356 | boost::make_tuple(v)); | |
357 | ||
358 | // Emplace with hint | |
359 | ||
360 | r.emplace_hint(r.begin(), k, v); | |
361 | r.emplace_hint(r.begin(), k_lvalue, v_lvalue); | |
362 | r.emplace_hint(r.begin(), rvalue(k), rvalue(v)); | |
363 | ||
364 | r.emplace_hint(r.begin(), boost::unordered::piecewise_construct, | |
365 | boost::make_tuple(k), boost::make_tuple(v)); | |
366 | ||
367 | // Extract | |
368 | ||
369 | test::check_return_type<node_type>::equals(r.extract(r.begin())); | |
370 | ||
371 | r.emplace(k, v); | |
372 | test::check_return_type<node_type>::equals(r.extract(k)); | |
373 | ||
374 | r.emplace(k, v); | |
375 | node_type n1 = r.extract(r.begin()); | |
376 | test::check_return_type<key_type>::equals_ref(n1.key()); | |
377 | test::check_return_type<T>::equals_ref(n1.mapped()); | |
378 | ||
379 | node_type n2 = boost::move(n1); | |
380 | r.insert(boost::move(n2)); | |
381 | r.insert(r.extract(r.begin())); | |
382 | n2 = r.extract(r.begin()); | |
383 | r.insert(r.begin(), boost::move(n2)); | |
384 | r.insert(r.end(), r.extract(r.begin())); | |
385 | ||
386 | node_type n = r.extract(r.begin()); | |
387 | test::check_return_type<node_key_type>::equals_ref(n.key()); | |
388 | test::check_return_type<node_mapped_type>::equals_ref(n.mapped()); | |
7c673cae FG |
389 | } |
390 | ||
b32b8144 | 391 | template <class X> void equality_test(X& r) |
7c673cae | 392 | { |
b32b8144 | 393 | X const a = r, b = r; |
7c673cae | 394 | |
b32b8144 FG |
395 | test::check_return_type<bool>::equals(a == b); |
396 | test::check_return_type<bool>::equals(a != b); | |
397 | test::check_return_type<bool>::equals(boost::operator==(a, b)); | |
398 | test::check_return_type<bool>::equals(boost::operator!=(a, b)); | |
7c673cae FG |
399 | } |
400 | ||
b32b8144 | 401 | template <class X, class T> void unordered_unique_test(X& r, T const& t) |
7c673cae | 402 | { |
b32b8144 FG |
403 | typedef BOOST_DEDUCED_TYPENAME X::iterator iterator; |
404 | test::check_return_type<std::pair<iterator, bool> >::equals(r.insert(t)); | |
405 | test::check_return_type<std::pair<iterator, bool> >::equals(r.emplace(t)); | |
406 | ||
407 | typedef BOOST_DEDUCED_TYPENAME X::node_type node_type; | |
408 | typedef BOOST_DEDUCED_TYPENAME X::insert_return_type insert_return_type; | |
409 | ||
410 | // insert_return_type | |
411 | ||
412 | // TODO; | |
413 | // boost::function_requires< | |
414 | // boost::MoveConstructibleConcept<insert_return_type> | |
415 | // >(); | |
416 | // TODO; | |
417 | // boost::function_requires< | |
418 | // boost::MoveAssignableConcept<insert_return_type> | |
419 | // >(); | |
420 | boost::function_requires< | |
421 | boost::DefaultConstructibleConcept<insert_return_type> >(); | |
422 | // TODO: | |
423 | // boost::function_requires< | |
424 | // boost::DestructibleConcept<insert_return_type> | |
425 | // >(); | |
426 | insert_return_type insert_return, insert_return2; | |
427 | test::check_return_type<bool>::equals(insert_return.inserted); | |
428 | test::check_return_type<iterator>::equals(insert_return.position); | |
429 | test::check_return_type<node_type>::equals_ref(insert_return.node); | |
430 | boost::swap(insert_return, insert_return2); | |
7c673cae FG |
431 | } |
432 | ||
b32b8144 | 433 | template <class X, class T> void unordered_equivalent_test(X& r, T const& t) |
7c673cae | 434 | { |
b32b8144 FG |
435 | typedef BOOST_DEDUCED_TYPENAME X::iterator iterator; |
436 | test::check_return_type<iterator>::equals(r.insert(t)); | |
437 | test::check_return_type<iterator>::equals(r.emplace(t)); | |
7c673cae FG |
438 | } |
439 | ||
440 | template <class X, class Key, class T> | |
b32b8144 | 441 | void unordered_map_functions(X&, Key const& k, T const& v) |
7c673cae | 442 | { |
b32b8144 FG |
443 | typedef BOOST_DEDUCED_TYPENAME X::mapped_type mapped_type; |
444 | typedef BOOST_DEDUCED_TYPENAME X::iterator iterator; | |
445 | ||
446 | X a; | |
447 | test::check_return_type<mapped_type>::equals_ref(a[k]); | |
448 | test::check_return_type<mapped_type>::equals_ref(a[rvalue(k)]); | |
449 | test::check_return_type<mapped_type>::equals_ref(a.at(k)); | |
450 | test::check_return_type<std::pair<iterator, bool> >::equals( | |
451 | a.try_emplace(k, v)); | |
452 | test::check_return_type<std::pair<iterator, bool> >::equals( | |
453 | a.try_emplace(rvalue(k), v)); | |
454 | test::check_return_type<iterator>::equals(a.try_emplace(a.begin(), k, v)); | |
455 | test::check_return_type<iterator>::equals( | |
456 | a.try_emplace(a.begin(), rvalue(k), v)); | |
457 | test::check_return_type<std::pair<iterator, bool> >::equals( | |
458 | a.insert_or_assign(k, v)); | |
459 | test::check_return_type<std::pair<iterator, bool> >::equals( | |
460 | a.insert_or_assign(rvalue(k), v)); | |
461 | test::check_return_type<iterator>::equals( | |
462 | a.insert_or_assign(a.begin(), k, v)); | |
463 | test::check_return_type<iterator>::equals( | |
464 | a.insert_or_assign(a.begin(), rvalue(k), v)); | |
465 | ||
466 | X const b = a; | |
467 | test::check_return_type<mapped_type const>::equals_ref(b.at(k)); | |
7c673cae FG |
468 | } |
469 | ||
470 | template <class X, class Key, class Hash, class Pred> | |
471 | void unordered_test(X& x, Key& k, Hash& hf, Pred& eq) | |
472 | { | |
b32b8144 FG |
473 | unordered_destructible_test(x); |
474 | ||
475 | typedef BOOST_DEDUCED_TYPENAME X::key_type key_type; | |
476 | typedef BOOST_DEDUCED_TYPENAME X::hasher hasher; | |
477 | typedef BOOST_DEDUCED_TYPENAME X::key_equal key_equal; | |
478 | typedef BOOST_DEDUCED_TYPENAME X::size_type size_type; | |
479 | ||
480 | typedef BOOST_DEDUCED_TYPENAME X::iterator iterator; | |
481 | typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator; | |
482 | typedef BOOST_DEDUCED_TYPENAME X::local_iterator local_iterator; | |
483 | typedef BOOST_DEDUCED_TYPENAME X::const_local_iterator const_local_iterator; | |
484 | ||
485 | typedef BOOST_DEDUCED_TYPENAME boost::BOOST_ITERATOR_CATEGORY<iterator>::type | |
486 | iterator_category; | |
487 | typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference<iterator>::type | |
488 | iterator_difference; | |
489 | typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer<iterator>::type | |
490 | iterator_pointer; | |
491 | typedef BOOST_DEDUCED_TYPENAME boost::iterator_reference<iterator>::type | |
492 | iterator_reference; | |
493 | ||
494 | typedef BOOST_DEDUCED_TYPENAME boost::BOOST_ITERATOR_CATEGORY< | |
495 | local_iterator>::type local_iterator_category; | |
496 | typedef BOOST_DEDUCED_TYPENAME | |
497 | boost::iterator_difference<local_iterator>::type local_iterator_difference; | |
498 | typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer<local_iterator>::type | |
499 | local_iterator_pointer; | |
500 | typedef BOOST_DEDUCED_TYPENAME boost::iterator_reference<local_iterator>::type | |
501 | local_iterator_reference; | |
502 | ||
503 | typedef BOOST_DEDUCED_TYPENAME boost::BOOST_ITERATOR_CATEGORY< | |
504 | const_iterator>::type const_iterator_category; | |
505 | typedef BOOST_DEDUCED_TYPENAME | |
506 | boost::iterator_difference<const_iterator>::type const_iterator_difference; | |
507 | typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer<const_iterator>::type | |
508 | const_iterator_pointer; | |
509 | typedef BOOST_DEDUCED_TYPENAME boost::iterator_reference<const_iterator>::type | |
510 | const_iterator_reference; | |
511 | ||
512 | typedef BOOST_DEDUCED_TYPENAME boost::BOOST_ITERATOR_CATEGORY< | |
513 | const_local_iterator>::type const_local_iterator_category; | |
514 | typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference< | |
515 | const_local_iterator>::type const_local_iterator_difference; | |
516 | typedef BOOST_DEDUCED_TYPENAME boost::iterator_pointer< | |
517 | const_local_iterator>::type const_local_iterator_pointer; | |
518 | typedef BOOST_DEDUCED_TYPENAME boost::iterator_reference< | |
519 | const_local_iterator>::type const_local_iterator_reference; | |
520 | typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type; | |
521 | ||
522 | BOOST_STATIC_ASSERT((boost::is_same<Key, key_type>::value)); | |
523 | // boost::function_requires<boost::CopyConstructibleConcept<key_type> >(); | |
524 | // boost::function_requires<boost::AssignableConcept<key_type> >(); | |
525 | ||
526 | BOOST_STATIC_ASSERT((boost::is_same<Hash, hasher>::value)); | |
527 | test::check_return_type<std::size_t>::equals(hf(k)); | |
528 | ||
529 | BOOST_STATIC_ASSERT((boost::is_same<Pred, key_equal>::value)); | |
530 | test::check_return_type<bool>::convertible(eq(k, k)); | |
531 | ||
532 | boost::function_requires<boost::InputIteratorConcept<local_iterator> >(); | |
533 | BOOST_STATIC_ASSERT( | |
534 | (boost::is_same<local_iterator_category, iterator_category>::value)); | |
535 | BOOST_STATIC_ASSERT( | |
536 | (boost::is_same<local_iterator_difference, iterator_difference>::value)); | |
537 | BOOST_STATIC_ASSERT( | |
538 | (boost::is_same<local_iterator_pointer, iterator_pointer>::value)); | |
539 | BOOST_STATIC_ASSERT( | |
540 | (boost::is_same<local_iterator_reference, iterator_reference>::value)); | |
541 | ||
542 | boost::function_requires< | |
543 | boost::InputIteratorConcept<const_local_iterator> >(); | |
544 | BOOST_STATIC_ASSERT((boost::is_same<const_local_iterator_category, | |
545 | const_iterator_category>::value)); | |
546 | BOOST_STATIC_ASSERT((boost::is_same<const_local_iterator_difference, | |
547 | const_iterator_difference>::value)); | |
548 | BOOST_STATIC_ASSERT((boost::is_same<const_local_iterator_pointer, | |
549 | const_iterator_pointer>::value)); | |
550 | BOOST_STATIC_ASSERT((boost::is_same<const_local_iterator_reference, | |
551 | const_iterator_reference>::value)); | |
552 | ||
553 | X a; | |
554 | allocator_type m = a.get_allocator(); | |
555 | ||
556 | // Constructors | |
557 | ||
558 | X(10, hf, eq); | |
559 | X a1(10, hf, eq); | |
560 | X(10, hf); | |
561 | X a2(10, hf); | |
562 | X(10); | |
563 | X a3(10); | |
564 | X(); | |
565 | X a4; | |
566 | ||
567 | X(10, hf, eq, m); | |
568 | X a1a(10, hf, eq, m); | |
569 | X(10, hf, m); | |
570 | X a2a(10, hf, m); | |
571 | X(10, m); | |
572 | X a3a(10, m); | |
573 | (X(m)); | |
574 | X a4a(m); | |
575 | ||
576 | test::check_return_type<size_type>::equals(a.erase(k)); | |
577 | ||
578 | const_iterator q1 = a.cbegin(), q2 = a.cend(); | |
579 | test::check_return_type<iterator>::equals(a.erase(q1, q2)); | |
580 | ||
581 | TEST_NOEXCEPT_EXPR(a.clear()); | |
582 | a.clear(); | |
583 | ||
584 | X const b; | |
585 | ||
586 | test::check_return_type<hasher>::equals(b.hash_function()); | |
587 | test::check_return_type<key_equal>::equals(b.key_eq()); | |
588 | ||
589 | test::check_return_type<iterator>::equals(a.find(k)); | |
590 | test::check_return_type<const_iterator>::equals(b.find(k)); | |
591 | test::check_return_type<size_type>::equals(b.count(k)); | |
592 | test::check_return_type<std::pair<iterator, iterator> >::equals( | |
593 | a.equal_range(k)); | |
594 | test::check_return_type<std::pair<const_iterator, const_iterator> >::equals( | |
595 | b.equal_range(k)); | |
596 | test::check_return_type<size_type>::equals(b.bucket_count()); | |
597 | test::check_return_type<size_type>::equals(b.max_bucket_count()); | |
598 | test::check_return_type<size_type>::equals(b.bucket(k)); | |
599 | test::check_return_type<size_type>::equals(b.bucket_size(0)); | |
600 | ||
601 | test::check_return_type<local_iterator>::equals(a.begin(0)); | |
602 | test::check_return_type<const_local_iterator>::equals(b.begin(0)); | |
603 | test::check_return_type<local_iterator>::equals(a.end(0)); | |
604 | test::check_return_type<const_local_iterator>::equals(b.end(0)); | |
605 | ||
606 | test::check_return_type<const_local_iterator>::equals(a.cbegin(0)); | |
607 | test::check_return_type<const_local_iterator>::equals(b.cbegin(0)); | |
608 | test::check_return_type<const_local_iterator>::equals(a.cend(0)); | |
609 | test::check_return_type<const_local_iterator>::equals(b.cend(0)); | |
610 | ||
611 | test::check_return_type<float>::equals(b.load_factor()); | |
612 | test::check_return_type<float>::equals(b.max_load_factor()); | |
613 | a.max_load_factor((float)2.0); | |
614 | a.rehash(100); | |
615 | ||
616 | a.merge(a2); | |
617 | #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) | |
618 | a.merge(rvalue_default<X>()); | |
619 | #endif | |
620 | ||
621 | // Avoid unused variable warnings: | |
622 | ||
623 | sink(a); | |
624 | sink(a1); | |
625 | sink(a2); | |
626 | sink(a3); | |
627 | sink(a4); | |
628 | sink(a1a); | |
629 | sink(a2a); | |
630 | sink(a3a); | |
631 | sink(a4a); | |
7c673cae FG |
632 | } |
633 | ||
634 | template <class X, class Key, class T, class Hash, class Pred> | |
635 | void unordered_copyable_test(X& x, Key& k, T& t, Hash& hf, Pred& eq) | |
636 | { | |
b32b8144 | 637 | unordered_test(x, k, hf, eq); |
7c673cae | 638 | |
b32b8144 FG |
639 | typedef BOOST_DEDUCED_TYPENAME X::iterator iterator; |
640 | typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator; | |
641 | typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type; | |
7c673cae | 642 | |
b32b8144 FG |
643 | X a; |
644 | allocator_type m = a.get_allocator(); | |
7c673cae | 645 | |
b32b8144 FG |
646 | BOOST_DEDUCED_TYPENAME X::value_type* i = 0; |
647 | BOOST_DEDUCED_TYPENAME X::value_type* j = 0; | |
7c673cae | 648 | |
b32b8144 | 649 | // Constructors |
7c673cae | 650 | |
b32b8144 FG |
651 | X(i, j, 10, hf, eq); |
652 | X a5(i, j, 10, hf, eq); | |
653 | X(i, j, 10, hf); | |
654 | X a6(i, j, 10, hf); | |
655 | X(i, j, 10); | |
656 | X a7(i, j, 10); | |
657 | X(i, j); | |
658 | X a8(i, j); | |
7c673cae | 659 | |
b32b8144 FG |
660 | X(i, j, 10, hf, eq, m); |
661 | X a5a(i, j, 10, hf, eq, m); | |
662 | X(i, j, 10, hf, m); | |
663 | X a6a(i, j, 10, hf, m); | |
664 | X(i, j, 10, m); | |
665 | X a7a(i, j, 10, m); | |
7c673cae | 666 | |
b32b8144 FG |
667 | // Not specified for some reason (maybe ambiguity with another constructor?) |
668 | // X(i, j, m); | |
669 | // X a8a(i, j, m); | |
670 | // sink(a8a); | |
7c673cae FG |
671 | |
672 | #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) | |
b32b8144 FG |
673 | std::size_t min_buckets = 10; |
674 | X({t}); | |
675 | X({t}, min_buckets); | |
676 | X({t}, min_buckets, hf); | |
677 | X({t}, min_buckets, hf, eq); | |
678 | // X({t}, m); | |
679 | X({t}, min_buckets, m); | |
680 | X({t}, min_buckets, hf, m); | |
681 | X({t}, min_buckets, hf, eq, m); | |
7c673cae FG |
682 | #endif |
683 | ||
b32b8144 FG |
684 | X const b; |
685 | sink(X(b)); | |
686 | X a9(b); | |
687 | a = b; | |
688 | ||
689 | sink(X(b, m)); | |
690 | X a9a(b, m); | |
7c673cae | 691 | |
b32b8144 FG |
692 | X b1; |
693 | b1.insert(t); | |
694 | X a9b(b1); | |
695 | sink(a9b); | |
696 | X a9c(b1, m); | |
697 | sink(a9c); | |
7c673cae | 698 | |
b32b8144 | 699 | const_iterator q = a.cbegin(); |
7c673cae | 700 | |
b32b8144 FG |
701 | test::check_return_type<iterator>::equals(a.insert(q, t)); |
702 | test::check_return_type<iterator>::equals(a.emplace_hint(q, t)); | |
7c673cae | 703 | |
b32b8144 | 704 | a.insert(i, j); |
7c673cae | 705 | #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) |
b32b8144 FG |
706 | std::initializer_list<T> list = {t}; |
707 | a.insert(list); | |
708 | a.insert({t, t, t}); | |
709 | ||
710 | #if !BOOST_WORKAROUND(BOOST_MSVC, < 1900) && \ | |
711 | (!defined(__clang__) || __clang_major__ >= 4 || \ | |
712 | (__clang_major__ == 3 && __clang_minor__ >= 4)) | |
713 | a.insert({}); | |
714 | a.insert({t}); | |
715 | a.insert({t, t}); | |
7c673cae FG |
716 | #endif |
717 | #endif | |
718 | ||
b32b8144 FG |
719 | X a10; |
720 | a10.insert(t); | |
721 | q = a10.cbegin(); | |
722 | test::check_return_type<iterator>::equals(a10.erase(q)); | |
723 | ||
724 | // Avoid unused variable warnings: | |
725 | ||
726 | sink(a); | |
727 | sink(a5); | |
728 | sink(a6); | |
729 | sink(a7); | |
730 | sink(a8); | |
731 | sink(a9); | |
732 | sink(a5a); | |
733 | sink(a6a); | |
734 | sink(a7a); | |
735 | sink(a9a); | |
736 | ||
737 | typedef BOOST_DEDUCED_TYPENAME X::node_type node_type; | |
738 | typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type; | |
739 | node_type const n_const = a.extract(a.begin()); | |
740 | test::check_return_type<allocator_type>::equals(n_const.get_allocator()); | |
7c673cae FG |
741 | } |
742 | ||
743 | template <class X, class Key, class T, class Hash, class Pred> | |
744 | void unordered_movable_test(X& x, Key& k, T& /* t */, Hash& hf, Pred& eq) | |
745 | { | |
b32b8144 | 746 | unordered_test(x, k, hf, eq); |
7c673cae | 747 | |
b32b8144 FG |
748 | typedef BOOST_DEDUCED_TYPENAME X::iterator iterator; |
749 | typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator; | |
750 | typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type; | |
7c673cae FG |
751 | |
752 | #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) | |
b32b8144 FG |
753 | X x1(rvalue_default<X>()); |
754 | X x2(boost::move(x1)); | |
755 | x1 = rvalue_default<X>(); | |
756 | x2 = boost::move(x1); | |
7c673cae FG |
757 | #endif |
758 | ||
b32b8144 FG |
759 | X a; |
760 | allocator_type m = a.get_allocator(); | |
761 | ||
762 | test::minimal::constructor_param* i = 0; | |
763 | test::minimal::constructor_param* j = 0; | |
764 | ||
765 | // Constructors | |
766 | ||
767 | X(i, j, 10, hf, eq); | |
768 | X a5(i, j, 10, hf, eq); | |
769 | X(i, j, 10, hf); | |
770 | X a6(i, j, 10, hf); | |
771 | X(i, j, 10); | |
772 | X a7(i, j, 10); | |
773 | X(i, j); | |
774 | X a8(i, j); | |
775 | ||
776 | X(i, j, 10, hf, eq, m); | |
777 | X a5a(i, j, 10, hf, eq, m); | |
778 | X(i, j, 10, hf, m); | |
779 | X a6a(i, j, 10, hf, m); | |
780 | X(i, j, 10, m); | |
781 | X a7a(i, j, 10, m); | |
782 | ||
783 | // Not specified for some reason (maybe ambiguity with another constructor?) | |
784 | // X(i, j, m); | |
785 | // X a8a(i, j, m); | |
786 | // sink(a8a); | |
787 | ||
788 | const_iterator q = a.cbegin(); | |
789 | ||
790 | test::minimal::constructor_param v; | |
791 | a.emplace(v); | |
792 | test::check_return_type<iterator>::equals(a.emplace_hint(q, v)); | |
793 | ||
794 | T v1(v); | |
795 | a.emplace(boost::move(v1)); | |
796 | T v2(v); | |
797 | a.insert(boost::move(v2)); | |
798 | T v3(v); | |
799 | test::check_return_type<iterator>::equals(a.emplace_hint(q, boost::move(v3))); | |
800 | T v4(v); | |
801 | test::check_return_type<iterator>::equals(a.insert(q, boost::move(v4))); | |
802 | ||
803 | a.insert(i, j); | |
804 | ||
805 | X a10; | |
806 | T v5(v); | |
807 | a10.insert(boost::move(v5)); | |
808 | q = a10.cbegin(); | |
809 | test::check_return_type<iterator>::equals(a10.erase(q)); | |
810 | ||
811 | // Avoid unused variable warnings: | |
812 | ||
813 | sink(a); | |
814 | sink(a5); | |
815 | sink(a6); | |
816 | sink(a7); | |
817 | sink(a8); | |
818 | sink(a5a); | |
819 | sink(a6a); | |
820 | sink(a7a); | |
821 | sink(a10); | |
7c673cae FG |
822 | } |
823 | ||
b32b8144 | 824 | template <class X, class T> void unordered_set_member_test(X& x, T& t) |
7c673cae | 825 | { |
b32b8144 FG |
826 | X x1(x); |
827 | x1.insert(t); | |
828 | x1.begin()->dummy_member(); | |
829 | x1.cbegin()->dummy_member(); | |
7c673cae FG |
830 | } |
831 | ||
b32b8144 | 832 | template <class X, class T> void unordered_map_member_test(X& x, T& t) |
7c673cae | 833 | { |
b32b8144 FG |
834 | X x1(x); |
835 | x1.insert(t); | |
836 | x1.begin()->first.dummy_member(); | |
837 | x1.cbegin()->first.dummy_member(); | |
838 | x1.begin()->second.dummy_member(); | |
839 | x1.cbegin()->second.dummy_member(); | |
7c673cae | 840 | } |