| 
									
										
										
										
											2006-05-17 17:19:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-09 20:56:23 +00:00
										 |  |  | // Copyright 2006-2009 Daniel James.
 | 
					
						
							| 
									
										
										
										
											2006-07-01 22:31:26 +00:00
										 |  |  | // Distributed under the Boost Software License, Version 1.0. (See accompanying
 | 
					
						
							|  |  |  | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 | 
					
						
							| 
									
										
										
										
											2006-05-17 17:19:16 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | // This header contains metafunctions/functions to get the equivalent
 | 
					
						
							|  |  |  | // associative container for an unordered container, and compare the contents.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if !defined(BOOST_UNORDERED_TEST_HELPERS_INVARIANT_HEADER)
 | 
					
						
							|  |  |  | #define BOOST_UNORDERED_TEST_HELPERS_INVARIANT_HEADER
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "./helpers.hpp"
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  | #include "./metafunctions.hpp"
 | 
					
						
							|  |  |  | #include <cmath>
 | 
					
						
							|  |  |  | #include <set>
 | 
					
						
							| 
									
										
										
										
											2006-05-17 17:19:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-08-14 09:55:30 +00:00
										 |  |  | #if defined(BOOST_MSVC)
 | 
					
						
							|  |  |  | #pragma warning(push)
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  | #pragma warning(disable : 4127) // conditional expression is constant
 | 
					
						
							|  |  |  | #pragma warning(disable : 4267) // conversion from 'size_t' to 'unsigned int',
 | 
					
						
							| 
									
										
										
										
											2010-01-04 22:49:39 +00:00
										 |  |  |                                 // possible loss of data
 | 
					
						
							| 
									
										
										
										
											2007-08-14 09:55:30 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  | namespace test { | 
					
						
							|  |  |  | template <class X> void check_equivalent_keys(X const& x1) | 
					
						
							| 
									
										
										
										
											2006-05-17 17:19:16 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |     BOOST_DEDUCED_TYPENAME X::key_equal eq = x1.key_eq(); | 
					
						
							|  |  |  |     typedef BOOST_DEDUCED_TYPENAME X::key_type key_type; | 
					
						
							|  |  |  |     std::set<key_type, std::less<key_type> > found_; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     BOOST_DEDUCED_TYPENAME X::const_iterator it = x1.begin(), end = x1.end(); | 
					
						
							|  |  |  |     BOOST_DEDUCED_TYPENAME X::size_type size = 0; | 
					
						
							|  |  |  |     while (it != end) { | 
					
						
							|  |  |  |         // First test that the current key has not occurred before, required
 | 
					
						
							|  |  |  |         // to test either that keys are unique or that equivalent keys are
 | 
					
						
							|  |  |  |         // adjacent. (6.3.1/6)
 | 
					
						
							|  |  |  |         key_type key = get_key<X>(*it); | 
					
						
							|  |  |  |         if (!found_.insert(key).second) | 
					
						
							|  |  |  |             BOOST_ERROR("Elements with equivalent keys aren't adjacent."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Iterate over equivalent keys, counting them.
 | 
					
						
							|  |  |  |         unsigned int count = 0; | 
					
						
							|  |  |  |         do { | 
					
						
							|  |  |  |             ++it; | 
					
						
							|  |  |  |             ++count; | 
					
						
							|  |  |  |             ++size; | 
					
						
							|  |  |  |         } while (it != end && eq(get_key<X>(*it), key)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // If the container has unique keys, test that there's only one.
 | 
					
						
							|  |  |  |         // Since the previous test makes sure that all equivalent keys are
 | 
					
						
							|  |  |  |         // adjacent, this is all the equivalent keys - so the test is
 | 
					
						
							|  |  |  |         // sufficient. (6.3.1/6 again).
 | 
					
						
							|  |  |  |         if (test::has_unique_keys<X>::value && count != 1) | 
					
						
							|  |  |  |             BOOST_ERROR("Non-unique key."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (x1.count(key) != count) { | 
					
						
							|  |  |  |             BOOST_ERROR("Incorrect output of count."); | 
					
						
							|  |  |  |             std::cerr << x1.count(key) << "," << count << "\n"; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2006-05-17 17:19:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |         // Check that the keys are in the correct bucket and are
 | 
					
						
							|  |  |  |         // adjacent in the bucket.
 | 
					
						
							|  |  |  |         BOOST_DEDUCED_TYPENAME X::size_type bucket = x1.bucket(key); | 
					
						
							|  |  |  |         BOOST_DEDUCED_TYPENAME X::const_local_iterator lit = x1.begin(bucket), | 
					
						
							|  |  |  |                                                        lend = x1.end(bucket); | 
					
						
							|  |  |  |         for (; lit != lend && !eq(get_key<X>(*lit), key); ++lit) | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         if (lit == lend) | 
					
						
							|  |  |  |             BOOST_ERROR("Unable to find element with a local_iterator"); | 
					
						
							|  |  |  |         unsigned int count2 = 0; | 
					
						
							|  |  |  |         for (; lit != lend && eq(get_key<X>(*lit), key); ++lit) | 
					
						
							|  |  |  |             ++count2; | 
					
						
							|  |  |  |         if (count != count2) | 
					
						
							|  |  |  |             BOOST_ERROR("Element count doesn't match local_iterator."); | 
					
						
							|  |  |  |         for (; lit != lend; ++lit) { | 
					
						
							|  |  |  |             if (eq(get_key<X>(*lit), key)) { | 
					
						
							|  |  |  |                 BOOST_ERROR("Non-adjacent element with equivalent key " | 
					
						
							|  |  |  |                             "in bucket."); | 
					
						
							|  |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2011-04-16 18:47:33 +00:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2006-05-17 17:19:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |     // Check that size matches up.
 | 
					
						
							| 
									
										
										
										
											2012-08-25 21:55:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |     if (x1.size() != size) { | 
					
						
							|  |  |  |         BOOST_ERROR("x1.size() doesn't match actual size."); | 
					
						
							|  |  |  |         std::cout << x1.size() << "/" << size << std::endl; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-08-25 21:55:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |     // Check the load factor.
 | 
					
						
							| 
									
										
										
										
											2012-08-25 21:55:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |     float load_factor = | 
					
						
							|  |  |  |         size == 0 ? 0 : static_cast<float>(size) / | 
					
						
							|  |  |  |                             static_cast<float>(x1.bucket_count()); | 
					
						
							|  |  |  |     using namespace std; | 
					
						
							|  |  |  |     if (fabs(x1.load_factor() - load_factor) > x1.load_factor() / 64) | 
					
						
							|  |  |  |         BOOST_ERROR("x1.load_factor() doesn't match actual load_factor."); | 
					
						
							| 
									
										
										
										
											2012-08-25 21:55:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |     // Check that size in the buckets matches up.
 | 
					
						
							| 
									
										
										
										
											2012-08-25 21:55:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |     BOOST_DEDUCED_TYPENAME X::size_type bucket_size = 0; | 
					
						
							| 
									
										
										
										
											2012-08-25 21:55:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |     for (BOOST_DEDUCED_TYPENAME X::size_type i = 0; i < x1.bucket_count(); | 
					
						
							|  |  |  |          ++i) { | 
					
						
							|  |  |  |         for (BOOST_DEDUCED_TYPENAME X::const_local_iterator | 
					
						
							|  |  |  |                  begin2 = x1.begin(i), | 
					
						
							|  |  |  |                  end2 = x1.end(i); | 
					
						
							|  |  |  |              begin2 != end2; ++begin2) { | 
					
						
							|  |  |  |             ++bucket_size; | 
					
						
							| 
									
										
										
										
											2012-08-25 21:55:18 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-08-25 21:55:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  |     if (x1.size() != bucket_size) { | 
					
						
							|  |  |  |         BOOST_ERROR("x1.size() doesn't match bucket size."); | 
					
						
							|  |  |  |         std::cout << x1.size() << "/" << bucket_size << std::endl; | 
					
						
							| 
									
										
										
										
											2006-05-17 17:19:16 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-02-19 13:05:17 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2006-05-17 17:19:16 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-08-14 09:55:30 +00:00
										 |  |  | #if defined(BOOST_MSVC)
 | 
					
						
							|  |  |  | #pragma warning(pop)
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-17 17:19:16 +00:00
										 |  |  | #endif
 |