From 0be800472489f09634da383c661dadee3d52f53a Mon Sep 17 00:00:00 2001 From: Daniel James Date: Tue, 20 May 2008 15:24:20 +0000 Subject: [PATCH] Merge in a few small changes to unordered. Merged revisions 45277-45280 via svnmerge from https://svn.boost.org/svn/boost/branches/unordered/trunk ........ r45277 | danieljames | 2008-05-11 14:09:05 +0100 (Sun, 11 May 2008) | 2 lines Put the prime number list into a template so that they (hopefully) only get included once. ........ r45278 | danieljames | 2008-05-11 14:12:27 +0100 (Sun, 11 May 2008) | 2 lines Add a quick explanation for an odd looking constructor. ........ r45279 | danieljames | 2008-05-11 14:12:37 +0100 (Sun, 11 May 2008) | 2 lines No need to include the exception objects in helpers/strong.hpp. Now helpers on depend on the forwarding header from the objects. ........ r45280 | danieljames | 2008-05-11 14:14:31 +0100 (Sun, 11 May 2008) | 1 line Instead of comparing potentially dangling pointers in move_tests check if any objects have been constructed. ........ [SVN r45574] --- include/boost/unordered/detail/hash_table.hpp | 26 +++++--- test/helpers/count.hpp | 61 +++++++++++++++++++ test/helpers/strong.hpp | 2 +- test/objects/test.hpp | 5 +- test/unordered/move_tests.cpp | 34 +++++------ test/unordered/unnecessary_copy_tests.cpp | 14 ++++- 6 files changed, 113 insertions(+), 29 deletions(-) create mode 100644 test/helpers/count.hpp diff --git a/include/boost/unordered/detail/hash_table.hpp b/include/boost/unordered/detail/hash_table.hpp index b238c7a7..f3eba852 100644 --- a/include/boost/unordered/detail/hash_table.hpp +++ b/include/boost/unordered/detail/hash_table.hpp @@ -78,7 +78,13 @@ namespace boost { // prime number list, accessor - static const std::size_t prime_list[] = { + template struct prime_list_template + { + static std::size_t const value[]; + }; + + template + std::size_t const prime_list_template::value[] = { 53ul, 97ul, 193ul, 389ul, 769ul, 1543ul, 3079ul, 6151ul, 12289ul, 24593ul, 49157ul, 98317ul, 196613ul, 393241ul, 786433ul, @@ -86,12 +92,15 @@ namespace boost { 50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul, 1610612741ul, 3221225473ul, 4294967291ul }; + typedef prime_list_template prime_list; + // no throw inline std::size_t next_prime(std::size_t n) { - std::size_t const* const prime_list_end = prime_list + - sizeof(prime_list) / sizeof(*prime_list); + std::size_t const* const prime_list_begin = prime_list::value; + std::size_t const* const prime_list_end = prime_list_begin + + sizeof(prime_list::value) / sizeof(*prime_list::value); std::size_t const* bound = - std::lower_bound(prime_list,prime_list_end, n); + std::lower_bound(prime_list_begin, prime_list_end, n); if(bound == prime_list_end) bound--; return *bound; @@ -99,11 +108,12 @@ namespace boost { // no throw inline std::size_t prev_prime(std::size_t n) { - std::size_t const* const prime_list_end = prime_list + - sizeof(prime_list) / sizeof(*prime_list); + std::size_t const* const prime_list_begin = prime_list::value; + std::size_t const* const prime_list_end = prime_list_begin + + sizeof(prime_list::value) / sizeof(*prime_list::value); std::size_t const* bound = - std::upper_bound(prime_list,prime_list_end, n); - if(bound != prime_list) + std::upper_bound(prime_list_begin,prime_list_end, n); + if(bound != prime_list_begin) bound--; return *bound; } diff --git a/test/helpers/count.hpp b/test/helpers/count.hpp new file mode 100644 index 00000000..6e3478da --- /dev/null +++ b/test/helpers/count.hpp @@ -0,0 +1,61 @@ + +// Copyright 2008 Daniel James. +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or move at http://www.boost.org/LICENSE_1_0.txt) + +#if !defined(BOOST_UNORDERED_TEST_HELPERS_COUNT_HEAD) +#define BOOST_UNORDERED_TEST_HELPERS_COUNT_HEAD + +namespace test { + struct object_count { + int instances; + int constructions; + + object_count() : instances(0), constructions(0) {} + void reset() { *this = object_count(); } + + void construct() { + ++instances; + ++constructions; + } + + void destruct() { + if(instances == 0) { + BOOST_ERROR("Unbalanced constructions."); + } + else { + --instances; + } + } + + bool operator==(object_count const& x) const { + return instances == x.instances && + constructions == x.constructions; + } + + bool operator!=(object_count const& x) const { + return !(*this == x); + } + }; + + template + struct counted_object + { + static object_count count_; + + counted_object() { count_.construct(); } + counted_object(counted_object const&) { count_.construct(); } + ~counted_object() { count_.destruct(); } + }; + + template object_count counted_object::count_; + + struct globally_counted_object + : counted_object {}; + + namespace { + object_count& global_object_count = globally_counted_object::count_; + } +} + +#endif diff --git a/test/helpers/strong.hpp b/test/helpers/strong.hpp index e71e8b5b..c23e66c2 100644 --- a/test/helpers/strong.hpp +++ b/test/helpers/strong.hpp @@ -11,7 +11,7 @@ #include "./metafunctions.hpp" #include "./equivalent.hpp" #include "./list.hpp" -#include "../objects/exception.hpp" +#include "./exception_test.hpp" namespace test { diff --git a/test/objects/test.hpp b/test/objects/test.hpp index d8555bec..fd1b6ddf 100644 --- a/test/objects/test.hpp +++ b/test/objects/test.hpp @@ -11,7 +11,8 @@ #include #include #include "../helpers/fwd.hpp" -#include "memory.hpp" +#include "../helpers/count.hpp" +#include "./memory.hpp" #include namespace test @@ -25,7 +26,7 @@ namespace test template class allocator; object generate(object const*); - class object + class object : globally_counted_object { friend class hash; friend class equal_to; diff --git a/test/unordered/move_tests.cpp b/test/unordered/move_tests.cpp index 966734a9..83dd4312 100644 --- a/test/unordered/move_tests.cpp +++ b/test/unordered/move_tests.cpp @@ -23,15 +23,15 @@ namespace move_tests template T create(test::random_values const& v, - BOOST_DEDUCED_TYPENAME T::value_type const*& first) { + test::object_count& count) { T x(v.begin(), v.end()); - first = &*x.begin(); + count = test::global_object_count; return x; } template T create(test::random_values const& v, - BOOST_DEDUCED_TYPENAME T::value_type const*& first, + test::object_count& count, BOOST_DEDUCED_TYPENAME T::hasher hf, BOOST_DEDUCED_TYPENAME T::key_equal eq, BOOST_DEDUCED_TYPENAME T::allocator_type al, @@ -39,7 +39,7 @@ namespace move_tests T x(0, hf, eq, al); x.max_load_factor(mlf); x.insert(v.begin(), v.end()); - first = &*x.begin(); + count = test::global_object_count; return x; } @@ -62,9 +62,9 @@ namespace move_tests { test::random_values v(1000); - BOOST_DEDUCED_TYPENAME T::value_type const* first = 0; - T y(create(v, first)); - BOOST_CHECK(first == &*y.begin()); + test::object_count count; + T y(create(v, count)); + BOOST_CHECK(count == test::global_object_count); test::check_container(y, v); test::check_equivalent_keys(y); } @@ -75,10 +75,10 @@ namespace move_tests { { test::random_values v(500); - BOOST_DEDUCED_TYPENAME T::value_type const* first = 0; + test::object_count count; T y; - y = create(v, first); - BOOST_CHECK(first == &*y.begin()); + y = create(v, count); + BOOST_CHECK(count == test::global_object_count); test::check_container(y, v); test::check_equivalent_keys(y); } @@ -95,12 +95,12 @@ namespace move_tests BOOST_DEDUCED_TYPENAME T::allocator_type al(1); BOOST_DEDUCED_TYPENAME T::allocator_type al2(2); - BOOST_DEDUCED_TYPENAME T::value_type const* first; + test::object_count count; { test::random_values v(500); - T y(create(v, first, hf, eq, al, 0.5)); - BOOST_CHECK(first == &*y.begin()); + T y(create(v, count, hf, eq, al, 0.5)); + BOOST_CHECK(count == test::global_object_count); test::check_container(y, v); BOOST_CHECK(test::equivalent(y.hash_function(), hf)); BOOST_CHECK(test::equivalent(y.key_eq(), eq)); @@ -112,8 +112,8 @@ namespace move_tests { // TODO: To do this correctly requires the fancy new allocator stuff. test::random_values v(500); - T y(create(v, first, hf, eq, al, 2.0), al2); - BOOST_CHECK(first != &*y.begin()); + T y(create(v, count, hf, eq, al, 2.0), al2); + BOOST_CHECK(count != test::global_object_count); test::check_container(y, v); BOOST_CHECK(test::equivalent(y.hash_function(), hf)); BOOST_CHECK(test::equivalent(y.key_eq(), eq)); @@ -124,8 +124,8 @@ namespace move_tests { test::random_values v(25); - T y(create(v, first, hf, eq, al, 1.0), al); - BOOST_CHECK(first == &*y.begin()); + T y(create(v, count, hf, eq, al, 1.0), al); + BOOST_CHECK(count == test::global_object_count); test::check_container(y, v); BOOST_CHECK(test::equivalent(y.hash_function(), hf)); BOOST_CHECK(test::equivalent(y.key_eq(), eq)); diff --git a/test/unordered/unnecessary_copy_tests.cpp b/test/unordered/unnecessary_copy_tests.cpp index f28daed3..87e6d158 100644 --- a/test/unordered/unnecessary_copy_tests.cpp +++ b/test/unordered/unnecessary_copy_tests.cpp @@ -15,7 +15,19 @@ namespace unnecessary_copy_tests static int moves; count_copies() : tag_(0) { ++copies; } explicit count_copies(int tag) : tag_(tag) { ++copies; } - count_copies(count_copies const&, count_copies const& x) : tag_(x.tag_) { ++copies; } + + // This bizarre constructor is an attempt to confuse emplace. + // + // unordered_map x: + // x.emplace(count_copies(1), count_copies(2)); + // x.emplace(count_copies(1), count_copies(2), count_copies(3)); + // + // The first emplace should use the single argument constructor twice. + // The second emplace should use the single argument contructor for + // the key, and this constructor for the value. + count_copies(count_copies const&, count_copies const& x) + : tag_(x.tag_) { ++copies; } + count_copies(count_copies const& x) : tag_(x.tag_) { ++copies; } #if defined(BOOST_HAS_RVALUE_REFS) count_copies(count_copies&& x) : tag_(x.tag_) {