forked from boostorg/unordered
Compare commits
2 Commits
boost-1.45
...
boost-1.46
Author | SHA1 | Date | |
---|---|---|---|
c75b042ca3 | |||
54f9626c12 |
@ -3,6 +3,9 @@
|
||||
# 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)
|
||||
|
||||
using boostbook ;
|
||||
using quickbook ;
|
||||
|
||||
path-constant images_location : ../ ;
|
||||
path-constant admonishment_location : ../../../../doc/src/images ;
|
||||
|
||||
|
@ -64,7 +64,7 @@ namespace boost { namespace unordered_detail {
|
||||
inline void hash_buckets<A, G>::delete_node(node_ptr b)
|
||||
{
|
||||
node* raw_ptr = static_cast<node*>(&*b);
|
||||
boost::unordered_detail::destroy(&raw_ptr->value());
|
||||
boost::unordered_detail::destroy(raw_ptr->value_ptr());
|
||||
real_node_ptr n(node_alloc().address(*raw_ptr));
|
||||
node_alloc().destroy(n);
|
||||
node_alloc().deallocate(n, 1);
|
||||
|
@ -21,14 +21,14 @@
|
||||
|
||||
// This header defines most of the classes used to implement the unordered
|
||||
// containers. It doesn't include the insert methods as they require a lot
|
||||
// of preprocessor metaprogramming - they are in insert.hpp
|
||||
// of preprocessor metaprogramming - they are in unique.hpp and equivalent.hpp.
|
||||
|
||||
// Template parameters:
|
||||
//
|
||||
// H = Hash Function
|
||||
// P = Predicate
|
||||
// A = Value Allocator
|
||||
// G = Grouped/Ungrouped
|
||||
// G = Bucket group policy, 'grouped' or 'ungrouped'
|
||||
// E = Key Extractor
|
||||
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
@ -90,7 +90,37 @@ namespace boost { namespace unordered_detail {
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This section implements buckets and nodes. Here's a rough
|
||||
// inheritance diagram, to show how they pull together.
|
||||
//
|
||||
// For unordered_set/unordered_map:
|
||||
//
|
||||
// hash_bucket<A>
|
||||
// |
|
||||
// ungrouped_node_base<A> value_base<A::value_type>
|
||||
// | |
|
||||
// +--------------+-------------+
|
||||
// |
|
||||
// hash_node<A, ungrouped>
|
||||
//
|
||||
// For unordered_multiset/unordered_multimap:
|
||||
//
|
||||
// hash_bucket<A>
|
||||
// |
|
||||
// grouped_node_base<A> value_base<A::value_type>
|
||||
// | |
|
||||
// +--------------+-------------+
|
||||
// |
|
||||
// hash_node<A, grouped>
|
||||
|
||||
// hash_bucket
|
||||
//
|
||||
// hash_bucket is used for both the buckets and as a base class for
|
||||
// nodes. By using 'bucket_ptr' for 'node_ptr', 'next_' can point
|
||||
// to either a bucket or a node. This is used later to implement a
|
||||
// sentinel at the end of the bucket array.
|
||||
|
||||
template <class A>
|
||||
class hash_bucket
|
||||
@ -109,6 +139,16 @@ namespace boost { namespace unordered_detail {
|
||||
hash_bucket() : next_() {}
|
||||
};
|
||||
|
||||
// In containers with equivalent keys (unordered_multimap and
|
||||
// unordered_multiset) equivalent nodes are grouped together, in
|
||||
// containers with unique keys (unordered_map and unordered_set)
|
||||
// individual nodes are treated as groups of one. The following two
|
||||
// classes implement the data structure.
|
||||
|
||||
// This is used for containers with unique keys. There are no groups
|
||||
// so it doesn't add any extra members, and just treats individual
|
||||
// nodes as groups of one.
|
||||
|
||||
template <class A>
|
||||
struct ungrouped_node_base : hash_bucket<A> {
|
||||
typedef hash_bucket<A> bucket;
|
||||
@ -125,6 +165,10 @@ namespace boost { namespace unordered_detail {
|
||||
static void unlink_nodes(bucket& b, node_ptr end);
|
||||
};
|
||||
|
||||
// This is used for containers with equivalent keys. It implements a
|
||||
// circular list running in the opposite direction to the linked
|
||||
// list through the nodes.
|
||||
|
||||
template <class A>
|
||||
struct grouped_node_base : hash_bucket<A>
|
||||
{
|
||||
@ -151,6 +195,10 @@ namespace boost { namespace unordered_detail {
|
||||
}
|
||||
};
|
||||
|
||||
// These two classes implement an easy way to pass around the node
|
||||
// group policy classes without the messy template parameters.
|
||||
// Whenever you see the template parameter 'G' it's one of these.
|
||||
|
||||
struct ungrouped
|
||||
{
|
||||
template <class A>
|
||||
@ -167,6 +215,8 @@ namespace boost { namespace unordered_detail {
|
||||
};
|
||||
};
|
||||
|
||||
// The space used to store values in a node.
|
||||
|
||||
template <class ValueType>
|
||||
struct value_base
|
||||
{
|
||||
@ -181,6 +231,9 @@ namespace boost { namespace unordered_detail {
|
||||
value_type& value() {
|
||||
return *(ValueType*) this;
|
||||
}
|
||||
value_type* value_ptr() {
|
||||
return (ValueType*) this;
|
||||
}
|
||||
private:
|
||||
value_base& operator=(value_base const&);
|
||||
};
|
||||
@ -199,11 +252,20 @@ namespace boost { namespace unordered_detail {
|
||||
static value_type& get_value(node_ptr p) {
|
||||
return static_cast<hash_node&>(*p).value();
|
||||
}
|
||||
static value_type* get_value_ptr(node_ptr p) {
|
||||
return static_cast<hash_node&>(*p).value_ptr();
|
||||
}
|
||||
private:
|
||||
hash_node& operator=(hash_node const&);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Iterator Base
|
||||
//
|
||||
// This is the iterator used internally, the external iterators are
|
||||
// provided by lightweight wrappers (hash_iterator and
|
||||
// hast_const_iterator) which provide the full iterator interface.
|
||||
|
||||
template <class A, class G>
|
||||
class hash_iterator_base
|
||||
@ -248,12 +310,24 @@ namespace boost { namespace unordered_detail {
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Now the main data structure:
|
||||
//
|
||||
// hash_buckets<A, G> hash_buffered_functions<H, P>
|
||||
// | |
|
||||
// +-------------+--------------+
|
||||
// |
|
||||
// hash_table<T>
|
||||
//
|
||||
// T is a class which contains typedefs for all the types we need.
|
||||
|
||||
// hash_buckets
|
||||
//
|
||||
// This is responsible for allocating and deallocating buckets and nodes.
|
||||
//
|
||||
// Notes:
|
||||
// 1. For the sake exception safety the allocators themselves don't allocate
|
||||
// 1. For the sake exception safety the consturctors don't allocate
|
||||
// anything.
|
||||
// 2. It's the callers responsibility to allocate the buckets before calling
|
||||
// any of the methods (other than getters and setters).
|
||||
@ -327,6 +401,17 @@ namespace boost { namespace unordered_detail {
|
||||
std::size_t delete_to_bucket_end(node_ptr begin);
|
||||
};
|
||||
|
||||
// Assigning and swapping the equality and hash function objects
|
||||
// needs strong exception safety. To implement that normally we'd
|
||||
// require one of them to be known to not throw and the other to
|
||||
// guarantee strong exception safety. Unfortunately they both only
|
||||
// have basic exception safety. So to acheive strong exception
|
||||
// safety we have storage space for two copies, and assign the new
|
||||
// copies to the unused space. Then switch to using that to use
|
||||
// them. This is implemented in 'set_hash_functions' which
|
||||
// atomically assigns the new function objects in a strongly
|
||||
// exception safe manner.
|
||||
|
||||
template <class H, class P> class set_hash_functions;
|
||||
|
||||
template <class H, class P>
|
||||
@ -429,6 +514,12 @@ namespace boost { namespace unordered_detail {
|
||||
}
|
||||
};
|
||||
|
||||
// This implements almost all of the required functionality, apart
|
||||
// from some things that are specific to containers with unique and
|
||||
// equivalent keys which is implemented in hash_unique_table and
|
||||
// hash_equivalent_table. See unique.hpp and equivalent.hpp for
|
||||
// their declaration and implementation.
|
||||
|
||||
template <class T>
|
||||
class hash_table : public T::buckets, public T::buffered_functions
|
||||
{
|
||||
@ -569,9 +660,13 @@ namespace boost { namespace unordered_detail {
|
||||
node_constructor&, std::size_t);
|
||||
};
|
||||
|
||||
// Iterator Access
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Iterators
|
||||
|
||||
// iterator_access is used to access the internal iterator without
|
||||
// making it publicly available.
|
||||
|
||||
#if !defined(__clang__)
|
||||
class iterator_access
|
||||
{
|
||||
public:
|
||||
@ -582,30 +677,6 @@ namespace boost { namespace unordered_detail {
|
||||
return it.base_;
|
||||
}
|
||||
};
|
||||
#else
|
||||
class iterator_access
|
||||
{
|
||||
public:
|
||||
// Note: we access Iterator::base here, rather than in the function
|
||||
// signature to work around a bug in the friend support of an
|
||||
// early version of clang.
|
||||
|
||||
template <class Iterator>
|
||||
struct base
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME Iterator::base type;
|
||||
};
|
||||
|
||||
template <class Iterator>
|
||||
static BOOST_DEDUCED_TYPENAME base<Iterator>::type const&
|
||||
get(Iterator const& it)
|
||||
{
|
||||
return it.base_;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
// Iterators
|
||||
|
||||
template <class A, class G> class hash_iterator;
|
||||
template <class A, class G> class hash_const_iterator;
|
||||
@ -644,7 +715,7 @@ namespace boost { namespace unordered_detail {
|
||||
return node::get_value(ptr_);
|
||||
}
|
||||
value_type* operator->() const {
|
||||
return &node::get_value(ptr_);
|
||||
return node::get_value_ptr(ptr_);
|
||||
}
|
||||
hash_local_iterator& operator++() {
|
||||
ptr_ = ptr_->next_; return *this;
|
||||
@ -694,7 +765,7 @@ namespace boost { namespace unordered_detail {
|
||||
return node::get_value(ptr_);
|
||||
}
|
||||
value_type const* operator->() const {
|
||||
return &node::get_value(ptr_);
|
||||
return node::get_value_ptr(ptr_);
|
||||
}
|
||||
hash_const_local_iterator& operator++() {
|
||||
ptr_ = ptr_->next_; return *this;
|
||||
@ -716,7 +787,7 @@ namespace boost { namespace unordered_detail {
|
||||
}
|
||||
};
|
||||
|
||||
// iterators
|
||||
// Iterators
|
||||
//
|
||||
// all no throw
|
||||
|
||||
@ -823,7 +894,12 @@ namespace boost { namespace unordered_detail {
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// types
|
||||
//
|
||||
// This is used to convieniently pass around a container's typedefs
|
||||
// without having 7 template parameters.
|
||||
|
||||
template <class K, class V, class H, class P, class A, class E, class G>
|
||||
struct types
|
||||
|
@ -299,7 +299,7 @@ namespace boost { namespace unordered_detail {
|
||||
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
|
||||
struct dummy { hash_node<Alloc, Grouped> x; };
|
||||
#endif
|
||||
boost::unordered_detail::destroy(&node_->value());
|
||||
boost::unordered_detail::destroy(node_->value_ptr());
|
||||
}
|
||||
|
||||
if (node_constructed_)
|
||||
@ -322,7 +322,7 @@ namespace boost { namespace unordered_detail {
|
||||
}
|
||||
else {
|
||||
BOOST_ASSERT(node_constructed_ && value_constructed_);
|
||||
boost::unordered_detail::destroy(&node_->value());
|
||||
boost::unordered_detail::destroy(node_->value_ptr());
|
||||
value_constructed_ = false;
|
||||
}
|
||||
}
|
||||
|
@ -24,13 +24,13 @@ namespace boost
|
||||
class A = std::allocator<std::pair<const K, T> > >
|
||||
class unordered_map;
|
||||
template <class K, class T, class H, class P, class A>
|
||||
bool operator==(unordered_map<K, T, H, P, A> const&,
|
||||
inline bool operator==(unordered_map<K, T, H, P, A> const&,
|
||||
unordered_map<K, T, H, P, A> const&);
|
||||
template <class K, class T, class H, class P, class A>
|
||||
bool operator!=(unordered_map<K, T, H, P, A> const&,
|
||||
inline bool operator!=(unordered_map<K, T, H, P, A> const&,
|
||||
unordered_map<K, T, H, P, A> const&);
|
||||
template <class K, class T, class H, class P, class A>
|
||||
void swap(unordered_map<K, T, H, P, A>&,
|
||||
inline void swap(unordered_map<K, T, H, P, A>&,
|
||||
unordered_map<K, T, H, P, A>&);
|
||||
|
||||
template <class K,
|
||||
@ -40,13 +40,13 @@ namespace boost
|
||||
class A = std::allocator<std::pair<const K, T> > >
|
||||
class unordered_multimap;
|
||||
template <class K, class T, class H, class P, class A>
|
||||
bool operator==(unordered_multimap<K, T, H, P, A> const&,
|
||||
inline bool operator==(unordered_multimap<K, T, H, P, A> const&,
|
||||
unordered_multimap<K, T, H, P, A> const&);
|
||||
template <class K, class T, class H, class P, class A>
|
||||
bool operator!=(unordered_multimap<K, T, H, P, A> const&,
|
||||
inline bool operator!=(unordered_multimap<K, T, H, P, A> const&,
|
||||
unordered_multimap<K, T, H, P, A> const&);
|
||||
template <class K, class T, class H, class P, class A>
|
||||
void swap(unordered_multimap<K, T, H, P, A>&,
|
||||
inline void swap(unordered_multimap<K, T, H, P, A>&,
|
||||
unordered_multimap<K, T, H, P, A>&);
|
||||
}
|
||||
|
||||
|
@ -23,13 +23,13 @@ namespace boost
|
||||
class A = std::allocator<T> >
|
||||
class unordered_set;
|
||||
template <class T, class H, class P, class A>
|
||||
bool operator==(unordered_set<T, H, P, A> const&,
|
||||
inline bool operator==(unordered_set<T, H, P, A> const&,
|
||||
unordered_set<T, H, P, A> const&);
|
||||
template <class T, class H, class P, class A>
|
||||
bool operator!=(unordered_set<T, H, P, A> const&,
|
||||
inline bool operator!=(unordered_set<T, H, P, A> const&,
|
||||
unordered_set<T, H, P, A> const&);
|
||||
template <class T, class H, class P, class A>
|
||||
void swap(unordered_set<T, H, P, A> &m1,
|
||||
inline void swap(unordered_set<T, H, P, A> &m1,
|
||||
unordered_set<T, H, P, A> &m2);
|
||||
|
||||
template <class T,
|
||||
@ -38,13 +38,13 @@ namespace boost
|
||||
class A = std::allocator<T> >
|
||||
class unordered_multiset;
|
||||
template <class T, class H, class P, class A>
|
||||
bool operator==(unordered_multiset<T, H, P, A> const&,
|
||||
inline bool operator==(unordered_multiset<T, H, P, A> const&,
|
||||
unordered_multiset<T, H, P, A> const&);
|
||||
template <class T, class H, class P, class A>
|
||||
bool operator!=(unordered_multiset<T, H, P, A> const&,
|
||||
inline bool operator!=(unordered_multiset<T, H, P, A> const&,
|
||||
unordered_multiset<T, H, P, A> const&);
|
||||
template <class T, class H, class P, class A>
|
||||
void swap(unordered_multiset<T, H, P, A> &m1,
|
||||
inline void swap(unordered_multiset<T, H, P, A> &m1,
|
||||
unordered_multiset<T, H, P, A> &m2);
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,8 @@ namespace minimal
|
||||
class default_copy_constructible;
|
||||
class assignable;
|
||||
|
||||
struct ampersand_operator_used {};
|
||||
|
||||
template <class T> class hash;
|
||||
template <class T> class equal_to;
|
||||
template <class T> class ptr;
|
||||
@ -63,6 +65,7 @@ namespace minimal
|
||||
copy_constructible_equality_comparable& operator=(
|
||||
copy_constructible_equality_comparable const&);
|
||||
copy_constructible_equality_comparable() {}
|
||||
ampersand_operator_used operator&() const { return ampersand_operator_used(); }
|
||||
};
|
||||
|
||||
bool operator==(
|
||||
@ -98,9 +101,11 @@ namespace minimal
|
||||
~default_copy_constructible()
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
default_copy_constructible& operator=(
|
||||
default_copy_constructible const&);
|
||||
ampersand_operator_used operator&() const { return ampersand_operator_used(); }
|
||||
};
|
||||
|
||||
class assignable
|
||||
@ -110,8 +115,11 @@ namespace minimal
|
||||
assignable(assignable const&) {}
|
||||
assignable& operator=(assignable const&) { return *this; }
|
||||
~assignable() {}
|
||||
|
||||
private:
|
||||
assignable() {}
|
||||
// TODO: This messes up a concept check in the tests.
|
||||
//ampersand_operator_used operator&() const { return ampersand_operator_used(); }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
@ -125,6 +133,8 @@ namespace minimal
|
||||
~hash() {}
|
||||
|
||||
std::size_t operator()(T const&) const { return 0; }
|
||||
private:
|
||||
ampersand_operator_used operator&() const { return ampersand_operator_used(); }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
@ -138,6 +148,8 @@ namespace minimal
|
||||
~equal_to() {}
|
||||
|
||||
bool operator()(T const&, T const&) const { return true; }
|
||||
private:
|
||||
ampersand_operator_used operator&() const { return ampersand_operator_used(); }
|
||||
};
|
||||
|
||||
template <class T> class ptr;
|
||||
@ -182,6 +194,9 @@ namespace minimal
|
||||
bool operator>(const_ptr<T> const& x) const { return ptr_ > x.ptr_; }
|
||||
bool operator<=(const_ptr<T> const& x) const { return ptr_ <= x.ptr_; }
|
||||
bool operator>=(const_ptr<T> const& x) const { return ptr_ >= x.ptr_; }
|
||||
private:
|
||||
// TODO:
|
||||
//ampersand_operator_used operator&() const { return ampersand_operator_used(); }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
@ -221,6 +236,9 @@ namespace minimal
|
||||
bool operator>(const_ptr const& x) const { return ptr_ > x.ptr_; }
|
||||
bool operator<=(const_ptr const& x) const { return ptr_ <= x.ptr_; }
|
||||
bool operator>=(const_ptr const& x) const { return ptr_ >= x.ptr_; }
|
||||
private:
|
||||
// TODO:
|
||||
//ampersand_operator_used operator&() const { return ampersand_operator_used(); }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
@ -278,6 +296,8 @@ namespace minimal
|
||||
#else
|
||||
private: allocator& operator=(allocator const&);
|
||||
#endif
|
||||
private:
|
||||
ampersand_operator_used operator&() const { return ampersand_operator_used(); }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
|
@ -9,8 +9,8 @@ project unordered-test/unordered
|
||||
: requirements
|
||||
<warnings>all
|
||||
<toolset>intel:<warnings>on
|
||||
<toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter"
|
||||
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter"
|
||||
<toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion"
|
||||
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion"
|
||||
<toolset>gcc:<define>_GLIBCXX_DEBUG
|
||||
#<toolset>darwin:<define>_GLIBCXX_DEBUG
|
||||
<toolset>msvc:<warnings-as-errors>on
|
||||
@ -30,7 +30,7 @@ test-suite unordered
|
||||
[ run equivalent_keys_tests.cpp ]
|
||||
[ run constructor_tests.cpp ]
|
||||
[ run copy_tests.cpp ]
|
||||
[ run move_tests.cpp : : : <test-info>always_show_run_output ]
|
||||
[ run move_tests.cpp ]
|
||||
[ run assign_tests.cpp ]
|
||||
[ run insert_tests.cpp ]
|
||||
[ run insert_stable_tests.cpp ]
|
||||
|
@ -7,37 +7,54 @@
|
||||
|
||||
#include <boost/unordered/unordered_map_fwd.hpp>
|
||||
|
||||
typedef boost::unordered_map<int, int> int_map;
|
||||
|
||||
void call_swap(int_map& x, int_map& y) {
|
||||
template <typename T>
|
||||
void call_swap(boost::unordered_map<T,T>& x,
|
||||
boost::unordered_map<T,T>& y)
|
||||
{
|
||||
swap(x,y);
|
||||
}
|
||||
|
||||
bool call_equals(int_map& x, int_map& y) {
|
||||
template <typename T>
|
||||
bool call_equals(boost::unordered_map<T,T>& x,
|
||||
boost::unordered_map<T,T>& y)
|
||||
{
|
||||
return x == y;
|
||||
}
|
||||
|
||||
bool call_not_equals(int_map& x, int_map& y) {
|
||||
template <typename T>
|
||||
bool call_not_equals(boost::unordered_map<T,T>& x,
|
||||
boost::unordered_map<T,T>& y)
|
||||
{
|
||||
return x != y;
|
||||
}
|
||||
|
||||
typedef boost::unordered_multimap<int, int> int_multimap;
|
||||
|
||||
void call_swap(int_multimap& x, int_multimap& y) {
|
||||
template <typename T>
|
||||
void call_swap(boost::unordered_multimap<T,T>& x,
|
||||
boost::unordered_multimap<T,T>& y)
|
||||
{
|
||||
swap(x,y);
|
||||
}
|
||||
|
||||
bool call_equals(int_multimap& x, int_multimap& y) {
|
||||
template <typename T>
|
||||
bool call_equals(boost::unordered_multimap<T,T>& x,
|
||||
boost::unordered_multimap<T,T>& y)
|
||||
{
|
||||
return x == y;
|
||||
}
|
||||
|
||||
bool call_not_equals(int_multimap& x, int_multimap& y) {
|
||||
template <typename T>
|
||||
bool call_not_equals(boost::unordered_multimap<T,T>& x,
|
||||
boost::unordered_multimap<T,T>& y)
|
||||
{
|
||||
return x != y;
|
||||
}
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include "../helpers/test.hpp"
|
||||
|
||||
typedef boost::unordered_map<int, int> int_map;
|
||||
typedef boost::unordered_multimap<int, int> int_multimap;
|
||||
|
||||
UNORDERED_AUTO_TEST(use_map_fwd_declared_function) {
|
||||
int_map x, y;
|
||||
x[1] = 2;
|
||||
|
@ -16,36 +16,53 @@ template <class Value, class Hash, class Pred, class Alloc>
|
||||
true_type is_unordered_set_impl(
|
||||
boost::unordered_set<Value, Hash, Pred, Alloc>*);
|
||||
|
||||
typedef boost::unordered_set<int> int_set;
|
||||
|
||||
void call_swap(int_set& x, int_set& y) {
|
||||
template<typename T>
|
||||
void call_swap(boost::unordered_set<T>& x,
|
||||
boost::unordered_set<T>& y)
|
||||
{
|
||||
swap(x,y);
|
||||
}
|
||||
|
||||
bool call_equals(int_set& x, int_set& y) {
|
||||
template<typename T>
|
||||
bool call_equals(boost::unordered_set<T>& x,
|
||||
boost::unordered_set<T>& y)
|
||||
{
|
||||
return x == y;
|
||||
}
|
||||
|
||||
bool call_not_equals(int_set& x, int_set& y) {
|
||||
template<typename T>
|
||||
bool call_not_equals(boost::unordered_set<T>& x,
|
||||
boost::unordered_set<T>& y)
|
||||
{
|
||||
return x != y;
|
||||
}
|
||||
|
||||
typedef boost::unordered_multiset<int> int_multiset;
|
||||
|
||||
void call_swap(int_multiset& x, int_multiset& y) {
|
||||
template<typename T>
|
||||
void call_swap(boost::unordered_multiset<T>& x,
|
||||
boost::unordered_multiset<T>& y)
|
||||
{
|
||||
swap(x,y);
|
||||
}
|
||||
|
||||
bool call_equals(int_multiset& x, int_multiset& y) {
|
||||
template<typename T>
|
||||
bool call_equals(boost::unordered_multiset<T>& x,
|
||||
boost::unordered_multiset<T>& y)
|
||||
{
|
||||
return x == y;
|
||||
}
|
||||
|
||||
bool call_not_equals(int_multiset& x, int_multiset& y) {
|
||||
template<typename T>
|
||||
bool call_not_equals(boost::unordered_multiset<T>& x,
|
||||
boost::unordered_multiset<T>& y)
|
||||
{
|
||||
return x != y;
|
||||
}
|
||||
|
||||
#include "../helpers/test.hpp"
|
||||
|
||||
typedef boost::unordered_set<int> int_set;
|
||||
typedef boost::unordered_multiset<int> int_multiset;
|
||||
|
||||
UNORDERED_AUTO_TEST(use_fwd_declared_trait_without_definition) {
|
||||
BOOST_TEST(sizeof(is_unordered_set_impl((int_set*) 0))
|
||||
== sizeof(true_type));
|
||||
|
@ -52,7 +52,7 @@ void unique_insert_tests1(X*,
|
||||
|
||||
tracker.compare_key(x, *it);
|
||||
|
||||
if(x.size() < b * old_bucket_count)
|
||||
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
|
||||
@ -83,7 +83,7 @@ void equivalent_insert_tests1(X*,
|
||||
|
||||
tracker.compare_key(x, *it);
|
||||
|
||||
if(x.size() < b * old_bucket_count)
|
||||
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
|
||||
@ -118,7 +118,7 @@ void insert_tests2(X*,
|
||||
BOOST_TEST(*r1 == *r2);
|
||||
tracker.compare_key(x, *it);
|
||||
|
||||
if(x.size() < b * old_bucket_count)
|
||||
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
|
||||
@ -145,7 +145,7 @@ void insert_tests2(X*,
|
||||
BOOST_TEST(*r1 == *r2);
|
||||
tracker.compare_key(x, *it);
|
||||
|
||||
if(x.size() < b * old_bucket_count)
|
||||
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
|
||||
@ -172,7 +172,7 @@ void insert_tests2(X*,
|
||||
BOOST_TEST(*pos == *r2);
|
||||
tracker.compare_key(x, *it);
|
||||
|
||||
if(x.size() < b * old_bucket_count)
|
||||
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
|
||||
@ -197,7 +197,7 @@ void insert_tests2(X*,
|
||||
tracker.insert(*it);
|
||||
tracker.compare_key(x, *it);
|
||||
|
||||
if(x.size() < b * old_bucket_count)
|
||||
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
|
||||
@ -275,7 +275,7 @@ void unique_emplace_tests1(X*,
|
||||
|
||||
tracker.compare_key(x, *it);
|
||||
|
||||
if(x.size() < b * old_bucket_count)
|
||||
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
|
||||
@ -306,7 +306,7 @@ void equivalent_emplace_tests1(X*,
|
||||
|
||||
tracker.compare_key(x, *it);
|
||||
|
||||
if(x.size() < b * old_bucket_count)
|
||||
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
|
||||
@ -335,7 +335,7 @@ void map_tests(X*, test::random_generator generator = test::default_generator)
|
||||
|
||||
tracker.compare_key(x, *it);
|
||||
|
||||
if(x.size() < b * old_bucket_count)
|
||||
if(static_cast<double>(x.size()) < b * static_cast<double>(old_bucket_count))
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ void insert_test(X*, float mlf,
|
||||
BOOST_DEDUCED_TYPENAME X::size_type old_size = x.size(),
|
||||
old_bucket_count = x.bucket_count();
|
||||
x.insert(*it);
|
||||
if(old_size + 1 < b * old_bucket_count)
|
||||
if(static_cast<double>(old_size + 1) < b * static_cast<double>(old_bucket_count))
|
||||
BOOST_TEST(x.bucket_count() == old_bucket_count);
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,8 @@ test::seed_t seed(2974);
|
||||
template <class X>
|
||||
bool postcondition(X const& x, BOOST_DEDUCED_TYPENAME X::size_type n)
|
||||
{
|
||||
return x.bucket_count() > x.size() / x.max_load_factor() &&
|
||||
return static_cast<double>(x.bucket_count()) >
|
||||
static_cast<double>(x.size()) / x.max_load_factor() &&
|
||||
x.bucket_count() >= n;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user