Merge pull request #143 from cmazakas/feature/no-alloc-default-construction

Update internal table to no longer allocate on default constructions and when the bucket count is 0
This commit is contained in:
Christian Mazakas
2022-08-31 09:21:13 -07:00
committed by GitHub
10 changed files with 297 additions and 24 deletions

View File

@ -494,11 +494,25 @@ namespace boost {
group_pointer groups; group_pointer groups;
public: public:
grouped_bucket_array()
: empty_value<node_allocator_type>(
empty_init_t(), node_allocator_type()),
size_index_(0), size_(0), buckets(), groups()
{
}
grouped_bucket_array(size_type n, const Allocator& al) grouped_bucket_array(size_type n, const Allocator& al)
: empty_value<node_allocator_type>(empty_init_t(), al), : empty_value<node_allocator_type>(empty_init_t(), al),
size_index_(size_policy::size_index(n)), size_index_(0),
size_(size_policy::size(size_index_)), buckets(), groups() size_(0), buckets(), groups()
{ {
if (n == 0) {
return;
}
size_index_ = size_policy::size_index(n);
size_ = size_policy::size(size_index_);
bucket_allocator_type bucket_alloc = this->get_bucket_allocator(); bucket_allocator_type bucket_alloc = this->get_bucket_allocator();
group_allocator_type group_alloc = this->get_group_allocator(); group_allocator_type group_alloc = this->get_group_allocator();

View File

@ -200,7 +200,7 @@ namespace boost {
template <typename Types> struct table; template <typename Types> struct table;
static const float minimum_max_load_factor = 1e-3f; static const float minimum_max_load_factor = 1e-3f;
static const std::size_t default_bucket_count = 11; static const std::size_t default_bucket_count = 0;
struct move_tag struct move_tag
{ {
@ -2075,9 +2075,16 @@ namespace boost {
// From 6.3.1/13: // From 6.3.1/13:
// Only resize when size >= mlf_ * count // Only resize when size >= mlf_ * count
max_load_ = boost::unordered::detail::double_to_size( std::size_t const bc = buckets_.bucket_count();
floor(static_cast<double>(mlf_) *
static_cast<double>(buckets_.bucket_count()))); // it's important we do the `bc == 0` check here because the `mlf_`
// can be specified to be infinity. The operation `n * INF` is `INF`
// for all `n > 0` but NaN for `n == 0`.
//
max_load_ =
bc == 0 ? 0
: boost::unordered::detail::double_to_size(floor(
static_cast<double>(mlf_) * static_cast<double>(bc)));
} }
void max_load_factor(float z) void max_load_factor(float z)
@ -2090,6 +2097,12 @@ namespace boost {
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// Constructors // Constructors
table()
: functions(hasher(), key_equal()), size_(0), mlf_(1.0f),
max_load_(0)
{
}
table(std::size_t num_buckets, hasher const& hf, key_equal const& eq, table(std::size_t num_buckets, hasher const& hf, key_equal const& eq,
node_allocator_type const& a) node_allocator_type const& a)
: functions(hf, eq), size_(0), mlf_(1.0f), max_load_(0), : functions(hf, eq), size_(0), mlf_(1.0f), max_load_(0),
@ -2361,7 +2374,10 @@ namespace boost {
template <typename UniqueType> template <typename UniqueType>
void move_assign(table& x, UniqueType is_unique, false_type) void move_assign(table& x, UniqueType is_unique, false_type)
{ {
reserve(x.size_); if (x.size_ > 0) {
reserve(x.size_);
}
if (node_alloc() == x.node_alloc()) { if (node_alloc() == x.node_alloc()) {
move_assign_equal_alloc(x); move_assign_equal_alloc(x);
} else { } else {
@ -2390,7 +2406,9 @@ namespace boost {
{ {
mlf_ = x.mlf_; mlf_ = x.mlf_;
recalculate_max_load(); recalculate_max_load();
this->reserve_for_insert(x.size_); if (x.size_ > 0) {
this->reserve_for_insert(x.size_);
}
this->clear_impl(); this->clear_impl();
} }
BOOST_CATCH(...) BOOST_CATCH(...)

View File

@ -1664,8 +1664,6 @@ namespace boost {
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
unordered_map<K, T, H, P, A>::unordered_map() unordered_map<K, T, H, P, A>::unordered_map()
: table_(boost::unordered::detail::default_bucket_count, hasher(),
key_equal(), allocator_type())
{ {
} }
@ -2147,8 +2145,6 @@ namespace boost {
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
unordered_multimap<K, T, H, P, A>::unordered_multimap() unordered_multimap<K, T, H, P, A>::unordered_multimap()
: table_(boost::unordered::detail::default_bucket_count, hasher(),
key_equal(), allocator_type())
{ {
} }

View File

@ -1266,8 +1266,6 @@ namespace boost {
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
unordered_set<T, H, P, A>::unordered_set() unordered_set<T, H, P, A>::unordered_set()
: table_(boost::unordered::detail::default_bucket_count, hasher(),
key_equal(), allocator_type())
{ {
} }
@ -1664,8 +1662,6 @@ namespace boost {
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
unordered_multiset<T, H, P, A>::unordered_multiset() unordered_multiset<T, H, P, A>::unordered_multiset()
: table_(boost::unordered::detail::default_bucket_count, hasher(),
key_equal(), allocator_type())
{ {
} }

View File

@ -95,7 +95,7 @@ void insert_rehash_exception_test(
T*, Inserter insert, test::random_generator gen) T*, Inserter insert, test::random_generator gen)
{ {
for (int i = 0; i < 5; ++i) { for (int i = 0; i < 5; ++i) {
T x; T x(1);
rehash_prep(x); rehash_prep(x);
test::random_values<T> v2(5, gen); test::random_values<T> v2(5, gen);
@ -393,7 +393,7 @@ template <typename T>
void insert_range_rehash_exception_test(T*, test::random_generator gen) void insert_range_rehash_exception_test(T*, test::random_generator gen)
{ {
for (int i = 0; i < 5; ++i) { for (int i = 0; i < 5; ++i) {
T x; T x(1);
rehash_prep(x); rehash_prep(x);
test::random_values<T> v2(5, gen); test::random_values<T> v2(5, gen);

View File

@ -45,6 +45,7 @@ namespace assign_tests {
BOOST_TEST(x.empty()); BOOST_TEST(x.empty());
BOOST_TEST(test::equivalent(x.hash_function(), hf)); BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq)); BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::detail::tracker.count_allocations == 0);
} }
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests1.2\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests1.2\n";
@ -94,6 +95,7 @@ namespace assign_tests {
BOOST_TEST(test::equivalent(x1.key_eq(), eq1)); BOOST_TEST(test::equivalent(x1.key_eq(), eq1));
BOOST_TEST(test::equivalent(x2.hash_function(), hf1)); BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
BOOST_TEST(test::equivalent(x2.key_eq(), eq1)); BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
BOOST_TEST(test::detail::tracker.count_allocations == 0);
test::check_container(x1, x2); test::check_container(x1, x2);
} }

View File

@ -35,6 +35,7 @@ namespace constructor_tests {
T x(0, hf, eq); T x(0, hf, eq);
BOOST_TEST(x.empty()); BOOST_TEST(x.empty());
BOOST_TEST_EQ(x.bucket_count(), 0u);
BOOST_TEST(test::equivalent(x.hash_function(), hf)); BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq)); BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al)); BOOST_TEST(test::equivalent(x.get_allocator(), al));
@ -73,6 +74,7 @@ namespace constructor_tests {
T x; T x;
BOOST_TEST(x.empty()); BOOST_TEST(x.empty());
BOOST_TEST_EQ(x.bucket_count(), 0u);
BOOST_TEST(test::equivalent(x.hash_function(), hf)); BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq)); BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al)); BOOST_TEST(test::equivalent(x.get_allocator(), al));
@ -140,6 +142,7 @@ namespace constructor_tests {
T x(0, hf, eq, al); T x(0, hf, eq, al);
BOOST_TEST(x.empty()); BOOST_TEST(x.empty());
BOOST_TEST_EQ(x.bucket_count(), 0u);
BOOST_TEST(test::equivalent(x.hash_function(), hf)); BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq)); BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al)); BOOST_TEST(test::equivalent(x.get_allocator(), al));
@ -166,6 +169,7 @@ namespace constructor_tests {
T x(al); T x(al);
BOOST_TEST(x.empty()); BOOST_TEST(x.empty());
BOOST_TEST_EQ(x.bucket_count(), 0u);
BOOST_TEST(test::equivalent(x.hash_function(), hf)); BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq)); BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al)); BOOST_TEST(test::equivalent(x.get_allocator(), al));
@ -325,6 +329,7 @@ namespace constructor_tests {
T x(list); T x(list);
BOOST_TEST(x.empty()); BOOST_TEST(x.empty());
BOOST_TEST_EQ(x.bucket_count(), 0u);
BOOST_TEST(test::equivalent(x.hash_function(), hf)); BOOST_TEST(test::equivalent(x.hash_function(), hf));
BOOST_TEST(test::equivalent(x.key_eq(), eq)); BOOST_TEST(test::equivalent(x.key_eq(), eq));
BOOST_TEST(test::equivalent(x.get_allocator(), al)); BOOST_TEST(test::equivalent(x.get_allocator(), al));
@ -380,6 +385,104 @@ namespace constructor_tests {
#endif #endif
} }
template <class T>
void no_alloc_default_construct_test(T*, test::random_generator)
{
UNORDERED_SUB_TEST("Construct 1")
{
T x;
BOOST_TEST_EQ(x.bucket_count(), 0u);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
}
UNORDERED_SUB_TEST("Construct 2")
{
{
T x(0);
BOOST_TEST_EQ(x.bucket_count(), 0u);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
}
{
T x(1);
BOOST_TEST_GT(x.bucket_count(), 0u);
BOOST_TEST_GT(test::detail::tracker.count_allocations, 0u);
}
}
UNORDERED_SUB_TEST("Construct 3")
{
test::random_values<T> v;
T x(v.begin(), v.end());
BOOST_TEST_EQ(x.bucket_count(), 0u);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
}
UNORDERED_SUB_TEST("Construct 4")
{
{
test::random_values<T> v;
T x(v.begin(), v.end(), 0);
BOOST_TEST_EQ(x.bucket_count(), 0u);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
}
{
test::random_values<T> v;
T x(v.begin(), v.end(), 1);
BOOST_TEST_GT(x.bucket_count(), 0u);
BOOST_TEST_GT(test::detail::tracker.count_allocations, 0u);
}
}
UNORDERED_SUB_TEST("Construct 5")
{
typename T::allocator_type al;
{
T x(al);
BOOST_TEST_EQ(x.bucket_count(), 0u);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
}
}
UNORDERED_SUB_TEST("Construct 6")
{
typename T::allocator_type al;
T x(0, al);
BOOST_TEST_EQ(x.bucket_count(), 0u);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
}
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_SUB_TEST("Initializer list 1")
{
std::initializer_list<typename T::value_type> list;
T x(list);
BOOST_TEST_EQ(x.bucket_count(), 0u);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
}
UNORDERED_SUB_TEST("Initializer list 2")
{
{
std::initializer_list<typename T::value_type> list;
T x(list, 0);
BOOST_TEST_EQ(x.bucket_count(), 0u);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
}
{
std::initializer_list<typename T::value_type> list;
T x(list, 1);
BOOST_TEST_GT(x.bucket_count(), 0u);
BOOST_TEST_GT(test::detail::tracker.count_allocations, 0u);
}
}
#endif
}
template <class T> template <class T>
void map_constructor_test(T*, test::random_generator const& generator) void map_constructor_test(T*, test::random_generator const& generator)
{ {
@ -422,6 +525,10 @@ namespace constructor_tests {
((test_map_std_alloc)(test_map)(test_multimap))( ((test_map_std_alloc)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range))) (default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(no_alloc_default_construct_test,
((test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range)))
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST (test_default_initializer_list) { UNORDERED_AUTO_TEST (test_default_initializer_list) {

View File

@ -43,6 +43,23 @@ namespace copy_tests {
BOOST_TEST(x.max_load_factor() == y.max_load_factor()); BOOST_TEST(x.max_load_factor() == y.max_load_factor());
BOOST_TEST(test::selected_count(y.get_allocator()) == BOOST_TEST(test::selected_count(y.get_allocator()) ==
(allocator_type::is_select_on_copy)); (allocator_type::is_select_on_copy));
BOOST_TEST(test::detail::tracker.count_allocations == 0);
test::check_equivalent_keys(y);
}
{
test::check_instances check_;
T x(0);
T y(x);
BOOST_TEST(y.empty());
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(x.max_load_factor() == y.max_load_factor());
BOOST_TEST(test::selected_count(y.get_allocator()) ==
(allocator_type::is_select_on_copy));
BOOST_TEST(test::detail::tracker.count_allocations == 0);
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
} }
@ -91,6 +108,22 @@ namespace copy_tests {
typedef typename T::allocator_type allocator_type; typedef typename T::allocator_type allocator_type;
{
test::check_instances check_;
T x(0, hf, eq, al);
T y(x);
BOOST_TEST(y.empty());
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(x.max_load_factor() == y.max_load_factor());
BOOST_TEST(test::selected_count(y.get_allocator()) ==
(allocator_type::is_select_on_copy));
BOOST_TEST(test::detail::tracker.count_allocations == 0);
test::check_equivalent_keys(y);
}
{ {
test::check_instances check_; test::check_instances check_;
@ -106,6 +139,21 @@ namespace copy_tests {
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
} }
{
test::check_instances check_;
T x(0, hf, eq, al);
T y(x, al2);
BOOST_TEST(y.empty());
BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
BOOST_TEST(x.max_load_factor() == y.max_load_factor());
BOOST_TEST(test::selected_count(y.get_allocator()) == 0);
BOOST_TEST(test::detail::tracker.count_allocations == 0);
test::check_equivalent_keys(y);
}
{ {
test::check_instances check_; test::check_instances check_;
@ -120,6 +168,22 @@ namespace copy_tests {
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
} }
{
test::check_instances check_;
test::random_values<T> v;
T x(v.begin(), v.end(), 0, hf, eq, al);
T y(x);
test::unordered_equivalence_tester<T> equivalent(x);
BOOST_TEST(equivalent(y));
test::check_equivalent_keys(y);
BOOST_TEST(test::selected_count(y.get_allocator()) ==
(allocator_type::is_select_on_copy));
BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(test::detail::tracker.count_allocations == 0);
}
{ {
test::check_instances check_; test::check_instances check_;
@ -135,6 +199,21 @@ namespace copy_tests {
BOOST_TEST(test::equivalent(y.get_allocator(), al)); BOOST_TEST(test::equivalent(y.get_allocator(), al));
} }
{
test::check_instances check_;
test::random_values<T> v;
T x(v.begin(), v.end(), 0, hf, eq, al);
T y(x, al2);
test::unordered_equivalence_tester<T> equivalent(x);
BOOST_TEST(equivalent(y));
test::check_equivalent_keys(y);
BOOST_TEST(test::selected_count(y.get_allocator()) == 0);
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
BOOST_TEST(test::detail::tracker.count_allocations == 0);
}
{ {
test::check_instances check_; test::check_instances check_;

View File

@ -73,6 +73,10 @@ namespace move_tests {
BOOST_TEST(test::equivalent(y.get_allocator(), al)); BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(y.max_load_factor() == 1.0); BOOST_TEST(y.max_load_factor() == 1.0);
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
#if defined(BOOST_UNORDERED_USE_MOVE) || \
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
#endif
} }
{ {
@ -90,7 +94,7 @@ namespace move_tests {
} }
template <class T> template <class T>
void move_assign_tests1(T*, test::random_generator const& generator) void move_assign_tests1(T* p, test::random_generator const& generator)
{ {
{ {
test::check_instances check_; test::check_instances check_;
@ -101,6 +105,19 @@ namespace move_tests {
y = create(v, count); y = create(v, count);
#if BOOST_UNORDERED_TEST_MOVING && defined(BOOST_HAS_NRVO) #if BOOST_UNORDERED_TEST_MOVING && defined(BOOST_HAS_NRVO)
BOOST_TEST(count == test::global_object_count); BOOST_TEST(count == test::global_object_count);
#endif
test::check_container(y, v);
test::check_equivalent_keys(y);
}
{
test::random_values<T> v;
T y;
y = empty(p);
#if defined(BOOST_UNORDERED_USE_MOVE) || \
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
#endif #endif
test::check_container(y, v); test::check_container(y, v);
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
@ -236,6 +253,32 @@ namespace move_tests {
#endif #endif
} }
{
test::random_values<T> v;
T y(0, hf, eq, al1);
T x(0, hf, eq, al2);
x.max_load_factor(0.25);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
y = boost::move(x);
#if defined(BOOST_UNORDERED_USE_MOVE) || \
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_TEST_EQ(test::detail::tracker.count_allocations, 0u);
#endif
test::check_container(y, v);
test::check_equivalent_keys(y);
BOOST_TEST(y.max_load_factor() == 0.25);
if (BOOST_UNORDERED_TEST_MOVING
? (bool)allocator_type::is_propagate_on_move
: (bool)allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(y.get_allocator(), al2));
} else {
BOOST_TEST(test::equivalent(y.get_allocator(), al1));
}
}
{ {
test::check_instances check_; test::check_instances check_;
@ -701,12 +744,18 @@ namespace move_tests {
test::random_values<T> const v(1000, generator); test::random_values<T> const v(1000, generator);
test::object_count count; test::object_count count;
T y(create(v, count)); T y(create(v, count));
unsigned num_allocs = test::detail::tracker.count_allocations;
(void)num_allocs;
T x(boost::move(y)); T x(boost::move(y));
#if defined(BOOST_UNORDERED_USE_MOVE) || \ #if defined(BOOST_UNORDERED_USE_MOVE) || \
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES) !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_TEST(y.empty()); BOOST_TEST(y.empty());
BOOST_TEST(y.begin() == y.end()); BOOST_TEST(y.begin() == y.end());
BOOST_TEST_EQ(y.bucket_count(), 0u);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, num_allocs);
#endif #endif
fps[i](y, v); fps[i](y, v);
@ -743,6 +792,10 @@ namespace move_tests {
test::random_values<T> v(1000, generator); test::random_values<T> v(1000, generator);
test::object_count count; test::object_count count;
T y(create(v, count)); T y(create(v, count));
unsigned num_allocs = test::detail::tracker.count_allocations;
(void)num_allocs;
T x(empty(ptr)); T x(empty(ptr));
x = boost::move(y); x = boost::move(y);
@ -750,6 +803,8 @@ namespace move_tests {
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES) !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_TEST(y.empty()); BOOST_TEST(y.empty());
BOOST_TEST(y.begin() == y.end()); BOOST_TEST(y.begin() == y.end());
BOOST_TEST_EQ(y.bucket_count(), 0u);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, num_allocs);
#endif #endif
fps[i](y, v); fps[i](y, v);
@ -769,17 +824,23 @@ namespace move_tests {
test::random_values<T> v(1000, generator); test::random_values<T> v(1000, generator);
test::object_count count; test::object_count count;
T y(v.begin(), v.end(), 0, hf, eq, al1); T y(v.begin(), v.end(), 0, hf, eq, al1);
unsigned num_allocs = test::detail::tracker.count_allocations;
(void)num_allocs;
T x(al2); T x(al2);
x = boost::move(y); x = boost::move(y);
bool b = boost::allocator_propagate_on_container_move_assignment< bool b = boost::allocator_propagate_on_container_move_assignment<
typename T::allocator_type>::type::value; typename T::allocator_type>::type::value;
if (b) { if (b) {
#if defined(BOOST_UNORDERED_USE_MOVE) || \ #if defined(BOOST_UNORDERED_USE_MOVE) || \
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES) !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_TEST(y.empty()); BOOST_TEST(y.empty());
BOOST_TEST(y.begin() == y.end()); BOOST_TEST(y.begin() == y.end());
#else BOOST_TEST_EQ(y.bucket_count(), 0u);
BOOST_TEST_EQ(test::detail::tracker.count_allocations, num_allocs);
#else
BOOST_TEST_NOT(y.empty()); BOOST_TEST_NOT(y.empty());
BOOST_TEST(y.begin() != y.end()); BOOST_TEST(y.begin() != y.end());

View File

@ -224,7 +224,7 @@ template <class C1, class C2> void scary_test()
typename C2::const_iterator cbegin(x.cbegin()); typename C2::const_iterator cbegin(x.cbegin());
BOOST_TEST(cbegin == x.cend()); BOOST_TEST(cbegin == x.cend());
BOOST_ASSERT(x.bucket_count() > 0); BOOST_TEST_EQ(x.bucket_count(), 0u);
typename C2::local_iterator lbegin(x.begin(0)); typename C2::local_iterator lbegin(x.begin(0));
BOOST_TEST(lbegin == x.end(0)); BOOST_TEST(lbegin == x.end(0));