Change clang format indentation + .editorconfig file

This commit is contained in:
Daniel James
2017-06-11 20:55:59 +01:00
parent 5190a5d7f8
commit 0676b4f4ca
77 changed files with 14113 additions and 14052 deletions

7
.editorconfig Normal file
View File

@ -0,0 +1,7 @@
[*]
end_of_line = lf
insert_final_newline = true
indent_style = space
[*.?pp]
indent_size = 2

View File

@ -11,8 +11,9 @@ BasedOnStyle: LLVM
# Basic settings # Basic settings
ColumnLimit: 80 ColumnLimit: 80
ContinuationIndentWidth: 4 NamespaceIndentation: All
IndentWidth: 4 ContinuationIndentWidth: 2
IndentWidth: 2
UseTab: Never UseTab: Never
Language: Cpp Language: Cpp
Standard: Cpp03 Standard: Cpp03

View File

@ -43,17 +43,17 @@
#endif #endif
namespace boost { namespace boost {
namespace unordered { namespace unordered {
#if BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT #if BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT
using std::piecewise_construct_t; using std::piecewise_construct_t;
using std::piecewise_construct; using std::piecewise_construct;
#else #else
struct piecewise_construct_t struct piecewise_construct_t
{ {
}; };
const piecewise_construct_t piecewise_construct = piecewise_construct_t(); const piecewise_construct_t piecewise_construct = piecewise_construct_t();
#endif #endif
} }
} }
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -7,58 +7,60 @@
#include <boost/unordered/unordered_map_fwd.hpp> #include <boost/unordered/unordered_map_fwd.hpp>
namespace boost { namespace boost {
namespace unordered { namespace unordered {
namespace detail { namespace detail {
template <typename A, typename K, typename M, typename H, typename P> struct map template <typename A, typename K, typename M, typename H, typename P>
{ struct map
typedef boost::unordered::detail::map<A, K, M, H, P> types; {
typedef boost::unordered::detail::map<A, K, M, H, P> types;
typedef std::pair<K const, M> value_type; typedef std::pair<K const, M> value_type;
typedef H hasher; typedef H hasher;
typedef P key_equal; typedef P key_equal;
typedef K const const_key_type; typedef K const const_key_type;
typedef typename ::boost::unordered::detail::rebind_wrap<A, typedef typename ::boost::unordered::detail::rebind_wrap<A,
value_type>::type value_allocator; value_type>::type value_allocator;
typedef boost::unordered::detail::allocator_traits<value_allocator> typedef boost::unordered::detail::allocator_traits<value_allocator>
value_allocator_traits; value_allocator_traits;
typedef boost::unordered::detail::pick_node<A, value_type> pick; typedef boost::unordered::detail::pick_node<A, value_type> pick;
typedef typename pick::node node; typedef typename pick::node node;
typedef typename pick::bucket bucket; typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer; typedef typename pick::link_pointer link_pointer;
typedef boost::unordered::detail::table<types> table; typedef boost::unordered::detail::table<types> table;
typedef boost::unordered::detail::map_extractor<value_type> extractor; typedef boost::unordered::detail::map_extractor<value_type> extractor;
typedef typename boost::unordered::detail::pick_policy<K>::type policy; typedef typename boost::unordered::detail::pick_policy<K>::type policy;
typedef boost::unordered::iterator_detail::iterator<node> iterator; typedef boost::unordered::iterator_detail::iterator<node> iterator;
typedef boost::unordered::iterator_detail::c_iterator<node> c_iterator; typedef boost::unordered::iterator_detail::c_iterator<node> c_iterator;
typedef boost::unordered::iterator_detail::l_iterator<node> l_iterator; typedef boost::unordered::iterator_detail::l_iterator<node> l_iterator;
typedef boost::unordered::iterator_detail::cl_iterator<node> cl_iterator; typedef boost::unordered::iterator_detail::cl_iterator<node>
cl_iterator;
typedef boost::unordered::node_handle_map<node, K, M, A> node_type; typedef boost::unordered::node_handle_map<node, K, M, A> node_type;
typedef boost::unordered::insert_return_type_map<node, K, M, A> typedef boost::unordered::insert_return_type_map<node, K, M, A>
insert_return_type; insert_return_type;
}; };
template <typename K, typename M, typename H, typename P, typename A> template <typename K, typename M, typename H, typename P, typename A>
class instantiate_map class instantiate_map
{ {
typedef boost::unordered_map<K, M, H, P, A> container; typedef boost::unordered_map<K, M, H, P, A> container;
container x; container x;
typename container::node_type node_type; typename container::node_type node_type;
typename container::insert_return_type insert_return_type; typename container::insert_return_type insert_return_type;
}; };
template <typename K, typename M, typename H, typename P, typename A> template <typename K, typename M, typename H, typename P, typename A>
class instantiate_multimap class instantiate_multimap
{ {
typedef boost::unordered_multimap<K, M, H, P, A> container; typedef boost::unordered_multimap<K, M, H, P, A> container;
container x; container x;
typename container::node_type node_type; typename container::node_type node_type;
}; };
} }
} }
} }

View File

@ -7,57 +7,59 @@
#include <boost/unordered/unordered_set_fwd.hpp> #include <boost/unordered/unordered_set_fwd.hpp>
namespace boost { namespace boost {
namespace unordered { namespace unordered {
namespace detail { namespace detail {
template <typename A, typename T, typename H, typename P> struct set template <typename A, typename T, typename H, typename P> struct set
{ {
typedef boost::unordered::detail::set<A, T, H, P> types; typedef boost::unordered::detail::set<A, T, H, P> types;
typedef T value_type; typedef T value_type;
typedef H hasher; typedef H hasher;
typedef P key_equal; typedef P key_equal;
typedef T const const_key_type; typedef T const const_key_type;
typedef typename ::boost::unordered::detail::rebind_wrap<A, typedef typename ::boost::unordered::detail::rebind_wrap<A,
value_type>::type value_allocator; value_type>::type value_allocator;
typedef boost::unordered::detail::allocator_traits<value_allocator> typedef boost::unordered::detail::allocator_traits<value_allocator>
value_allocator_traits; value_allocator_traits;
typedef boost::unordered::detail::pick_node<A, value_type> pick; typedef boost::unordered::detail::pick_node<A, value_type> pick;
typedef typename pick::node node; typedef typename pick::node node;
typedef typename pick::bucket bucket; typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer; typedef typename pick::link_pointer link_pointer;
typedef boost::unordered::detail::table<types> table; typedef boost::unordered::detail::table<types> table;
typedef boost::unordered::detail::set_extractor<value_type> extractor; typedef boost::unordered::detail::set_extractor<value_type> extractor;
typedef typename boost::unordered::detail::pick_policy<T>::type policy; typedef typename boost::unordered::detail::pick_policy<T>::type policy;
typedef boost::unordered::iterator_detail::c_iterator<node> iterator; typedef boost::unordered::iterator_detail::c_iterator<node> iterator;
typedef boost::unordered::iterator_detail::c_iterator<node> c_iterator; typedef boost::unordered::iterator_detail::c_iterator<node> c_iterator;
typedef boost::unordered::iterator_detail::cl_iterator<node> l_iterator; typedef boost::unordered::iterator_detail::cl_iterator<node> l_iterator;
typedef boost::unordered::iterator_detail::cl_iterator<node> cl_iterator; typedef boost::unordered::iterator_detail::cl_iterator<node>
cl_iterator;
typedef boost::unordered::node_handle_set<node, T, A> node_type; typedef boost::unordered::node_handle_set<node, T, A> node_type;
typedef boost::unordered::insert_return_type_set<node, T, A> typedef boost::unordered::insert_return_type_set<node, T, A>
insert_return_type; insert_return_type;
}; };
template <typename T, typename H, typename P, typename A> class instantiate_set template <typename T, typename H, typename P, typename A>
{ class instantiate_set
typedef boost::unordered_set<T, H, P, A> container; {
container x; typedef boost::unordered_set<T, H, P, A> container;
typename container::node_type node_type; container x;
typename container::insert_return_type insert_return_type; typename container::node_type node_type;
}; typename container::insert_return_type insert_return_type;
};
template <typename T, typename H, typename P, typename A> template <typename T, typename H, typename P, typename A>
class instantiate_multiset class instantiate_multiset
{ {
typedef boost::unordered_multiset<T, H, P, A> container; typedef boost::unordered_multiset<T, H, P, A> container;
container x; container x;
typename container::node_type node_type; typename container::node_type node_type;
}; };
} }
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -17,48 +17,48 @@
#include <memory> #include <memory>
namespace boost { namespace boost {
namespace unordered { namespace unordered {
template <class K, class T, class H = boost::hash<K>, template <class K, class T, class H = boost::hash<K>,
class P = std::equal_to<K>, class P = std::equal_to<K>,
class A = std::allocator<std::pair<const K, T> > > class A = std::allocator<std::pair<const K, T> > >
class unordered_map; class unordered_map;
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
inline bool operator==( inline bool operator==(
unordered_map<K, T, H, P, A> const&, unordered_map<K, T, H, P, A> const&); 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> template <class K, class T, class H, class P, class A>
inline bool operator!=( inline bool operator!=(
unordered_map<K, T, H, P, A> const&, unordered_map<K, T, H, P, A> const&); 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> template <class K, class T, class H, class P, class A>
inline void swap( inline void swap(
unordered_map<K, T, H, P, A>& m1, unordered_map<K, T, H, P, A>& m2) unordered_map<K, T, H, P, A>& m1, unordered_map<K, T, H, P, A>& m2)
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2))); BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
template <class K, class T, class H = boost::hash<K>, template <class K, class T, class H = boost::hash<K>,
class P = std::equal_to<K>, class P = std::equal_to<K>,
class A = std::allocator<std::pair<const K, T> > > class A = std::allocator<std::pair<const K, T> > >
class unordered_multimap; class unordered_multimap;
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
inline 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&); unordered_multimap<K, T, H, P, A> const&);
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
inline 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&); unordered_multimap<K, T, H, P, A> const&);
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
inline void swap(unordered_multimap<K, T, H, P, A>& m1, inline void swap(unordered_multimap<K, T, H, P, A>& m1,
unordered_multimap<K, T, H, P, A>& m2) unordered_multimap<K, T, H, P, A>& m2)
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2))); BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
template <class N, class K, class T, class A> class node_handle_map; template <class N, class K, class T, class A> class node_handle_map;
template <class N, class K, class T, class A> struct insert_return_type_map; template <class N, class K, class T, class A> struct insert_return_type_map;
} }
using boost::unordered::unordered_map; using boost::unordered::unordered_map;
using boost::unordered::unordered_multimap; using boost::unordered::unordered_multimap;
using boost::unordered::swap; using boost::unordered::swap;
using boost::unordered::operator==; using boost::unordered::operator==;
using boost::unordered::operator!=; using boost::unordered::operator!=;
} }
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -17,45 +17,46 @@
#include <memory> #include <memory>
namespace boost { namespace boost {
namespace unordered { namespace unordered {
template <class T, class H = boost::hash<T>, class P = std::equal_to<T>, template <class T, class H = boost::hash<T>, class P = std::equal_to<T>,
class A = std::allocator<T> > class A = std::allocator<T> >
class unordered_set; class unordered_set;
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
inline bool operator==( inline bool operator==(
unordered_set<T, H, P, A> const&, unordered_set<T, H, P, A> const&); unordered_set<T, H, P, A> const&, unordered_set<T, H, P, A> const&);
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
inline bool operator!=( inline bool operator!=(
unordered_set<T, H, P, A> const&, unordered_set<T, H, P, A> const&); unordered_set<T, H, P, A> const&, unordered_set<T, H, P, A> const&);
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
inline void swap(unordered_set<T, H, P, A>& m1, unordered_set<T, H, P, A>& m2) inline void swap(
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2))); unordered_set<T, H, P, A>& m1, unordered_set<T, H, P, A>& m2)
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
template <class T, class H = boost::hash<T>, class P = std::equal_to<T>, template <class T, class H = boost::hash<T>, class P = std::equal_to<T>,
class A = std::allocator<T> > class A = std::allocator<T> >
class unordered_multiset; class unordered_multiset;
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
inline 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&); unordered_multiset<T, H, P, A> const&);
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
inline 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&); unordered_multiset<T, H, P, A> const&);
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
inline void swap( inline void swap(
unordered_multiset<T, H, P, A>& m1, unordered_multiset<T, H, P, A>& m2) unordered_multiset<T, H, P, A>& m1, unordered_multiset<T, H, P, A>& m2)
BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2))); BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(m1.swap(m2)));
template <class N, class T, class A> class node_handle_set; template <class N, class T, class A> class node_handle_set;
template <class N, class T, class A> struct insert_return_type_set; template <class N, class T, class A> struct insert_return_type_set;
} }
using boost::unordered::unordered_set; using boost::unordered::unordered_set;
using boost::unordered::unordered_multiset; using boost::unordered::unordered_multiset;
using boost::unordered::swap; using boost::unordered::swap;
using boost::unordered::operator==; using boost::unordered::operator==;
using boost::unordered::operator!=; using boost::unordered::operator!=;
} }
#endif #endif

View File

@ -17,27 +17,27 @@ test::seed_t initialize_seed(12847);
template <class T> struct self_assign_base : public test::exception_base template <class T> struct self_assign_base : public test::exception_base
{ {
test::random_values<T> values; test::random_values<T> values;
self_assign_base(std::size_t count = 0) : values(count, test::limited_range) self_assign_base(std::size_t count = 0) : values(count, test::limited_range)
{ {
} }
typedef T data_type; typedef T data_type;
T init() const { return T(values.begin(), values.end()); } T init() const { return T(values.begin(), values.end()); }
void run(T& x) const void run(T& x) const
{ {
x = x; x = x;
DISABLE_EXCEPTIONS; DISABLE_EXCEPTIONS;
test::check_container(x, values); test::check_container(x, values);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const
{ {
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
}; };
template <class T> struct self_assign_test1 : self_assign_base<T> template <class T> struct self_assign_test1 : self_assign_base<T>
@ -46,129 +46,129 @@ template <class T> struct self_assign_test1 : self_assign_base<T>
template <class T> struct self_assign_test2 : self_assign_base<T> template <class T> struct self_assign_test2 : self_assign_base<T>
{ {
self_assign_test2() : self_assign_base<T>(100) {} self_assign_test2() : self_assign_base<T>(100) {}
}; };
template <class T> struct assign_base : public test::exception_base template <class T> struct assign_base : public test::exception_base
{ {
test::random_values<T> x_values, y_values; test::random_values<T> x_values, y_values;
T x, y; T x, y;
typedef BOOST_DEDUCED_TYPENAME T::hasher hasher; typedef BOOST_DEDUCED_TYPENAME T::hasher hasher;
typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal; typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal;
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type; typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
assign_base(int tag1, int tag2, float mlf1 = 1.0, float mlf2 = 1.0) assign_base(int tag1, int tag2, float mlf1 = 1.0, float mlf2 = 1.0)
: x_values(), y_values(), : x_values(), y_values(),
x(0, hasher(tag1), key_equal(tag1), allocator_type(tag1)), x(0, hasher(tag1), key_equal(tag1), allocator_type(tag1)),
y(0, hasher(tag2), key_equal(tag2), allocator_type(tag2)) y(0, hasher(tag2), key_equal(tag2), allocator_type(tag2))
{ {
x.max_load_factor(mlf1); x.max_load_factor(mlf1);
y.max_load_factor(mlf2); y.max_load_factor(mlf2);
} }
typedef T data_type; typedef T data_type;
T init() const { return T(x); } T init() const { return T(x); }
void run(T& x1) const void run(T& x1) const
{ {
x1 = y; x1 = y;
DISABLE_EXCEPTIONS; DISABLE_EXCEPTIONS;
test::check_container(x1, y_values); test::check_container(x1, y_values);
test::check_equivalent_keys(x1); test::check_equivalent_keys(x1);
} }
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x1) const void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x1) const
{ {
test::check_equivalent_keys(x1); test::check_equivalent_keys(x1);
// If the container is empty at the point of the exception, the // If the container is empty at the point of the exception, the
// internal structure is hidden, this exposes it, at the cost of // internal structure is hidden, this exposes it, at the cost of
// messing up the data. // messing up the data.
if (x_values.size()) { if (x_values.size()) {
T& x2 = const_cast<T&>(x1); T& x2 = const_cast<T&>(x1);
x2.emplace(*x_values.begin()); x2.emplace(*x_values.begin());
test::check_equivalent_keys(x2); test::check_equivalent_keys(x2);
}
} }
}
}; };
template <class T> struct assign_values : assign_base<T> template <class T> struct assign_values : assign_base<T>
{ {
assign_values(unsigned int count1, unsigned int count2, int tag1, int tag2, assign_values(unsigned int count1, unsigned int count2, int tag1, int tag2,
test::random_generator gen = test::default_generator, float mlf1 = 1.0, test::random_generator gen = test::default_generator, float mlf1 = 1.0,
float mlf2 = 1.0) float mlf2 = 1.0)
: assign_base<T>(tag1, tag2, mlf1, mlf2) : assign_base<T>(tag1, tag2, mlf1, mlf2)
{ {
this->x_values.fill(count1, gen); this->x_values.fill(count1, gen);
this->y_values.fill(count2, gen); this->y_values.fill(count2, gen);
this->x.insert(this->x_values.begin(), this->x_values.end()); this->x.insert(this->x_values.begin(), this->x_values.end());
this->y.insert(this->y_values.begin(), this->y_values.end()); this->y.insert(this->y_values.begin(), this->y_values.end());
} }
}; };
template <class T> struct assign_test1 : assign_values<T> template <class T> struct assign_test1 : assign_values<T>
{ {
assign_test1() : assign_values<T>(0, 0, 0, 0) {} assign_test1() : assign_values<T>(0, 0, 0, 0) {}
}; };
template <class T> struct assign_test2 : assign_values<T> template <class T> struct assign_test2 : assign_values<T>
{ {
assign_test2() : assign_values<T>(60, 0, 0, 0) {} assign_test2() : assign_values<T>(60, 0, 0, 0) {}
}; };
template <class T> struct assign_test2a : assign_values<T> template <class T> struct assign_test2a : assign_values<T>
{ {
assign_test2a() : assign_values<T>(60, 0, 0, 0, test::limited_range) {} assign_test2a() : assign_values<T>(60, 0, 0, 0, test::limited_range) {}
}; };
template <class T> struct assign_test3 : assign_values<T> template <class T> struct assign_test3 : assign_values<T>
{ {
assign_test3() : assign_values<T>(0, 60, 0, 0) {} assign_test3() : assign_values<T>(0, 60, 0, 0) {}
}; };
template <class T> struct assign_test3a : assign_values<T> template <class T> struct assign_test3a : assign_values<T>
{ {
assign_test3a() : assign_values<T>(0, 60, 0, 0, test::limited_range) {} assign_test3a() : assign_values<T>(0, 60, 0, 0, test::limited_range) {}
}; };
template <class T> struct assign_test4 : assign_values<T> template <class T> struct assign_test4 : assign_values<T>
{ {
assign_test4() : assign_values<T>(10, 10, 1, 2) {} assign_test4() : assign_values<T>(10, 10, 1, 2) {}
}; };
template <class T> struct assign_test4a : assign_values<T> template <class T> struct assign_test4a : assign_values<T>
{ {
assign_test4a() : assign_values<T>(10, 100, 1, 2) {} assign_test4a() : assign_values<T>(10, 100, 1, 2) {}
}; };
template <class T> struct assign_test4b : assign_values<T> template <class T> struct assign_test4b : assign_values<T>
{ {
assign_test4b() : assign_values<T>(10, 100, 1, 2, test::limited_range) {} assign_test4b() : assign_values<T>(10, 100, 1, 2, test::limited_range) {}
}; };
template <class T> struct assign_test5 : assign_values<T> template <class T> struct assign_test5 : assign_values<T>
{ {
assign_test5() assign_test5()
: assign_values<T>(5, 60, 0, 0, test::default_generator, 1.0f, 0.1f) : assign_values<T>(5, 60, 0, 0, test::default_generator, 1.0f, 0.1f)
{ {
} }
}; };
template <class T> struct equivalent_test1 : assign_base<T> template <class T> struct equivalent_test1 : assign_base<T>
{ {
equivalent_test1() : assign_base<T>(0, 0) equivalent_test1() : assign_base<T>(0, 0)
{ {
test::random_values<T> x_values2(10); test::random_values<T> x_values2(10);
this->x_values.insert(x_values2.begin(), x_values2.end()); this->x_values.insert(x_values2.begin(), x_values2.end());
this->x_values.insert(x_values2.begin(), x_values2.end()); this->x_values.insert(x_values2.begin(), x_values2.end());
test::random_values<T> y_values2(10); test::random_values<T> y_values2(10);
this->y_values.insert(y_values2.begin(), y_values2.end()); this->y_values.insert(y_values2.begin(), y_values2.end());
this->y_values.insert(y_values2.begin(), y_values2.end()); this->y_values.insert(y_values2.begin(), y_values2.end());
this->x.insert(this->x_values.begin(), this->x_values.end()); this->x.insert(this->x_values.begin(), this->x_values.end());
this->y.insert(this->y_values.begin(), this->y_values.end()); this->y.insert(this->y_values.begin(), this->y_values.end());
} }
}; };
// clang-format off // clang-format off

View File

@ -16,196 +16,194 @@ test::seed_t initialize_seed(91274);
struct objects struct objects
{ {
test::exception::object obj; test::exception::object obj;
test::exception::hash hash; test::exception::hash hash;
test::exception::equal_to equal_to; test::exception::equal_to equal_to;
test::exception::allocator<test::exception::object> allocator; test::exception::allocator<test::exception::object> allocator;
}; };
template <class T> struct construct_test1 : public objects, test::exception_base template <class T> struct construct_test1 : public objects, test::exception_base
{ {
void run() const void run() const
{ {
T x; T x;
DISABLE_EXCEPTIONS; DISABLE_EXCEPTIONS;
BOOST_TEST(x.empty()); BOOST_TEST(x.empty());
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
}; };
template <class T> struct construct_test2 : public objects, test::exception_base template <class T> struct construct_test2 : public objects, test::exception_base
{ {
void run() const void run() const
{ {
T x(300); T x(300);
DISABLE_EXCEPTIONS; DISABLE_EXCEPTIONS;
BOOST_TEST(x.empty()); BOOST_TEST(x.empty());
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
}; };
template <class T> struct construct_test3 : public objects, test::exception_base template <class T> struct construct_test3 : public objects, test::exception_base
{ {
void run() const void run() const
{ {
T x(0, hash); T x(0, hash);
DISABLE_EXCEPTIONS; DISABLE_EXCEPTIONS;
BOOST_TEST(x.empty()); BOOST_TEST(x.empty());
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
}; };
template <class T> struct construct_test4 : public objects, test::exception_base template <class T> struct construct_test4 : public objects, test::exception_base
{ {
void run() const void run() const
{ {
T x(0, hash, equal_to); T x(0, hash, equal_to);
DISABLE_EXCEPTIONS; DISABLE_EXCEPTIONS;
BOOST_TEST(x.empty()); BOOST_TEST(x.empty());
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
}; };
template <class T> struct construct_test5 : public objects, test::exception_base template <class T> struct construct_test5 : public objects, test::exception_base
{ {
void run() const void run() const
{ {
T x(50, hash, equal_to, allocator); T x(50, hash, equal_to, allocator);
DISABLE_EXCEPTIONS; DISABLE_EXCEPTIONS;
BOOST_TEST(x.empty()); BOOST_TEST(x.empty());
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
}; };
template <class T> struct construct_test6 : public objects, test::exception_base template <class T> struct construct_test6 : public objects, test::exception_base
{ {
void run() const void run() const
{ {
T x(allocator); T x(allocator);
DISABLE_EXCEPTIONS; DISABLE_EXCEPTIONS;
BOOST_TEST(x.empty()); BOOST_TEST(x.empty());
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
}; };
template <class T> struct range : public test::exception_base template <class T> struct range : public test::exception_base
{ {
test::random_values<T> values; test::random_values<T> values;
range() : values(5, test::limited_range) {} range() : values(5, test::limited_range) {}
range(unsigned int count) : values(count, test::limited_range) {} range(unsigned int count) : values(count, test::limited_range) {}
}; };
template <class T> struct range_construct_test1 : public range<T>, objects template <class T> struct range_construct_test1 : public range<T>, objects
{ {
void run() const void run() const
{ {
T x(this->values.begin(), this->values.end()); T x(this->values.begin(), this->values.end());
DISABLE_EXCEPTIONS; DISABLE_EXCEPTIONS;
test::check_container(x, this->values); test::check_container(x, this->values);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
}; };
template <class T> struct range_construct_test2 : public range<T>, objects template <class T> struct range_construct_test2 : public range<T>, objects
{ {
void run() const void run() const
{ {
T x(this->values.begin(), this->values.end(), 0); T x(this->values.begin(), this->values.end(), 0);
DISABLE_EXCEPTIONS; DISABLE_EXCEPTIONS;
test::check_container(x, this->values); test::check_container(x, this->values);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
}; };
template <class T> struct range_construct_test3 : public range<T>, objects template <class T> struct range_construct_test3 : public range<T>, objects
{ {
void run() const void run() const
{ {
T x(this->values.begin(), this->values.end(), 0, hash); T x(this->values.begin(), this->values.end(), 0, hash);
DISABLE_EXCEPTIONS; DISABLE_EXCEPTIONS;
test::check_container(x, this->values); test::check_container(x, this->values);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
}; };
template <class T> struct range_construct_test4 : public range<T>, objects template <class T> struct range_construct_test4 : public range<T>, objects
{ {
void run() const void run() const
{ {
T x(this->values.begin(), this->values.end(), 100, hash, equal_to); T x(this->values.begin(), this->values.end(), 100, hash, equal_to);
DISABLE_EXCEPTIONS; DISABLE_EXCEPTIONS;
test::check_container(x, this->values); test::check_container(x, this->values);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
}; };
// Need to run at least one test with a fairly large number // Need to run at least one test with a fairly large number
// of objects in case it triggers a rehash. // of objects in case it triggers a rehash.
template <class T> struct range_construct_test5 : public range<T>, objects template <class T> struct range_construct_test5 : public range<T>, objects
{ {
range_construct_test5() : range<T>(60) {} range_construct_test5() : range<T>(60) {}
void run() const void run() const
{ {
T x(this->values.begin(), this->values.end(), 0, hash, equal_to, T x(this->values.begin(), this->values.end(), 0, hash, equal_to, allocator);
allocator);
DISABLE_EXCEPTIONS; DISABLE_EXCEPTIONS;
test::check_container(x, this->values); test::check_container(x, this->values);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
}; };
template <class T> struct input_range_construct_test : public range<T>, objects template <class T> struct input_range_construct_test : public range<T>, objects
{ {
input_range_construct_test() : range<T>(60) {} input_range_construct_test() : range<T>(60) {}
void run() const void run() const
{ {
BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
begin = this->values.begin(), begin = this->values.begin(),
end = this->values.end(); end = this->values.end();
T x(test::input_iterator(begin), test::input_iterator(end), 0, hash, T x(test::input_iterator(begin), test::input_iterator(end), 0, hash,
equal_to, allocator); equal_to, allocator);
DISABLE_EXCEPTIONS; DISABLE_EXCEPTIONS;
test::check_container(x, this->values); test::check_container(x, this->values);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
}; };
template <class T> struct copy_range_construct_test : public range<T>, objects template <class T> struct copy_range_construct_test : public range<T>, objects
{ {
copy_range_construct_test() : range<T>(60) {} copy_range_construct_test() : range<T>(60) {}
void run() const void run() const
{ {
T x(test::copy_iterator(this->values.begin()), T x(test::copy_iterator(this->values.begin()),
test::copy_iterator(this->values.end()), 0, hash, equal_to, test::copy_iterator(this->values.end()), 0, hash, equal_to, allocator);
allocator);
DISABLE_EXCEPTIONS; DISABLE_EXCEPTIONS;
test::check_container(x, this->values); test::check_container(x, this->values);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
}; };
EXCEPTION_TESTS( EXCEPTION_TESTS(
(construct_test1)(construct_test2)(construct_test3)(construct_test4)( (construct_test1)(construct_test2)(construct_test3)(construct_test4)(
construct_test5)(construct_test6)(range_construct_test1)( construct_test5)(construct_test6)(range_construct_test1)(
range_construct_test2)(range_construct_test3)(range_construct_test4)( range_construct_test2)(range_construct_test3)(range_construct_test4)(
range_construct_test5)(input_range_construct_test)( range_construct_test5)(input_range_construct_test)(
copy_range_construct_test), copy_range_construct_test),
CONTAINER_SEQ) CONTAINER_SEQ)
RUN_TESTS() RUN_TESTS()

View File

@ -13,32 +13,32 @@
#include "../objects/exception.hpp" #include "../objects/exception.hpp"
typedef boost::unordered_set<test::exception::object, test::exception::hash, typedef boost::unordered_set<test::exception::object, test::exception::hash,
test::exception::equal_to, test::exception::equal_to,
test::exception::allocator<test::exception::object> > test::exception::allocator<test::exception::object> >
test_set; test_set;
typedef boost::unordered_multiset<test::exception::object, typedef boost::unordered_multiset<test::exception::object,
test::exception::hash, test::exception::equal_to, test::exception::hash, test::exception::equal_to,
test::exception::allocator2<test::exception::object> > test::exception::allocator2<test::exception::object> >
test_multiset; test_multiset;
typedef boost::unordered_map<test::exception::object, test::exception::object, typedef boost::unordered_map<test::exception::object, test::exception::object,
test::exception::hash, test::exception::equal_to, test::exception::hash, test::exception::equal_to,
test::exception::allocator2<test::exception::object> > test::exception::allocator2<test::exception::object> >
test_map; test_map;
typedef boost::unordered_multimap<test::exception::object, typedef boost::unordered_multimap<test::exception::object,
test::exception::object, test::exception::hash, test::exception::equal_to, test::exception::object, test::exception::hash, test::exception::equal_to,
test::exception::allocator<test::exception::object> > test::exception::allocator<test::exception::object> >
test_multimap; test_multimap;
typedef boost::unordered_set< typedef boost::unordered_set<
std::pair<test::exception::object, test::exception::object>, std::pair<test::exception::object, test::exception::object>,
test::exception::hash, test::exception::equal_to, test::exception::hash, test::exception::equal_to,
test::exception::allocator<test::exception::object> > test::exception::allocator<test::exception::object> >
test_pair_set; test_pair_set;
typedef boost::unordered_multiset< typedef boost::unordered_multiset<
std::pair<test::exception::object, test::exception::object>, std::pair<test::exception::object, test::exception::object>,
test::exception::hash, test::exception::equal_to, test::exception::hash, test::exception::equal_to,
test::exception::allocator2<test::exception::object> > test::exception::allocator2<test::exception::object> >
test_pair_multiset; test_pair_multiset;
#define CONTAINER_SEQ (test_set)(test_multiset)(test_map)(test_multimap) #define CONTAINER_SEQ (test_set)(test_multiset)(test_map)(test_multimap)
#define CONTAINER_PAIR_SEQ \ #define CONTAINER_PAIR_SEQ \
(test_pair_set)(test_pair_multiset)(test_map)(test_multimap) (test_pair_set)(test_pair_multiset)(test_map)(test_multimap)

View File

@ -15,91 +15,90 @@ test::seed_t initialize_seed(73041);
template <class T> struct copy_test1 : public test::exception_base template <class T> struct copy_test1 : public test::exception_base
{ {
T x; T x;
void run() const void run() const
{ {
T y(x); T y(x);
DISABLE_EXCEPTIONS; DISABLE_EXCEPTIONS;
BOOST_TEST(y.empty()); BOOST_TEST(y.empty());
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
} }
}; };
template <class T> struct copy_test2 : public test::exception_base template <class T> struct copy_test2 : public test::exception_base
{ {
test::random_values<T> values; test::random_values<T> values;
T x; T x;
copy_test2() copy_test2() : values(5, test::limited_range), x(values.begin(), values.end())
: values(5, test::limited_range), x(values.begin(), values.end()) {
{ }
}
void run() const void run() const
{ {
T y(x); T y(x);
DISABLE_EXCEPTIONS; DISABLE_EXCEPTIONS;
test::check_container(y, this->values); test::check_container(y, this->values);
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
} }
}; };
template <class T> struct copy_test3 : public test::exception_base template <class T> struct copy_test3 : public test::exception_base
{ {
test::random_values<T> values; test::random_values<T> values;
T x; T x;
copy_test3() : values(100), x(values.begin(), values.end()) {} copy_test3() : values(100), x(values.begin(), values.end()) {}
void run() const void run() const
{ {
T y(x); T y(x);
DISABLE_EXCEPTIONS; DISABLE_EXCEPTIONS;
test::check_container(y, this->values); test::check_container(y, this->values);
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
} }
}; };
template <class T> struct copy_test3a : public test::exception_base template <class T> struct copy_test3a : public test::exception_base
{ {
test::random_values<T> values; test::random_values<T> values;
T x; T x;
copy_test3a() copy_test3a()
: values(100, test::limited_range), x(values.begin(), values.end()) : values(100, test::limited_range), x(values.begin(), values.end())
{ {
} }
void run() const void run() const
{ {
T y(x); T y(x);
DISABLE_EXCEPTIONS; DISABLE_EXCEPTIONS;
test::check_container(y, this->values); test::check_container(y, this->values);
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
} }
}; };
template <class T> struct copy_with_allocator_test : public test::exception_base template <class T> struct copy_with_allocator_test : public test::exception_base
{ {
test::random_values<T> values; test::random_values<T> values;
T x; T x;
test::exception::allocator<test::exception::object> allocator; test::exception::allocator<test::exception::object> allocator;
copy_with_allocator_test() : values(100), x(values.begin(), values.end()) {} copy_with_allocator_test() : values(100), x(values.begin(), values.end()) {}
void run() const void run() const
{ {
T y(x, allocator); T y(x, allocator);
DISABLE_EXCEPTIONS; DISABLE_EXCEPTIONS;
test::check_container(y, this->values); test::check_container(y, this->values);
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
} }
}; };
// clang-format off // clang-format off

View File

@ -13,43 +13,43 @@ test::seed_t initialize_seed(835193);
template <class T> struct erase_test_base : public test::exception_base template <class T> struct erase_test_base : public test::exception_base
{ {
test::random_values<T> values; test::random_values<T> values;
erase_test_base(unsigned int count = 5) : values(count, test::limited_range) erase_test_base(unsigned int count = 5) : values(count, test::limited_range)
{ {
} }
typedef T data_type; typedef T data_type;
data_type init() const { return T(values.begin(), values.end()); } data_type init() const { return T(values.begin(), values.end()); }
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const
{ {
std::string scope(test::scope); std::string scope(test::scope);
BOOST_TEST(scope.find("hash::") != std::string::npos || BOOST_TEST(scope.find("hash::") != std::string::npos ||
scope.find("equal_to::") != std::string::npos || scope.find("equal_to::") != std::string::npos ||
scope == "operator==(object, object)"); scope == "operator==(object, object)");
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
}; };
template <class T> struct erase_by_key_test1 : public erase_test_base<T> template <class T> struct erase_by_key_test1 : public erase_test_base<T>
{ {
void run(T& x) const void run(T& x) const
{ {
typedef BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator typedef BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator
iterator; iterator;
for (iterator it = this->values.begin(), end = this->values.end(); for (iterator it = this->values.begin(), end = this->values.end();
it != end; ++it) { it != end; ++it) {
x.erase(test::get_key<T>(*it)); x.erase(test::get_key<T>(*it));
}
DISABLE_EXCEPTIONS;
BOOST_TEST(x.empty());
test::check_equivalent_keys(x);
} }
DISABLE_EXCEPTIONS;
BOOST_TEST(x.empty());
test::check_equivalent_keys(x);
}
}; };
EXCEPTION_TESTS((erase_by_key_test1), CONTAINER_SEQ) EXCEPTION_TESTS((erase_by_key_test1), CONTAINER_SEQ)

View File

@ -17,16 +17,16 @@ test::seed_t initialize_seed(747373);
// Fill in a container so that it's about to rehash // Fill in a container so that it's about to rehash
template <typename T> void rehash_prep(T& x) template <typename T> void rehash_prep(T& x)
{ {
using namespace std; using namespace std;
typedef BOOST_DEDUCED_TYPENAME T::size_type size_type; typedef BOOST_DEDUCED_TYPENAME T::size_type size_type;
x.max_load_factor(0.25); x.max_load_factor(0.25);
size_type bucket_count = x.bucket_count(); size_type bucket_count = x.bucket_count();
size_type initial_elements = static_cast<size_type>( size_type initial_elements = static_cast<size_type>(
ceil((double)bucket_count * (double)x.max_load_factor()) - 1); ceil((double)bucket_count * (double)x.max_load_factor()) - 1);
test::random_values<T> v(initial_elements); test::random_values<T> v(initial_elements);
x.insert(v.begin(), v.end()); x.insert(v.begin(), v.end());
BOOST_TEST(bucket_count == x.bucket_count()); BOOST_TEST(bucket_count == x.bucket_count());
} }
// Overload to generate inserters that need type information. // Overload to generate inserters that need type information.
@ -34,7 +34,7 @@ template <typename T> void rehash_prep(T& x)
template <typename Inserter, typename T> template <typename Inserter, typename T>
Inserter generate(Inserter inserter, T&) Inserter generate(Inserter inserter, T&)
{ {
return inserter; return inserter;
} }
// Get the iterator returned from an insert/emplace. // Get the iterator returned from an insert/emplace.
@ -43,7 +43,7 @@ template <typename T> T get_iterator(T const& x) { return x; }
template <typename T> T get_iterator(std::pair<T, bool> const& x) template <typename T> T get_iterator(std::pair<T, bool> const& x)
{ {
return x.first; return x.first;
} }
// Generic insert exception test for typical single element inserts.. // Generic insert exception test for typical single element inserts..
@ -51,28 +51,27 @@ template <typename T> T get_iterator(std::pair<T, bool> const& x)
template <typename T, typename Inserter, typename Values> template <typename T, typename Inserter, typename Values>
void insert_exception_test_impl(T x, Inserter insert, Values const& v) void insert_exception_test_impl(T x, Inserter insert, Values const& v)
{ {
test::strong<T> strong; test::strong<T> strong;
test::ordered<T> tracker; test::ordered<T> tracker;
tracker.insert(x.begin(), x.end()); tracker.insert(x.begin(), x.end());
try { try {
ENABLE_EXCEPTIONS; ENABLE_EXCEPTIONS;
for (typename Values::const_iterator it = v.begin(); it != v.end(); for (typename Values::const_iterator it = v.begin(); it != v.end(); ++it) {
++it) { strong.store(x, test::detail::tracker.count_allocations);
strong.store(x, test::detail::tracker.count_allocations); insert(x, it);
insert(x, it);
}
} catch (...) {
test::check_equivalent_keys(x);
insert.exception_check(x, strong);
throw;
} }
} catch (...) {
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
insert.track(tracker, v.begin(), v.end()); insert.exception_check(x, strong);
tracker.compare(x); throw;
}
test::check_equivalent_keys(x);
insert.track(tracker, v.begin(), v.end());
tracker.compare(x);
} }
// Simple insert exception test // Simple insert exception test
@ -80,12 +79,12 @@ void insert_exception_test_impl(T x, Inserter insert, Values const& v)
template <typename T, typename Inserter> template <typename T, typename Inserter>
void insert_exception_test(T*, Inserter insert, test::random_generator gen) void insert_exception_test(T*, Inserter insert, test::random_generator gen)
{ {
for (int i = 0; i < 5; ++i) { for (int i = 0; i < 5; ++i) {
test::random_values<T> v(10, gen); test::random_values<T> v(10, gen);
T x; T x;
EXCEPTION_LOOP(insert_exception_test_impl(x, generate(insert, x), v)); EXCEPTION_LOOP(insert_exception_test_impl(x, generate(insert, x), v));
} }
} }
// Insert into a container which is about to hit its max load, so that it // Insert into a container which is about to hit its max load, so that it
@ -93,130 +92,130 @@ void insert_exception_test(T*, Inserter insert, test::random_generator gen)
template <typename T, typename Inserter> template <typename T, typename Inserter>
void insert_rehash_exception_test( 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;
rehash_prep(x); rehash_prep(x);
test::random_values<T> v2(5, gen); test::random_values<T> v2(5, gen);
EXCEPTION_LOOP(insert_exception_test_impl(x, generate(insert, x), v2)); EXCEPTION_LOOP(insert_exception_test_impl(x, generate(insert, x), v2));
} }
} }
// Various methods for inserting a single element // Various methods for inserting a single element
struct inserter_base struct inserter_base
{ {
template <typename T> void exception_check(T& x, test::strong<T>& strong) template <typename T> void exception_check(T& x, test::strong<T>& strong)
{ {
std::string scope(test::scope); std::string scope(test::scope);
if (scope.find("hash::operator()") == std::string::npos) if (scope.find("hash::operator()") == std::string::npos)
strong.test(x, test::detail::tracker.count_allocations); strong.test(x, test::detail::tracker.count_allocations);
} }
template <typename T, typename Iterator> template <typename T, typename Iterator>
void track(T& tracker, Iterator begin, Iterator end) void track(T& tracker, Iterator begin, Iterator end)
{ {
tracker.insert(begin, end); tracker.insert(begin, end);
} }
}; };
struct insert_lvalue_type : inserter_base struct insert_lvalue_type : inserter_base
{ {
template <typename T, typename Iterator> void operator()(T& x, Iterator it) template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{ {
x.insert(*it); x.insert(*it);
} }
} insert_lvalue; } insert_lvalue;
struct insert_lvalue_begin_type : inserter_base struct insert_lvalue_begin_type : inserter_base
{ {
template <typename T, typename Iterator> void operator()(T& x, Iterator it) template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{ {
x.insert(x.begin(), *it); x.insert(x.begin(), *it);
} }
} insert_lvalue_begin; } insert_lvalue_begin;
struct insert_lvalue_end_type : inserter_base struct insert_lvalue_end_type : inserter_base
{ {
template <typename T, typename Iterator> void operator()(T& x, Iterator it) template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{ {
x.insert(x.end(), *it); x.insert(x.end(), *it);
} }
} insert_lvalue_end; } insert_lvalue_end;
struct insert_lvalue_pos_type struct insert_lvalue_pos_type
{ {
template <typename T> struct impl : inserter_base template <typename T> struct impl : inserter_base
{
typename T::iterator pos;
impl(T& x) : pos(x.begin()) {}
template <typename Iterator> void operator()(T& x, Iterator it)
{ {
typename T::iterator pos; pos = get_iterator(x.insert(pos, *it));
impl(T& x) : pos(x.begin()) {}
template <typename Iterator> void operator()(T& x, Iterator it)
{
pos = get_iterator(x.insert(pos, *it));
}
};
template <typename T> friend impl<T> generate(insert_lvalue_pos_type, T& x)
{
return impl<T>(x);
} }
};
template <typename T> friend impl<T> generate(insert_lvalue_pos_type, T& x)
{
return impl<T>(x);
}
} insert_lvalue_pos; } insert_lvalue_pos;
struct insert_single_item_range_type : inserter_base struct insert_single_item_range_type : inserter_base
{ {
template <typename T, typename Iterator> void operator()(T& x, Iterator it) template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{ {
x.insert(it, test::next(it)); x.insert(it, test::next(it));
} }
} insert_single_item_range; } insert_single_item_range;
struct emplace_lvalue_type : inserter_base struct emplace_lvalue_type : inserter_base
{ {
template <typename T, typename Iterator> void operator()(T& x, Iterator it) template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{ {
x.emplace(*it); x.emplace(*it);
} }
} emplace_lvalue; } emplace_lvalue;
struct emplace_lvalue_begin_type : inserter_base struct emplace_lvalue_begin_type : inserter_base
{ {
template <typename T, typename Iterator> void operator()(T& x, Iterator it) template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{ {
x.emplace_hint(x.begin(), *it); x.emplace_hint(x.begin(), *it);
} }
} emplace_lvalue_begin; } emplace_lvalue_begin;
struct emplace_lvalue_end_type : inserter_base struct emplace_lvalue_end_type : inserter_base
{ {
template <typename T, typename Iterator> void operator()(T& x, Iterator it) template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{ {
x.emplace_hint(x.end(), *it); x.emplace_hint(x.end(), *it);
} }
} emplace_lvalue_end; } emplace_lvalue_end;
struct emplace_lvalue_pos_type struct emplace_lvalue_pos_type
{ {
template <typename T> struct impl : inserter_base template <typename T> struct impl : inserter_base
{
typename T::iterator pos;
impl(T& x) : pos(x.begin()) {}
template <typename Iterator> void operator()(T& x, Iterator it)
{ {
typename T::iterator pos; pos = get_iterator(x.emplace_hint(pos, *it));
impl(T& x) : pos(x.begin()) {}
template <typename Iterator> void operator()(T& x, Iterator it)
{
pos = get_iterator(x.emplace_hint(pos, *it));
}
};
template <typename T> friend impl<T> generate(emplace_lvalue_pos_type, T& x)
{
return impl<T>(x);
} }
};
template <typename T> friend impl<T> generate(emplace_lvalue_pos_type, T& x)
{
return impl<T>(x);
}
} emplace_lvalue_pos; } emplace_lvalue_pos;
// Run the exception tests in various combinations. // Run the exception tests in various combinations.
@ -256,21 +255,21 @@ UNORDERED_TEST(insert_rehash_exception_test,
struct pair_emplace_type : inserter_base struct pair_emplace_type : inserter_base
{ {
template <typename T, typename Iterator> void operator()(T& x, Iterator it) template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{ {
x.emplace(boost::unordered::piecewise_construct, x.emplace(boost::unordered::piecewise_construct,
boost::make_tuple(it->first), boost::make_tuple(it->second)); boost::make_tuple(it->first), boost::make_tuple(it->second));
} }
} pair_emplace; } pair_emplace;
struct pair_emplace2_type : inserter_base struct pair_emplace2_type : inserter_base
{ {
template <typename T, typename Iterator> void operator()(T& x, Iterator it) template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{ {
x.emplace_hint(x.begin(), boost::unordered::piecewise_construct, x.emplace_hint(x.begin(), boost::unordered::piecewise_construct,
boost::make_tuple(it->first), boost::make_tuple(it->first),
boost::make_tuple(it->second.tag1_, it->second.tag2_)); boost::make_tuple(it->second.tag1_, it->second.tag2_));
} }
} pair_emplace2; } pair_emplace2;
test_pair_set* test_pair_set_; test_pair_set* test_pair_set_;
@ -293,54 +292,54 @@ UNORDERED_TEST(insert_rehash_exception_test,
struct try_emplace_type : inserter_base struct try_emplace_type : inserter_base
{ {
template <typename T, typename Iterator> void operator()(T& x, Iterator it) template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{ {
x.try_emplace(it->first, it->second); x.try_emplace(it->first, it->second);
} }
} try_emplace; } try_emplace;
struct try_emplace2_type : inserter_base struct try_emplace2_type : inserter_base
{ {
template <typename T, typename Iterator> void operator()(T& x, Iterator it) template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{ {
x.try_emplace(it->first, it->second.tag1_, it->second.tag2_); x.try_emplace(it->first, it->second.tag1_, it->second.tag2_);
} }
} try_emplace2; } try_emplace2;
struct map_inserter_base struct map_inserter_base
{ {
template <typename T> void exception_check(T& x, test::strong<T>& strong) template <typename T> void exception_check(T& x, test::strong<T>& strong)
{ {
std::string scope(test::scope); std::string scope(test::scope);
if (scope.find("hash::operator()") == std::string::npos && if (scope.find("hash::operator()") == std::string::npos &&
scope.find("::operator=") == std::string::npos) scope.find("::operator=") == std::string::npos)
strong.test(x, test::detail::tracker.count_allocations); strong.test(x, test::detail::tracker.count_allocations);
} }
template <typename T, typename Iterator> template <typename T, typename Iterator>
void track(T& tracker, Iterator begin, Iterator end) void track(T& tracker, Iterator begin, Iterator end)
{ {
for (; begin != end; ++begin) { for (; begin != end; ++begin) {
tracker[begin->first] = begin->second; tracker[begin->first] = begin->second;
}
} }
}
}; };
struct map_insert_operator_type : map_inserter_base struct map_insert_operator_type : map_inserter_base
{ {
template <typename T, typename Iterator> void operator()(T& x, Iterator it) template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{ {
x[it->first] = it->second; x[it->first] = it->second;
} }
} map_insert_operator; } map_insert_operator;
struct map_insert_or_assign_type : map_inserter_base struct map_insert_or_assign_type : map_inserter_base
{ {
template <typename T, typename Iterator> void operator()(T& x, Iterator it) template <typename T, typename Iterator> void operator()(T& x, Iterator it)
{ {
x.insert_or_assign(it->first, it->second); x.insert_or_assign(it->first, it->second);
} }
} map_insert_or_assign; } map_insert_or_assign;
// clang-format off // clang-format off
@ -361,43 +360,43 @@ UNORDERED_TEST(insert_rehash_exception_test,
template <typename T, typename Values> template <typename T, typename Values>
void insert_range_exception_test_impl(T x, Values const& v) void insert_range_exception_test_impl(T x, Values const& v)
{ {
test::ordered<T> tracker; test::ordered<T> tracker;
tracker.insert(x.begin(), x.end()); tracker.insert(x.begin(), x.end());
try {
ENABLE_EXCEPTIONS;
x.insert(v.begin(), v.end());
} catch (...) {
test::check_equivalent_keys(x);
throw;
}
try {
ENABLE_EXCEPTIONS;
x.insert(v.begin(), v.end());
} catch (...) {
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
tracker.insert(v.begin(), v.end()); throw;
tracker.compare(x); }
test::check_equivalent_keys(x);
tracker.insert(v.begin(), v.end());
tracker.compare(x);
} }
template <typename T> template <typename T>
void insert_range_exception_test(T*, test::random_generator gen) void insert_range_exception_test(T*, test::random_generator gen)
{ {
for (int i = 0; i < 5; ++i) { for (int i = 0; i < 5; ++i) {
test::random_values<T> v(10, gen); test::random_values<T> v(10, gen);
T x; T x;
EXCEPTION_LOOP(insert_range_exception_test_impl(x, v)); EXCEPTION_LOOP(insert_range_exception_test_impl(x, v));
} }
} }
template <typename T> 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;
rehash_prep(x); rehash_prep(x);
test::random_values<T> v2(5, gen); test::random_values<T> v2(5, gen);
EXCEPTION_LOOP(insert_range_exception_test_impl(x, v2)); EXCEPTION_LOOP(insert_range_exception_test_impl(x, v2));
} }
} }
// clang-format off // clang-format off

View File

@ -6,59 +6,59 @@
template <typename T1, typename T2> void merge_exception_test(T1 x, T2 y) template <typename T1, typename T2> void merge_exception_test(T1 x, T2 y)
{ {
std::size_t size = x.size() + y.size(); std::size_t size = x.size() + y.size();
try { try {
ENABLE_EXCEPTIONS; ENABLE_EXCEPTIONS;
x.merge(y); x.merge(y);
} catch (...) { } catch (...) {
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
throw;
}
// Not a full check, just want to make sure the merge completed.
BOOST_TEST(size == x.size() + y.size());
if (y.size()) {
BOOST_TEST(test::has_unique_keys<T1>::value);
for (typename T2::iterator it = y.begin(); it != y.end(); ++it) {
BOOST_TEST(x.find(test::get_key<T2>(*it)) != x.end());
}
}
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
throw;
}
// Not a full check, just want to make sure the merge completed.
BOOST_TEST(size == x.size() + y.size());
if (y.size()) {
BOOST_TEST(test::has_unique_keys<T1>::value);
for (typename T2::iterator it = y.begin(); it != y.end(); ++it) {
BOOST_TEST(x.find(test::get_key<T2>(*it)) != x.end());
}
}
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
} }
template <typename T1, typename T2> template <typename T1, typename T2>
void merge_exception_test(T1 const*, T2 const*, std::size_t count12, int tag12, void merge_exception_test(T1 const*, T2 const*, std::size_t count12, int tag12,
test::random_generator gen1, test::random_generator gen2) test::random_generator gen1, test::random_generator gen2)
{ {
std::size_t count1 = count12 / 256; std::size_t count1 = count12 / 256;
std::size_t count2 = count12 % 256; std::size_t count2 = count12 % 256;
int tag1 = tag12 / 256; int tag1 = tag12 / 256;
int tag2 = tag12 % 256; int tag2 = tag12 % 256;
test::random_values<T1> v1(count1, gen1); test::random_values<T1> v1(count1, gen1);
test::random_values<T2> v2(count2, gen2); test::random_values<T2> v2(count2, gen2);
T1 x(v1.begin(), v1.end(), 0, test::exception::hash(tag1), T1 x(v1.begin(), v1.end(), 0, test::exception::hash(tag1),
test::exception::equal_to(tag1)); test::exception::equal_to(tag1));
T2 y(v2.begin(), v2.end(), 0, test::exception::hash(tag2), T2 y(v2.begin(), v2.end(), 0, test::exception::hash(tag2),
test::exception::equal_to(tag2)); test::exception::equal_to(tag2));
EXCEPTION_LOOP(merge_exception_test(x, y)) EXCEPTION_LOOP(merge_exception_test(x, y))
} }
boost::unordered_set<test::exception::object, test::exception::hash, boost::unordered_set<test::exception::object, test::exception::hash,
test::exception::equal_to, test::exception::equal_to,
test::exception::allocator<test::exception::object> >* test_set_; test::exception::allocator<test::exception::object> >* test_set_;
boost::unordered_multiset<test::exception::object, test::exception::hash, boost::unordered_multiset<test::exception::object, test::exception::hash,
test::exception::equal_to, test::exception::equal_to,
test::exception::allocator<test::exception::object> >* test_multiset_; test::exception::allocator<test::exception::object> >* test_multiset_;
boost::unordered_map<test::exception::object, test::exception::object, boost::unordered_map<test::exception::object, test::exception::object,
test::exception::hash, test::exception::equal_to, test::exception::hash, test::exception::equal_to,
test::exception::allocator2<test::exception::object> >* test_map_; test::exception::allocator2<test::exception::object> >* test_map_;
boost::unordered_multimap<test::exception::object, test::exception::object, boost::unordered_multimap<test::exception::object, test::exception::object,
test::exception::hash, test::exception::equal_to, test::exception::hash, test::exception::equal_to,
test::exception::allocator2<test::exception::object> >* test_multimap_; test::exception::allocator2<test::exception::object> >* test_multimap_;
using test::default_generator; using test::default_generator;
using test::generate_collisions; using test::generate_collisions;

View File

@ -11,118 +11,118 @@
#if defined(BOOST_MSVC) #if defined(BOOST_MSVC)
#pragma warning( \ #pragma warning( \
disable : 4512) // move_assignment operator could not be generated disable : 4512) // move_assignment operator could not be generated
#endif #endif
test::seed_t initialize_seed(12847); test::seed_t initialize_seed(12847);
template <class T> struct move_assign_base : public test::exception_base template <class T> struct move_assign_base : public test::exception_base
{ {
test::random_values<T> x_values, y_values; test::random_values<T> x_values, y_values;
T x, y; T x, y;
typedef BOOST_DEDUCED_TYPENAME T::hasher hasher; typedef BOOST_DEDUCED_TYPENAME T::hasher hasher;
typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal; typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal;
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type; typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
move_assign_base(int tag1, int tag2, float mlf1 = 1.0, float mlf2 = 1.0) move_assign_base(int tag1, int tag2, float mlf1 = 1.0, float mlf2 = 1.0)
: x_values(), y_values(), : x_values(), y_values(),
x(0, hasher(tag1), key_equal(tag1), allocator_type(tag1)), x(0, hasher(tag1), key_equal(tag1), allocator_type(tag1)),
y(0, hasher(tag2), key_equal(tag2), allocator_type(tag2)) y(0, hasher(tag2), key_equal(tag2), allocator_type(tag2))
{ {
x.max_load_factor(mlf1); x.max_load_factor(mlf1);
y.max_load_factor(mlf2); y.max_load_factor(mlf2);
} }
typedef T data_type; typedef T data_type;
T init() const { return T(x); } T init() const { return T(x); }
void run(T& x1) const void run(T& x1) const
{ {
test::exceptions_enable disable_exceptions(false); test::exceptions_enable disable_exceptions(false);
T y1 = y; T y1 = y;
disable_exceptions.release(); disable_exceptions.release();
x1 = boost::move(y1); x1 = boost::move(y1);
DISABLE_EXCEPTIONS; DISABLE_EXCEPTIONS;
test::check_container(x1, y_values); test::check_container(x1, y_values);
test::check_equivalent_keys(x1); test::check_equivalent_keys(x1);
} }
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x1) const void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x1) const
{ {
test::check_equivalent_keys(x1); test::check_equivalent_keys(x1);
// If the container is empty at the point of the exception, the // If the container is empty at the point of the exception, the
// internal structure is hidden, this exposes it, at the cost of // internal structure is hidden, this exposes it, at the cost of
// messing up the data. // messing up the data.
if (x_values.size()) { if (x_values.size()) {
T& x2 = const_cast<T&>(x1); T& x2 = const_cast<T&>(x1);
x2.emplace(*x_values.begin()); x2.emplace(*x_values.begin());
test::check_equivalent_keys(x2); test::check_equivalent_keys(x2);
}
} }
}
}; };
template <class T> struct move_assign_values : move_assign_base<T> template <class T> struct move_assign_values : move_assign_base<T>
{ {
move_assign_values(unsigned int count1, unsigned int count2, int tag1, move_assign_values(unsigned int count1, unsigned int count2, int tag1,
int tag2, float mlf1 = 1.0, float mlf2 = 1.0) int tag2, float mlf1 = 1.0, float mlf2 = 1.0)
: move_assign_base<T>(tag1, tag2, mlf1, mlf2) : move_assign_base<T>(tag1, tag2, mlf1, mlf2)
{ {
this->x_values.fill(count1, test::limited_range); this->x_values.fill(count1, test::limited_range);
this->y_values.fill(count2, test::limited_range); this->y_values.fill(count2, test::limited_range);
this->x.insert(this->x_values.begin(), this->x_values.end()); this->x.insert(this->x_values.begin(), this->x_values.end());
this->y.insert(this->y_values.begin(), this->y_values.end()); this->y.insert(this->y_values.begin(), this->y_values.end());
} }
}; };
template <class T> struct move_assign_test1 : move_assign_values<T> template <class T> struct move_assign_test1 : move_assign_values<T>
{ {
move_assign_test1() : move_assign_values<T>(0, 0, 0, 0) {} move_assign_test1() : move_assign_values<T>(0, 0, 0, 0) {}
}; };
template <class T> struct move_assign_test2 : move_assign_values<T> template <class T> struct move_assign_test2 : move_assign_values<T>
{ {
move_assign_test2() : move_assign_values<T>(60, 0, 0, 0) {} move_assign_test2() : move_assign_values<T>(60, 0, 0, 0) {}
}; };
template <class T> struct move_assign_test3 : move_assign_values<T> template <class T> struct move_assign_test3 : move_assign_values<T>
{ {
move_assign_test3() : move_assign_values<T>(0, 60, 0, 0) {} move_assign_test3() : move_assign_values<T>(0, 60, 0, 0) {}
}; };
template <class T> struct move_assign_test4 : move_assign_values<T> template <class T> struct move_assign_test4 : move_assign_values<T>
{ {
move_assign_test4() : move_assign_values<T>(10, 10, 1, 2) {} move_assign_test4() : move_assign_values<T>(10, 10, 1, 2) {}
}; };
template <class T> struct move_assign_test4a : move_assign_values<T> template <class T> struct move_assign_test4a : move_assign_values<T>
{ {
move_assign_test4a() : move_assign_values<T>(10, 100, 1, 2) {} move_assign_test4a() : move_assign_values<T>(10, 100, 1, 2) {}
}; };
template <class T> struct move_assign_test5 : move_assign_values<T> template <class T> struct move_assign_test5 : move_assign_values<T>
{ {
move_assign_test5() : move_assign_values<T>(5, 60, 0, 0, 1.0f, 0.1f) {} move_assign_test5() : move_assign_values<T>(5, 60, 0, 0, 1.0f, 0.1f) {}
}; };
template <class T> struct equivalent_test1 : move_assign_base<T> template <class T> struct equivalent_test1 : move_assign_base<T>
{ {
equivalent_test1() : move_assign_base<T>(0, 0) equivalent_test1() : move_assign_base<T>(0, 0)
{ {
test::random_values<T> x_values2(10, test::limited_range); test::random_values<T> x_values2(10, test::limited_range);
this->x_values.insert(x_values2.begin(), x_values2.end()); this->x_values.insert(x_values2.begin(), x_values2.end());
this->x_values.insert(x_values2.begin(), x_values2.end()); this->x_values.insert(x_values2.begin(), x_values2.end());
test::random_values<T> y_values2(10, test::limited_range); test::random_values<T> y_values2(10, test::limited_range);
this->y_values.insert(y_values2.begin(), y_values2.end()); this->y_values.insert(y_values2.begin(), y_values2.end());
this->y_values.insert(y_values2.begin(), y_values2.end()); this->y_values.insert(y_values2.begin(), y_values2.end());
this->x.insert(this->x_values.begin(), this->x_values.end()); this->x.insert(this->x_values.begin(), this->x_values.end());
this->y.insert(this->y_values.begin(), this->y_values.end()); this->y.insert(this->y_values.begin(), this->y_values.end());
} }
}; };
EXCEPTION_TESTS((move_assign_test1)(move_assign_test2)(move_assign_test3)( EXCEPTION_TESTS(
move_assign_test4)(move_assign_test4a)(move_assign_test5)( (move_assign_test1)(move_assign_test2)(move_assign_test3)(move_assign_test4)(
equivalent_test1), move_assign_test4a)(move_assign_test5)(equivalent_test1),
CONTAINER_SEQ) CONTAINER_SEQ)
RUN_TESTS() RUN_TESTS()

View File

@ -15,115 +15,115 @@ test::seed_t initialize_seed(3298597);
template <class T> struct rehash_test_base : public test::exception_base template <class T> struct rehash_test_base : public test::exception_base
{ {
test::random_values<T> values; test::random_values<T> values;
unsigned int n; unsigned int n;
rehash_test_base(unsigned int count = 100, unsigned int n_ = 0) rehash_test_base(unsigned int count = 100, unsigned int n_ = 0)
: values(count, test::limited_range), n(n_) : values(count, test::limited_range), n(n_)
{ {
} }
typedef T data_type; typedef T data_type;
typedef test::strong<T> strong_type; typedef test::strong<T> strong_type;
data_type init() const data_type init() const
{ {
T x(values.begin(), values.end(), n); T x(values.begin(), values.end(), n);
return x; return x;
} }
void check BOOST_PREVENT_MACRO_SUBSTITUTION( void check BOOST_PREVENT_MACRO_SUBSTITUTION(
T const& x, strong_type const& strong) const T const& x, strong_type const& strong) const
{ {
std::string scope(test::scope); std::string scope(test::scope);
if (scope.find("hash::operator()") == std::string::npos && if (scope.find("hash::operator()") == std::string::npos &&
scope.find("equal_to::operator()") == std::string::npos && scope.find("equal_to::operator()") == std::string::npos &&
scope != "operator==(object, object)") scope != "operator==(object, object)")
strong.test(x); strong.test(x);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
}; };
template <class T> struct rehash_test0 : rehash_test_base<T> template <class T> struct rehash_test0 : rehash_test_base<T>
{ {
rehash_test0() : rehash_test_base<T>(0) {} rehash_test0() : rehash_test_base<T>(0) {}
void run(T& x) const void run(T& x) const
{ {
x.rehash(0); x.rehash(0);
DISABLE_EXCEPTIONS; DISABLE_EXCEPTIONS;
test::check_container(x, this->values); test::check_container(x, this->values);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
}; };
template <class T> struct rehash_test1 : rehash_test_base<T> template <class T> struct rehash_test1 : rehash_test_base<T>
{ {
rehash_test1() : rehash_test_base<T>(0) {} rehash_test1() : rehash_test_base<T>(0) {}
void run(T& x) const void run(T& x) const
{ {
x.rehash(200); x.rehash(200);
DISABLE_EXCEPTIONS; DISABLE_EXCEPTIONS;
test::check_container(x, this->values); test::check_container(x, this->values);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
}; };
template <class T> struct rehash_test2 : rehash_test_base<T> template <class T> struct rehash_test2 : rehash_test_base<T>
{ {
rehash_test2() : rehash_test_base<T>(0, 200) {} rehash_test2() : rehash_test_base<T>(0, 200) {}
void run(T& x) const void run(T& x) const
{ {
x.rehash(0); x.rehash(0);
DISABLE_EXCEPTIONS; DISABLE_EXCEPTIONS;
test::check_container(x, this->values); test::check_container(x, this->values);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
}; };
template <class T> struct rehash_test3 : rehash_test_base<T> template <class T> struct rehash_test3 : rehash_test_base<T>
{ {
rehash_test3() : rehash_test_base<T>(10, 0) {} rehash_test3() : rehash_test_base<T>(10, 0) {}
void run(T& x) const void run(T& x) const
{ {
x.rehash(200); x.rehash(200);
DISABLE_EXCEPTIONS; DISABLE_EXCEPTIONS;
test::check_container(x, this->values); test::check_container(x, this->values);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
}; };
template <class T> struct rehash_test4 : rehash_test_base<T> template <class T> struct rehash_test4 : rehash_test_base<T>
{ {
rehash_test4() : rehash_test_base<T>(10, 200) {} rehash_test4() : rehash_test_base<T>(10, 200) {}
void run(T& x) const void run(T& x) const
{ {
x.rehash(0); x.rehash(0);
DISABLE_EXCEPTIONS; DISABLE_EXCEPTIONS;
test::check_container(x, this->values); test::check_container(x, this->values);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
}; };
template <class T> struct rehash_test5 : rehash_test_base<T> template <class T> struct rehash_test5 : rehash_test_base<T>
{ {
rehash_test5() : rehash_test_base<T>(200, 10) {} rehash_test5() : rehash_test_base<T>(200, 10) {}
void run(T& x) const void run(T& x) const
{ {
x.rehash(0); x.rehash(0);
DISABLE_EXCEPTIONS; DISABLE_EXCEPTIONS;
test::check_container(x, this->values); test::check_container(x, this->values);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
}; };
EXCEPTION_TESTS((rehash_test0)(rehash_test1)(rehash_test2)(rehash_test3)( EXCEPTION_TESTS((rehash_test0)(rehash_test1)(rehash_test2)(rehash_test3)(
rehash_test4)(rehash_test5), rehash_test4)(rehash_test5),
CONTAINER_SEQ) CONTAINER_SEQ)
RUN_TESTS() RUN_TESTS()

View File

@ -17,35 +17,33 @@ test::seed_t initialize_seed(9387);
template <class T> struct self_swap_base : public test::exception_base template <class T> struct self_swap_base : public test::exception_base
{ {
test::random_values<T> values; test::random_values<T> values;
self_swap_base(std::size_t count = 0) : values(count, test::limited_range) self_swap_base(std::size_t count = 0) : values(count, test::limited_range) {}
{
}
typedef T data_type; typedef T data_type;
T init() const { return T(values.begin(), values.end()); } T init() const { return T(values.begin(), values.end()); }
void run(T& x) const void run(T& x) const
{ {
x.swap(x); x.swap(x);
DISABLE_EXCEPTIONS; DISABLE_EXCEPTIONS;
test::check_container(x, this->values); test::check_container(x, this->values);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const void check BOOST_PREVENT_MACRO_SUBSTITUTION(T const& x) const
{ {
std::string scope(test::scope); std::string scope(test::scope);
// TODO: In C++11 exceptions are only allowed in the swap function. // TODO: In C++11 exceptions are only allowed in the swap function.
BOOST_TEST(scope == "hash::hash(hash)" || BOOST_TEST(scope == "hash::hash(hash)" ||
scope == "hash::operator=(hash)" || scope == "hash::operator=(hash)" ||
scope == "equal_to::equal_to(equal_to)" || scope == "equal_to::equal_to(equal_to)" ||
scope == "equal_to::operator=(equal_to)"); scope == "equal_to::operator=(equal_to)");
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
}; };
template <class T> struct self_swap_test1 : self_swap_base<T> template <class T> struct self_swap_test1 : self_swap_base<T>
@ -54,91 +52,90 @@ template <class T> struct self_swap_test1 : self_swap_base<T>
template <class T> struct self_swap_test2 : self_swap_base<T> template <class T> struct self_swap_test2 : self_swap_base<T>
{ {
self_swap_test2() : self_swap_base<T>(100) {} self_swap_test2() : self_swap_base<T>(100) {}
}; };
template <class T> struct swap_base : public test::exception_base template <class T> struct swap_base : public test::exception_base
{ {
const test::random_values<T> x_values, y_values; const test::random_values<T> x_values, y_values;
const T initial_x, initial_y; const T initial_x, initial_y;
typedef BOOST_DEDUCED_TYPENAME T::hasher hasher; typedef BOOST_DEDUCED_TYPENAME T::hasher hasher;
typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal; typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal;
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type; typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
swap_base(unsigned int count1, unsigned int count2, int tag1, int tag2) swap_base(unsigned int count1, unsigned int count2, int tag1, int tag2)
: x_values(count1, test::limited_range), : x_values(count1, test::limited_range),
y_values(count2, test::limited_range), y_values(count2, test::limited_range),
initial_x(x_values.begin(), x_values.end(), 0, hasher(tag1), initial_x(x_values.begin(), x_values.end(), 0, hasher(tag1),
key_equal(tag1), allocator_type(tag1)), key_equal(tag1), allocator_type(tag1)),
initial_y( initial_y(y_values.begin(), y_values.end(), 0, hasher(tag2),
y_values.begin(), y_values.end(), 0, hasher(tag2), key_equal(tag2),
key_equal(tag2), allocator_type(T::allocator_type::propagate_on_container_swap::value
allocator_type( ? tag2
T::allocator_type::propagate_on_container_swap::value ? tag2 : tag1))
: tag1)) {
{ }
struct data_type
{
data_type(T const& x_, T const& y_) : x(x_), y(y_) {}
T x, y;
};
data_type init() const { return data_type(initial_x, initial_y); }
void run(data_type& d) const
{
try {
d.x.swap(d.y);
} catch (std::runtime_error) {
} }
struct data_type DISABLE_EXCEPTIONS;
{ test::check_container(d.x, this->y_values);
data_type(T const& x_, T const& y_) : x(x_), y(y_) {} test::check_equivalent_keys(d.x);
test::check_container(d.y, this->x_values);
test::check_equivalent_keys(d.y);
}
T x, y; void check BOOST_PREVENT_MACRO_SUBSTITUTION(data_type const& d) const
}; {
std::string scope(test::scope);
data_type init() const { return data_type(initial_x, initial_y); } // TODO: In C++11 exceptions are only allowed in the swap function.
BOOST_TEST(scope == "hash::hash(hash)" ||
scope == "hash::operator=(hash)" ||
scope == "equal_to::equal_to(equal_to)" ||
scope == "equal_to::operator=(equal_to)");
void run(data_type& d) const test::check_equivalent_keys(d.x);
{ test::check_equivalent_keys(d.y);
try { }
d.x.swap(d.y);
} catch (std::runtime_error) {
}
DISABLE_EXCEPTIONS;
test::check_container(d.x, this->y_values);
test::check_equivalent_keys(d.x);
test::check_container(d.y, this->x_values);
test::check_equivalent_keys(d.y);
}
void check BOOST_PREVENT_MACRO_SUBSTITUTION(data_type const& d) const
{
std::string scope(test::scope);
// TODO: In C++11 exceptions are only allowed in the swap function.
BOOST_TEST(scope == "hash::hash(hash)" ||
scope == "hash::operator=(hash)" ||
scope == "equal_to::equal_to(equal_to)" ||
scope == "equal_to::operator=(equal_to)");
test::check_equivalent_keys(d.x);
test::check_equivalent_keys(d.y);
}
}; };
template <class T> struct swap_test1 : swap_base<T> template <class T> struct swap_test1 : swap_base<T>
{ {
swap_test1() : swap_base<T>(0, 0, 0, 0) {} swap_test1() : swap_base<T>(0, 0, 0, 0) {}
}; };
template <class T> struct swap_test2 : swap_base<T> template <class T> struct swap_test2 : swap_base<T>
{ {
swap_test2() : swap_base<T>(60, 0, 0, 0) {} swap_test2() : swap_base<T>(60, 0, 0, 0) {}
}; };
template <class T> struct swap_test3 : swap_base<T> template <class T> struct swap_test3 : swap_base<T>
{ {
swap_test3() : swap_base<T>(0, 60, 0, 0) {} swap_test3() : swap_base<T>(0, 60, 0, 0) {}
}; };
template <class T> struct swap_test4 : swap_base<T> template <class T> struct swap_test4 : swap_base<T>
{ {
swap_test4() : swap_base<T>(10, 10, 1, 2) {} swap_test4() : swap_base<T>(10, 10, 1, 2) {}
}; };
EXCEPTION_TESTS((self_swap_test1)(self_swap_test2)(swap_test1)(swap_test2)( EXCEPTION_TESTS((self_swap_test1)(self_swap_test2)(swap_test1)(swap_test2)(
swap_test3)(swap_test4), swap_test3)(swap_test4),
CONTAINER_SEQ) CONTAINER_SEQ)
RUN_TESTS() RUN_TESTS()

View File

@ -11,23 +11,23 @@
#include <boost/type_traits/is_same.hpp> #include <boost/type_traits/is_same.hpp>
namespace test { namespace test {
template <class T1> struct check_return_type template <class T1> struct check_return_type
{ {
template <class T2> static void equals(T2) template <class T2> static void equals(T2)
{ {
BOOST_STATIC_ASSERT((boost::is_same<T1, T2>::value)); BOOST_STATIC_ASSERT((boost::is_same<T1, T2>::value));
} }
template <class T2> static void equals_ref(T2&) template <class T2> static void equals_ref(T2&)
{ {
BOOST_STATIC_ASSERT((boost::is_same<T1, T2>::value)); BOOST_STATIC_ASSERT((boost::is_same<T1, T2>::value));
} }
template <class T2> static void convertible(T2) template <class T2> static void convertible(T2)
{ {
BOOST_STATIC_ASSERT((boost::is_convertible<T2, T1>::value)); BOOST_STATIC_ASSERT((boost::is_convertible<T2, T1>::value));
} }
}; };
} }
#endif #endif

View File

@ -9,8 +9,8 @@
#include <boost/detail/lightweight_test.hpp> #include <boost/detail/lightweight_test.hpp>
namespace test { namespace test {
struct object_count struct object_count
{ {
int instances; int instances;
int constructions; int constructions;
@ -19,52 +19,52 @@ struct object_count
void construct() void construct()
{ {
++instances; ++instances;
++constructions; ++constructions;
} }
void destruct() void destruct()
{ {
if (instances == 0) { if (instances == 0) {
BOOST_ERROR("Unbalanced constructions."); BOOST_ERROR("Unbalanced constructions.");
} else { } else {
--instances; --instances;
} }
} }
bool operator==(object_count const& x) const bool operator==(object_count const& x) const
{ {
return instances == x.instances && constructions == x.constructions; return instances == x.instances && constructions == x.constructions;
} }
bool operator!=(object_count const& x) const { return !(*this == x); } bool operator!=(object_count const& x) const { return !(*this == x); }
friend std::ostream& operator<<(std::ostream& out, object_count const& c) friend std::ostream& operator<<(std::ostream& out, object_count const& c)
{ {
out << "[instances: " << c.instances out << "[instances: " << c.instances
<< ", constructions: " << c.constructions << "]"; << ", constructions: " << c.constructions << "]";
return out; return out;
} }
}; };
// This won't be a problem as I'm only using a single compile unit // This won't be a problem as I'm only using a single compile unit
// in each test (this is actually require by the minimal test // in each test (this is actually require by the minimal test
// framework). // framework).
// //
// boostinspect:nounnamed // boostinspect:nounnamed
namespace { namespace {
object_count global_object_count; object_count global_object_count;
} }
struct counted_object struct counted_object
{ {
counted_object() { global_object_count.construct(); } counted_object() { global_object_count.construct(); }
counted_object(counted_object const&) { global_object_count.construct(); } counted_object(counted_object const&) { global_object_count.construct(); }
~counted_object() { global_object_count.destruct(); } ~counted_object() { global_object_count.destruct(); }
}; };
struct check_instances struct check_instances
{ {
int instances_; int instances_;
int constructions_; int constructions_;
@ -75,15 +75,15 @@ struct check_instances
} }
~check_instances() ~check_instances()
{ {
BOOST_TEST(global_object_count.instances == instances_); BOOST_TEST(global_object_count.instances == instances_);
} }
int instances() const { return global_object_count.instances - instances_; } int instances() const { return global_object_count.instances - instances_; }
int constructions() const int constructions() const
{ {
return global_object_count.constructions - constructions_; return global_object_count.constructions - constructions_;
} }
}; };
} }
#endif #endif

View File

@ -15,48 +15,49 @@
#include <boost/unordered_set.hpp> #include <boost/unordered_set.hpp>
namespace test { namespace test {
template <class T1, class T2> template <class T1, class T2>
bool equivalent_impl(T1 const& x, T2 const& y, base_type) bool equivalent_impl(T1 const& x, T2 const& y, base_type)
{ {
return x == y; return x == y;
} }
template <class T> template <class T>
bool equivalent_impl(boost::hash<T> const&, boost::hash<T> const&, derived_type) bool equivalent_impl(
{ boost::hash<T> const&, boost::hash<T> const&, derived_type)
{
return true; return true;
} }
template <class T> template <class T>
bool equivalent_impl( bool equivalent_impl(
std::equal_to<T> const&, std::equal_to<T> const&, derived_type) std::equal_to<T> const&, std::equal_to<T> const&, derived_type)
{ {
return true; return true;
} }
template <class T1, class T2, class T3, class T4> template <class T1, class T2, class T3, class T4>
bool equivalent_impl( bool equivalent_impl(
std::pair<T1, T2> const& x1, std::pair<T3, T4> const& x2, derived_type) std::pair<T1, T2> const& x1, std::pair<T3, T4> const& x2, derived_type)
{ {
return equivalent_impl(x1.first, x2.first, derived) && return equivalent_impl(x1.first, x2.first, derived) &&
equivalent_impl(x1.second, x2.second, derived); equivalent_impl(x1.second, x2.second, derived);
} }
struct equivalent_type struct equivalent_type
{ {
equivalent_type() {} equivalent_type() {}
template <class T1, class T2> template <class T1, class T2>
bool operator()(T1 const& x, T2 const& y) const bool operator()(T1 const& x, T2 const& y) const
{ {
return equivalent_impl(x, y, derived); return equivalent_impl(x, y, derived);
} }
}; };
const equivalent_type equivalent; const equivalent_type equivalent;
template <class Container> class unordered_equivalence_tester template <class Container> class unordered_equivalence_tester
{ {
BOOST_DEDUCED_TYPENAME Container::size_type size_; BOOST_DEDUCED_TYPENAME Container::size_type size_;
BOOST_DEDUCED_TYPENAME Container::hasher hasher_; BOOST_DEDUCED_TYPENAME Container::hasher hasher_;
BOOST_DEDUCED_TYPENAME Container::key_equal key_equal_; BOOST_DEDUCED_TYPENAME Container::key_equal key_equal_;
@ -70,26 +71,26 @@ template <class Container> class unordered_equivalence_tester
: size_(x.size()), hasher_(x.hash_function()), key_equal_(x.key_eq()), : size_(x.size()), hasher_(x.hash_function()), key_equal_(x.key_eq()),
max_load_factor_(x.max_load_factor()), values_(x.begin(), x.end()) max_load_factor_(x.max_load_factor()), values_(x.begin(), x.end())
{ {
values_.sort(); values_.sort();
} }
bool operator()(Container const& x) const bool operator()(Container const& x) const
{ {
if (!((size_ == x.size()) && if (!((size_ == x.size()) &&
(test::equivalent(hasher_, x.hash_function())) && (test::equivalent(hasher_, x.hash_function())) &&
(test::equivalent(key_equal_, x.key_eq())) && (test::equivalent(key_equal_, x.key_eq())) &&
(max_load_factor_ == x.max_load_factor()) && (max_load_factor_ == x.max_load_factor()) &&
(values_.size() == x.size()))) (values_.size() == x.size())))
return false; return false;
value_list copy(x.begin(), x.end()); value_list copy(x.begin(), x.end());
copy.sort(); copy.sort();
return values_ == copy; return values_ == copy;
} }
private: private:
unordered_equivalence_tester(); unordered_equivalence_tester();
}; };
} }
#endif #endif

View File

@ -14,64 +14,61 @@
#include <boost/preprocessor/seq/for_each_product.hpp> #include <boost/preprocessor/seq/for_each_product.hpp>
#define UNORDERED_EXCEPTION_TEST_CASE(name, test_func, type) \ #define UNORDERED_EXCEPTION_TEST_CASE(name, test_func, type) \
UNORDERED_AUTO_TEST(name) \ UNORDERED_AUTO_TEST(name) \
{ \ { \
test_func<type> fixture; \ test_func<type> fixture; \
::test::lightweight::exception_safety( \ ::test::lightweight::exception_safety( \
fixture, BOOST_STRINGIZE(test_func<type>)); \ fixture, BOOST_STRINGIZE(test_func<type>)); \
} }
#define UNORDERED_EXCEPTION_TEST_CASE_REPEAT(name, test_func, n, type) \ #define UNORDERED_EXCEPTION_TEST_CASE_REPEAT(name, test_func, n, type) \
UNORDERED_AUTO_TEST(name) \ UNORDERED_AUTO_TEST(name) \
{ \ { \
for (unsigned i = 0; i < n; ++i) { \ for (unsigned i = 0; i < n; ++i) { \
test_func<type> fixture; \ test_func<type> fixture; \
::test::lightweight::exception_safety( \ ::test::lightweight::exception_safety( \
fixture, BOOST_STRINGIZE(test_func<type>)); \ fixture, BOOST_STRINGIZE(test_func<type>)); \
} \ } \
} }
#define UNORDERED_EPOINT_IMPL ::test::lightweight::epoint #define UNORDERED_EPOINT_IMPL ::test::lightweight::epoint
#define UNORDERED_EXCEPTION_TEST_POSTFIX RUN_TESTS() #define UNORDERED_EXCEPTION_TEST_POSTFIX RUN_TESTS()
#define EXCEPTION_TESTS(test_seq, param_seq) \ #define EXCEPTION_TESTS(test_seq, param_seq) \
BOOST_PP_SEQ_FOR_EACH_PRODUCT( \ BOOST_PP_SEQ_FOR_EACH_PRODUCT(EXCEPTION_TESTS_OP, (test_seq)((1))(param_seq))
EXCEPTION_TESTS_OP, (test_seq)((1))(param_seq))
#define EXCEPTION_TESTS_REPEAT(n, test_seq, param_seq) \ #define EXCEPTION_TESTS_REPEAT(n, test_seq, param_seq) \
BOOST_PP_SEQ_FOR_EACH_PRODUCT( \ BOOST_PP_SEQ_FOR_EACH_PRODUCT(EXCEPTION_TESTS_OP, (test_seq)((n))(param_seq))
EXCEPTION_TESTS_OP, (test_seq)((n))(param_seq))
#define EXCEPTION_TESTS_OP(r, product) \ #define EXCEPTION_TESTS_OP(r, product) \
UNORDERED_EXCEPTION_TEST_CASE_REPEAT( \ UNORDERED_EXCEPTION_TEST_CASE_REPEAT( \
BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(0, product), \ BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(0, product), \
BOOST_PP_CAT(_, BOOST_PP_SEQ_ELEM(2, product))), \ BOOST_PP_CAT(_, BOOST_PP_SEQ_ELEM(2, product))), \
BOOST_PP_SEQ_ELEM(0, product), BOOST_PP_SEQ_ELEM(1, product), \ BOOST_PP_SEQ_ELEM(0, product), BOOST_PP_SEQ_ELEM(1, product), \
BOOST_PP_SEQ_ELEM(2, product)) BOOST_PP_SEQ_ELEM(2, product))
#define UNORDERED_SCOPE(scope_name) \ #define UNORDERED_SCOPE(scope_name) \
for (::test::scope_guard unordered_test_guard( \ for (::test::scope_guard unordered_test_guard(BOOST_STRINGIZE(scope_name)); \
BOOST_STRINGIZE(scope_name)); \ !unordered_test_guard.dismissed(); unordered_test_guard.dismiss())
!unordered_test_guard.dismissed(); unordered_test_guard.dismiss())
#define UNORDERED_EPOINT(name) \ #define UNORDERED_EPOINT(name) \
if (::test::exceptions_enabled) { \ if (::test::exceptions_enabled) { \
UNORDERED_EPOINT_IMPL(name); \ UNORDERED_EPOINT_IMPL(name); \
} }
#define ENABLE_EXCEPTIONS \ #define ENABLE_EXCEPTIONS \
::test::exceptions_enable BOOST_PP_CAT(ENABLE_EXCEPTIONS_, __LINE__)(true) ::test::exceptions_enable BOOST_PP_CAT(ENABLE_EXCEPTIONS_, __LINE__)(true)
#define DISABLE_EXCEPTIONS \ #define DISABLE_EXCEPTIONS \
::test::exceptions_enable BOOST_PP_CAT(ENABLE_EXCEPTIONS_, __LINE__)(false) ::test::exceptions_enable BOOST_PP_CAT(ENABLE_EXCEPTIONS_, __LINE__)(false)
namespace test { namespace test {
static char const* scope = ""; static char const* scope = "";
bool exceptions_enabled = false; bool exceptions_enabled = false;
class scope_guard class scope_guard
{ {
scope_guard& operator=(scope_guard const&); scope_guard& operator=(scope_guard const&);
scope_guard(scope_guard const&); scope_guard(scope_guard const&);
@ -83,22 +80,22 @@ class scope_guard
scope_guard(char const* name) scope_guard(char const* name)
: old_scope_(scope), scope_(name), dismissed_(false) : old_scope_(scope), scope_(name), dismissed_(false)
{ {
scope = scope_; scope = scope_;
} }
~scope_guard() ~scope_guard()
{ {
if (dismissed_) if (dismissed_)
scope = old_scope_; scope = old_scope_;
} }
void dismiss() { dismissed_ = true; } void dismiss() { dismissed_ = true; }
bool dismissed() const { return dismissed_; } bool dismissed() const { return dismissed_; }
}; };
class exceptions_enable class exceptions_enable
{ {
exceptions_enable& operator=(exceptions_enable const&); exceptions_enable& operator=(exceptions_enable const&);
exceptions_enable(exceptions_enable const&); exceptions_enable(exceptions_enable const&);
@ -109,65 +106,65 @@ class exceptions_enable
exceptions_enable(bool enable) exceptions_enable(bool enable)
: old_value_(exceptions_enabled), released_(false) : old_value_(exceptions_enabled), released_(false)
{ {
exceptions_enabled = enable; exceptions_enabled = enable;
} }
~exceptions_enable() ~exceptions_enable()
{ {
if (!released_) { if (!released_) {
exceptions_enabled = old_value_; exceptions_enabled = old_value_;
released_ = true; released_ = true;
} }
} }
void release() void release()
{ {
if (!released_) { if (!released_) {
exceptions_enabled = old_value_; exceptions_enabled = old_value_;
released_ = true; released_ = true;
} }
} }
}; };
struct exception_base struct exception_base
{ {
struct data_type struct data_type
{ {
}; };
struct strong_type struct strong_type
{ {
template <class T> void store(T const&) {} template <class T> void store(T const&) {}
template <class T> void test(T const&) const {} template <class T> void test(T const&) const {}
}; };
data_type init() const { return data_type(); } data_type init() const { return data_type(); }
void check BOOST_PREVENT_MACRO_SUBSTITUTION() const {} void check BOOST_PREVENT_MACRO_SUBSTITUTION() const {}
}; };
template <class T, class P1, class P2, class T2> template <class T, class P1, class P2, class T2>
inline void call_ignore_extra_parameters( inline void call_ignore_extra_parameters(
void (T::*fn)() const, T2 const& obj, P1&, P2&) void (T::*fn)() const, T2 const& obj, P1&, P2&)
{ {
(obj.*fn)(); (obj.*fn)();
} }
template <class T, class P1, class P2, class T2> template <class T, class P1, class P2, class T2>
inline void call_ignore_extra_parameters( inline void call_ignore_extra_parameters(
void (T::*fn)(P1&) const, T2 const& obj, P1& p1, P2&) void (T::*fn)(P1&) const, T2 const& obj, P1& p1, P2&)
{ {
(obj.*fn)(p1); (obj.*fn)(p1);
} }
template <class T, class P1, class P2, class T2> template <class T, class P1, class P2, class T2>
inline void call_ignore_extra_parameters( inline void call_ignore_extra_parameters(
void (T::*fn)(P1&, P2&) const, T2 const& obj, P1& p1, P2& p2) void (T::*fn)(P1&, P2&) const, T2 const& obj, P1& p1, P2& p2)
{ {
(obj.*fn)(p1, p2); (obj.*fn)(p1, p2);
} }
template <class T> T const& constant(T const& x) { return x; } template <class T> T const& constant(T const& x) { return x; }
template <class Test> class test_runner template <class Test> class test_runner
{ {
Test const& test_; Test const& test_;
bool exception_in_check_; bool exception_in_check_;
@ -178,175 +175,179 @@ template <class Test> class test_runner
test_runner(Test const& t) : test_(t), exception_in_check_(false) {} test_runner(Test const& t) : test_(t), exception_in_check_(false) {}
void run() void run()
{ {
DISABLE_EXCEPTIONS; DISABLE_EXCEPTIONS;
test::check_instances check; test::check_instances check;
test::scope = ""; test::scope = "";
BOOST_DEDUCED_TYPENAME Test::data_type x(test_.init()); BOOST_DEDUCED_TYPENAME Test::data_type x(test_.init());
BOOST_DEDUCED_TYPENAME Test::strong_type strong; BOOST_DEDUCED_TYPENAME Test::strong_type strong;
strong.store(x); strong.store(x);
try {
ENABLE_EXCEPTIONS;
call_ignore_extra_parameters<Test,
BOOST_DEDUCED_TYPENAME Test::data_type,
BOOST_DEDUCED_TYPENAME Test::strong_type>(
&Test::run, test_, x, strong);
} catch (...) {
try { try {
ENABLE_EXCEPTIONS; DISABLE_EXCEPTIONS;
call_ignore_extra_parameters<Test, call_ignore_extra_parameters<Test,
BOOST_DEDUCED_TYPENAME Test::data_type, BOOST_DEDUCED_TYPENAME Test::data_type const,
BOOST_DEDUCED_TYPENAME Test::strong_type>( BOOST_DEDUCED_TYPENAME Test::strong_type const>(
&Test::run, test_, x, strong); &Test::check, test_, constant(x), constant(strong));
} catch (...) { } catch (...) {
try { exception_in_check_ = true;
DISABLE_EXCEPTIONS;
call_ignore_extra_parameters<Test,
BOOST_DEDUCED_TYPENAME Test::data_type const,
BOOST_DEDUCED_TYPENAME Test::strong_type const>(
&Test::check, test_, constant(x), constant(strong));
} catch (...) {
exception_in_check_ = true;
}
throw;
} }
throw;
}
} }
void end() void end()
{ {
if (exception_in_check_) { if (exception_in_check_) {
BOOST_ERROR("Unexcpected exception in test_runner check call."); BOOST_ERROR("Unexcpected exception in test_runner check call.");
} }
} }
}; };
// Quick exception testing based on lightweight test // Quick exception testing based on lightweight test
namespace lightweight { namespace lightweight {
static int iteration; static int iteration;
static int count; static int count;
struct test_exception struct test_exception
{ {
char const* name; char const* name;
test_exception(char const* n) : name(n) {} test_exception(char const* n) : name(n) {}
}; };
struct test_failure struct test_failure
{ {
}; };
void epoint(char const* name) void epoint(char const* name)
{ {
++count; ++count;
if (count == iteration) { if (count == iteration) {
throw test_exception(name); throw test_exception(name);
}
} }
}
template <class Test> void exception_safety(Test const& f, char const* /*name*/) template <class Test>
{ void exception_safety(Test const& f, char const* /*name*/)
test_runner<Test> runner(f); {
test_runner<Test> runner(f);
iteration = 0; iteration = 0;
bool success = false; bool success = false;
unsigned int failure_count = 0; unsigned int failure_count = 0;
char const* error_msg = 0; char const* error_msg = 0;
do { do {
int error_count = boost::detail::test_errors(); int error_count = boost::detail::test_errors();
++iteration; ++iteration;
count = 0; count = 0;
try { try {
runner.run(); runner.run();
success = true; success = true;
} catch (test_failure) { } catch (test_failure) {
error_msg = "test_failure caught."; error_msg = "test_failure caught.";
break; break;
} catch (test_exception e) { } catch (test_exception e) {
if (error_count != boost::detail::test_errors()) { if (error_count != boost::detail::test_errors()) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM BOOST_LIGHTWEIGHT_TEST_OSTREAM
<< "Iteration: " << iteration << "Iteration: " << iteration
<< " Error found for epoint: " << e.name << std::endl; << " Error found for epoint: " << e.name << std::endl;
} }
} catch (...) { } catch (...) {
error_msg = "Unexpected exception."; error_msg = "Unexpected exception.";
break; break;
} }
if (error_count != boost::detail::test_errors()) { if (error_count != boost::detail::test_errors()) {
++failure_count; ++failure_count;
} }
} while (!success && failure_count < 5); } while (!success && failure_count < 5);
if (error_msg) { if (error_msg) {
BOOST_ERROR(error_msg); BOOST_ERROR(error_msg);
}
runner.end();
} }
runner.end();
}
// //
// An alternative way to run exception tests. // An alternative way to run exception tests.
// See merge_exception_tests.cpp for an example. // See merge_exception_tests.cpp for an example.
struct exception_looper struct exception_looper
{
bool success;
unsigned int failure_count;
char const* error_msg;
int error_count;
exception_looper() : success(false), failure_count(0), error_msg(0) {}
void start() { iteration = 0; }
bool loop_condition() const
{ {
bool success;
unsigned int failure_count;
char const* error_msg;
int error_count;
exception_looper() : success(false), failure_count(0), error_msg(0) {}
void start() { iteration = 0; }
bool loop_condition() const
{
return !error_msg && !success && failure_count < 5; return !error_msg && !success && failure_count < 5;
} }
void start_iteration() void start_iteration()
{ {
error_count = boost::detail::test_errors(); error_count = boost::detail::test_errors();
++iteration; ++iteration;
count = 0; count = 0;
} }
void successful_run() { success = true; } void successful_run() { success = true; }
void test_failure_caught(test_failure const&) void test_failure_caught(test_failure const&)
{ {
error_msg = "test_failure caught."; error_msg = "test_failure caught.";
} }
void test_exception_caught(test_exception const& e) void test_exception_caught(test_exception const& e)
{ {
if (error_count != boost::detail::test_errors()) { if (error_count != boost::detail::test_errors()) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM BOOST_LIGHTWEIGHT_TEST_OSTREAM
<< "Iteration: " << iteration << "Iteration: " << iteration
<< " Error found for epoint: " << e.name << std::endl; << " Error found for epoint: " << e.name << std::endl;
} }
} }
void unexpected_exception_caught() { error_msg = "Unexpected exception."; } void unexpected_exception_caught()
{
error_msg = "Unexpected exception.";
}
void end() void end()
{ {
if (error_msg) { if (error_msg) {
BOOST_ERROR(error_msg); BOOST_ERROR(error_msg);
} }
} }
}; };
#define EXCEPTION_LOOP(op) \ #define EXCEPTION_LOOP(op) \
test::lightweight::exception_looper looper; \ test::lightweight::exception_looper looper; \
looper.start(); \ looper.start(); \
while (looper.loop_condition()) { \ while (looper.loop_condition()) { \
looper.start_iteration(); \ looper.start_iteration(); \
try { \ try { \
op; \ op; \
looper.successful_run(); \ looper.successful_run(); \
} catch (test::lightweight::test_failure e) { \ } catch (test::lightweight::test_failure e) { \
looper.test_failure_caught(e); \ looper.test_failure_caught(e); \
} catch (test::lightweight::test_exception e) { \ } catch (test::lightweight::test_exception e) { \
looper.test_exception_caught(e); \ looper.test_exception_caught(e); \
} catch (...) { \ } catch (...) { \
looper.unexpected_exception_caught(); \ looper.unexpected_exception_caught(); \
} \
} \ } \
looper.end(); } \
} looper.end();
}
} }
#endif #endif

View File

@ -9,24 +9,24 @@
#include <string> #include <string>
namespace test { namespace test {
typedef enum { typedef enum {
default_generator, default_generator,
generate_collisions, generate_collisions,
limited_range limited_range
} random_generator; } random_generator;
int generate(int const*, random_generator); int generate(int const*, random_generator);
char generate(char const*, random_generator); char generate(char const*, random_generator);
signed char generate(signed char const*, random_generator); signed char generate(signed char const*, random_generator);
std::string generate(std::string const*, random_generator); std::string generate(std::string const*, random_generator);
float generate(float const*, random_generator); float generate(float const*, random_generator);
struct base_type struct base_type
{ {
} base; } base;
struct derived_type : base_type struct derived_type : base_type
{ {
} derived; } derived;
} }
#endif #endif

View File

@ -19,45 +19,45 @@
#include <utility> #include <utility>
namespace test { namespace test {
struct seed_t struct seed_t
{ {
seed_t(unsigned int x) seed_t(unsigned int x)
{ {
using namespace std; using namespace std;
srand(x); srand(x);
} }
}; };
std::size_t random_value(std::size_t max) std::size_t random_value(std::size_t max)
{ {
using namespace std; using namespace std;
return static_cast<std::size_t>(rand()) % max; return static_cast<std::size_t>(rand()) % max;
} }
inline int generate(int const*, random_generator g) inline int generate(int const*, random_generator g)
{ {
using namespace std; using namespace std;
int value = rand(); int value = rand();
if (g == limited_range) { if (g == limited_range) {
value = value % 100; value = value % 100;
} }
return value; return value;
} }
inline char generate(char const*, random_generator) inline char generate(char const*, random_generator)
{ {
using namespace std; using namespace std;
return static_cast<char>((rand() >> 1) % (128 - 32) + 32); return static_cast<char>((rand() >> 1) % (128 - 32) + 32);
} }
inline signed char generate(signed char const*, random_generator) inline signed char generate(signed char const*, random_generator)
{ {
using namespace std; using namespace std;
return static_cast<signed char>(rand()); return static_cast<signed char>(rand());
} }
inline std::string generate(std::string const*, random_generator g) inline std::string generate(std::string const*, random_generator g)
{ {
using namespace std; using namespace std;
char* char_ptr = 0; char* char_ptr = 0;
@ -65,30 +65,29 @@ inline std::string generate(std::string const*, random_generator g)
std::string result; std::string result;
if (g == limited_range) { if (g == limited_range) {
std::size_t length = test::random_value(2) + 2; std::size_t length = test::random_value(2) + 2;
char const* strings[] = {"'vZh(3~ms", "%m", "_Y%U", "N'Y", "4,J_J"}; char const* strings[] = {"'vZh(3~ms", "%m", "_Y%U", "N'Y", "4,J_J"};
for (std::size_t i = 0; i < length; ++i) { for (std::size_t i = 0; i < length; ++i) {
result += result += strings[random_value(sizeof(strings) / sizeof(strings[0]))];
strings[random_value(sizeof(strings) / sizeof(strings[0]))]; }
}
} else { } else {
std::size_t length = test::random_value(10) + 1; std::size_t length = test::random_value(10) + 1;
for (std::size_t i = 0; i < length; ++i) { for (std::size_t i = 0; i < length; ++i) {
result += generate(char_ptr, g); result += generate(char_ptr, g);
} }
} }
return result; return result;
} }
float generate(float const*, random_generator g) float generate(float const*, random_generator g)
{ {
using namespace std; using namespace std;
int x = 0; int x = 0;
int value = generate(&x, g); int value = generate(&x, g);
return (float)value / (float)RAND_MAX; return (float)value / (float)RAND_MAX;
} }
} }
#endif #endif

View File

@ -7,8 +7,8 @@
#define BOOST_UNORDERED_TEST_HELPERS_HEADER #define BOOST_UNORDERED_TEST_HELPERS_HEADER
namespace test { namespace test {
template <class Container> struct get_key_impl template <class Container> struct get_key_impl
{ {
typedef BOOST_DEDUCED_TYPENAME Container::key_type key_type; typedef BOOST_DEDUCED_TYPENAME Container::key_type key_type;
static key_type const& get_key(key_type const& x) { return x; } static key_type const& get_key(key_type const& x) { return x; }
@ -16,38 +16,38 @@ template <class Container> struct get_key_impl
template <class T> template <class T>
static key_type const& get_key(std::pair<key_type, T> const& x, char = 0) static key_type const& get_key(std::pair<key_type, T> const& x, char = 0)
{ {
return x.first; return x.first;
} }
template <class T> template <class T>
static key_type const& get_key( static key_type const& get_key(
std::pair<key_type const, T> const& x, unsigned char = 0) std::pair<key_type const, T> const& x, unsigned char = 0)
{ {
return x.first; return x.first;
} }
}; };
template <class Container, class T> template <class Container, class T>
inline BOOST_DEDUCED_TYPENAME Container::key_type const& get_key(T const& x) inline BOOST_DEDUCED_TYPENAME Container::key_type const& get_key(T const& x)
{ {
return get_key_impl<Container>::get_key(x); return get_key_impl<Container>::get_key(x);
} }
// test::next // test::next
// //
// Increments an iterator by 1 or a given value. // Increments an iterator by 1 or a given value.
// Like boost::next, but simpler and slower. // Like boost::next, but simpler and slower.
template <typename Iterator> Iterator next(Iterator it) { return ++it; } template <typename Iterator> Iterator next(Iterator it) { return ++it; }
template <typename Iterator, typename IntType> template <typename Iterator, typename IntType>
Iterator next(Iterator it, IntType x) Iterator next(Iterator it, IntType x)
{ {
for (; x > 0; --x) { for (; x > 0; --x) {
++it; ++it;
} }
return it; return it;
} }
} }
#endif #endif

View File

@ -11,8 +11,8 @@
#include <iterator> #include <iterator>
namespace test { namespace test {
template <class Iterator> struct proxy template <class Iterator> struct proxy
{ {
typedef BOOST_DEDUCED_TYPENAME Iterator::value_type value_type; typedef BOOST_DEDUCED_TYPENAME Iterator::value_type value_type;
explicit proxy(value_type const& v) : v_(v) {} explicit proxy(value_type const& v) : v_(v) {}
@ -23,18 +23,18 @@ template <class Iterator> struct proxy
private: private:
proxy& operator=(proxy const&); proxy& operator=(proxy const&);
}; };
template <class Iterator> template <class Iterator>
struct input_iterator_adaptor struct input_iterator_adaptor
: public std::iterator<std::input_iterator_tag, : public std::iterator<std::input_iterator_tag,
BOOST_DEDUCED_TYPENAME boost::iterator_value<Iterator>::type, BOOST_DEDUCED_TYPENAME boost::iterator_value<Iterator>::type,
std::ptrdiff_t, std::ptrdiff_t,
BOOST_DEDUCED_TYPENAME boost::iterator_pointer<Iterator>::type, BOOST_DEDUCED_TYPENAME boost::iterator_pointer<Iterator>::type,
proxy<Iterator> > proxy<Iterator> >
{ {
typedef BOOST_DEDUCED_TYPENAME boost::iterator_value<Iterator>::type typedef BOOST_DEDUCED_TYPENAME boost::iterator_value<Iterator>::type
value_type; value_type;
input_iterator_adaptor() : base_() {} input_iterator_adaptor() : base_() {}
explicit input_iterator_adaptor(Iterator& it) : base_(&it) {} explicit input_iterator_adaptor(Iterator& it) : base_(&it) {}
@ -42,43 +42,43 @@ struct input_iterator_adaptor
value_type* operator->() const { return &**base_; } value_type* operator->() const { return &**base_; }
input_iterator_adaptor& operator++() input_iterator_adaptor& operator++()
{ {
++*base_; ++*base_;
return *this; return *this;
} }
// input_iterator_adaptor operator++(int) { // input_iterator_adaptor operator++(int) {
//} //}
bool operator==(input_iterator_adaptor const& x) const bool operator==(input_iterator_adaptor const& x) const
{ {
return *base_ == *x.base_; return *base_ == *x.base_;
} }
bool operator!=(input_iterator_adaptor const& x) const bool operator!=(input_iterator_adaptor const& x) const
{ {
return *base_ != *x.base_; return *base_ != *x.base_;
} }
private: private:
Iterator* base_; Iterator* base_;
}; };
template <class Iterator> template <class Iterator>
input_iterator_adaptor<Iterator> input_iterator(Iterator& it) input_iterator_adaptor<Iterator> input_iterator(Iterator& it)
{ {
return input_iterator_adaptor<Iterator>(it); return input_iterator_adaptor<Iterator>(it);
} }
template <class Iterator> template <class Iterator>
struct copy_iterator_adaptor struct copy_iterator_adaptor
: public std::iterator< : public std::iterator<
BOOST_DEDUCED_TYPENAME boost::iterator_category<Iterator>::type, BOOST_DEDUCED_TYPENAME boost::iterator_category<Iterator>::type,
BOOST_DEDUCED_TYPENAME boost::iterator_value<Iterator>::type, BOOST_DEDUCED_TYPENAME boost::iterator_value<Iterator>::type,
BOOST_DEDUCED_TYPENAME boost::iterator_difference<Iterator>::type, BOOST_DEDUCED_TYPENAME boost::iterator_difference<Iterator>::type,
BOOST_DEDUCED_TYPENAME boost::iterator_pointer<Iterator>::type, BOOST_DEDUCED_TYPENAME boost::iterator_pointer<Iterator>::type,
proxy<Iterator> > proxy<Iterator> >
{ {
typedef BOOST_DEDUCED_TYPENAME boost::iterator_value<Iterator>::type typedef BOOST_DEDUCED_TYPENAME boost::iterator_value<Iterator>::type
value_type; value_type;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference<Iterator>::type typedef BOOST_DEDUCED_TYPENAME boost::iterator_difference<Iterator>::type
difference_type; difference_type;
copy_iterator_adaptor() : base_() {} copy_iterator_adaptor() : base_() {}
explicit copy_iterator_adaptor(Iterator const& it) : base_(it) {} explicit copy_iterator_adaptor(Iterator const& it) : base_(it) {}
@ -87,87 +87,87 @@ struct copy_iterator_adaptor
value_type operator[](difference_type d) { return base_[d]; } value_type operator[](difference_type d) { return base_[d]; }
copy_iterator_adaptor& operator++() copy_iterator_adaptor& operator++()
{ {
++base_; ++base_;
return *this; return *this;
} }
copy_iterator_adaptor operator++(int) copy_iterator_adaptor operator++(int)
{ {
copy_iterator_adaptor tmp(*this); copy_iterator_adaptor tmp(*this);
++base_; ++base_;
return tmp; return tmp;
} }
copy_iterator_adaptor& operator--() copy_iterator_adaptor& operator--()
{ {
--base_; --base_;
return *this; return *this;
} }
copy_iterator_adaptor operator--(int) copy_iterator_adaptor operator--(int)
{ {
copy_iterator_adaptor tmp(*this); copy_iterator_adaptor tmp(*this);
--base_; --base_;
return tmp; return tmp;
} }
copy_iterator_adaptor operator+=(difference_type x) copy_iterator_adaptor operator+=(difference_type x)
{ {
base_ += x; base_ += x;
return *this; return *this;
} }
copy_iterator_adaptor operator-=(difference_type x) copy_iterator_adaptor operator-=(difference_type x)
{ {
base_ -= x; base_ -= x;
return *this; return *this;
} }
copy_iterator_adaptor operator+(difference_type n) copy_iterator_adaptor operator+(difference_type n)
{ {
return copy_iterator_adaptor(base_ + n); return copy_iterator_adaptor(base_ + n);
} }
copy_iterator_adaptor operator-(difference_type n) copy_iterator_adaptor operator-(difference_type n)
{ {
return copy_iterator_adaptor(base_ - n); return copy_iterator_adaptor(base_ - n);
} }
friend copy_iterator_adaptor operator+( friend copy_iterator_adaptor operator+(
difference_type n, copy_iterator_adaptor x) difference_type n, copy_iterator_adaptor x)
{ {
return x + n; return x + n;
} }
difference_type operator-(copy_iterator_adaptor const& other) difference_type operator-(copy_iterator_adaptor const& other)
{ {
return base_ - other.base_; return base_ - other.base_;
} }
bool operator==(copy_iterator_adaptor const& x) const bool operator==(copy_iterator_adaptor const& x) const
{ {
return base_ == x.base_; return base_ == x.base_;
} }
bool operator!=(copy_iterator_adaptor const& x) const bool operator!=(copy_iterator_adaptor const& x) const
{ {
return base_ != x.base_; return base_ != x.base_;
} }
bool operator<(copy_iterator_adaptor const& x) const bool operator<(copy_iterator_adaptor const& x) const
{ {
return base_ < x.base_; return base_ < x.base_;
} }
bool operator>(copy_iterator_adaptor const& x) const bool operator>(copy_iterator_adaptor const& x) const
{ {
return base_ > x.base_; return base_ > x.base_;
} }
bool operator<=(copy_iterator_adaptor const& x) const bool operator<=(copy_iterator_adaptor const& x) const
{ {
return base_ <= x.base_; return base_ <= x.base_;
} }
bool operator>=(copy_iterator_adaptor const& x) const bool operator>=(copy_iterator_adaptor const& x) const
{ {
return base_ >= x.base_; return base_ >= x.base_;
} }
private: private:
Iterator base_; Iterator base_;
}; };
template <class Iterator> template <class Iterator>
copy_iterator_adaptor<Iterator> copy_iterator(Iterator const& it) copy_iterator_adaptor<Iterator> copy_iterator(Iterator const& it)
{ {
return copy_iterator_adaptor<Iterator>(it); return copy_iterator_adaptor<Iterator>(it);
} }
} }
#endif #endif

View File

@ -22,8 +22,8 @@
#endif #endif
namespace test { namespace test {
template <class X> void check_equivalent_keys(X const& x1) template <class X> void check_equivalent_keys(X const& x1)
{ {
BOOST_DEDUCED_TYPENAME X::key_equal eq = x1.key_eq(); BOOST_DEDUCED_TYPENAME X::key_equal eq = x1.key_eq();
typedef BOOST_DEDUCED_TYPENAME X::key_type key_type; typedef BOOST_DEDUCED_TYPENAME X::key_type key_type;
std::set<key_type, std::less<key_type> > found_; std::set<key_type, std::less<key_type> > found_;
@ -31,79 +31,77 @@ template <class X> void check_equivalent_keys(X const& x1)
BOOST_DEDUCED_TYPENAME X::const_iterator it = x1.begin(), end = x1.end(); BOOST_DEDUCED_TYPENAME X::const_iterator it = x1.begin(), end = x1.end();
BOOST_DEDUCED_TYPENAME X::size_type size = 0; BOOST_DEDUCED_TYPENAME X::size_type size = 0;
while (it != end) { while (it != end) {
// First test that the current key has not occurred before, required // First test that the current key has not occurred before, required
// to test either that keys are unique or that equivalent keys are // to test either that keys are unique or that equivalent keys are
// adjacent. (6.3.1/6) // adjacent. (6.3.1/6)
key_type key = get_key<X>(*it); key_type key = get_key<X>(*it);
if (!found_.insert(key).second) if (!found_.insert(key).second)
BOOST_ERROR("Elements with equivalent keys aren't adjacent."); BOOST_ERROR("Elements with equivalent keys aren't adjacent.");
// Iterate over equivalent keys, counting them. // Iterate over equivalent keys, counting them.
unsigned int count = 0; unsigned int count = 0;
do { do {
++it; ++it;
++count; ++count;
++size; ++size;
} while (it != end && eq(get_key<X>(*it), key)); } while (it != end && eq(get_key<X>(*it), key));
// If the container has unique keys, test that there's only one. // If the container has unique keys, test that there's only one.
// Since the previous test makes sure that all equivalent keys are // Since the previous test makes sure that all equivalent keys are
// adjacent, this is all the equivalent keys - so the test is // adjacent, this is all the equivalent keys - so the test is
// sufficient. (6.3.1/6 again). // sufficient. (6.3.1/6 again).
if (test::has_unique_keys<X>::value && count != 1) if (test::has_unique_keys<X>::value && count != 1)
BOOST_ERROR("Non-unique key."); BOOST_ERROR("Non-unique key.");
if (x1.count(key) != count) { if (x1.count(key) != count) {
BOOST_ERROR("Incorrect output of count."); BOOST_ERROR("Incorrect output of count.");
std::cerr << x1.count(key) << "," << count << "\n"; std::cerr << x1.count(key) << "," << count << "\n";
} }
// Check that the keys are in the correct bucket and are // Check that the keys are in the correct bucket and are
// adjacent in the bucket. // adjacent in the bucket.
BOOST_DEDUCED_TYPENAME X::size_type bucket = x1.bucket(key); BOOST_DEDUCED_TYPENAME X::size_type bucket = x1.bucket(key);
BOOST_DEDUCED_TYPENAME X::const_local_iterator lit = x1.begin(bucket), BOOST_DEDUCED_TYPENAME X::const_local_iterator lit = x1.begin(bucket),
lend = x1.end(bucket); lend = x1.end(bucket);
unsigned int count_checked = 0; unsigned int count_checked = 0;
for (; lit != lend && !eq(get_key<X>(*lit), key); ++lit) { for (; lit != lend && !eq(get_key<X>(*lit), key); ++lit) {
++count_checked; ++count_checked;
} }
if (lit == lend) { if (lit == lend) {
BOOST_ERROR("Unable to find element with a local_iterator"); BOOST_ERROR("Unable to find element with a local_iterator");
std::cerr << "Checked: " << count_checked << " elements" std::cerr << "Checked: " << count_checked << " elements" << std::endl;
<< std::endl; } else {
} else { unsigned int count2 = 0;
unsigned int count2 = 0; for (; lit != lend && eq(get_key<X>(*lit), key); ++lit)
for (; lit != lend && eq(get_key<X>(*lit), key); ++lit) ++count2;
++count2; if (count != count2)
if (count != count2) BOOST_ERROR("Element count doesn't match local_iterator.");
BOOST_ERROR("Element count doesn't match local_iterator."); for (; lit != lend; ++lit) {
for (; lit != lend; ++lit) { if (eq(get_key<X>(*lit), key)) {
if (eq(get_key<X>(*lit), key)) { BOOST_ERROR("Non-adjacent element with equivalent key "
BOOST_ERROR("Non-adjacent element with equivalent key " "in bucket.");
"in bucket."); break;
break; }
}
}
} }
}
}; };
// Check that size matches up. // Check that size matches up.
if (x1.size() != size) { if (x1.size() != size) {
BOOST_ERROR("x1.size() doesn't match actual size."); BOOST_ERROR("x1.size() doesn't match actual size.");
std::cout << x1.size() << "/" << size << std::endl; std::cout << x1.size() << "/" << size << std::endl;
} }
// Check the load factor. // Check the load factor.
float load_factor = float load_factor = size == 0 ? 0 : static_cast<float>(size) /
size == 0 ? 0 : static_cast<float>(size) / static_cast<float>(x1.bucket_count());
static_cast<float>(x1.bucket_count());
using namespace std; using namespace std;
if (fabs(x1.load_factor() - load_factor) > x1.load_factor() / 64) if (fabs(x1.load_factor() - load_factor) > x1.load_factor() / 64)
BOOST_ERROR("x1.load_factor() doesn't match actual load_factor."); BOOST_ERROR("x1.load_factor() doesn't match actual load_factor.");
// Check that size in the buckets matches up. // Check that size in the buckets matches up.
@ -111,19 +109,18 @@ template <class X> void check_equivalent_keys(X const& x1)
for (BOOST_DEDUCED_TYPENAME X::size_type i = 0; i < x1.bucket_count(); for (BOOST_DEDUCED_TYPENAME X::size_type i = 0; i < x1.bucket_count();
++i) { ++i) {
for (BOOST_DEDUCED_TYPENAME X::const_local_iterator for (BOOST_DEDUCED_TYPENAME X::const_local_iterator begin2 = x1.begin(i),
begin2 = x1.begin(i), end2 = x1.end(i);
end2 = x1.end(i); begin2 != end2; ++begin2) {
begin2 != end2; ++begin2) { ++bucket_size;
++bucket_size; }
}
} }
if (x1.size() != bucket_size) { if (x1.size() != bucket_size) {
BOOST_ERROR("x1.size() doesn't match bucket size."); BOOST_ERROR("x1.size() doesn't match bucket size.");
std::cout << x1.size() << "/" << bucket_size << std::endl; std::cout << x1.size() << "/" << bucket_size << std::endl;
} }
} }
} }
#if defined(BOOST_MSVC) #if defined(BOOST_MSVC)

View File

@ -16,143 +16,143 @@
#include <iterator> #include <iterator>
namespace test { namespace test {
template <typename It1, typename It2> template <typename It1, typename It2>
bool equal(It1 begin, It1 end, It2 compare) bool equal(It1 begin, It1 end, It2 compare)
{ {
for (; begin != end; ++begin, ++compare) for (; begin != end; ++begin, ++compare)
if (*begin != *compare) if (*begin != *compare)
return false; return false;
return true; return true;
} }
template <typename It1, typename It2, typename Pred> template <typename It1, typename It2, typename Pred>
bool equal(It1 begin, It1 end, It2 compare, Pred predicate) bool equal(It1 begin, It1 end, It2 compare, Pred predicate)
{ {
for (; begin != end; ++begin, ++compare) for (; begin != end; ++begin, ++compare)
if (!predicate(*begin, *compare)) if (!predicate(*begin, *compare))
return false; return false;
return true; return true;
} }
template <typename T> class list; template <typename T> class list;
namespace test_detail { namespace test_detail {
template <typename T> class list_node; template <typename T> class list_node;
template <typename T> class list_data; template <typename T> class list_data;
template <typename T> class list_iterator; template <typename T> class list_iterator;
template <typename T> class list_const_iterator; template <typename T> class list_const_iterator;
template <typename T> class list_node template <typename T> class list_node
{
list_node(list_node const&);
list_node& operator=(list_node const&);
public:
T value_;
list_node* next_;
list_node(T const& v) : value_(v), next_(0) {}
list_node(T const& v, list_node* n) : value_(v), next_(n) {}
};
template <typename T> class list_data
{
public:
typedef list_node<T> node;
typedef unsigned int size_type;
node* first_;
node** last_ptr_;
size_type size_;
list_data() : first_(0), last_ptr_(&first_), size_(0) {}
~list_data()
{ {
list_node(list_node const&);
list_node& operator=(list_node const&);
public:
T value_;
list_node* next_;
list_node(T const& v) : value_(v), next_(0) {}
list_node(T const& v, list_node* n) : value_(v), next_(n) {}
};
template <typename T> class list_data
{
public:
typedef list_node<T> node;
typedef unsigned int size_type;
node* first_;
node** last_ptr_;
size_type size_;
list_data() : first_(0), last_ptr_(&first_), size_(0) {}
~list_data()
{
while (first_) { while (first_) {
node* tmp = first_; node* tmp = first_;
first_ = first_->next_; first_ = first_->next_;
delete tmp; delete tmp;
} }
} }
private: private:
list_data(list_data const&); list_data(list_data const&);
list_data& operator=(list_data const&); list_data& operator=(list_data const&);
}; };
template <typename T> template <typename T>
class list_iterator class list_iterator
: public std::iterator<std::forward_iterator_tag, T, int, T*, T&> : public std::iterator<std::forward_iterator_tag, T, int, T*, T&>
{
friend class list_const_iterator<T>;
friend class test::list<T>;
typedef list_node<T> node;
typedef list_const_iterator<T> const_iterator;
node* ptr_;
public:
list_iterator() : ptr_(0) {}
explicit list_iterator(node* x) : ptr_(x) {}
T& operator*() const { return ptr_->value_; }
T* operator->() const { return &ptr_->value_; }
list_iterator& operator++()
{ {
friend class list_const_iterator<T>;
friend class test::list<T>;
typedef list_node<T> node;
typedef list_const_iterator<T> const_iterator;
node* ptr_;
public:
list_iterator() : ptr_(0) {}
explicit list_iterator(node* x) : ptr_(x) {}
T& operator*() const { return ptr_->value_; }
T* operator->() const { return &ptr_->value_; }
list_iterator& operator++()
{
ptr_ = ptr_->next_; ptr_ = ptr_->next_;
return *this; return *this;
} }
list_iterator operator++(int) list_iterator operator++(int)
{ {
list_iterator tmp = *this; list_iterator tmp = *this;
ptr_ = ptr_->next_; ptr_ = ptr_->next_;
return tmp; return tmp;
} }
bool operator==(const_iterator y) const { return ptr_ == y.ptr_; } bool operator==(const_iterator y) const { return ptr_ == y.ptr_; }
bool operator!=(const_iterator y) const { return ptr_ != y.ptr_; } bool operator!=(const_iterator y) const { return ptr_ != y.ptr_; }
}; };
template <typename T> template <typename T>
class list_const_iterator : public std::iterator<std::forward_iterator_tag, T, class list_const_iterator : public std::iterator<std::forward_iterator_tag,
int, T const*, T const&> T, int, T const*, T const&>
{
friend class list_iterator<T>;
friend class test::list<T>;
typedef list_node<T> node;
typedef list_iterator<T> iterator;
typedef list_const_iterator<T> const_iterator;
node* ptr_;
public:
list_const_iterator() : ptr_(0) {}
list_const_iterator(list_iterator<T> const& x) : ptr_(x.ptr_) {}
T const& operator*() const { return ptr_->value_; }
T const* operator->() const { return &ptr_->value_; }
list_const_iterator& operator++()
{ {
friend class list_iterator<T>;
friend class test::list<T>;
typedef list_node<T> node;
typedef list_iterator<T> iterator;
typedef list_const_iterator<T> const_iterator;
node* ptr_;
public:
list_const_iterator() : ptr_(0) {}
list_const_iterator(list_iterator<T> const& x) : ptr_(x.ptr_) {}
T const& operator*() const { return ptr_->value_; }
T const* operator->() const { return &ptr_->value_; }
list_const_iterator& operator++()
{
ptr_ = ptr_->next_; ptr_ = ptr_->next_;
return *this; return *this;
} }
list_const_iterator operator++(int) list_const_iterator operator++(int)
{ {
list_const_iterator tmp = *this; list_const_iterator tmp = *this;
ptr_ = ptr_->next_; ptr_ = ptr_->next_;
return tmp; return tmp;
} }
bool operator==(const_iterator y) const { return ptr_ == y.ptr_; } bool operator==(const_iterator y) const { return ptr_ == y.ptr_; }
bool operator!=(const_iterator y) const { return ptr_ != y.ptr_; } bool operator!=(const_iterator y) const { return ptr_ != y.ptr_; }
}; };
} }
template <typename T> class list template <typename T> class list
{ {
typedef test::test_detail::list_data<T> data; typedef test::test_detail::list_data<T> data;
typedef test::test_detail::list_node<T> node; typedef test::test_detail::list_node<T> node;
data data_; data data_;
@ -173,14 +173,14 @@ template <typename T> class list
template <class InputIterator> template <class InputIterator>
list(InputIterator i, InputIterator j) : data_() list(InputIterator i, InputIterator j) : data_()
{ {
insert(i, j); insert(i, j);
} }
list& operator=(list const& other) list& operator=(list const& other)
{ {
clear(); clear();
insert(other.begin(), other.end()); insert(other.begin(), other.end());
return *this; return *this;
} }
iterator begin() { return iterator(data_.first_); } iterator begin() { return iterator(data_.first_); }
@ -192,53 +192,53 @@ template <typename T> class list
template <class InputIterator> void insert(InputIterator i, InputIterator j) template <class InputIterator> void insert(InputIterator i, InputIterator j)
{ {
for (; i != j; ++i) for (; i != j; ++i)
push_back(*i); push_back(*i);
} }
void push_front(value_type const& v) void push_front(value_type const& v)
{ {
data_.first_ = new node(v, data_.first_); data_.first_ = new node(v, data_.first_);
if (!data_.size_) if (!data_.size_)
data_.last_ptr_ = &(*data_.last_ptr_)->next_; data_.last_ptr_ = &(*data_.last_ptr_)->next_;
++data_.size_; ++data_.size_;
} }
void push_back(value_type const& v) void push_back(value_type const& v)
{ {
*data_.last_ptr_ = new node(v); *data_.last_ptr_ = new node(v);
data_.last_ptr_ = &(*data_.last_ptr_)->next_; data_.last_ptr_ = &(*data_.last_ptr_)->next_;
++data_.size_; ++data_.size_;
} }
void clear() void clear()
{ {
while (data_.first_) { while (data_.first_) {
node* tmp = data_.first_; node* tmp = data_.first_;
data_.first_ = data_.first_->next_; data_.first_ = data_.first_->next_;
--data_.size_; --data_.size_;
delete tmp; delete tmp;
} }
data_.last_ptr_ = &data_.first_; data_.last_ptr_ = &data_.first_;
} }
void erase(const_iterator i, const_iterator j) void erase(const_iterator i, const_iterator j)
{ {
node** ptr = &data_.first_; node** ptr = &data_.first_;
while (*ptr != i.ptr_) { while (*ptr != i.ptr_) {
ptr = &(*ptr)->next_; ptr = &(*ptr)->next_;
} }
while (*ptr != j.ptr_) { while (*ptr != j.ptr_) {
node* to_delete = *ptr; node* to_delete = *ptr;
*ptr = (*ptr)->next_; *ptr = (*ptr)->next_;
--data_.size_; --data_.size_;
delete to_delete; delete to_delete;
} }
if (!*ptr) if (!*ptr)
data_.last_ptr_ = ptr; data_.last_ptr_ = ptr;
} }
bool empty() const { return !data_.size_; } bool empty() const { return !data_.size_; }
@ -249,14 +249,14 @@ template <typename T> class list
template <typename Less> void sort(Less less = Less()) template <typename Less> void sort(Less less = Less())
{ {
if (!empty()) if (!empty())
merge_sort( merge_sort(
&data_.first_, (std::numeric_limits<size_type>::max)(), less); &data_.first_, (std::numeric_limits<size_type>::max)(), less);
} }
bool operator==(list const& y) const bool operator==(list const& y) const
{ {
return size() == y.size() && test::equal(begin(), end(), y.begin()); return size() == y.size() && test::equal(begin(), end(), y.begin());
} }
bool operator!=(list const& y) const { return !(*this == y); } bool operator!=(list const& y) const { return !(*this == y); }
@ -265,56 +265,55 @@ template <typename T> class list
template <typename Less> template <typename Less>
node** merge_sort(node** l, size_type recurse_limit, Less less) node** merge_sort(node** l, size_type recurse_limit, Less less)
{ {
node** ptr = &(*l)->next_; node** ptr = &(*l)->next_;
for (size_type count = 0; count < recurse_limit && *ptr; ++count) { for (size_type count = 0; count < recurse_limit && *ptr; ++count) {
ptr = merge_adjacent_ranges( ptr = merge_adjacent_ranges(l, ptr, merge_sort(ptr, count, less), less);
l, ptr, merge_sort(ptr, count, less), less); }
} return ptr;
return ptr;
} }
template <typename Less> template <typename Less>
node** merge_adjacent_ranges( node** merge_adjacent_ranges(
node** first, node** second, node** third, Less less) node** first, node** second, node** third, Less less)
{ {
for (;;) {
for (;;) { for (;;) {
for (;;) { if (first == second)
if (first == second) return third;
return third; if (less((*second)->value_, (*first)->value_))
if (less((*second)->value_, (*first)->value_)) break;
break; first = &(*first)->next_;
first = &(*first)->next_;
}
swap_adjacent_ranges(first, second, third);
first = &(*first)->next_;
// Since the two ranges we just swapped, the order is now:
// first...third...second
for (;;) {
if (first == third)
return second;
if (!less((*first)->value_, (*third)->value_))
break;
first = &(*first)->next_;
}
swap_adjacent_ranges(first, third, second);
first = &(*first)->next_;
} }
swap_adjacent_ranges(first, second, third);
first = &(*first)->next_;
// Since the two ranges we just swapped, the order is now:
// first...third...second
for (;;) {
if (first == third)
return second;
if (!less((*first)->value_, (*third)->value_))
break;
first = &(*first)->next_;
}
swap_adjacent_ranges(first, third, second);
first = &(*first)->next_;
}
} }
void swap_adjacent_ranges(node** first, node** second, node** third) void swap_adjacent_ranges(node** first, node** second, node** third)
{ {
node* tmp = *first; node* tmp = *first;
*first = *second; *first = *second;
*second = *third; *second = *third;
*third = tmp; *third = tmp;
if (!*second) if (!*second)
data_.last_ptr_ = second; data_.last_ptr_ = second;
} }
}; };
} }
#endif #endif

View File

@ -13,177 +13,177 @@
#include <memory> #include <memory>
namespace test { namespace test {
namespace detail { namespace detail {
struct memory_area struct memory_area
{
void const* start;
void const* end;
memory_area(void const* s, void const* e) : start(s), end(e)
{ {
void const* start;
void const* end;
memory_area(void const* s, void const* e) : start(s), end(e)
{
BOOST_ASSERT(start != end); BOOST_ASSERT(start != end);
} }
}; };
struct memory_track struct memory_track
{
explicit memory_track(int tag = -1) : constructed_(0), tag_(tag) {}
int constructed_;
int tag_;
};
// This is a bit dodgy as it defines overlapping
// areas as 'equal', so this isn't a total ordering.
// But it is for non-overlapping memory regions - which
// is what'll be stored.
//
// All searches will be for areas entirely contained by
// a member of the set - so it should find the area that contains
// the region that is searched for.
struct memory_area_compare
{
bool operator()(memory_area const& x, memory_area const& y) const
{ {
return x.end <= y.start; explicit memory_track(int tag = -1) : constructed_(0), tag_(tag) {}
}
};
struct memory_tracker int constructed_;
{ int tag_;
typedef std::map<memory_area, memory_track, memory_area_compare, };
// This is a bit dodgy as it defines overlapping
// areas as 'equal', so this isn't a total ordering.
// But it is for non-overlapping memory regions - which
// is what'll be stored.
//
// All searches will be for areas entirely contained by
// a member of the set - so it should find the area that contains
// the region that is searched for.
struct memory_area_compare
{
bool operator()(memory_area const& x, memory_area const& y) const
{
return x.end <= y.start;
}
};
struct memory_tracker
{
typedef std::map<memory_area, memory_track, memory_area_compare,
std::allocator<std::pair<memory_area const, memory_track> > > std::allocator<std::pair<memory_area const, memory_track> > >
allocated_memory_type; allocated_memory_type;
allocated_memory_type allocated_memory; allocated_memory_type allocated_memory;
unsigned int count_allocators; unsigned int count_allocators;
unsigned int count_allocations; unsigned int count_allocations;
unsigned int count_constructions; unsigned int count_constructions;
bool tracking_constructions; bool tracking_constructions;
memory_tracker() memory_tracker()
: count_allocators(0), count_allocations(0), count_constructions(0), : count_allocators(0), count_allocations(0), count_constructions(0),
tracking_constructions(true) tracking_constructions(true)
{ {
} }
~memory_tracker() { BOOST_TEST(count_allocators == 0); } ~memory_tracker() { BOOST_TEST(count_allocators == 0); }
void allocator_ref() void allocator_ref()
{ {
if (count_allocators == 0) { if (count_allocators == 0) {
count_allocations = 0;
count_constructions = 0;
allocated_memory.clear();
}
++count_allocators;
}
void allocator_unref()
{
BOOST_TEST(count_allocators > 0);
if (count_allocators > 0) {
--count_allocators;
if (count_allocators == 0) {
bool no_allocations_left = (count_allocations == 0);
bool no_constructions_left = (count_constructions == 0);
bool allocated_memory_empty = allocated_memory.empty();
// Clearing the data before the checks terminate the
// tests.
count_allocations = 0; count_allocations = 0;
count_constructions = 0; count_constructions = 0;
allocated_memory.clear(); allocated_memory.clear();
BOOST_TEST(no_allocations_left);
BOOST_TEST(no_constructions_left);
BOOST_TEST(allocated_memory_empty);
}
} }
++count_allocators; }
}
void allocator_unref() void track_allocate(void* ptr, std::size_t n, std::size_t size, int tag)
{ {
BOOST_TEST(count_allocators > 0);
if (count_allocators > 0) {
--count_allocators;
if (count_allocators == 0) {
bool no_allocations_left = (count_allocations == 0);
bool no_constructions_left = (count_constructions == 0);
bool allocated_memory_empty = allocated_memory.empty();
// Clearing the data before the checks terminate the
// tests.
count_allocations = 0;
count_constructions = 0;
allocated_memory.clear();
BOOST_TEST(no_allocations_left);
BOOST_TEST(no_constructions_left);
BOOST_TEST(allocated_memory_empty);
}
}
}
void track_allocate(void* ptr, std::size_t n, std::size_t size, int tag)
{
if (n == 0) { if (n == 0) {
BOOST_ERROR("Allocating 0 length array."); BOOST_ERROR("Allocating 0 length array.");
} else { } else {
++count_allocations; ++count_allocations;
allocated_memory.insert(std::pair<memory_area const, memory_track>( allocated_memory.insert(std::pair<memory_area const, memory_track>(
memory_area(ptr, (char*)ptr + n * size), memory_track(tag))); memory_area(ptr, (char*)ptr + n * size), memory_track(tag)));
} }
} }
void track_deallocate(void* ptr, std::size_t n, std::size_t size, int tag, void track_deallocate(void* ptr, std::size_t n, std::size_t size, int tag,
bool check_tag_ = true) bool check_tag_ = true)
{ {
allocated_memory_type::iterator pos = allocated_memory_type::iterator pos =
allocated_memory.find(memory_area(ptr, (char*)ptr + n * size)); allocated_memory.find(memory_area(ptr, (char*)ptr + n * size));
if (pos == allocated_memory.end()) { if (pos == allocated_memory.end()) {
BOOST_ERROR("Deallocating unknown pointer."); BOOST_ERROR("Deallocating unknown pointer.");
} else { } else {
BOOST_TEST(pos->first.start == ptr); BOOST_TEST(pos->first.start == ptr);
BOOST_TEST(pos->first.end == (char*)ptr + n * size); BOOST_TEST(pos->first.end == (char*)ptr + n * size);
if (check_tag_) if (check_tag_)
BOOST_TEST(pos->second.tag_ == tag); BOOST_TEST(pos->second.tag_ == tag);
allocated_memory.erase(pos); allocated_memory.erase(pos);
} }
BOOST_TEST(count_allocations > 0); BOOST_TEST(count_allocations > 0);
if (count_allocations > 0) if (count_allocations > 0)
--count_allocations; --count_allocations;
} }
void track_construct(void* /*ptr*/, std::size_t /*size*/, int /*tag*/) void track_construct(void* /*ptr*/, std::size_t /*size*/, int /*tag*/)
{ {
if (tracking_constructions) { if (tracking_constructions) {
++count_constructions; ++count_constructions;
} }
} }
void track_destroy(void* /*ptr*/, std::size_t /*size*/, int /*tag*/) void track_destroy(void* /*ptr*/, std::size_t /*size*/, int /*tag*/)
{ {
if (tracking_constructions) { if (tracking_constructions) {
BOOST_TEST(count_constructions > 0); BOOST_TEST(count_constructions > 0);
if (count_constructions > 0) if (count_constructions > 0)
--count_constructions; --count_constructions;
} }
}
};
}
namespace detail {
// This won't be a problem as I'm only using a single compile unit
// in each test (this is actually required by the minimal test
// framework).
//
// boostinspect:nounnamed
namespace {
test::detail::memory_tracker tracker;
} }
}; }
}
namespace detail { namespace detail {
// This won't be a problem as I'm only using a single compile unit struct disable_construction_tracking
// in each test (this is actually required by the minimal test
// framework).
//
// boostinspect:nounnamed
namespace {
test::detail::memory_tracker tracker;
}
}
namespace detail {
struct disable_construction_tracking
{
bool old_value;
disable_construction_tracking()
: old_value(detail::tracker.tracking_constructions)
{ {
bool old_value;
disable_construction_tracking()
: old_value(detail::tracker.tracking_constructions)
{
test::detail::tracker.tracking_constructions = false; test::detail::tracker.tracking_constructions = false;
} }
~disable_construction_tracking() ~disable_construction_tracking()
{ {
test::detail::tracker.tracking_constructions = old_value; test::detail::tracker.tracking_constructions = old_value;
} }
private: private:
disable_construction_tracking(disable_construction_tracking const&); disable_construction_tracking(disable_construction_tracking const&);
disable_construction_tracking& operator=( disable_construction_tracking& operator=(
disable_construction_tracking const&); disable_construction_tracking const&);
}; };
} }
} }
#endif #endif

View File

@ -10,25 +10,25 @@
#include <boost/type_traits/is_same.hpp> #include <boost/type_traits/is_same.hpp>
namespace test { namespace test {
template <class Container> template <class Container>
struct is_set struct is_set
: public boost::is_same<BOOST_DEDUCED_TYPENAME Container::key_type, : public boost::is_same<BOOST_DEDUCED_TYPENAME Container::key_type,
BOOST_DEDUCED_TYPENAME Container::value_type> BOOST_DEDUCED_TYPENAME Container::value_type>
{ {
}; };
template <class Container> struct has_unique_keys template <class Container> struct has_unique_keys
{ {
static char flip(BOOST_DEDUCED_TYPENAME Container::iterator const&); static char flip(BOOST_DEDUCED_TYPENAME Container::iterator const&);
static long flip( static long flip(
std::pair<BOOST_DEDUCED_TYPENAME Container::iterator, bool> const&); std::pair<BOOST_DEDUCED_TYPENAME Container::iterator, bool> const&);
BOOST_STATIC_CONSTANT(bool, BOOST_STATIC_CONSTANT(bool,
value = sizeof(long) == value = sizeof(long) ==
sizeof(flip( sizeof(
((Container*)0) flip(((Container*)0)
->insert(*( ->insert(
BOOST_DEDUCED_TYPENAME Container::value_type*)0)))); *(BOOST_DEDUCED_TYPENAME Container::value_type*)0))));
}; };
} }
#endif #endif

View File

@ -13,8 +13,8 @@
#include <boost/detail/select_type.hpp> #include <boost/detail/select_type.hpp>
namespace test { namespace test {
template <class X> struct unordered_generator_set template <class X> struct unordered_generator_set
{ {
typedef BOOST_DEDUCED_TYPENAME X::value_type value_type; typedef BOOST_DEDUCED_TYPENAME X::value_type value_type;
random_generator type_; random_generator type_;
@ -23,24 +23,24 @@ template <class X> struct unordered_generator_set
template <class T> void fill(T& x, std::size_t len) template <class T> void fill(T& x, std::size_t len)
{ {
value_type* value_ptr = 0; value_type* value_ptr = 0;
len += x.size(); len += x.size();
for (std::size_t i = 0; i < len; ++i) { for (std::size_t i = 0; i < len; ++i) {
value_type value = generate(value_ptr, type_); value_type value = generate(value_ptr, type_);
std::size_t count = std::size_t count =
type_ == generate_collisions ? random_value(5) + 1 : 1; type_ == generate_collisions ? random_value(5) + 1 : 1;
for (std::size_t j = 0; j < count; ++j) { for (std::size_t j = 0; j < count; ++j) {
x.push_back(value); x.push_back(value);
}
} }
}
} }
}; };
template <class X> struct unordered_generator_map template <class X> struct unordered_generator_map
{ {
typedef BOOST_DEDUCED_TYPENAME X::key_type key_type; typedef BOOST_DEDUCED_TYPENAME X::key_type key_type;
typedef BOOST_DEDUCED_TYPENAME X::mapped_type mapped_type; typedef BOOST_DEDUCED_TYPENAME X::mapped_type mapped_type;
@ -50,60 +50,60 @@ template <class X> struct unordered_generator_map
template <class T> void fill(T& x, std::size_t len) template <class T> void fill(T& x, std::size_t len)
{ {
key_type* key_ptr = 0; key_type* key_ptr = 0;
mapped_type* mapped_ptr = 0; mapped_type* mapped_ptr = 0;
for (std::size_t i = 0; i < len; ++i) { for (std::size_t i = 0; i < len; ++i) {
key_type key = generate(key_ptr, type_); key_type key = generate(key_ptr, type_);
std::size_t count = std::size_t count =
type_ == generate_collisions ? random_value(5) + 1 : 1; type_ == generate_collisions ? random_value(5) + 1 : 1;
for (std::size_t j = 0; j < count; ++j) { for (std::size_t j = 0; j < count; ++j) {
x.push_back(std::pair<key_type const, mapped_type>( x.push_back(std::pair<key_type const, mapped_type>(
key, generate(mapped_ptr, type_))); key, generate(mapped_ptr, type_)));
}
} }
}
} }
}; };
template <class X> template <class X>
struct unordered_generator_base struct unordered_generator_base
: public boost::detail::if_true<test::is_set<X>::value>:: : public boost::detail::if_true<test::is_set<X>::value>::
BOOST_NESTED_TEMPLATE then<test::unordered_generator_set<X>, BOOST_NESTED_TEMPLATE then<test::unordered_generator_set<X>,
test::unordered_generator_map<X> > test::unordered_generator_map<X> >
{ {
}; };
template <class X> template <class X>
struct unordered_generator : public unordered_generator_base<X>::type struct unordered_generator : public unordered_generator_base<X>::type
{ {
typedef BOOST_DEDUCED_TYPENAME unordered_generator_base<X>::type base; typedef BOOST_DEDUCED_TYPENAME unordered_generator_base<X>::type base;
unordered_generator(random_generator const& type = default_generator) unordered_generator(random_generator const& type = default_generator)
: base(type) : base(type)
{ {
} }
}; };
template <class X> template <class X>
struct random_values : public test::list<BOOST_DEDUCED_TYPENAME X::value_type> struct random_values : public test::list<BOOST_DEDUCED_TYPENAME X::value_type>
{ {
random_values() {} random_values() {}
explicit random_values(std::size_t count, explicit random_values(std::size_t count,
test::random_generator const& generator = test::default_generator) test::random_generator const& generator = test::default_generator)
{ {
fill(count, generator); fill(count, generator);
} }
void fill(std::size_t count, void fill(std::size_t count,
test::random_generator const& generator = test::default_generator) test::random_generator const& generator = test::default_generator)
{ {
test::unordered_generator<X> gen(generator); test::unordered_generator<X> gen(generator);
gen.fill(*this, count); gen.fill(*this, count);
} }
}; };
} }
#endif #endif

View File

@ -13,8 +13,8 @@
#include <iterator> #include <iterator>
namespace test { namespace test {
template <class X> class strong template <class X> class strong
{ {
typedef test::list<BOOST_DEDUCED_TYPENAME X::value_type> values_type; typedef test::list<BOOST_DEDUCED_TYPENAME X::value_type> values_type;
values_type values_; values_type values_;
unsigned int allocations_; unsigned int allocations_;
@ -22,22 +22,21 @@ template <class X> class strong
public: public:
void store(X const& x, unsigned int allocations = 0) void store(X const& x, unsigned int allocations = 0)
{ {
DISABLE_EXCEPTIONS; DISABLE_EXCEPTIONS;
values_.clear(); values_.clear();
values_.insert(x.cbegin(), x.cend()); values_.insert(x.cbegin(), x.cend());
allocations_ = allocations; allocations_ = allocations;
} }
void test(X const& x, unsigned int allocations = 0) const void test(X const& x, unsigned int allocations = 0) const
{ {
if (!(x.size() == values_.size() && if (!(x.size() == values_.size() && test::equal(x.cbegin(), x.cend(),
test::equal( values_.begin(), test::equivalent)))
x.cbegin(), x.cend(), values_.begin(), test::equivalent))) BOOST_ERROR("Strong exception safety failure.");
BOOST_ERROR("Strong exception safety failure."); if (allocations != allocations_)
if (allocations != allocations_) BOOST_ERROR("Strong exception failure: extra allocations.");
BOOST_ERROR("Strong exception failure: extra allocations.");
} }
}; };
} }
#endif #endif

View File

@ -11,53 +11,53 @@
#include <boost/preprocessor/stringize.hpp> #include <boost/preprocessor/stringize.hpp>
#define UNORDERED_AUTO_TEST(x) \ #define UNORDERED_AUTO_TEST(x) \
struct BOOST_PP_CAT(x, _type) : public ::test::registered_test_base \ struct BOOST_PP_CAT(x, _type) : public ::test::registered_test_base \
{ \
BOOST_PP_CAT(x, _type) \
() : ::test::registered_test_base(BOOST_PP_STRINGIZE(x)) \
{ \ { \
BOOST_PP_CAT(x, _type) \ ::test::get_state().add_test(this); \
() : ::test::registered_test_base(BOOST_PP_STRINGIZE(x)) \ } \
{ \ void run(); \
::test::get_state().add_test(this); \ }; \
} \ BOOST_PP_CAT(x, _type) x; \
void run(); \ void BOOST_PP_CAT(x, _type)::run()
}; \
BOOST_PP_CAT(x, _type) x; \
void BOOST_PP_CAT(x, _type)::run()
#define RUN_TESTS() \ #define RUN_TESTS() \
int main(int, char**) \ int main(int, char**) \
{ \ { \
BOOST_UNORDERED_TEST_COMPILER_INFO() \ BOOST_UNORDERED_TEST_COMPILER_INFO() \
::test::get_state().run_tests(); \ ::test::get_state().run_tests(); \
return boost::report_errors(); \ return boost::report_errors(); \
} }
#define RUN_TESTS_QUIET() \ #define RUN_TESTS_QUIET() \
int main(int, char**) \ int main(int, char**) \
{ \ { \
BOOST_UNORDERED_TEST_COMPILER_INFO() \ BOOST_UNORDERED_TEST_COMPILER_INFO() \
::test::get_state().run_tests(true); \ ::test::get_state().run_tests(true); \
return boost::report_errors(); \ return boost::report_errors(); \
} }
#define UNORDERED_SUB_TEST(x) \ #define UNORDERED_SUB_TEST(x) \
for (int UNORDERED_SUB_TEST_VALUE = ::test::get_state().start_sub_test(x); \ for (int UNORDERED_SUB_TEST_VALUE = ::test::get_state().start_sub_test(x); \
UNORDERED_SUB_TEST_VALUE; \ UNORDERED_SUB_TEST_VALUE; \
UNORDERED_SUB_TEST_VALUE = \ UNORDERED_SUB_TEST_VALUE = \
::test::get_state().end_sub_test(x, UNORDERED_SUB_TEST_VALUE)) ::test::get_state().end_sub_test(x, UNORDERED_SUB_TEST_VALUE))
namespace test { namespace test {
struct registered_test_base struct registered_test_base
{ {
registered_test_base* next; registered_test_base* next;
char const* name; char const* name;
explicit registered_test_base(char const* n) : name(n) {} explicit registered_test_base(char const* n) : name(n) {}
virtual void run() = 0; virtual void run() = 0;
virtual ~registered_test_base() {} virtual ~registered_test_base() {}
}; };
struct state struct state
{ {
bool is_quiet; bool is_quiet;
registered_test_base* first_test; registered_test_base* first_test;
registered_test_base* last_test; registered_test_base* last_test;
@ -66,61 +66,59 @@ struct state
void add_test(registered_test_base* test) void add_test(registered_test_base* test)
{ {
if (last_test) { if (last_test) {
last_test->next = test; last_test->next = test;
} else { } else {
first_test = test; first_test = test;
} }
last_test = test; last_test = test;
} }
void run_tests(bool quiet = false) void run_tests(bool quiet = false)
{ {
is_quiet = quiet; is_quiet = quiet;
for (registered_test_base* i = first_test; i; i = i->next) { for (registered_test_base* i = first_test; i; i = i->next) {
int error_count = boost::detail::test_errors(); int error_count = boost::detail::test_errors();
if (!quiet) { if (!quiet) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Running " << i->name << "\n" BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Running " << i->name << "\n"
<< std::flush; << std::flush;
}
i->run();
BOOST_LIGHTWEIGHT_TEST_OSTREAM << std::flush;
if (quiet && error_count != boost::detail::test_errors()) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Error in: " << i->name
<< "\n"
<< std::flush;
}
} }
i->run();
BOOST_LIGHTWEIGHT_TEST_OSTREAM << std::flush;
if (quiet && error_count != boost::detail::test_errors()) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Error in: " << i->name << "\n"
<< std::flush;
}
}
} }
int start_sub_test(char const* name) int start_sub_test(char const* name)
{ {
if (!is_quiet) { if (!is_quiet) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Sub-test: " << name << "\n" BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Sub-test: " << name << "\n"
<< std::flush; << std::flush;
} }
// Add one because it's used as a loop condition. // Add one because it's used as a loop condition.
return boost::detail::test_errors() + 1; return boost::detail::test_errors() + 1;
} }
int end_sub_test(char const* name, int value) int end_sub_test(char const* name, int value)
{ {
if (is_quiet && value != boost::detail::test_errors() + 1) { if (is_quiet && value != boost::detail::test_errors() + 1) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Error in sub-test: " << name BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Error in sub-test: " << name << "\n"
<< "\n" << std::flush;
<< std::flush; }
} return 0;
return 0;
} }
}; };
// Get the currnet translation unit's test state. // Get the currnet translation unit's test state.
static inline state& get_state() static inline state& get_state()
{ {
static state instance; static state instance;
return instance; return instance;
} }
} }
#if defined(__cplusplus) #if defined(__cplusplus)
@ -130,21 +128,21 @@ static inline state& get_state()
#endif #endif
#define BOOST_UNORDERED_TEST_COMPILER_INFO() \ #define BOOST_UNORDERED_TEST_COMPILER_INFO() \
{ \ { \
BOOST_LIGHTWEIGHT_TEST_OSTREAM \ BOOST_LIGHTWEIGHT_TEST_OSTREAM \
<< "Compiler: " << BOOST_COMPILER << "\n" \ << "Compiler: " << BOOST_COMPILER << "\n" \
<< "Library: " << BOOST_STDLIB << "\n" \ << "Library: " << BOOST_STDLIB << "\n" \
<< "__cplusplus: " << BOOST_UNORDERED_CPLUSPLUS << "\n\n" \ << "__cplusplus: " << BOOST_UNORDERED_CPLUSPLUS << "\n\n" \
<< "BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT: " \ << "BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT: " \
<< BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT << "\n" \ << BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT << "\n" \
<< "BOOST_UNORDERED_EMPLACE_LIMIT: " \ << "BOOST_UNORDERED_EMPLACE_LIMIT: " << BOOST_UNORDERED_EMPLACE_LIMIT \
<< BOOST_UNORDERED_EMPLACE_LIMIT << "\n" \ << "\n" \
<< "BOOST_UNORDERED_USE_ALLOCATOR_TRAITS: " \ << "BOOST_UNORDERED_USE_ALLOCATOR_TRAITS: " \
<< BOOST_UNORDERED_USE_ALLOCATOR_TRAITS << "\n" \ << BOOST_UNORDERED_USE_ALLOCATOR_TRAITS << "\n" \
<< "BOOST_UNORDERED_CXX11_CONSTRUCTION: " \ << "BOOST_UNORDERED_CXX11_CONSTRUCTION: " \
<< BOOST_UNORDERED_CXX11_CONSTRUCTION << "\n\n" \ << BOOST_UNORDERED_CXX11_CONSTRUCTION << "\n\n" \
<< std::flush; \ << std::flush; \
} }
#include <boost/preprocessor/cat.hpp> #include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/seq/fold_left.hpp> #include <boost/preprocessor/seq/fold_left.hpp>
@ -154,52 +152,52 @@ static inline state& get_state()
// Run test with every combination of the parameters (a sequence of sequences) // Run test with every combination of the parameters (a sequence of sequences)
#define UNORDERED_TEST(name, parameters) \ #define UNORDERED_TEST(name, parameters) \
BOOST_PP_SEQ_FOR_EACH_PRODUCT(UNORDERED_TEST_OP, ((name))((1))parameters) BOOST_PP_SEQ_FOR_EACH_PRODUCT(UNORDERED_TEST_OP, ((name))((1))parameters)
#define UNORDERED_TEST_REPEAT(name, n, parameters) \ #define UNORDERED_TEST_REPEAT(name, n, parameters) \
BOOST_PP_SEQ_FOR_EACH_PRODUCT(UNORDERED_TEST_OP, ((name))((n))parameters) BOOST_PP_SEQ_FOR_EACH_PRODUCT(UNORDERED_TEST_OP, ((name))((n))parameters)
#define UNORDERED_TEST_OP(r, product) \ #define UNORDERED_TEST_OP(r, product) \
UNORDERED_TEST_OP2(BOOST_PP_SEQ_ELEM(0, product), \ UNORDERED_TEST_OP2(BOOST_PP_SEQ_ELEM(0, product), \
BOOST_PP_SEQ_ELEM(1, product), \ BOOST_PP_SEQ_ELEM(1, product), \
BOOST_PP_SEQ_TAIL(BOOST_PP_SEQ_TAIL(product))) BOOST_PP_SEQ_TAIL(BOOST_PP_SEQ_TAIL(product)))
#define UNORDERED_TEST_OP2(name, n, params) \ #define UNORDERED_TEST_OP2(name, n, params) \
UNORDERED_AUTO_TEST( \ UNORDERED_AUTO_TEST( \
BOOST_PP_SEQ_FOLD_LEFT(UNORDERED_TEST_OP_JOIN, name, params)) \ BOOST_PP_SEQ_FOLD_LEFT(UNORDERED_TEST_OP_JOIN, name, params)) \
{ \ { \
for (int i = 0; i < n; ++i) \ for (int i = 0; i < n; ++i) \
name BOOST_PP_SEQ_TO_TUPLE(params); \ name BOOST_PP_SEQ_TO_TUPLE(params); \
} }
#define UNORDERED_TEST_OP_JOIN(s, state, elem) \ #define UNORDERED_TEST_OP_JOIN(s, state, elem) \
BOOST_PP_CAT(state, BOOST_PP_CAT(_, elem)) BOOST_PP_CAT(state, BOOST_PP_CAT(_, elem))
#define UNORDERED_MULTI_TEST(name, impl, parameters) \ #define UNORDERED_MULTI_TEST(name, impl, parameters) \
UNORDERED_MULTI_TEST_REPEAT(name, impl, 1, parameters) UNORDERED_MULTI_TEST_REPEAT(name, impl, 1, parameters)
#define UNORDERED_MULTI_TEST_REPEAT(name, impl, n, parameters) \ #define UNORDERED_MULTI_TEST_REPEAT(name, impl, n, parameters) \
UNORDERED_AUTO_TEST(name) \ UNORDERED_AUTO_TEST(name) \
{ \ { \
BOOST_PP_SEQ_FOR_EACH_PRODUCT( \ BOOST_PP_SEQ_FOR_EACH_PRODUCT( \
UNORDERED_MULTI_TEST_OP, ((impl))((n))parameters) \ UNORDERED_MULTI_TEST_OP, ((impl))((n))parameters) \
} }
#define UNORDERED_MULTI_TEST_OP(r, product) \ #define UNORDERED_MULTI_TEST_OP(r, product) \
UNORDERED_MULTI_TEST_OP2(BOOST_PP_SEQ_ELEM(0, product), \ UNORDERED_MULTI_TEST_OP2(BOOST_PP_SEQ_ELEM(0, product), \
BOOST_PP_SEQ_ELEM(1, product), \ BOOST_PP_SEQ_ELEM(1, product), \
BOOST_PP_SEQ_TAIL(BOOST_PP_SEQ_TAIL(product))) BOOST_PP_SEQ_TAIL(BOOST_PP_SEQ_TAIL(product)))
// Need to wrap UNORDERED_SUB_TEST in a block to avoid an msvc bug. // Need to wrap UNORDERED_SUB_TEST in a block to avoid an msvc bug.
// https://support.microsoft.com/en-gb/help/315481/bug-too-many-unnested-loops-incorrectly-causes-a-c1061-compiler-error-in-visual-c // https://support.microsoft.com/en-gb/help/315481/bug-too-many-unnested-loops-incorrectly-causes-a-c1061-compiler-error-in-visual-c
#define UNORDERED_MULTI_TEST_OP2(name, n, params) \ #define UNORDERED_MULTI_TEST_OP2(name, n, params) \
{ \
UNORDERED_SUB_TEST(BOOST_PP_STRINGIZE( \
BOOST_PP_SEQ_FOLD_LEFT(UNORDERED_TEST_OP_JOIN, name, params))) \
{ \ { \
UNORDERED_SUB_TEST(BOOST_PP_STRINGIZE( \ for (int i = 0; i < n; ++i) \
BOOST_PP_SEQ_FOLD_LEFT(UNORDERED_TEST_OP_JOIN, name, params))) \ name BOOST_PP_SEQ_TO_TUPLE(params); \
{ \ } \
for (int i = 0; i < n; ++i) \ }
name BOOST_PP_SEQ_TO_TUPLE(params); \
} \
}
#endif #endif

View File

@ -20,18 +20,18 @@
#include <set> #include <set>
namespace test { namespace test {
template <typename X> struct equals_to_compare template <typename X> struct equals_to_compare
{ {
typedef std::less<BOOST_DEDUCED_TYPENAME X::first_argument_type> type; typedef std::less<BOOST_DEDUCED_TYPENAME X::first_argument_type> type;
}; };
template <> struct equals_to_compare<test::equal_to> template <> struct equals_to_compare<test::equal_to>
{ {
typedef test::less type; typedef test::less type;
}; };
template <class X1, class X2> void compare_range(X1 const& x1, X2 const& x2) template <class X1, class X2> void compare_range(X1 const& x1, X2 const& x2)
{ {
typedef test::list<BOOST_DEDUCED_TYPENAME X1::value_type> value_list; typedef test::list<BOOST_DEDUCED_TYPENAME X1::value_type> value_list;
value_list values1(x1.begin(), x1.end()); value_list values1(x1.begin(), x1.end());
value_list values2(x2.begin(), x2.end()); value_list values2(x2.begin(), x2.end());
@ -39,61 +39,61 @@ template <class X1, class X2> void compare_range(X1 const& x1, X2 const& x2)
values2.sort(); values2.sort();
BOOST_TEST(values1.size() == values2.size() && BOOST_TEST(values1.size() == values2.size() &&
test::equal(values1.begin(), values1.end(), values2.begin(), test::equal(values1.begin(), values1.end(), values2.begin(),
test::equivalent)); test::equivalent));
} }
template <class X1, class X2, class T> template <class X1, class X2, class T>
void compare_pairs(X1 const& x1, X2 const& x2, T*) void compare_pairs(X1 const& x1, X2 const& x2, T*)
{ {
test::list<T> values1(x1.first, x1.second); test::list<T> values1(x1.first, x1.second);
test::list<T> values2(x2.first, x2.second); test::list<T> values2(x2.first, x2.second);
values1.sort(); values1.sort();
values2.sort(); values2.sort();
BOOST_TEST(values1.size() == values2.size() && BOOST_TEST(values1.size() == values2.size() &&
test::equal(values1.begin(), values1.end(), values2.begin(), test::equal(values1.begin(), values1.end(), values2.begin(),
test::equivalent)); test::equivalent));
} }
template <typename X, bool is_set = test::is_set<X>::value, template <typename X, bool is_set = test::is_set<X>::value,
bool has_unique_keys = test::has_unique_keys<X>::value> bool has_unique_keys = test::has_unique_keys<X>::value>
struct ordered_base; struct ordered_base;
template <typename X> struct ordered_base<X, true, true> template <typename X> struct ordered_base<X, true, true>
{ {
typedef std::set<BOOST_DEDUCED_TYPENAME X::value_type, typedef std::set<BOOST_DEDUCED_TYPENAME X::value_type,
BOOST_DEDUCED_TYPENAME BOOST_DEDUCED_TYPENAME
equals_to_compare<BOOST_DEDUCED_TYPENAME X::key_equal>::type> equals_to_compare<BOOST_DEDUCED_TYPENAME X::key_equal>::type>
type; type;
}; };
template <typename X> struct ordered_base<X, true, false> template <typename X> struct ordered_base<X, true, false>
{ {
typedef std::multiset<BOOST_DEDUCED_TYPENAME X::value_type, typedef std::multiset<BOOST_DEDUCED_TYPENAME X::value_type,
BOOST_DEDUCED_TYPENAME BOOST_DEDUCED_TYPENAME
equals_to_compare<BOOST_DEDUCED_TYPENAME X::key_equal>::type> equals_to_compare<BOOST_DEDUCED_TYPENAME X::key_equal>::type>
type; type;
}; };
template <typename X> struct ordered_base<X, false, true> template <typename X> struct ordered_base<X, false, true>
{ {
typedef std::map<BOOST_DEDUCED_TYPENAME X::key_type, typedef std::map<BOOST_DEDUCED_TYPENAME X::key_type,
BOOST_DEDUCED_TYPENAME X::mapped_type, BOOST_DEDUCED_TYPENAME X::mapped_type,
BOOST_DEDUCED_TYPENAME BOOST_DEDUCED_TYPENAME
equals_to_compare<BOOST_DEDUCED_TYPENAME X::key_equal>::type> equals_to_compare<BOOST_DEDUCED_TYPENAME X::key_equal>::type>
type; type;
}; };
template <typename X> struct ordered_base<X, false, false> template <typename X> struct ordered_base<X, false, false>
{ {
typedef std::multimap<BOOST_DEDUCED_TYPENAME X::key_type, typedef std::multimap<BOOST_DEDUCED_TYPENAME X::key_type,
BOOST_DEDUCED_TYPENAME X::mapped_type, BOOST_DEDUCED_TYPENAME X::mapped_type,
BOOST_DEDUCED_TYPENAME BOOST_DEDUCED_TYPENAME
equals_to_compare<BOOST_DEDUCED_TYPENAME X::key_equal>::type> equals_to_compare<BOOST_DEDUCED_TYPENAME X::key_equal>::type>
type; type;
}; };
template <class X> class ordered : public ordered_base<X>::type template <class X> class ordered : public ordered_base<X>::type
{ {
typedef BOOST_DEDUCED_TYPENAME ordered_base<X>::type base; typedef BOOST_DEDUCED_TYPENAME ordered_base<X>::type base;
public: public:
@ -106,42 +106,42 @@ template <class X> class ordered : public ordered_base<X>::type
void compare(X const& x) { compare_range(x, *this); } void compare(X const& x) { compare_range(x, *this); }
void compare_key( void compare_key(
X const& x, BOOST_DEDUCED_TYPENAME X::value_type const& val) X const& x, BOOST_DEDUCED_TYPENAME X::value_type const& val)
{ {
compare_pairs(x.equal_range(get_key<X>(val)), compare_pairs(x.equal_range(get_key<X>(val)),
this->equal_range(get_key<X>(val)), this->equal_range(get_key<X>(val)),
(BOOST_DEDUCED_TYPENAME X::value_type*)0); (BOOST_DEDUCED_TYPENAME X::value_type*)0);
} }
template <class It> void insert_range(It b, It e) template <class It> void insert_range(It b, It e)
{ {
while (b != e) { while (b != e) {
this->insert(*b); this->insert(*b);
++b; ++b;
} }
} }
}; };
template <class Equals> template <class Equals>
BOOST_DEDUCED_TYPENAME equals_to_compare<Equals>::type create_compare( BOOST_DEDUCED_TYPENAME equals_to_compare<Equals>::type create_compare(
Equals const&) Equals const&)
{ {
BOOST_DEDUCED_TYPENAME equals_to_compare<Equals>::type x; BOOST_DEDUCED_TYPENAME equals_to_compare<Equals>::type x;
return x; return x;
} }
template <class X> ordered<X> create_ordered(X const& container) template <class X> ordered<X> create_ordered(X const& container)
{ {
return ordered<X>(create_compare(container.key_eq())); return ordered<X>(create_compare(container.key_eq()));
} }
template <class X1, class X2> template <class X1, class X2>
void check_container(X1 const& container, X2 const& values) void check_container(X1 const& container, X2 const& values)
{ {
ordered<X1> tracker = create_ordered(container); ordered<X1> tracker = create_ordered(container);
tracker.insert_range(values.begin(), values.end()); tracker.insert_range(values.begin(), values.end());
tracker.compare(container); tracker.compare(container);
} }
} }
#endif #endif

View File

@ -14,141 +14,141 @@
#include "../helpers/memory.hpp" #include "../helpers/memory.hpp"
namespace test { namespace test {
struct allocator_false struct allocator_false
{ {
enum enum
{ {
is_select_on_copy = 0, is_select_on_copy = 0,
is_propagate_on_swap = 0, is_propagate_on_swap = 0,
is_propagate_on_assign = 0, is_propagate_on_assign = 0,
is_propagate_on_move = 0, is_propagate_on_move = 0,
cxx11_construct = 0 cxx11_construct = 0
}; };
}; };
struct allocator_flags_all struct allocator_flags_all
{ {
enum enum
{ {
is_select_on_copy = 1, is_select_on_copy = 1,
is_propagate_on_swap = 1, is_propagate_on_swap = 1,
is_propagate_on_assign = 1, is_propagate_on_assign = 1,
is_propagate_on_move = 1, is_propagate_on_move = 1,
cxx11_construct = 1 cxx11_construct = 1
}; };
}; };
struct select_copy : allocator_false struct select_copy : allocator_false
{ {
enum enum
{ {
is_select_on_copy = 1 is_select_on_copy = 1
}; };
}; };
struct propagate_swap : allocator_false struct propagate_swap : allocator_false
{ {
enum enum
{ {
is_propagate_on_swap = 1 is_propagate_on_swap = 1
}; };
}; };
struct propagate_assign : allocator_false struct propagate_assign : allocator_false
{ {
enum enum
{ {
is_propagate_on_assign = 1 is_propagate_on_assign = 1
}; };
}; };
struct propagate_move : allocator_false struct propagate_move : allocator_false
{ {
enum enum
{ {
is_propagate_on_move = 1 is_propagate_on_move = 1
}; };
}; };
struct no_select_copy : allocator_flags_all struct no_select_copy : allocator_flags_all
{ {
enum enum
{ {
is_select_on_copy = 0 is_select_on_copy = 0
}; };
}; };
struct no_propagate_swap : allocator_flags_all struct no_propagate_swap : allocator_flags_all
{ {
enum enum
{ {
is_propagate_on_swap = 0 is_propagate_on_swap = 0
}; };
}; };
struct no_propagate_assign : allocator_flags_all struct no_propagate_assign : allocator_flags_all
{ {
enum enum
{ {
is_propagate_on_assign = 0 is_propagate_on_assign = 0
}; };
}; };
struct no_propagate_move : allocator_flags_all struct no_propagate_move : allocator_flags_all
{ {
enum enum
{ {
is_propagate_on_move = 0 is_propagate_on_move = 0
}; };
}; };
template <typename Flag> struct swap_allocator_base template <typename Flag> struct swap_allocator_base
{ {
struct propagate_on_container_swap struct propagate_on_container_swap
{ {
enum enum
{ {
value = Flag::is_propagate_on_swap value = Flag::is_propagate_on_swap
}; };
}; };
}; };
template <typename Flag> struct assign_allocator_base template <typename Flag> struct assign_allocator_base
{ {
struct propagate_on_container_copy_assignment struct propagate_on_container_copy_assignment
{ {
enum enum
{ {
value = Flag::is_propagate_on_assign value = Flag::is_propagate_on_assign
}; };
}; };
}; };
template <typename Flag> struct move_allocator_base template <typename Flag> struct move_allocator_base
{ {
struct propagate_on_container_move_assignment struct propagate_on_container_move_assignment
{ {
enum enum
{ {
value = Flag::is_propagate_on_move value = Flag::is_propagate_on_move
}; };
}; };
}; };
namespace { namespace {
// boostinspect:nounnamed // boostinspect:nounnamed
bool force_equal_allocator_value = false; bool force_equal_allocator_value = false;
} }
struct force_equal_allocator struct force_equal_allocator
{ {
bool old_value_; bool old_value_;
explicit force_equal_allocator(bool value) explicit force_equal_allocator(bool value)
: old_value_(force_equal_allocator_value) : old_value_(force_equal_allocator_value)
{ {
force_equal_allocator_value = value; force_equal_allocator_value = value;
} }
~force_equal_allocator() { force_equal_allocator_value = old_value_; } ~force_equal_allocator() { force_equal_allocator_value = old_value_; }
}; };
template <typename T> struct cxx11_allocator_base template <typename T> struct cxx11_allocator_base
{ {
int tag_; int tag_;
int selected_; int selected_;
@ -162,20 +162,20 @@ template <typename T> struct cxx11_allocator_base
explicit cxx11_allocator_base(int t) : tag_(t), selected_(0) explicit cxx11_allocator_base(int t) : tag_(t), selected_(0)
{ {
detail::tracker.allocator_ref(); detail::tracker.allocator_ref();
} }
template <typename Y> template <typename Y>
cxx11_allocator_base(cxx11_allocator_base<Y> const& x) cxx11_allocator_base(cxx11_allocator_base<Y> const& x)
: tag_(x.tag_), selected_(x.selected_) : tag_(x.tag_), selected_(x.selected_)
{ {
detail::tracker.allocator_ref(); detail::tracker.allocator_ref();
} }
cxx11_allocator_base(cxx11_allocator_base const& x) cxx11_allocator_base(cxx11_allocator_base const& x)
: tag_(x.tag_), selected_(x.selected_) : tag_(x.tag_), selected_(x.selected_)
{ {
detail::tracker.allocator_ref(); detail::tracker.allocator_ref();
} }
~cxx11_allocator_base() { detail::tracker.allocator_unref(); } ~cxx11_allocator_base() { detail::tracker.allocator_unref(); }
@ -186,71 +186,71 @@ template <typename T> struct cxx11_allocator_base
pointer allocate(size_type n) pointer allocate(size_type n)
{ {
pointer ptr(static_cast<T*>(::operator new(n * sizeof(T)))); pointer ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_); detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_);
return ptr; return ptr;
} }
pointer allocate(size_type n, void const*) pointer allocate(size_type n, void const*)
{ {
pointer ptr(static_cast<T*>(::operator new(n * sizeof(T)))); pointer ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_); detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_);
return ptr; return ptr;
} }
void deallocate(pointer p, size_type n) void deallocate(pointer p, size_type n)
{ {
// Only checking tags when propagating swap. // Only checking tags when propagating swap.
// Note that tags will be tested // Note that tags will be tested
// properly in the normal allocator. // properly in the normal allocator.
detail::tracker.track_deallocate( detail::tracker.track_deallocate(
(void*)p, n, sizeof(T), tag_, !force_equal_allocator_value); (void*)p, n, sizeof(T), tag_, !force_equal_allocator_value);
::operator delete((void*)p); ::operator delete((void*)p);
} }
void construct(T* p, T const& t) void construct(T* p, T const& t)
{ {
detail::tracker.track_construct((void*)p, sizeof(T), tag_); detail::tracker.track_construct((void*)p, sizeof(T), tag_);
new (p) T(t); new (p) T(t);
} }
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <typename... Args> template <typename... Args>
void construct(T* p, BOOST_FWD_REF(Args)... args) void construct(T* p, BOOST_FWD_REF(Args)... args)
{ {
detail::tracker.track_construct((void*)p, sizeof(T), tag_); detail::tracker.track_construct((void*)p, sizeof(T), tag_);
new (p) T(boost::forward<Args>(args)...); new (p) T(boost::forward<Args>(args)...);
} }
#endif #endif
void destroy(T* p) void destroy(T* p)
{ {
detail::tracker.track_destroy((void*)p, sizeof(T), tag_); detail::tracker.track_destroy((void*)p, sizeof(T), tag_);
p->~T(); p->~T();
} }
size_type max_size() const size_type max_size() const
{ {
return (std::numeric_limits<size_type>::max)(); return (std::numeric_limits<size_type>::max)();
} }
}; };
template <typename T, typename Flags = propagate_swap, typename Enable = void> template <typename T, typename Flags = propagate_swap, typename Enable = void>
struct cxx11_allocator; struct cxx11_allocator;
template <typename T, typename Flags> template <typename T, typename Flags>
struct cxx11_allocator<T, Flags, struct cxx11_allocator<T, Flags,
typename boost::disable_if_c<Flags::is_select_on_copy>::type> typename boost::disable_if_c<Flags::is_select_on_copy>::type>
: public cxx11_allocator_base<T>, : public cxx11_allocator_base<T>,
public swap_allocator_base<Flags>, public swap_allocator_base<Flags>,
public assign_allocator_base<Flags>, public assign_allocator_base<Flags>,
public move_allocator_base<Flags>, public move_allocator_base<Flags>,
Flags Flags
{ {
#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 402000) #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 402000)
template <typename U> struct rebind template <typename U> struct rebind
{ {
typedef cxx11_allocator<U, Flags> other; typedef cxx11_allocator<U, Flags> other;
}; };
#endif #endif
@ -268,32 +268,32 @@ struct cxx11_allocator<T, Flags,
// to avoid undefined behaviour. // to avoid undefined behaviour.
bool operator==(cxx11_allocator const& x) const bool operator==(cxx11_allocator const& x) const
{ {
return force_equal_allocator_value || (this->tag_ == x.tag_); return force_equal_allocator_value || (this->tag_ == x.tag_);
} }
bool operator!=(cxx11_allocator const& x) const { return !(*this == x); } bool operator!=(cxx11_allocator const& x) const { return !(*this == x); }
}; };
template <typename T, typename Flags> template <typename T, typename Flags>
struct cxx11_allocator<T, Flags, struct cxx11_allocator<T, Flags,
typename boost::enable_if_c<Flags::is_select_on_copy>::type> typename boost::enable_if_c<Flags::is_select_on_copy>::type>
: public cxx11_allocator_base<T>, : public cxx11_allocator_base<T>,
public swap_allocator_base<Flags>, public swap_allocator_base<Flags>,
public assign_allocator_base<Flags>, public assign_allocator_base<Flags>,
public move_allocator_base<Flags>, public move_allocator_base<Flags>,
Flags Flags
{ {
cxx11_allocator select_on_container_copy_construction() const cxx11_allocator select_on_container_copy_construction() const
{ {
cxx11_allocator tmp(*this); cxx11_allocator tmp(*this);
++tmp.selected_; ++tmp.selected_;
return tmp; return tmp;
} }
#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 402000) #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 402000)
template <typename U> struct rebind template <typename U> struct rebind
{ {
typedef cxx11_allocator<U, Flags> other; typedef cxx11_allocator<U, Flags> other;
}; };
#endif #endif
@ -311,34 +311,34 @@ struct cxx11_allocator<T, Flags,
// to avoid undefined behaviour. // to avoid undefined behaviour.
bool operator==(cxx11_allocator const& x) const bool operator==(cxx11_allocator const& x) const
{ {
return force_equal_allocator_value || (this->tag_ == x.tag_); return force_equal_allocator_value || (this->tag_ == x.tag_);
} }
bool operator!=(cxx11_allocator const& x) const { return !(*this == x); } bool operator!=(cxx11_allocator const& x) const { return !(*this == x); }
}; };
template <typename T, typename Flags> template <typename T, typename Flags>
bool equivalent_impl(cxx11_allocator<T, Flags> const& x, bool equivalent_impl(cxx11_allocator<T, Flags> const& x,
cxx11_allocator<T, Flags> const& y, test::derived_type) cxx11_allocator<T, Flags> const& y, test::derived_type)
{ {
return x.tag_ == y.tag_; return x.tag_ == y.tag_;
} }
// Function to check how many times an allocator has been selected, // Function to check how many times an allocator has been selected,
// return 0 for other allocators. // return 0 for other allocators.
struct convert_from_anything struct convert_from_anything
{ {
template <typename T> convert_from_anything(T const&) {} template <typename T> convert_from_anything(T const&) {}
}; };
inline int selected_count(convert_from_anything) { return 0; } inline int selected_count(convert_from_anything) { return 0; }
template <typename T, typename Flags> template <typename T, typename Flags>
int selected_count(cxx11_allocator<T, Flags> const& x) int selected_count(cxx11_allocator<T, Flags> const& x)
{ {
return x.selected_; return x.selected_;
} }
} }
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -7,11 +7,11 @@
#define BOOST_UNORDERED_TEST_OBJECTS_FWD_HEADER #define BOOST_UNORDERED_TEST_OBJECTS_FWD_HEADER
namespace test { namespace test {
class object; class object;
class hash; class hash;
class less; class less;
class equal_to; class equal_to;
template <class T> class allocator; template <class T> class allocator;
} }
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -14,25 +14,25 @@
#include <cstddef> #include <cstddef>
namespace test { namespace test {
// Note that the default hash function will work for any equal_to (but not // Note that the default hash function will work for any equal_to (but not
// very well). // very well).
class object; class object;
class movable; class movable;
class implicitly_convertible; class implicitly_convertible;
class hash; class hash;
class less; class less;
class equal_to; class equal_to;
template <class T> class allocator1; template <class T> class allocator1;
template <class T> class allocator2; template <class T> class allocator2;
object generate(object const*, random_generator); object generate(object const*, random_generator);
movable generate(movable const*, random_generator); movable generate(movable const*, random_generator);
implicitly_convertible generate( implicitly_convertible generate(
implicitly_convertible const*, random_generator); implicitly_convertible const*, random_generator);
inline void ignore_variable(void const*) {} inline void ignore_variable(void const*) {}
class object : private counted_object class object : private counted_object
{ {
friend class hash; friend class hash;
friend class equal_to; friend class equal_to;
friend class less; friend class less;
@ -43,40 +43,40 @@ class object : private counted_object
~object() ~object()
{ {
tag1_ = -1; tag1_ = -1;
tag2_ = -1; tag2_ = -1;
} }
friend bool operator==(object const& x1, object const& x2) friend bool operator==(object const& x1, object const& x2)
{ {
return x1.tag1_ == x2.tag1_ && x1.tag2_ == x2.tag2_; return x1.tag1_ == x2.tag1_ && x1.tag2_ == x2.tag2_;
} }
friend bool operator!=(object const& x1, object const& x2) friend bool operator!=(object const& x1, object const& x2)
{ {
return x1.tag1_ != x2.tag1_ || x1.tag2_ != x2.tag2_; return x1.tag1_ != x2.tag1_ || x1.tag2_ != x2.tag2_;
} }
friend bool operator<(object const& x1, object const& x2) friend bool operator<(object const& x1, object const& x2)
{ {
return x1.tag1_ < x2.tag1_ || return x1.tag1_ < x2.tag1_ ||
(x1.tag1_ == x2.tag1_ && x1.tag2_ < x2.tag2_); (x1.tag1_ == x2.tag1_ && x1.tag2_ < x2.tag2_);
} }
friend object generate(object const*, random_generator g) friend object generate(object const*, random_generator g)
{ {
int* x = 0; int* x = 0;
return object(generate(x, g), generate(x, g)); return object(generate(x, g), generate(x, g));
} }
friend std::ostream& operator<<(std::ostream& out, object const& o) friend std::ostream& operator<<(std::ostream& out, object const& o)
{ {
return out << "(" << o.tag1_ << "," << o.tag2_ << ")"; return out << "(" << o.tag1_ << "," << o.tag2_ << ")";
} }
}; };
class movable : private counted_object class movable : private counted_object
{ {
friend class hash; friend class hash;
friend class equal_to; friend class equal_to;
friend class less; friend class less;
@ -89,74 +89,74 @@ class movable : private counted_object
movable(movable const& x) movable(movable const& x)
: counted_object(x), tag1_(x.tag1_), tag2_(x.tag2_) : counted_object(x), tag1_(x.tag1_), tag2_(x.tag2_)
{ {
BOOST_TEST(x.tag1_ != -1); BOOST_TEST(x.tag1_ != -1);
} }
movable(BOOST_RV_REF(movable) x) movable(BOOST_RV_REF(movable) x)
: counted_object(x), tag1_(x.tag1_), tag2_(x.tag2_) : counted_object(x), tag1_(x.tag1_), tag2_(x.tag2_)
{ {
BOOST_TEST(x.tag1_ != -1); BOOST_TEST(x.tag1_ != -1);
x.tag1_ = -1; x.tag1_ = -1;
x.tag2_ = -1; x.tag2_ = -1;
} }
movable& operator=(BOOST_COPY_ASSIGN_REF(movable) x) // Copy assignment movable& operator=(BOOST_COPY_ASSIGN_REF(movable) x) // Copy assignment
{ {
BOOST_TEST(x.tag1_ != -1); BOOST_TEST(x.tag1_ != -1);
tag1_ = x.tag1_; tag1_ = x.tag1_;
tag2_ = x.tag2_; tag2_ = x.tag2_;
return *this; return *this;
} }
movable& operator=(BOOST_RV_REF(movable) x) // Move assignment movable& operator=(BOOST_RV_REF(movable) x) // Move assignment
{ {
BOOST_TEST(x.tag1_ != -1); BOOST_TEST(x.tag1_ != -1);
tag1_ = x.tag1_; tag1_ = x.tag1_;
tag2_ = x.tag2_; tag2_ = x.tag2_;
x.tag1_ = -1; x.tag1_ = -1;
x.tag2_ = -1; x.tag2_ = -1;
return *this; return *this;
} }
~movable() ~movable()
{ {
tag1_ = -1; tag1_ = -1;
tag2_ = -1; tag2_ = -1;
} }
friend bool operator==(movable const& x1, movable const& x2) friend bool operator==(movable const& x1, movable const& x2)
{ {
BOOST_TEST(x1.tag1_ != -1 && x2.tag1_ != -1); BOOST_TEST(x1.tag1_ != -1 && x2.tag1_ != -1);
return x1.tag1_ == x2.tag1_ && x1.tag2_ == x2.tag2_; return x1.tag1_ == x2.tag1_ && x1.tag2_ == x2.tag2_;
} }
friend bool operator!=(movable const& x1, movable const& x2) friend bool operator!=(movable const& x1, movable const& x2)
{ {
BOOST_TEST(x1.tag1_ != -1 && x2.tag1_ != -1); BOOST_TEST(x1.tag1_ != -1 && x2.tag1_ != -1);
return x1.tag1_ != x2.tag1_ || x1.tag2_ != x2.tag2_; return x1.tag1_ != x2.tag1_ || x1.tag2_ != x2.tag2_;
} }
friend bool operator<(movable const& x1, movable const& x2) friend bool operator<(movable const& x1, movable const& x2)
{ {
BOOST_TEST(x1.tag1_ != -1 && x2.tag1_ != -1); BOOST_TEST(x1.tag1_ != -1 && x2.tag1_ != -1);
return x1.tag1_ < x2.tag1_ || return x1.tag1_ < x2.tag1_ ||
(x1.tag1_ == x2.tag1_ && x1.tag2_ < x2.tag2_); (x1.tag1_ == x2.tag1_ && x1.tag2_ < x2.tag2_);
} }
friend movable generate(movable const*, random_generator g) friend movable generate(movable const*, random_generator g)
{ {
int* x = 0; int* x = 0;
return movable(generate(x, g), generate(x, g)); return movable(generate(x, g), generate(x, g));
} }
friend std::ostream& operator<<(std::ostream& out, movable const& o) friend std::ostream& operator<<(std::ostream& out, movable const& o)
{ {
return out << "(" << o.tag1_ << "," << o.tag2_ << ")"; return out << "(" << o.tag1_ << "," << o.tag2_ << ")";
} }
}; };
class implicitly_convertible : private counted_object class implicitly_convertible : private counted_object
{ {
int tag1_, tag2_; int tag1_, tag2_;
public: public:
@ -170,22 +170,22 @@ class implicitly_convertible : private counted_object
operator movable() const { return movable(tag1_, tag2_); } operator movable() const { return movable(tag1_, tag2_); }
friend implicitly_convertible generate( friend implicitly_convertible generate(
implicitly_convertible const*, random_generator g) implicitly_convertible const*, random_generator g)
{ {
int* x = 0; int* x = 0;
return implicitly_convertible(generate(x, g), generate(x, g)); return implicitly_convertible(generate(x, g), generate(x, g));
} }
friend std::ostream& operator<<( friend std::ostream& operator<<(
std::ostream& out, implicitly_convertible const& o) std::ostream& out, implicitly_convertible const& o)
{ {
return out << "(" << o.tag1_ << "," << o.tag2_ << ")"; return out << "(" << o.tag1_ << "," << o.tag2_ << ")";
} }
}; };
// Note: This is a deliberately bad hash function. // Note: This is a deliberately bad hash function.
class hash class hash
{ {
int type_; int type_;
public: public:
@ -193,69 +193,69 @@ class hash
std::size_t operator()(object const& x) const std::size_t operator()(object const& x) const
{ {
int result; int result;
switch (type_) { switch (type_) {
case 1: case 1:
result = x.tag1_; result = x.tag1_;
break; break;
case 2: case 2:
result = x.tag2_; result = x.tag2_;
break; break;
default: default:
result = x.tag1_ + x.tag2_; result = x.tag1_ + x.tag2_;
} }
return static_cast<std::size_t>(result); return static_cast<std::size_t>(result);
} }
std::size_t operator()(movable const& x) const std::size_t operator()(movable const& x) const
{ {
int result; int result;
switch (type_) { switch (type_) {
case 1: case 1:
result = x.tag1_; result = x.tag1_;
break; break;
case 2: case 2:
result = x.tag2_; result = x.tag2_;
break; break;
default: default:
result = x.tag1_ + x.tag2_; result = x.tag1_ + x.tag2_;
} }
return static_cast<std::size_t>(result); return static_cast<std::size_t>(result);
} }
std::size_t operator()(int x) const std::size_t operator()(int x) const
{ {
int result; int result;
switch (type_) { switch (type_) {
case 1: case 1:
result = x; result = x;
break; break;
case 2: case 2:
result = x * 7; result = x * 7;
break; break;
default: default:
result = x * 256; result = x * 256;
} }
return static_cast<std::size_t>(result); return static_cast<std::size_t>(result);
} }
friend bool operator==(hash const& x1, hash const& x2) friend bool operator==(hash const& x1, hash const& x2)
{ {
return x1.type_ == x2.type_; return x1.type_ == x2.type_;
} }
friend bool operator!=(hash const& x1, hash const& x2) friend bool operator!=(hash const& x1, hash const& x2)
{ {
return x1.type_ != x2.type_; return x1.type_ != x2.type_;
} }
}; };
std::size_t hash_value(test::object const& x) { return hash()(x); } std::size_t hash_value(test::object const& x) { return hash()(x); }
std::size_t hash_value(test::movable const& x) { return hash()(x); } std::size_t hash_value(test::movable const& x) { return hash()(x); }
class less class less
{ {
int type_; int type_;
public: public:
@ -263,38 +263,38 @@ class less
bool operator()(object const& x1, object const& x2) const bool operator()(object const& x1, object const& x2) const
{ {
switch (type_) { switch (type_) {
case 1: case 1:
return x1.tag1_ < x2.tag1_; return x1.tag1_ < x2.tag1_;
case 2: case 2:
return x1.tag2_ < x2.tag2_; return x1.tag2_ < x2.tag2_;
default: default:
return x1 < x2; return x1 < x2;
} }
} }
bool operator()(movable const& x1, movable const& x2) const bool operator()(movable const& x1, movable const& x2) const
{ {
switch (type_) { switch (type_) {
case 1: case 1:
return x1.tag1_ < x2.tag1_; return x1.tag1_ < x2.tag1_;
case 2: case 2:
return x1.tag2_ < x2.tag2_; return x1.tag2_ < x2.tag2_;
default: default:
return x1 < x2; return x1 < x2;
} }
} }
std::size_t operator()(int x1, int x2) const { return x1 < x2; } std::size_t operator()(int x1, int x2) const { return x1 < x2; }
friend bool operator==(less const& x1, less const& x2) friend bool operator==(less const& x1, less const& x2)
{ {
return x1.type_ == x2.type_; return x1.type_ == x2.type_;
} }
}; };
class equal_to class equal_to
{ {
int type_; int type_;
public: public:
@ -302,48 +302,48 @@ class equal_to
bool operator()(object const& x1, object const& x2) const bool operator()(object const& x1, object const& x2) const
{ {
switch (type_) { switch (type_) {
case 1: case 1:
return x1.tag1_ == x2.tag1_; return x1.tag1_ == x2.tag1_;
case 2: case 2:
return x1.tag2_ == x2.tag2_; return x1.tag2_ == x2.tag2_;
default: default:
return x1 == x2; return x1 == x2;
} }
} }
bool operator()(movable const& x1, movable const& x2) const bool operator()(movable const& x1, movable const& x2) const
{ {
switch (type_) { switch (type_) {
case 1: case 1:
return x1.tag1_ == x2.tag1_; return x1.tag1_ == x2.tag1_;
case 2: case 2:
return x1.tag2_ == x2.tag2_; return x1.tag2_ == x2.tag2_;
default: default:
return x1 == x2; return x1 == x2;
} }
} }
std::size_t operator()(int x1, int x2) const { return x1 == x2; } std::size_t operator()(int x1, int x2) const { return x1 == x2; }
friend bool operator==(equal_to const& x1, equal_to const& x2) friend bool operator==(equal_to const& x1, equal_to const& x2)
{ {
return x1.type_ == x2.type_; return x1.type_ == x2.type_;
} }
friend bool operator!=(equal_to const& x1, equal_to const& x2) friend bool operator!=(equal_to const& x1, equal_to const& x2)
{ {
return x1.type_ != x2.type_; return x1.type_ != x2.type_;
} }
friend less create_compare(equal_to x) { return less(x.type_); } friend less create_compare(equal_to x) { return less(x.type_); }
}; };
// allocator1 only has the old fashioned 'construct' method and has // allocator1 only has the old fashioned 'construct' method and has
// a few less typedefs. allocator2 uses a custom pointer class. // a few less typedefs. allocator2 uses a custom pointer class.
template <class T> class allocator1 template <class T> class allocator1
{ {
public: public:
int tag_; int tag_;
@ -351,60 +351,60 @@ template <class T> class allocator1
template <class U> struct rebind template <class U> struct rebind
{ {
typedef allocator1<U> other; typedef allocator1<U> other;
}; };
explicit allocator1(int t = 0) : tag_(t) explicit allocator1(int t = 0) : tag_(t)
{ {
detail::tracker.allocator_ref(); detail::tracker.allocator_ref();
} }
template <class Y> allocator1(allocator1<Y> const& x) : tag_(x.tag_) template <class Y> allocator1(allocator1<Y> const& x) : tag_(x.tag_)
{ {
detail::tracker.allocator_ref(); detail::tracker.allocator_ref();
} }
allocator1(allocator1 const& x) : tag_(x.tag_) allocator1(allocator1 const& x) : tag_(x.tag_)
{ {
detail::tracker.allocator_ref(); detail::tracker.allocator_ref();
} }
~allocator1() { detail::tracker.allocator_unref(); } ~allocator1() { detail::tracker.allocator_unref(); }
T* allocate(std::size_t n) T* allocate(std::size_t n)
{ {
T* ptr(static_cast<T*>(::operator new(n * sizeof(T)))); T* ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_); detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_);
return ptr; return ptr;
} }
T* allocate(std::size_t n, void const*) T* allocate(std::size_t n, void const*)
{ {
T* ptr(static_cast<T*>(::operator new(n * sizeof(T)))); T* ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_); detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_);
return ptr; return ptr;
} }
void deallocate(T* p, std::size_t n) void deallocate(T* p, std::size_t n)
{ {
detail::tracker.track_deallocate((void*)p, n, sizeof(T), tag_); detail::tracker.track_deallocate((void*)p, n, sizeof(T), tag_);
::operator delete((void*)p); ::operator delete((void*)p);
} }
#if BOOST_UNORDERED_CXX11_CONSTRUCTION #if BOOST_UNORDERED_CXX11_CONSTRUCTION
template <typename U, typename... Args> void construct(U* p, Args&&... args) template <typename U, typename... Args> void construct(U* p, Args&&... args)
{ {
detail::tracker.track_construct((void*)p, sizeof(U), tag_); detail::tracker.track_construct((void*)p, sizeof(U), tag_);
new (p) U(boost::forward<Args>(args)...); new (p) U(boost::forward<Args>(args)...);
} }
template <typename U> void destroy(U* p) template <typename U> void destroy(U* p)
{ {
detail::tracker.track_destroy((void*)p, sizeof(U), tag_); detail::tracker.track_destroy((void*)p, sizeof(U), tag_);
p->~U(); p->~U();
// Work around MSVC buggy unused parameter warning. // Work around MSVC buggy unused parameter warning.
ignore_variable(&p); ignore_variable(&p);
} }
#else #else
private: private:
@ -429,18 +429,18 @@ template <class T> class allocator1
enum enum
{ {
is_select_on_copy = false, is_select_on_copy = false,
is_propagate_on_swap = false, is_propagate_on_swap = false,
is_propagate_on_assign = false, is_propagate_on_assign = false,
is_propagate_on_move = false is_propagate_on_move = false
}; };
}; };
template <class T> class ptr; template <class T> class ptr;
template <class T> class const_ptr; template <class T> class const_ptr;
struct void_ptr struct void_ptr
{ {
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename T> friend class ptr; template <typename T> friend class ptr;
@ -460,10 +460,10 @@ struct void_ptr
bool operator==(void_ptr const& x) const { return ptr_ == x.ptr_; } bool operator==(void_ptr const& x) const { return ptr_ == x.ptr_; }
bool operator!=(void_ptr const& x) const { return ptr_ != x.ptr_; } bool operator!=(void_ptr const& x) const { return ptr_ != x.ptr_; }
}; };
class void_const_ptr class void_const_ptr
{ {
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename T> friend class const_ptr; template <typename T> friend class const_ptr;
@ -486,10 +486,10 @@ class void_const_ptr
bool operator==(void_const_ptr const& x) const { return ptr_ == x.ptr_; } bool operator==(void_const_ptr const& x) const { return ptr_ == x.ptr_; }
bool operator!=(void_const_ptr const& x) const { return ptr_ != x.ptr_; } bool operator!=(void_const_ptr const& x) const { return ptr_ != x.ptr_; }
}; };
template <class T> class ptr template <class T> class ptr
{ {
friend class allocator2<T>; friend class allocator2<T>;
friend class const_ptr<T>; friend class const_ptr<T>;
friend struct void_ptr; friend struct void_ptr;
@ -505,14 +505,14 @@ template <class T> class ptr
T* operator->() const { return ptr_; } T* operator->() const { return ptr_; }
ptr& operator++() ptr& operator++()
{ {
++ptr_; ++ptr_;
return *this; return *this;
} }
ptr operator++(int) ptr operator++(int)
{ {
ptr tmp(*this); ptr tmp(*this);
++ptr_; ++ptr_;
return tmp; return tmp;
} }
ptr operator+(std::ptrdiff_t s) const { return ptr<T>(ptr_ + s); } ptr operator+(std::ptrdiff_t s) const { return ptr<T>(ptr_ + s); }
friend ptr operator+(std::ptrdiff_t s, ptr p) { return ptr<T>(s + p.ptr_); } friend ptr operator+(std::ptrdiff_t s, ptr p) { return ptr<T>(s + p.ptr_); }
@ -529,10 +529,10 @@ template <class T> class ptr
bool operator>(ptr const& x) const { return ptr_ > x.ptr_; } bool operator>(ptr const& x) const { return ptr_ > x.ptr_; }
bool operator<=(ptr const& x) const { return ptr_ <= x.ptr_; } bool operator<=(ptr const& x) const { return ptr_ <= x.ptr_; }
bool operator>=(ptr const& x) const { return ptr_ >= x.ptr_; } bool operator>=(ptr const& x) const { return ptr_ >= x.ptr_; }
}; };
template <class T> class const_ptr template <class T> class const_ptr
{ {
friend class allocator2<T>; friend class allocator2<T>;
friend struct const_void_ptr; friend struct const_void_ptr;
@ -548,19 +548,19 @@ template <class T> class const_ptr
T const* operator->() const { return ptr_; } T const* operator->() const { return ptr_; }
const_ptr& operator++() const_ptr& operator++()
{ {
++ptr_; ++ptr_;
return *this; return *this;
} }
const_ptr operator++(int) const_ptr operator++(int)
{ {
const_ptr tmp(*this); const_ptr tmp(*this);
++ptr_; ++ptr_;
return tmp; return tmp;
} }
const_ptr operator+(std::ptrdiff_t s) const { return const_ptr(ptr_ + s); } const_ptr operator+(std::ptrdiff_t s) const { return const_ptr(ptr_ + s); }
friend const_ptr operator+(std::ptrdiff_t s, const_ptr p) friend const_ptr operator+(std::ptrdiff_t s, const_ptr p)
{ {
return ptr<T>(s + p.ptr_); return ptr<T>(s + p.ptr_);
} }
T const& operator[](int s) const { return ptr_[s]; } T const& operator[](int s) const { return ptr_[s]; }
bool operator!() const { return !ptr_; } bool operator!() const { return !ptr_; }
@ -572,10 +572,10 @@ template <class T> class const_ptr
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_; } 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_; }
}; };
template <class T> class allocator2 template <class T> class allocator2
{ {
#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS #ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
public: public:
#else #else
@ -596,22 +596,22 @@ template <class T> class allocator2
template <class U> struct rebind template <class U> struct rebind
{ {
typedef allocator2<U> other; typedef allocator2<U> other;
}; };
explicit allocator2(int t = 0) : tag_(t) explicit allocator2(int t = 0) : tag_(t)
{ {
detail::tracker.allocator_ref(); detail::tracker.allocator_ref();
} }
template <class Y> allocator2(allocator2<Y> const& x) : tag_(x.tag_) template <class Y> allocator2(allocator2<Y> const& x) : tag_(x.tag_)
{ {
detail::tracker.allocator_ref(); detail::tracker.allocator_ref();
} }
allocator2(allocator2 const& x) : tag_(x.tag_) allocator2(allocator2 const& x) : tag_(x.tag_)
{ {
detail::tracker.allocator_ref(); detail::tracker.allocator_ref();
} }
~allocator2() { detail::tracker.allocator_unref(); } ~allocator2() { detail::tracker.allocator_unref(); }
@ -622,47 +622,47 @@ template <class T> class allocator2
pointer allocate(size_type n) pointer allocate(size_type n)
{ {
pointer p(static_cast<T*>(::operator new(n * sizeof(T)))); pointer p(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*)p.ptr_, n, sizeof(T), tag_); detail::tracker.track_allocate((void*)p.ptr_, n, sizeof(T), tag_);
return p; return p;
} }
pointer allocate(size_type n, void const*) pointer allocate(size_type n, void const*)
{ {
pointer ptr(static_cast<T*>(::operator new(n * sizeof(T)))); pointer ptr(static_cast<T*>(::operator new(n * sizeof(T))));
detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_); detail::tracker.track_allocate((void*)ptr, n, sizeof(T), tag_);
return ptr; return ptr;
} }
void deallocate(pointer p, size_type n) void deallocate(pointer p, size_type n)
{ {
detail::tracker.track_deallocate((void*)p.ptr_, n, sizeof(T), tag_); detail::tracker.track_deallocate((void*)p.ptr_, n, sizeof(T), tag_);
::operator delete((void*)p.ptr_); ::operator delete((void*)p.ptr_);
} }
void construct(T* p, T const& t) void construct(T* p, T const& t)
{ {
detail::tracker.track_construct((void*)p, sizeof(T), tag_); detail::tracker.track_construct((void*)p, sizeof(T), tag_);
new (p) T(t); new (p) T(t);
} }
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) template <class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args)
{ {
detail::tracker.track_construct((void*)p, sizeof(T), tag_); detail::tracker.track_construct((void*)p, sizeof(T), tag_);
new (p) T(boost::forward<Args>(args)...); new (p) T(boost::forward<Args>(args)...);
} }
#endif #endif
void destroy(T* p) void destroy(T* p)
{ {
detail::tracker.track_destroy((void*)p, sizeof(T), tag_); detail::tracker.track_destroy((void*)p, sizeof(T), tag_);
p->~T(); p->~T();
} }
size_type max_size() const size_type max_size() const
{ {
return (std::numeric_limits<size_type>::max)(); return (std::numeric_limits<size_type>::max)();
} }
bool operator==(allocator2 const& x) const { return tag_ == x.tag_; } bool operator==(allocator2 const& x) const { return tag_ == x.tag_; }
@ -671,26 +671,26 @@ template <class T> class allocator2
enum enum
{ {
is_select_on_copy = false, is_select_on_copy = false,
is_propagate_on_swap = false, is_propagate_on_swap = false,
is_propagate_on_assign = false, is_propagate_on_assign = false,
is_propagate_on_move = false is_propagate_on_move = false
}; };
}; };
template <class T> template <class T>
bool equivalent_impl( bool equivalent_impl(
allocator1<T> const& x, allocator1<T> const& y, test::derived_type) allocator1<T> const& x, allocator1<T> const& y, test::derived_type)
{ {
return x == y; return x == y;
} }
template <class T> template <class T>
bool equivalent_impl( bool equivalent_impl(
allocator2<T> const& x, allocator2<T> const& y, test::derived_type) allocator2<T> const& x, allocator2<T> const& y, test::derived_type)
{ {
return x == y; return x == y;
} }
} }
#endif #endif

View File

@ -12,76 +12,76 @@
// Boilerplate // Boilerplate
#define ALLOCATOR_METHODS(name) \ #define ALLOCATOR_METHODS(name) \
template <typename U> struct rebind \ template <typename U> struct rebind \
{ \ { \
typedef name<U> other; \ typedef name<U> other; \
}; \ }; \
\ \
name() {} \ name() {} \
template <typename Y> name(name<Y> const&) {} \ template <typename Y> name(name<Y> const&) {} \
T* address(T& r) { return &r; } \ T* address(T& r) { return &r; } \
T const* address(T const& r) { return &r; } \ T const* address(T const& r) { return &r; } \
T* allocate(std::size_t n) \ T* allocate(std::size_t n) \
{ \ { \
return static_cast<T*>(::operator new(n * sizeof(T))); \ return static_cast<T*>(::operator new(n * sizeof(T))); \
} \ } \
T* allocate(std::size_t n, void const*) \ T* allocate(std::size_t n, void const*) \
{ \ { \
return static_cast<T*>(::operator new(n * sizeof(T))); \ return static_cast<T*>(::operator new(n * sizeof(T))); \
} \ } \
void deallocate(T* p, std::size_t) { ::operator delete((void*)p); } \ void deallocate(T* p, std::size_t) { ::operator delete((void*)p); } \
void construct(T* p, T const& t) { new (p) T(t); } \ void construct(T* p, T const& t) { new (p) T(t); } \
void destroy(T* p) { p->~T(); } \ void destroy(T* p) { p->~T(); } \
std::size_t max_size() const \ std::size_t max_size() const \
{ \ { \
return (std::numeric_limits<std::size_t>::max)(); \ return (std::numeric_limits<std::size_t>::max)(); \
} \ } \
bool operator==(name<T> const&) { return true; } \ bool operator==(name<T> const&) { return true; } \
bool operator!=(name<T> const&) { return false; } \ bool operator!=(name<T> const&) { return false; } \
/**/ /**/
#define ALLOCATOR_METHODS_TYPEDEFS(name) \ #define ALLOCATOR_METHODS_TYPEDEFS(name) \
template <typename U> struct rebind \ template <typename U> struct rebind \
{ \ { \
typedef name<U> other; \ typedef name<U> other; \
}; \ }; \
\ \
name() {} \ name() {} \
template <typename Y> name(name<Y> const&) {} \ template <typename Y> name(name<Y> const&) {} \
pointer address(T& r) { return &r; } \ pointer address(T& r) { return &r; } \
const_pointer address(T const& r) { return &r; } \ const_pointer address(T const& r) { return &r; } \
pointer allocate(std::size_t n) \ pointer allocate(std::size_t n) \
{ \ { \
return pointer(::operator new(n * sizeof(T))); \ return pointer(::operator new(n * sizeof(T))); \
} \ } \
pointer allocate(std::size_t n, void const*) \ pointer allocate(std::size_t n, void const*) \
{ \ { \
return pointer(::operator new(n * sizeof(T))); \ return pointer(::operator new(n * sizeof(T))); \
} \ } \
void deallocate(pointer p, std::size_t) { ::operator delete((void*)p); } \ void deallocate(pointer p, std::size_t) { ::operator delete((void*)p); } \
void construct(T* p, T const& t) { new (p) T(t); } \ void construct(T* p, T const& t) { new (p) T(t); } \
void destroy(T* p) { p->~T(); } \ void destroy(T* p) { p->~T(); } \
size_type max_size() const \ size_type max_size() const \
{ \ { \
return (std::numeric_limits<size_type>::max)(); \ return (std::numeric_limits<size_type>::max)(); \
} \ } \
bool operator==(name<T> const&) { return true; } \ bool operator==(name<T> const&) { return true; } \
bool operator!=(name<T> const&) { return false; } \ bool operator!=(name<T> const&) { return false; } \
/**/ /**/
struct yes_type struct yes_type
{ {
enum enum
{ {
value = true value = true
}; };
}; };
struct no_type struct no_type
{ {
enum enum
{ {
value = false value = false
}; };
}; };
// For tracking calls... // For tracking calls...
@ -91,193 +91,190 @@ void reset() { selected = 0; }
template <typename Allocator> int call_select() template <typename Allocator> int call_select()
{ {
typedef boost::unordered::detail::allocator_traits<Allocator> traits; typedef boost::unordered::detail::allocator_traits<Allocator> traits;
Allocator a; Allocator a;
reset(); reset();
BOOST_TEST(traits::select_on_container_copy_construction(a) == a); BOOST_TEST(traits::select_on_container_copy_construction(a) == a);
return selected; return selected;
} }
// Empty allocator test // Empty allocator test
template <typename T> struct empty_allocator template <typename T> struct empty_allocator
{ {
typedef T value_type; typedef T value_type;
ALLOCATOR_METHODS(empty_allocator) ALLOCATOR_METHODS(empty_allocator)
}; };
void test_empty_allocator() void test_empty_allocator()
{ {
typedef empty_allocator<int> allocator; typedef empty_allocator<int> allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits; typedef boost::unordered::detail::allocator_traits<allocator> traits;
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1 #if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, BOOST_STATIC_ASSERT((boost::is_same<traits::size_type,
std::make_unsigned<std::ptrdiff_t>::type>::value)); std::make_unsigned<std::ptrdiff_t>::type>::value));
#else #else
BOOST_STATIC_ASSERT( BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, std::size_t>::value));
(boost::is_same<traits::size_type, std::size_t>::value));
#endif #endif
BOOST_STATIC_ASSERT( BOOST_STATIC_ASSERT(
(boost::is_same<traits::difference_type, std::ptrdiff_t>::value)); (boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value)); BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value));
BOOST_STATIC_ASSERT( BOOST_STATIC_ASSERT(
(boost::is_same<traits::const_pointer, int const*>::value)); (boost::is_same<traits::const_pointer, int const*>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value)); BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
BOOST_TEST(!traits::propagate_on_container_copy_assignment::value); BOOST_TEST(!traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(!traits::propagate_on_container_move_assignment::value); BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
BOOST_TEST(!traits::propagate_on_container_swap::value); BOOST_TEST(!traits::propagate_on_container_swap::value);
BOOST_TEST(call_select<allocator>() == 0); BOOST_TEST(call_select<allocator>() == 0);
} }
// allocator 1 // allocator 1
template <typename T> struct allocator1 template <typename T> struct allocator1
{ {
typedef T value_type; typedef T value_type;
ALLOCATOR_METHODS(allocator1) ALLOCATOR_METHODS(allocator1)
typedef yes_type propagate_on_container_copy_assignment; typedef yes_type propagate_on_container_copy_assignment;
typedef yes_type propagate_on_container_move_assignment; typedef yes_type propagate_on_container_move_assignment;
typedef yes_type propagate_on_container_swap; typedef yes_type propagate_on_container_swap;
allocator1<T> select_on_container_copy_construction() const allocator1<T> select_on_container_copy_construction() const
{ {
++selected; ++selected;
return allocator1<T>(); return allocator1<T>();
} }
}; };
void test_allocator1() void test_allocator1()
{ {
typedef allocator1<int> allocator; typedef allocator1<int> allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits; typedef boost::unordered::detail::allocator_traits<allocator> traits;
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1 #if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, BOOST_STATIC_ASSERT((boost::is_same<traits::size_type,
std::make_unsigned<std::ptrdiff_t>::type>::value)); std::make_unsigned<std::ptrdiff_t>::type>::value));
#else #else
BOOST_STATIC_ASSERT( BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, std::size_t>::value));
(boost::is_same<traits::size_type, std::size_t>::value));
#endif #endif
BOOST_STATIC_ASSERT( BOOST_STATIC_ASSERT(
(boost::is_same<traits::difference_type, std::ptrdiff_t>::value)); (boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value)); BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value));
BOOST_STATIC_ASSERT( BOOST_STATIC_ASSERT(
(boost::is_same<traits::const_pointer, int const*>::value)); (boost::is_same<traits::const_pointer, int const*>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value)); BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
BOOST_TEST(traits::propagate_on_container_copy_assignment::value); BOOST_TEST(traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(traits::propagate_on_container_move_assignment::value); BOOST_TEST(traits::propagate_on_container_move_assignment::value);
BOOST_TEST(traits::propagate_on_container_swap::value); BOOST_TEST(traits::propagate_on_container_swap::value);
BOOST_TEST(call_select<allocator>() == 1); BOOST_TEST(call_select<allocator>() == 1);
} }
// allocator 2 // allocator 2
template <typename Alloc> struct allocator2_base template <typename Alloc> struct allocator2_base
{ {
Alloc select_on_container_copy_construction() const Alloc select_on_container_copy_construction() const
{ {
++selected; ++selected;
return Alloc(); return Alloc();
} }
}; };
template <typename T> struct allocator2 : allocator2_base<allocator2<T> > template <typename T> struct allocator2 : allocator2_base<allocator2<T> >
{ {
typedef T value_type; typedef T value_type;
typedef T* pointer; typedef T* pointer;
typedef T const* const_pointer; typedef T const* const_pointer;
typedef std::size_t size_type; typedef std::size_t size_type;
ALLOCATOR_METHODS(allocator2) ALLOCATOR_METHODS(allocator2)
typedef no_type propagate_on_container_copy_assignment; typedef no_type propagate_on_container_copy_assignment;
typedef no_type propagate_on_container_move_assignment; typedef no_type propagate_on_container_move_assignment;
typedef no_type propagate_on_container_swap; typedef no_type propagate_on_container_swap;
}; };
void test_allocator2() void test_allocator2()
{ {
typedef allocator2<int> allocator; typedef allocator2<int> allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits; typedef boost::unordered::detail::allocator_traits<allocator> traits;
BOOST_STATIC_ASSERT( BOOST_STATIC_ASSERT((boost::is_same<traits::size_type, std::size_t>::value));
(boost::is_same<traits::size_type, std::size_t>::value)); BOOST_STATIC_ASSERT(
BOOST_STATIC_ASSERT( (boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
(boost::is_same<traits::difference_type, std::ptrdiff_t>::value)); BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, int*>::value)); BOOST_STATIC_ASSERT(
BOOST_STATIC_ASSERT( (boost::is_same<traits::const_pointer, int const*>::value));
(boost::is_same<traits::const_pointer, int const*>::value)); BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value)); BOOST_TEST(!traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(!traits::propagate_on_container_copy_assignment::value); BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
BOOST_TEST(!traits::propagate_on_container_move_assignment::value); BOOST_TEST(!traits::propagate_on_container_swap::value);
BOOST_TEST(!traits::propagate_on_container_swap::value); BOOST_TEST(call_select<allocator>() == 1);
BOOST_TEST(call_select<allocator>() == 1);
} }
// allocator 3 // allocator 3
template <typename T> struct ptr template <typename T> struct ptr
{ {
T* value_; T* value_;
ptr(void* v) : value_((T*)v) {} ptr(void* v) : value_((T*)v) {}
T& operator*() const { return *value_; } T& operator*() const { return *value_; }
}; };
template <> struct ptr<void> template <> struct ptr<void>
{ {
void* value_; void* value_;
ptr(void* v) : value_(v) {} ptr(void* v) : value_(v) {}
}; };
template <> struct ptr<const void> template <> struct ptr<const void>
{ {
void const* value_; void const* value_;
ptr(void const* v) : value_(v) {} ptr(void const* v) : value_(v) {}
}; };
template <typename T> struct allocator3 template <typename T> struct allocator3
{ {
typedef T value_type; typedef T value_type;
typedef ptr<T> pointer; typedef ptr<T> pointer;
typedef ptr<T const> const_pointer; typedef ptr<T const> const_pointer;
typedef unsigned short size_type; typedef unsigned short size_type;
ALLOCATOR_METHODS_TYPEDEFS(allocator3) ALLOCATOR_METHODS_TYPEDEFS(allocator3)
typedef yes_type propagate_on_container_copy_assignment; typedef yes_type propagate_on_container_copy_assignment;
typedef no_type propagate_on_container_move_assignment; typedef no_type propagate_on_container_move_assignment;
allocator3<T> select_on_container_copy_construction() const allocator3<T> select_on_container_copy_construction() const
{ {
++selected; ++selected;
return allocator3<T>(); return allocator3<T>();
} }
}; };
void test_allocator3() void test_allocator3()
{ {
typedef allocator3<int> allocator; typedef allocator3<int> allocator;
typedef boost::unordered::detail::allocator_traits<allocator> traits; typedef boost::unordered::detail::allocator_traits<allocator> traits;
BOOST_STATIC_ASSERT( BOOST_STATIC_ASSERT(
(boost::is_same<traits::size_type, unsigned short>::value)); (boost::is_same<traits::size_type, unsigned short>::value));
BOOST_STATIC_ASSERT( BOOST_STATIC_ASSERT(
(boost::is_same<traits::difference_type, std::ptrdiff_t>::value)); (boost::is_same<traits::difference_type, std::ptrdiff_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, ptr<int> >::value)); BOOST_STATIC_ASSERT((boost::is_same<traits::pointer, ptr<int> >::value));
BOOST_STATIC_ASSERT( BOOST_STATIC_ASSERT(
(boost::is_same<traits::const_pointer, ptr<int const> >::value)); (boost::is_same<traits::const_pointer, ptr<int const> >::value));
BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value)); BOOST_STATIC_ASSERT((boost::is_same<traits::value_type, int>::value));
BOOST_TEST(traits::propagate_on_container_copy_assignment::value); BOOST_TEST(traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(!traits::propagate_on_container_move_assignment::value); BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
BOOST_TEST(!traits::propagate_on_container_swap::value); BOOST_TEST(!traits::propagate_on_container_swap::value);
BOOST_TEST(call_select<allocator>() == 1); BOOST_TEST(call_select<allocator>() == 1);
} }
int main() int main()
{ {
test_empty_allocator(); test_empty_allocator();
test_allocator1(); test_allocator1();
test_allocator2(); test_allocator2();
test_allocator3(); test_allocator3();
return boost::report_errors(); return boost::report_errors();
} }

View File

@ -23,51 +23,51 @@
namespace assign_tests { namespace assign_tests {
test::seed_t initialize_seed(96785); test::seed_t initialize_seed(96785);
template <class T> void assign_tests1(T*, test::random_generator generator) template <class T> void assign_tests1(T*, test::random_generator generator)
{ {
BOOST_DEDUCED_TYPENAME T::hasher hf; BOOST_DEDUCED_TYPENAME T::hasher hf;
BOOST_DEDUCED_TYPENAME T::key_equal eq; BOOST_DEDUCED_TYPENAME T::key_equal eq;
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests1.1\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests1.1\n";
{ {
test::check_instances check_; test::check_instances check_;
T x; T x;
x = x; x = x;
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_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests1.2\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests1.2\n";
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<T> v(1000, generator); test::random_values<T> v(1000, generator);
T x(v.begin(), v.end()); T x(v.begin(), v.end());
test::ordered<T> tracker = test::create_ordered(x); test::ordered<T> tracker = test::create_ordered(x);
tracker.insert_range(v.begin(), v.end()); tracker.insert_range(v.begin(), v.end());
x = x; x = x;
tracker.compare(x); tracker.compare(x);
T y; T y;
y.max_load_factor(x.max_load_factor() / 20); y.max_load_factor(x.max_load_factor() / 20);
float mlf = x.max_load_factor(); float mlf = x.max_load_factor();
y = x; y = x;
tracker.compare(x); tracker.compare(x);
tracker.compare(y); tracker.compare(y);
BOOST_TEST(x.max_load_factor() == mlf); BOOST_TEST(x.max_load_factor() == mlf);
BOOST_TEST(y.max_load_factor() == mlf); BOOST_TEST(y.max_load_factor() == mlf);
BOOST_TEST(y.load_factor() <= y.max_load_factor()); BOOST_TEST(y.load_factor() <= y.max_load_factor());
} }
} }
template <class T> void assign_tests2(T*, test::random_generator generator) template <class T> void assign_tests2(T*, test::random_generator generator)
{ {
BOOST_DEDUCED_TYPENAME T::hasher hf1(1); BOOST_DEDUCED_TYPENAME T::hasher hf1(1);
BOOST_DEDUCED_TYPENAME T::hasher hf2(2); BOOST_DEDUCED_TYPENAME T::hasher hf2(2);
BOOST_DEDUCED_TYPENAME T::key_equal eq1(1); BOOST_DEDUCED_TYPENAME T::key_equal eq1(1);
@ -79,196 +79,196 @@ template <class T> void assign_tests2(T*, test::random_generator generator)
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.0 - empty container\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.0 - empty container\n";
{ {
test::check_instances check_; test::check_instances check_;
T x1(0, hf1, eq1); T x1(0, hf1, eq1);
T x2(0, hf2, eq2); T x2(0, hf2, eq2);
x2 = x1; x2 = x1;
BOOST_TEST(test::equivalent(x1.hash_function(), hf1)); BOOST_TEST(test::equivalent(x1.hash_function(), hf1));
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));
test::check_container(x1, x2); test::check_container(x1, x2);
} }
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.1\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.1\n";
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<T> v(1000, generator); test::random_values<T> v(1000, generator);
T x1(v.begin(), v.end(), 0, hf1, eq1); T x1(v.begin(), v.end(), 0, hf1, eq1);
T x2(0, hf2, eq2); T x2(0, hf2, eq2);
x2 = x1; x2 = x1;
BOOST_TEST(test::equivalent(x1.hash_function(), hf1)); BOOST_TEST(test::equivalent(x1.hash_function(), hf1));
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));
test::check_container(x1, v); test::check_container(x1, v);
test::check_container(x2, v); test::check_container(x2, v);
BOOST_TEST(x2.load_factor() <= x2.max_load_factor()); BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
} }
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.1a\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.1a\n";
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<T> v1(0, generator); test::random_values<T> v1(0, generator);
test::random_values<T> v2(1000, generator); test::random_values<T> v2(1000, generator);
T x1(0, hf2, eq2); T x1(0, hf2, eq2);
T x2(v2.begin(), v2.end(), 0, hf1, eq1); T x2(v2.begin(), v2.end(), 0, hf1, eq1);
x2 = x1; x2 = x1;
BOOST_TEST(test::equivalent(x1.hash_function(), hf2)); BOOST_TEST(test::equivalent(x1.hash_function(), hf2));
BOOST_TEST(test::equivalent(x1.key_eq(), eq2)); BOOST_TEST(test::equivalent(x1.key_eq(), eq2));
BOOST_TEST(test::equivalent(x2.hash_function(), hf2)); BOOST_TEST(test::equivalent(x2.hash_function(), hf2));
BOOST_TEST(test::equivalent(x2.key_eq(), eq2)); BOOST_TEST(test::equivalent(x2.key_eq(), eq2));
test::check_container(x1, v1); test::check_container(x1, v1);
test::check_container(x2, v1); test::check_container(x2, v1);
BOOST_TEST(x2.load_factor() <= x2.max_load_factor()); BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
} }
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.2\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.2\n";
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<T> v1(100, generator), v2(100, generator); test::random_values<T> v1(100, generator), v2(100, generator);
T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1); T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1);
T x2(v2.begin(), v2.end(), 0, hf2, eq2, al2); T x2(v2.begin(), v2.end(), 0, hf2, eq2, al2);
x2 = x1; x2 = x1;
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));
if (allocator_type::is_propagate_on_assign) { if (allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(x2.get_allocator(), al1)); BOOST_TEST(test::equivalent(x2.get_allocator(), al1));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al2)); BOOST_TEST(!test::equivalent(x2.get_allocator(), al2));
} else { } else {
BOOST_TEST(test::equivalent(x2.get_allocator(), al2)); BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al1)); BOOST_TEST(!test::equivalent(x2.get_allocator(), al1));
} }
test::check_container(x1, v1); test::check_container(x1, v1);
test::check_container(x2, v1); test::check_container(x2, v1);
BOOST_TEST(x2.load_factor() <= x2.max_load_factor()); BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
} }
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.3\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.3\n";
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<T> v1(100, generator), v2(1000, generator); test::random_values<T> v1(100, generator), v2(1000, generator);
T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1); T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1);
T x2(v2.begin(), v2.end(), 0, hf2, eq2, al2); T x2(v2.begin(), v2.end(), 0, hf2, eq2, al2);
x2 = x1; x2 = x1;
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));
if (allocator_type::is_propagate_on_assign) { if (allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(x2.get_allocator(), al1)); BOOST_TEST(test::equivalent(x2.get_allocator(), al1));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al2)); BOOST_TEST(!test::equivalent(x2.get_allocator(), al2));
} else { } else {
BOOST_TEST(test::equivalent(x2.get_allocator(), al2)); BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al1)); BOOST_TEST(!test::equivalent(x2.get_allocator(), al1));
} }
test::check_container(x1, v1); test::check_container(x1, v1);
test::check_container(x2, v1); test::check_container(x2, v1);
BOOST_TEST(x2.load_factor() <= x2.max_load_factor()); BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
} }
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.4\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "assign_tests2.4\n";
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<T> v1(1000, generator), v2(100, generator); test::random_values<T> v1(1000, generator), v2(100, generator);
T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1); T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1);
T x2(v2.begin(), v2.end(), 0, hf2, eq2, al2); T x2(v2.begin(), v2.end(), 0, hf2, eq2, al2);
x2 = x1; x2 = x1;
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));
if (allocator_type::is_propagate_on_assign) { if (allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(x2.get_allocator(), al1)); BOOST_TEST(test::equivalent(x2.get_allocator(), al1));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al2)); BOOST_TEST(!test::equivalent(x2.get_allocator(), al2));
} else { } else {
BOOST_TEST(test::equivalent(x2.get_allocator(), al2)); BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
BOOST_TEST(!test::equivalent(x2.get_allocator(), al1)); BOOST_TEST(!test::equivalent(x2.get_allocator(), al1));
} }
test::check_container(x1, v1); test::check_container(x1, v1);
test::check_container(x2, v1); test::check_container(x2, v1);
BOOST_TEST(x2.load_factor() <= x2.max_load_factor()); BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
} }
} }
boost::unordered_map<test::object, test::object, test::hash, test::equal_to, boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
std::allocator<test::object> >* test_map_std_alloc; std::allocator<test::object> >* test_map_std_alloc;
boost::unordered_set<test::object, test::hash, test::equal_to, boost::unordered_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set; test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to, boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset; test::allocator2<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to, boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_map; test::allocator2<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash, boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator1<test::object> >* test_multimap; test::equal_to, test::allocator1<test::object> >* test_multimap;
boost::unordered_set<test::object, test::hash, test::equal_to, boost::unordered_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_assign> >* test::cxx11_allocator<test::object, test::propagate_assign> >*
test_set_prop_assign; test_set_prop_assign;
boost::unordered_multiset<test::object, test::hash, test::equal_to, boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_assign> >* test::cxx11_allocator<test::object, test::propagate_assign> >*
test_multiset_prop_assign; test_multiset_prop_assign;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to, boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_assign> >* test::cxx11_allocator<test::object, test::propagate_assign> >*
test_map_prop_assign; test_map_prop_assign;
boost::unordered_multimap<test::object, test::object, test::hash, boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_assign> >* test::cxx11_allocator<test::object, test::propagate_assign> >*
test_multimap_prop_assign; test_multimap_prop_assign;
boost::unordered_set<test::object, test::hash, test::equal_to, boost::unordered_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_assign> >* test::cxx11_allocator<test::object, test::no_propagate_assign> >*
test_set_no_prop_assign; test_set_no_prop_assign;
boost::unordered_multiset<test::object, test::hash, test::equal_to, boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_assign> >* test::cxx11_allocator<test::object, test::no_propagate_assign> >*
test_multiset_no_prop_assign; test_multiset_no_prop_assign;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to, boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_assign> >* test::cxx11_allocator<test::object, test::no_propagate_assign> >*
test_map_no_prop_assign; test_map_no_prop_assign;
boost::unordered_multimap<test::object, test::object, test::hash, boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_assign> >* test::cxx11_allocator<test::object, test::no_propagate_assign> >*
test_multimap_no_prop_assign; test_multimap_no_prop_assign;
using test::default_generator; using test::default_generator;
using test::generate_collisions; using test::generate_collisions;
using test::limited_range; using test::limited_range;
template <typename T> bool is_propagate(T*) template <typename T> bool is_propagate(T*)
{ {
return T::allocator_type::is_propagate_on_assign; return T::allocator_type::is_propagate_on_assign;
} }
UNORDERED_AUTO_TEST(check_traits) UNORDERED_AUTO_TEST(check_traits)
{ {
BOOST_TEST(!is_propagate(test_set)); BOOST_TEST(!is_propagate(test_set));
BOOST_TEST(is_propagate(test_set_prop_assign)); BOOST_TEST(is_propagate(test_set_prop_assign));
BOOST_TEST(!is_propagate(test_set_no_prop_assign)); BOOST_TEST(!is_propagate(test_set_no_prop_assign));
} }
UNORDERED_TEST(assign_tests1, UNORDERED_TEST(assign_tests1,
((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap)( ((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap)(
test_set_prop_assign)(test_multiset_prop_assign)(test_map_prop_assign)( test_set_prop_assign)(test_multiset_prop_assign)(test_map_prop_assign)(
test_multimap_prop_assign)(test_set_no_prop_assign)( test_multimap_prop_assign)(test_set_no_prop_assign)(
test_multiset_no_prop_assign)(test_map_no_prop_assign)( test_multiset_no_prop_assign)(test_map_no_prop_assign)(
test_multimap_no_prop_assign))( test_multimap_no_prop_assign))(
(default_generator)(generate_collisions)(limited_range))) (default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST( UNORDERED_TEST(
assign_tests2, ((test_set)(test_multiset)(test_map)(test_multimap)( assign_tests2, ((test_set)(test_multiset)(test_map)(test_multimap)(
test_set_prop_assign)(test_multiset_prop_assign)( test_set_prop_assign)(test_multiset_prop_assign)(
test_map_prop_assign)(test_multimap_prop_assign)( test_map_prop_assign)(test_multimap_prop_assign)(
test_set_no_prop_assign)(test_multiset_no_prop_assign)( test_set_no_prop_assign)(test_multiset_no_prop_assign)(
test_map_no_prop_assign)(test_multimap_no_prop_assign))( test_map_no_prop_assign)(test_multimap_no_prop_assign))(
(default_generator)(generate_collisions)(limited_range))) (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(assign_default_initializer_list) UNORDERED_AUTO_TEST(assign_default_initializer_list)
{ {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Initializer List Tests\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Initializer List Tests\n";
std::initializer_list<std::pair<int const, int> > init; std::initializer_list<std::pair<int const, int> > init;
boost::unordered_map<int, int> x1; boost::unordered_map<int, int> x1;
@ -277,13 +277,13 @@ UNORDERED_AUTO_TEST(assign_default_initializer_list)
BOOST_TEST(!x1.empty()); BOOST_TEST(!x1.empty());
x1 = init; x1 = init;
BOOST_TEST(x1.empty()); BOOST_TEST(x1.empty());
} }
#endif #endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST(assign_initializer_list) UNORDERED_AUTO_TEST(assign_initializer_list)
{ {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Initializer List Tests\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Initializer List Tests\n";
boost::unordered_set<int> x; boost::unordered_set<int> x;
@ -292,7 +292,7 @@ UNORDERED_AUTO_TEST(assign_initializer_list)
x = {1, 2, -10}; x = {1, 2, -10};
BOOST_TEST(x.find(10) == x.end()); BOOST_TEST(x.find(10) == x.end());
BOOST_TEST(x.find(-10) != x.end()); BOOST_TEST(x.find(-10) != x.end());
} }
#endif #endif
} }

View File

@ -14,8 +14,8 @@
namespace at_tests { namespace at_tests {
UNORDERED_AUTO_TEST(at_tests) UNORDERED_AUTO_TEST(at_tests)
{ {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Create Map" << std::endl; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Create Map" << std::endl;
boost::unordered_map<std::string, int> x; boost::unordered_map<std::string, int> x;
@ -24,14 +24,14 @@ UNORDERED_AUTO_TEST(at_tests)
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Check empty container" << std::endl; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Check empty container" << std::endl;
try { try {
x.at("one"); x.at("one");
BOOST_ERROR("Should have thrown."); BOOST_ERROR("Should have thrown.");
} catch (std::out_of_range) { } catch (std::out_of_range) {
} }
try { try {
x_const.at("one"); x_const.at("one");
BOOST_ERROR("Should have thrown."); BOOST_ERROR("Should have thrown.");
} catch (std::out_of_range) { } catch (std::out_of_range) {
} }
@ -50,19 +50,19 @@ UNORDERED_AUTO_TEST(at_tests)
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Check missing element" << std::endl; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Check missing element" << std::endl;
try { try {
x.at("three"); x.at("three");
BOOST_ERROR("Should have thrown."); BOOST_ERROR("Should have thrown.");
} catch (std::out_of_range) { } catch (std::out_of_range) {
} }
try { try {
x_const.at("three"); x_const.at("three");
BOOST_ERROR("Should have thrown."); BOOST_ERROR("Should have thrown.");
} catch (std::out_of_range) { } catch (std::out_of_range) {
} }
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Finished" << std::endl; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Finished" << std::endl;
} }
} }
RUN_TESTS() RUN_TESTS()

View File

@ -23,10 +23,10 @@
namespace bucket_tests { namespace bucket_tests {
test::seed_t initialize_seed(54635); test::seed_t initialize_seed(54635);
template <class X> void tests(X*, test::random_generator generator) template <class X> void tests(X*, test::random_generator generator)
{ {
test::check_instances check_; test::check_instances check_;
typedef BOOST_DEDUCED_TYPENAME X::size_type size_type; typedef BOOST_DEDUCED_TYPENAME X::size_type size_type;
@ -37,60 +37,59 @@ template <class X> void tests(X*, test::random_generator generator)
BOOST_TEST(x.bucket_count() <= x.max_bucket_count()); BOOST_TEST(x.bucket_count() <= x.max_bucket_count());
if (!(x.bucket_count() <= x.max_bucket_count())) { if (!(x.bucket_count() <= x.max_bucket_count())) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << x.bucket_count() BOOST_LIGHTWEIGHT_TEST_OSTREAM << x.bucket_count()
<< "<=" << x.max_bucket_count() << "\n"; << "<=" << x.max_bucket_count() << "\n";
} }
for (BOOST_DEDUCED_TYPENAME test::random_values<X>::const_iterator for (BOOST_DEDUCED_TYPENAME test::random_values<X>::const_iterator
it = v.begin(), it = v.begin(),
end = v.end(); end = v.end();
it != end; ++it) { it != end; ++it) {
size_type bucket = x.bucket(test::get_key<X>(*it)); size_type bucket = x.bucket(test::get_key<X>(*it));
BOOST_TEST(bucket < x.bucket_count()); BOOST_TEST(bucket < x.bucket_count());
if (bucket < x.bucket_count()) { if (bucket < x.bucket_count()) {
// lit? lend?? I need a new naming scheme. // lit? lend?? I need a new naming scheme.
const_local_iterator lit = x.begin(bucket), lend = x.end(bucket); const_local_iterator lit = x.begin(bucket), lend = x.end(bucket);
while (lit != lend && while (lit != lend && test::get_key<X>(*it) != test::get_key<X>(*lit)) {
test::get_key<X>(*it) != test::get_key<X>(*lit)) { ++lit;
++lit;
}
BOOST_TEST(lit != lend);
} }
BOOST_TEST(lit != lend);
}
} }
for (size_type i = 0; i < x.bucket_count(); ++i) { for (size_type i = 0; i < x.bucket_count(); ++i) {
BOOST_TEST(x.bucket_size(i) == BOOST_TEST(x.bucket_size(i) ==
static_cast<size_type>(std::distance(x.begin(i), x.end(i)))); static_cast<size_type>(std::distance(x.begin(i), x.end(i))));
BOOST_TEST(x.bucket_size(i) == static_cast<size_type>(std::distance( BOOST_TEST(x.bucket_size(i) ==
x.cbegin(i), x.cend(i)))); static_cast<size_type>(std::distance(x.cbegin(i), x.cend(i))));
X const& x_ref = x; X const& x_ref = x;
BOOST_TEST(x.bucket_size(i) == static_cast<size_type>(std::distance( BOOST_TEST(x.bucket_size(i) == static_cast<size_type>(std::distance(
x_ref.begin(i), x_ref.end(i)))); x_ref.begin(i), x_ref.end(i))));
BOOST_TEST(x.bucket_size(i) == static_cast<size_type>(std::distance( BOOST_TEST(x.bucket_size(i) == static_cast<size_type>(std::distance(
x_ref.cbegin(i), x_ref.cend(i)))); x_ref.cbegin(i), x_ref.cend(i))));
} }
} }
boost::unordered_multimap<test::object, test::object, test::hash, boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, std::allocator<test::object> >* test_multimap_std_alloc; test::equal_to, std::allocator<test::object> >* test_multimap_std_alloc;
boost::unordered_set<test::object, test::hash, test::equal_to, boost::unordered_set<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_set; test::allocator2<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to, boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_multiset; test::allocator1<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to, boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_map; test::allocator1<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash, boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator2<test::object> >* test_multimap; test::equal_to, test::allocator2<test::object> >* test_multimap;
using test::default_generator; using test::default_generator;
using test::generate_collisions; using test::generate_collisions;
using test::limited_range; using test::limited_range;
UNORDERED_TEST(tests, ((test_multimap_std_alloc)(test_set)(test_multiset)( UNORDERED_TEST(tests,
test_map)(test_multimap))((default_generator)( ((test_multimap_std_alloc)(test_set)(test_multiset)(test_map)(
generate_collisions)(limited_range))) test_multimap))((default_generator)(generate_collisions)(limited_range)))
} }
RUN_TESTS() RUN_TESTS()

View File

@ -19,211 +19,203 @@
// Explicit instantiation to catch compile-time errors // Explicit instantiation to catch compile-time errors
#define INSTANTIATE(type) \ #define INSTANTIATE(type) \
template class boost::unordered::detail::instantiate_##type template class boost::unordered::detail::instantiate_##type
INSTANTIATE(map)<int, int, boost::hash<int>, std::equal_to<int>, INSTANTIATE(map)<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::allocator<int> >; test::minimal::allocator<int> >;
INSTANTIATE(multimap)<int const, int const, boost::hash<int>, INSTANTIATE(multimap)<int const, int const, boost::hash<int>,
std::equal_to<int>, test::minimal::allocator<int> >; std::equal_to<int>, test::minimal::allocator<int> >;
INSTANTIATE(map)<test::minimal::assignable const, INSTANTIATE(
test::minimal::default_assignable const, map)<test::minimal::assignable const, test::minimal::default_assignable const,
test::minimal::hash<test::minimal::assignable>, test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>, test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<int> >; test::minimal::allocator<int> >;
INSTANTIATE(multimap)<test::minimal::assignable, test::minimal::assignable, INSTANTIATE(multimap)<test::minimal::assignable, test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>, test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>, test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<int> >; test::minimal::allocator<int> >;
UNORDERED_AUTO_TEST(test0) UNORDERED_AUTO_TEST(test0)
{ {
test::minimal::constructor_param x; test::minimal::constructor_param x;
typedef std::pair<test::minimal::assignable const, typedef std::pair<test::minimal::assignable const, test::minimal::assignable>
test::minimal::assignable> value_type;
value_type; value_type value(x, x);
value_type value(x, x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n";
boost::unordered_map<int, int> int_map; boost::unordered_map<int, int> int_map;
boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>, boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > > test::minimal::cxx11_allocator<std::pair<int const, int> > >
int_map2; int_map2;
boost::unordered_map<test::minimal::assignable, test::minimal::assignable, boost::unordered_map<test::minimal::assignable, test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>, test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>, test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<value_type> > test::minimal::allocator<value_type> >
map; map;
container_test(int_map, std::pair<int const, int>(0, 0)); container_test(int_map, std::pair<int const, int>(0, 0));
container_test(int_map2, std::pair<int const, int>(0, 0)); container_test(int_map2, std::pair<int const, int>(0, 0));
container_test(map, value); container_test(map, value);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multimap.\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multimap.\n";
boost::unordered_multimap<int, int> int_multimap; boost::unordered_multimap<int, int> int_multimap;
boost::unordered_multimap<int, int, boost::hash<int>, std::equal_to<int>, boost::unordered_multimap<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > > test::minimal::cxx11_allocator<std::pair<int const, int> > >
int_multimap2; int_multimap2;
boost::unordered_multimap<test::minimal::assignable, boost::unordered_multimap<test::minimal::assignable,
test::minimal::assignable, test::minimal::assignable, test::minimal::hash<test::minimal::assignable>,
test::minimal::hash<test::minimal::assignable>, test::minimal::equal_to<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>, test::minimal::allocator<value_type> >
test::minimal::allocator<value_type> > multimap;
multimap;
container_test(int_multimap, std::pair<int const, int>(0, 0)); container_test(int_multimap, std::pair<int const, int>(0, 0));
container_test(int_multimap2, std::pair<int const, int>(0, 0)); container_test(int_multimap2, std::pair<int const, int>(0, 0));
container_test(multimap, value); container_test(multimap, value);
} }
UNORDERED_AUTO_TEST(equality_tests) UNORDERED_AUTO_TEST(equality_tests)
{ {
typedef std::pair< typedef std::pair<test::minimal::copy_constructible_equality_comparable const,
test::minimal::copy_constructible_equality_comparable const, test::minimal::copy_constructible_equality_comparable>
test::minimal::copy_constructible_equality_comparable> value_type;
value_type;
boost::unordered_map<int, int> int_map; boost::unordered_map<int, int> int_map;
boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>, boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > > test::minimal::cxx11_allocator<std::pair<int const, int> > >
int_map2; int_map2;
boost::unordered_map< boost::unordered_map<test::minimal::copy_constructible_equality_comparable,
test::minimal::copy_constructible_equality_comparable, test::minimal::copy_constructible_equality_comparable,
test::minimal::copy_constructible_equality_comparable, test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
test::minimal::hash< test::minimal::equal_to<
test::minimal::copy_constructible_equality_comparable>, test::minimal::copy_constructible_equality_comparable>,
test::minimal::equal_to< test::minimal::allocator<value_type> >
test::minimal::copy_constructible_equality_comparable>, map;
test::minimal::allocator<value_type> >
map;
equality_test(int_map); equality_test(int_map);
equality_test(int_map2); equality_test(int_map2);
equality_test(map); equality_test(map);
boost::unordered_multimap<int, int> int_multimap; boost::unordered_multimap<int, int> int_multimap;
boost::unordered_multimap<int, int, boost::hash<int>, std::equal_to<int>, boost::unordered_multimap<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > > test::minimal::cxx11_allocator<std::pair<int const, int> > >
int_multimap2; int_multimap2;
boost::unordered_multimap< boost::unordered_multimap<
test::minimal::copy_constructible_equality_comparable, test::minimal::copy_constructible_equality_comparable,
test::minimal::copy_constructible_equality_comparable, test::minimal::copy_constructible_equality_comparable,
test::minimal::hash< test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
test::minimal::copy_constructible_equality_comparable>, test::minimal::equal_to<
test::minimal::equal_to< test::minimal::copy_constructible_equality_comparable>,
test::minimal::copy_constructible_equality_comparable>, test::minimal::allocator<value_type> >
test::minimal::allocator<value_type> > multimap;
multimap;
equality_test(int_multimap); equality_test(int_multimap);
equality_test(int_multimap2); equality_test(int_multimap2);
equality_test(multimap); equality_test(multimap);
} }
UNORDERED_AUTO_TEST(test1) UNORDERED_AUTO_TEST(test1)
{ {
boost::hash<int> hash; boost::hash<int> hash;
std::equal_to<int> equal_to; std::equal_to<int> equal_to;
int value = 0; int value = 0;
std::pair<int const, int> map_value(0, 0); std::pair<int const, int> map_value(0, 0);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n";
boost::unordered_map<int, int> map; boost::unordered_map<int, int> map;
boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>, boost::unordered_map<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > > test::minimal::cxx11_allocator<std::pair<int const, int> > >
map2; map2;
unordered_unique_test(map, map_value); unordered_unique_test(map, map_value);
unordered_map_test(map, value, value); unordered_map_test(map, value, value);
unordered_copyable_test(map, value, map_value, hash, equal_to); unordered_copyable_test(map, value, map_value, hash, equal_to);
unordered_map_functions(map, value, value); unordered_map_functions(map, value, value);
unordered_unique_test(map2, map_value); unordered_unique_test(map2, map_value);
unordered_map_test(map2, value, value); unordered_map_test(map2, value, value);
unordered_copyable_test(map2, value, map_value, hash, equal_to); unordered_copyable_test(map2, value, map_value, hash, equal_to);
unordered_map_functions(map2, value, value); unordered_map_functions(map2, value, value);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multimap.\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multimap.\n";
boost::unordered_multimap<int, int> multimap; boost::unordered_multimap<int, int> multimap;
boost::unordered_multimap<int, int, boost::hash<int>, std::equal_to<int>, boost::unordered_multimap<int, int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<std::pair<int const, int> > > test::minimal::cxx11_allocator<std::pair<int const, int> > >
multimap2; multimap2;
unordered_equivalent_test(multimap, map_value); unordered_equivalent_test(multimap, map_value);
unordered_map_test(multimap, value, value); unordered_map_test(multimap, value, value);
unordered_copyable_test(multimap, value, map_value, hash, equal_to); unordered_copyable_test(multimap, value, map_value, hash, equal_to);
unordered_equivalent_test(multimap2, map_value); unordered_equivalent_test(multimap2, map_value);
unordered_map_test(multimap2, value, value); unordered_map_test(multimap2, value, value);
unordered_copyable_test(multimap2, value, map_value, hash, equal_to); unordered_copyable_test(multimap2, value, map_value, hash, equal_to);
} }
UNORDERED_AUTO_TEST(test2) UNORDERED_AUTO_TEST(test2)
{ {
test::minimal::constructor_param x; test::minimal::constructor_param x;
test::minimal::assignable assignable(x); test::minimal::assignable assignable(x);
test::minimal::copy_constructible copy_constructible(x); test::minimal::copy_constructible copy_constructible(x);
test::minimal::hash<test::minimal::assignable> hash(x); test::minimal::hash<test::minimal::assignable> hash(x);
test::minimal::equal_to<test::minimal::assignable> equal_to(x); test::minimal::equal_to<test::minimal::assignable> equal_to(x);
typedef std::pair<test::minimal::assignable const, typedef std::pair<test::minimal::assignable const, test::minimal::assignable>
test::minimal::assignable> map_value_type;
map_value_type; map_value_type map_value(assignable, assignable);
map_value_type map_value(assignable, assignable);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n";
boost::unordered_map<test::minimal::assignable, test::minimal::assignable, boost::unordered_map<test::minimal::assignable, test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>, test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>, test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<map_value_type> > test::minimal::allocator<map_value_type> >
map; map;
unordered_unique_test(map, map_value); unordered_unique_test(map, map_value);
unordered_map_test(map, assignable, assignable); unordered_map_test(map, assignable, assignable);
unordered_copyable_test(map, assignable, map_value, hash, equal_to); unordered_copyable_test(map, assignable, map_value, hash, equal_to);
unordered_map_member_test(map, map_value); unordered_map_member_test(map, map_value);
boost::unordered_map<test::minimal::assignable, boost::unordered_map<test::minimal::assignable,
test::minimal::default_assignable, test::minimal::default_assignable,
test::minimal::hash<test::minimal::assignable>, test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>, test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<map_value_type> > test::minimal::allocator<map_value_type> >
map2; map2;
test::minimal::default_assignable default_assignable; test::minimal::default_assignable default_assignable;
unordered_map_functions(map2, assignable, default_assignable); unordered_map_functions(map2, assignable, default_assignable);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multimap.\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multimap.\n";
boost::unordered_multimap<test::minimal::assignable, boost::unordered_multimap<test::minimal::assignable,
test::minimal::assignable, test::minimal::assignable, test::minimal::hash<test::minimal::assignable>,
test::minimal::hash<test::minimal::assignable>, test::minimal::equal_to<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>, test::minimal::allocator<map_value_type> >
test::minimal::allocator<map_value_type> > multimap;
multimap;
unordered_equivalent_test(multimap, map_value); unordered_equivalent_test(multimap, map_value);
unordered_map_test(multimap, assignable, assignable); unordered_map_test(multimap, assignable, assignable);
unordered_copyable_test(multimap, assignable, map_value, hash, equal_to); unordered_copyable_test(multimap, assignable, map_value, hash, equal_to);
unordered_map_member_test(multimap, map_value); unordered_map_member_test(multimap, map_value);
} }
// Test for ambiguity when using key convertible from iterator // Test for ambiguity when using key convertible from iterator
@ -231,31 +223,31 @@ UNORDERED_AUTO_TEST(test2)
struct lwg2059_key struct lwg2059_key
{ {
int value; int value;
template <typename T> lwg2059_key(T v) : value(v) {} template <typename T> lwg2059_key(T v) : value(v) {}
}; };
std::size_t hash_value(lwg2059_key x) std::size_t hash_value(lwg2059_key x)
{ {
return static_cast<std::size_t>(x.value); return static_cast<std::size_t>(x.value);
} }
bool operator==(lwg2059_key x, lwg2059_key y) { return x.value == y.value; } bool operator==(lwg2059_key x, lwg2059_key y) { return x.value == y.value; }
UNORDERED_AUTO_TEST(lwg2059) UNORDERED_AUTO_TEST(lwg2059)
{ {
{ {
boost::unordered_map<lwg2059_key, int> x; boost::unordered_map<lwg2059_key, int> x;
x.emplace(lwg2059_key(10), 5); x.emplace(lwg2059_key(10), 5);
x.erase(x.begin()); x.erase(x.begin());
} }
{ {
boost::unordered_multimap<lwg2059_key, int> x; boost::unordered_multimap<lwg2059_key, int> x;
x.emplace(lwg2059_key(10), 5); x.emplace(lwg2059_key(10), 5);
x.erase(x.begin()); x.erase(x.begin());
} }
} }
RUN_TESTS() RUN_TESTS()

View File

@ -19,274 +19,271 @@
// Explicit instantiation to catch compile-time errors // Explicit instantiation to catch compile-time errors
#define INSTANTIATE(type) \ #define INSTANTIATE(type) \
template class boost::unordered::detail::instantiate_##type template class boost::unordered::detail::instantiate_##type
INSTANTIATE(set)<int, boost::hash<int>, std::equal_to<int>, INSTANTIATE(set)<int, boost::hash<int>, std::equal_to<int>,
test::minimal::allocator<int> >; test::minimal::allocator<int> >;
INSTANTIATE(multiset)<int const, boost::hash<int>, std::equal_to<int>, INSTANTIATE(multiset)<int const, boost::hash<int>, std::equal_to<int>,
test::minimal::allocator<int> >; test::minimal::allocator<int> >;
INSTANTIATE(set)<test::minimal::assignable const, INSTANTIATE(set)<test::minimal::assignable const,
test::minimal::hash<test::minimal::assignable>, test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>, test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<int> >; test::minimal::allocator<int> >;
INSTANTIATE(multiset)<test::minimal::assignable, INSTANTIATE(multiset)<test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>, test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>, test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<int> >; test::minimal::allocator<int> >;
UNORDERED_AUTO_TEST(test0) UNORDERED_AUTO_TEST(test0)
{ {
test::minimal::constructor_param x; test::minimal::constructor_param x;
test::minimal::assignable assignable(x); test::minimal::assignable assignable(x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
boost::unordered_set<int> int_set; boost::unordered_set<int> int_set;
boost::unordered_set<int, boost::hash<int>, std::equal_to<int>, boost::unordered_set<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> > test::minimal::cxx11_allocator<int> >
int_set2; int_set2;
boost::unordered_set<test::minimal::assignable, boost::unordered_set<test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>, test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>, test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> > test::minimal::allocator<test::minimal::assignable> >
set; set;
container_test(int_set, 0); container_test(int_set, 0);
container_test(int_set2, 0); container_test(int_set2, 0);
container_test(set, assignable); container_test(set, assignable);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
boost::unordered_multiset<int> int_multiset; boost::unordered_multiset<int> int_multiset;
boost::unordered_multiset<int, boost::hash<int>, std::equal_to<int>, boost::unordered_multiset<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> > test::minimal::cxx11_allocator<int> >
int_multiset2; int_multiset2;
boost::unordered_multiset<test::minimal::assignable, boost::unordered_multiset<test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>, test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>, test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> > test::minimal::allocator<test::minimal::assignable> >
multiset; multiset;
container_test(int_multiset, 0); container_test(int_multiset, 0);
container_test(int_multiset2, 0); container_test(int_multiset2, 0);
container_test(multiset, assignable); container_test(multiset, assignable);
} }
UNORDERED_AUTO_TEST(equality_tests) UNORDERED_AUTO_TEST(equality_tests)
{ {
typedef test::minimal::copy_constructible_equality_comparable value_type; typedef test::minimal::copy_constructible_equality_comparable value_type;
boost::unordered_set<int> int_set; boost::unordered_set<int> int_set;
boost::unordered_set<int, boost::hash<int>, std::equal_to<int>, boost::unordered_set<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> > test::minimal::cxx11_allocator<int> >
int_set2; int_set2;
boost::unordered_set< boost::unordered_set<test::minimal::copy_constructible_equality_comparable,
test::minimal::copy_constructible_equality_comparable, test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
test::minimal::hash< test::minimal::equal_to<
test::minimal::copy_constructible_equality_comparable>, test::minimal::copy_constructible_equality_comparable>,
test::minimal::equal_to< test::minimal::allocator<value_type> >
test::minimal::copy_constructible_equality_comparable>, set;
test::minimal::allocator<value_type> >
set;
equality_test(int_set); equality_test(int_set);
equality_test(int_set2); equality_test(int_set2);
equality_test(set); equality_test(set);
boost::unordered_multiset<int> int_multiset; boost::unordered_multiset<int> int_multiset;
boost::unordered_multiset<int, boost::hash<int>, std::equal_to<int>, boost::unordered_multiset<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> > test::minimal::cxx11_allocator<int> >
int_multiset2; int_multiset2;
boost::unordered_multiset< boost::unordered_multiset<
test::minimal::copy_constructible_equality_comparable, test::minimal::copy_constructible_equality_comparable,
test::minimal::hash< test::minimal::hash<test::minimal::copy_constructible_equality_comparable>,
test::minimal::copy_constructible_equality_comparable>, test::minimal::equal_to<
test::minimal::equal_to< test::minimal::copy_constructible_equality_comparable>,
test::minimal::copy_constructible_equality_comparable>, test::minimal::allocator<value_type> >
test::minimal::allocator<value_type> > multiset;
multiset;
equality_test(int_multiset); equality_test(int_multiset);
equality_test(int_multiset2); equality_test(int_multiset2);
equality_test(multiset); equality_test(multiset);
} }
UNORDERED_AUTO_TEST(test1) UNORDERED_AUTO_TEST(test1)
{ {
boost::hash<int> hash; boost::hash<int> hash;
std::equal_to<int> equal_to; std::equal_to<int> equal_to;
int value = 0; int value = 0;
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set." << std::endl; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set." << std::endl;
boost::unordered_set<int> set; boost::unordered_set<int> set;
boost::unordered_set<int, boost::hash<int>, std::equal_to<int>, boost::unordered_set<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> > test::minimal::cxx11_allocator<int> >
set2; set2;
unordered_unique_test(set, value); unordered_unique_test(set, value);
unordered_set_test(set, value); unordered_set_test(set, value);
unordered_copyable_test(set, value, value, hash, equal_to); unordered_copyable_test(set, value, value, hash, equal_to);
unordered_unique_test(set2, value); unordered_unique_test(set2, value);
unordered_set_test(set2, value); unordered_set_test(set2, value);
unordered_copyable_test(set2, value, value, hash, equal_to); unordered_copyable_test(set2, value, value, hash, equal_to);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset." << std::endl; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset." << std::endl;
boost::unordered_multiset<int> multiset; boost::unordered_multiset<int> multiset;
boost::unordered_multiset<int, boost::hash<int>, std::equal_to<int>, boost::unordered_multiset<int, boost::hash<int>, std::equal_to<int>,
test::minimal::cxx11_allocator<int> > test::minimal::cxx11_allocator<int> >
multiset2; multiset2;
unordered_equivalent_test(multiset, value); unordered_equivalent_test(multiset, value);
unordered_set_test(multiset, value); unordered_set_test(multiset, value);
unordered_copyable_test(multiset, value, value, hash, equal_to); unordered_copyable_test(multiset, value, value, hash, equal_to);
unordered_equivalent_test(multiset2, value); unordered_equivalent_test(multiset2, value);
unordered_set_test(multiset2, value); unordered_set_test(multiset2, value);
unordered_copyable_test(multiset2, value, value, hash, equal_to); unordered_copyable_test(multiset2, value, value, hash, equal_to);
} }
UNORDERED_AUTO_TEST(test2) UNORDERED_AUTO_TEST(test2)
{ {
test::minimal::constructor_param x; test::minimal::constructor_param x;
test::minimal::assignable assignable(x); test::minimal::assignable assignable(x);
test::minimal::copy_constructible copy_constructible(x); test::minimal::copy_constructible copy_constructible(x);
test::minimal::hash<test::minimal::assignable> hash(x); test::minimal::hash<test::minimal::assignable> hash(x);
test::minimal::equal_to<test::minimal::assignable> equal_to(x); test::minimal::equal_to<test::minimal::assignable> equal_to(x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
boost::unordered_set<test::minimal::assignable, boost::unordered_set<test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>, test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>, test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> > test::minimal::allocator<test::minimal::assignable> >
set; set;
unordered_unique_test(set, assignable); unordered_unique_test(set, assignable);
unordered_set_test(set, assignable); unordered_set_test(set, assignable);
unordered_copyable_test(set, assignable, assignable, hash, equal_to); unordered_copyable_test(set, assignable, assignable, hash, equal_to);
unordered_set_member_test(set, assignable); unordered_set_member_test(set, assignable);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
boost::unordered_multiset<test::minimal::assignable, boost::unordered_multiset<test::minimal::assignable,
test::minimal::hash<test::minimal::assignable>, test::minimal::hash<test::minimal::assignable>,
test::minimal::equal_to<test::minimal::assignable>, test::minimal::equal_to<test::minimal::assignable>,
test::minimal::allocator<test::minimal::assignable> > test::minimal::allocator<test::minimal::assignable> >
multiset; multiset;
unordered_equivalent_test(multiset, assignable); unordered_equivalent_test(multiset, assignable);
unordered_set_test(multiset, assignable); unordered_set_test(multiset, assignable);
unordered_copyable_test(multiset, assignable, assignable, hash, equal_to); unordered_copyable_test(multiset, assignable, assignable, hash, equal_to);
unordered_set_member_test(multiset, assignable); unordered_set_member_test(multiset, assignable);
} }
UNORDERED_AUTO_TEST(movable1_tests) UNORDERED_AUTO_TEST(movable1_tests)
{ {
test::minimal::constructor_param x; test::minimal::constructor_param x;
test::minimal::movable1 movable1(x); test::minimal::movable1 movable1(x);
test::minimal::hash<test::minimal::movable1> hash(x); test::minimal::hash<test::minimal::movable1> hash(x);
test::minimal::equal_to<test::minimal::movable1> equal_to(x); test::minimal::equal_to<test::minimal::movable1> equal_to(x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
boost::unordered_set<test::minimal::movable1, boost::unordered_set<test::minimal::movable1,
test::minimal::hash<test::minimal::movable1>, test::minimal::hash<test::minimal::movable1>,
test::minimal::equal_to<test::minimal::movable1>, test::minimal::equal_to<test::minimal::movable1>,
test::minimal::allocator<test::minimal::movable1> > test::minimal::allocator<test::minimal::movable1> >
set; set;
// unordered_unique_test(set, movable1); // unordered_unique_test(set, movable1);
unordered_set_test(set, movable1); unordered_set_test(set, movable1);
unordered_movable_test(set, movable1, movable1, hash, equal_to); unordered_movable_test(set, movable1, movable1, hash, equal_to);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
boost::unordered_multiset<test::minimal::movable1, boost::unordered_multiset<test::minimal::movable1,
test::minimal::hash<test::minimal::movable1>, test::minimal::hash<test::minimal::movable1>,
test::minimal::equal_to<test::minimal::movable1>, test::minimal::equal_to<test::minimal::movable1>,
test::minimal::allocator<test::minimal::movable1> > test::minimal::allocator<test::minimal::movable1> >
multiset; multiset;
// unordered_equivalent_test(multiset, movable1); // unordered_equivalent_test(multiset, movable1);
unordered_set_test(multiset, movable1); unordered_set_test(multiset, movable1);
unordered_movable_test(multiset, movable1, movable1, hash, equal_to); unordered_movable_test(multiset, movable1, movable1, hash, equal_to);
} }
UNORDERED_AUTO_TEST(movable2_tests) UNORDERED_AUTO_TEST(movable2_tests)
{ {
test::minimal::constructor_param x; test::minimal::constructor_param x;
test::minimal::movable2 movable2(x); test::minimal::movable2 movable2(x);
test::minimal::hash<test::minimal::movable2> hash(x); test::minimal::hash<test::minimal::movable2> hash(x);
test::minimal::equal_to<test::minimal::movable2> equal_to(x); test::minimal::equal_to<test::minimal::movable2> equal_to(x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
boost::unordered_set<test::minimal::movable2, boost::unordered_set<test::minimal::movable2,
test::minimal::hash<test::minimal::movable2>, test::minimal::hash<test::minimal::movable2>,
test::minimal::equal_to<test::minimal::movable2>, test::minimal::equal_to<test::minimal::movable2>,
test::minimal::allocator<test::minimal::movable2> > test::minimal::allocator<test::minimal::movable2> >
set; set;
// unordered_unique_test(set, movable2); // unordered_unique_test(set, movable2);
unordered_set_test(set, movable2); unordered_set_test(set, movable2);
unordered_movable_test(set, movable2, movable2, hash, equal_to); unordered_movable_test(set, movable2, movable2, hash, equal_to);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
boost::unordered_multiset<test::minimal::movable2, boost::unordered_multiset<test::minimal::movable2,
test::minimal::hash<test::minimal::movable2>, test::minimal::hash<test::minimal::movable2>,
test::minimal::equal_to<test::minimal::movable2>, test::minimal::equal_to<test::minimal::movable2>,
test::minimal::allocator<test::minimal::movable2> > test::minimal::allocator<test::minimal::movable2> >
multiset; multiset;
// unordered_equivalent_test(multiset, movable2); // unordered_equivalent_test(multiset, movable2);
unordered_set_test(multiset, movable2); unordered_set_test(multiset, movable2);
unordered_movable_test(multiset, movable2, movable2, hash, equal_to); unordered_movable_test(multiset, movable2, movable2, hash, equal_to);
} }
UNORDERED_AUTO_TEST(destructible_tests) UNORDERED_AUTO_TEST(destructible_tests)
{ {
test::minimal::constructor_param x; test::minimal::constructor_param x;
test::minimal::destructible destructible(x); test::minimal::destructible destructible(x);
test::minimal::hash<test::minimal::destructible> hash(x); test::minimal::hash<test::minimal::destructible> hash(x);
test::minimal::equal_to<test::minimal::destructible> equal_to(x); test::minimal::equal_to<test::minimal::destructible> equal_to(x);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
boost::unordered_set<test::minimal::destructible, boost::unordered_set<test::minimal::destructible,
test::minimal::hash<test::minimal::destructible>, test::minimal::hash<test::minimal::destructible>,
test::minimal::equal_to<test::minimal::destructible> > test::minimal::equal_to<test::minimal::destructible> >
set; set;
unordered_destructible_test(set); unordered_destructible_test(set);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
boost::unordered_multiset<test::minimal::destructible, boost::unordered_multiset<test::minimal::destructible,
test::minimal::hash<test::minimal::destructible>, test::minimal::hash<test::minimal::destructible>,
test::minimal::equal_to<test::minimal::destructible> > test::minimal::equal_to<test::minimal::destructible> >
multiset; multiset;
unordered_destructible_test(multiset); unordered_destructible_test(multiset);
} }
// Test for ambiguity when using key convertible from iterator // Test for ambiguity when using key convertible from iterator
@ -294,31 +291,31 @@ UNORDERED_AUTO_TEST(destructible_tests)
struct lwg2059_key struct lwg2059_key
{ {
int value; int value;
template <typename T> lwg2059_key(T v) : value(v) {} template <typename T> lwg2059_key(T v) : value(v) {}
}; };
std::size_t hash_value(lwg2059_key x) std::size_t hash_value(lwg2059_key x)
{ {
return static_cast<std::size_t>(x.value); return static_cast<std::size_t>(x.value);
} }
bool operator==(lwg2059_key x, lwg2059_key y) { return x.value == y.value; } bool operator==(lwg2059_key x, lwg2059_key y) { return x.value == y.value; }
UNORDERED_AUTO_TEST(lwg2059) UNORDERED_AUTO_TEST(lwg2059)
{ {
{ {
boost::unordered_set<lwg2059_key> x; boost::unordered_set<lwg2059_key> x;
x.emplace(lwg2059_key(10)); x.emplace(lwg2059_key(10));
x.erase(x.begin()); x.erase(x.begin());
} }
{ {
boost::unordered_multiset<lwg2059_key> x; boost::unordered_multiset<lwg2059_key> x;
x.emplace(lwg2059_key(10)); x.emplace(lwg2059_key(10));
x.erase(x.begin()); x.erase(x.begin());
} }
} }
RUN_TESTS() RUN_TESTS()

File diff suppressed because it is too large Load Diff

View File

@ -20,161 +20,162 @@
namespace constructor_tests { namespace constructor_tests {
test::seed_t initialize_seed(356730); test::seed_t initialize_seed(356730);
template <class T> void constructor_tests1(T*, test::random_generator generator) template <class T>
{ void constructor_tests1(T*, test::random_generator generator)
{
BOOST_DEDUCED_TYPENAME T::hasher hf; BOOST_DEDUCED_TYPENAME T::hasher hf;
BOOST_DEDUCED_TYPENAME T::key_equal eq; BOOST_DEDUCED_TYPENAME T::key_equal eq;
BOOST_DEDUCED_TYPENAME T::allocator_type al; BOOST_DEDUCED_TYPENAME T::allocator_type al;
UNORDERED_SUB_TEST("Construct 1") UNORDERED_SUB_TEST("Construct 1")
{ {
test::check_instances check_; test::check_instances check_;
T x(0, hf, eq); T x(0, hf, eq);
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::equivalent(x.get_allocator(), al)); BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
UNORDERED_SUB_TEST("Construct 2") UNORDERED_SUB_TEST("Construct 2")
{ {
test::check_instances check_; test::check_instances check_;
T x(100, hf); T x(100, hf);
BOOST_TEST(x.empty()); BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 100); BOOST_TEST(x.bucket_count() >= 100);
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));
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
UNORDERED_SUB_TEST("Construct 3") UNORDERED_SUB_TEST("Construct 3")
{ {
test::check_instances check_; test::check_instances check_;
T x(2000); T x(2000);
BOOST_TEST(x.empty()); BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 2000); BOOST_TEST(x.bucket_count() >= 2000);
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));
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
UNORDERED_SUB_TEST("Construct 4") UNORDERED_SUB_TEST("Construct 4")
{ {
test::check_instances check_; test::check_instances check_;
T x; T x;
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::equivalent(x.get_allocator(), al)); BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
UNORDERED_SUB_TEST("Construct 5") UNORDERED_SUB_TEST("Construct 5")
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<T> v(1000, generator); test::random_values<T> v(1000, generator);
T x(v.begin(), v.end(), 10000, hf, eq); T x(v.begin(), v.end(), 10000, hf, eq);
BOOST_TEST(x.bucket_count() >= 10000); BOOST_TEST(x.bucket_count() >= 10000);
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));
test::check_container(x, v); test::check_container(x, v);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
UNORDERED_SUB_TEST("Construct 6") UNORDERED_SUB_TEST("Construct 6")
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<T> v(10, generator); test::random_values<T> v(10, generator);
T x(v.begin(), v.end(), 10000, hf); T x(v.begin(), v.end(), 10000, hf);
BOOST_TEST(x.bucket_count() >= 10000); BOOST_TEST(x.bucket_count() >= 10000);
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));
test::check_container(x, v); test::check_container(x, v);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
UNORDERED_SUB_TEST("Construct 7") UNORDERED_SUB_TEST("Construct 7")
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<T> v(100, generator); test::random_values<T> v(100, generator);
T x(v.begin(), v.end(), 100); T x(v.begin(), v.end(), 100);
BOOST_TEST(x.bucket_count() >= 100); BOOST_TEST(x.bucket_count() >= 100);
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));
test::check_container(x, v); test::check_container(x, v);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
UNORDERED_SUB_TEST("Construct 8") UNORDERED_SUB_TEST("Construct 8")
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<T> v(1, generator); test::random_values<T> v(1, generator);
T x(v.begin(), v.end()); T x(v.begin(), v.end());
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));
test::check_container(x, v); test::check_container(x, v);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
UNORDERED_SUB_TEST("Construct 9") UNORDERED_SUB_TEST("Construct 9")
{ {
test::check_instances check_; test::check_instances check_;
T x(0, hf, eq, al); T x(0, hf, eq, al);
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::equivalent(x.get_allocator(), al)); BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
UNORDERED_SUB_TEST("Construct 10") UNORDERED_SUB_TEST("Construct 10")
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<T> v(1000, generator); test::random_values<T> v(1000, generator);
T x(v.begin(), v.end(), 10000, hf, eq, al); T x(v.begin(), v.end(), 10000, hf, eq, al);
BOOST_TEST(x.bucket_count() >= 10000); BOOST_TEST(x.bucket_count() >= 10000);
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));
test::check_container(x, v); test::check_container(x, v);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
UNORDERED_SUB_TEST("Construct 11") UNORDERED_SUB_TEST("Construct 11")
{ {
test::check_instances check_; test::check_instances check_;
T x(al); T x(al);
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::equivalent(x.get_allocator(), al)); BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
} }
template <class T> template <class T>
void constructor_tests2(T*, test::random_generator const& generator) void constructor_tests2(T*, test::random_generator const& generator)
{ {
BOOST_DEDUCED_TYPENAME T::hasher hf; BOOST_DEDUCED_TYPENAME T::hasher hf;
BOOST_DEDUCED_TYPENAME T::hasher hf1(1); BOOST_DEDUCED_TYPENAME T::hasher hf1(1);
BOOST_DEDUCED_TYPENAME T::hasher hf2(2); BOOST_DEDUCED_TYPENAME T::hasher hf2(2);
@ -187,134 +188,135 @@ void constructor_tests2(T*, test::random_generator const& generator)
UNORDERED_SUB_TEST("Construct 1") UNORDERED_SUB_TEST("Construct 1")
{ {
test::check_instances check_; test::check_instances check_;
T x(10000, hf1, eq1); T x(10000, hf1, eq1);
BOOST_TEST(x.bucket_count() >= 10000); BOOST_TEST(x.bucket_count() >= 10000);
BOOST_TEST(test::equivalent(x.hash_function(), hf1)); BOOST_TEST(test::equivalent(x.hash_function(), hf1));
BOOST_TEST(test::equivalent(x.key_eq(), eq1)); BOOST_TEST(test::equivalent(x.key_eq(), eq1));
BOOST_TEST(test::equivalent(x.get_allocator(), al)); BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
UNORDERED_SUB_TEST("Construct 2") UNORDERED_SUB_TEST("Construct 2")
{ {
test::check_instances check_; test::check_instances check_;
T x(100, hf1); T x(100, hf1);
BOOST_TEST(x.empty()); BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 100); BOOST_TEST(x.bucket_count() >= 100);
BOOST_TEST(test::equivalent(x.hash_function(), hf1)); BOOST_TEST(test::equivalent(x.hash_function(), hf1));
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));
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
UNORDERED_SUB_TEST("Construct 3") UNORDERED_SUB_TEST("Construct 3")
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<T> v(100, generator); test::random_values<T> v(100, generator);
T x(v.begin(), v.end(), 0, hf1, eq1); T x(v.begin(), v.end(), 0, hf1, eq1);
BOOST_TEST(test::equivalent(x.hash_function(), hf1)); BOOST_TEST(test::equivalent(x.hash_function(), hf1));
BOOST_TEST(test::equivalent(x.key_eq(), eq1)); BOOST_TEST(test::equivalent(x.key_eq(), eq1));
BOOST_TEST(test::equivalent(x.get_allocator(), al)); BOOST_TEST(test::equivalent(x.get_allocator(), al));
test::check_container(x, v); test::check_container(x, v);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
UNORDERED_SUB_TEST("Construct 4") UNORDERED_SUB_TEST("Construct 4")
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<T> v(5, generator); test::random_values<T> v(5, generator);
T x(v.begin(), v.end(), 1000, hf1); T x(v.begin(), v.end(), 1000, hf1);
BOOST_TEST(x.bucket_count() >= 1000); BOOST_TEST(x.bucket_count() >= 1000);
BOOST_TEST(test::equivalent(x.hash_function(), hf1)); BOOST_TEST(test::equivalent(x.hash_function(), hf1));
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));
test::check_container(x, v); test::check_container(x, v);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
UNORDERED_SUB_TEST("Construct 5") UNORDERED_SUB_TEST("Construct 5")
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<T> v(100, generator); test::random_values<T> v(100, generator);
T x(v.begin(), v.end(), 0, hf, eq, al1); T x(v.begin(), v.end(), 0, hf, eq, al1);
T y(x.begin(), x.end(), 0, hf1, eq1, al2); T y(x.begin(), x.end(), 0, hf1, eq1, al2);
test::check_container(x, v); test::check_container(x, v);
test::check_container(y, x); test::check_container(y, x);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
} }
UNORDERED_SUB_TEST("Construct 6") UNORDERED_SUB_TEST("Construct 6")
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<T> v(100, generator); test::random_values<T> v(100, generator);
T x(v.begin(), v.end(), 0, hf1, eq1); T x(v.begin(), v.end(), 0, hf1, eq1);
T y(x.begin(), x.end(), 0, hf, eq); T y(x.begin(), x.end(), 0, hf, eq);
test::check_container(x, v); test::check_container(x, v);
test::check_container(y, x); test::check_container(y, x);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
} }
UNORDERED_SUB_TEST("Construct 7") UNORDERED_SUB_TEST("Construct 7")
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<T> v(100, generator); test::random_values<T> v(100, generator);
T x(v.begin(), v.end(), 0, hf1, eq1); T x(v.begin(), v.end(), 0, hf1, eq1);
T y(x.begin(), x.end(), 0, hf2, eq2); T y(x.begin(), x.end(), 0, hf2, eq2);
test::check_container(x, v); test::check_container(x, v);
test::check_container(y, x); test::check_container(y, x);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
} }
UNORDERED_SUB_TEST("Construct 8 - from input iterator") UNORDERED_SUB_TEST("Construct 8 - from input iterator")
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<T> v(100, generator); test::random_values<T> v(100, generator);
BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator BOOST_DEDUCED_TYPENAME test::random_values<T>::const_iterator v_begin =
v_begin = v.begin(), v.begin(),
v_end = v.end(); v_end =
T x(test::input_iterator(v_begin), test::input_iterator(v_end), 0, hf1, v.end();
eq1); T x(test::input_iterator(v_begin), test::input_iterator(v_end), 0, hf1,
BOOST_DEDUCED_TYPENAME T::const_iterator x_begin = x.begin(), eq1);
x_end = x.end(); BOOST_DEDUCED_TYPENAME T::const_iterator x_begin = x.begin(),
T y(test::input_iterator(x_begin), test::input_iterator(x_end), 0, hf2, x_end = x.end();
eq2); T y(test::input_iterator(x_begin), test::input_iterator(x_end), 0, hf2,
test::check_container(x, v); eq2);
test::check_container(y, x); test::check_container(x, v);
test::check_equivalent_keys(x); test::check_container(y, x);
test::check_equivalent_keys(y); test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
} }
UNORDERED_SUB_TEST("Construct 8.5 - from copy iterator") UNORDERED_SUB_TEST("Construct 8.5 - from copy iterator")
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<T> v(100, generator); test::random_values<T> v(100, generator);
T x(test::copy_iterator(v.begin()), test::copy_iterator(v.end()), 0, T x(test::copy_iterator(v.begin()), test::copy_iterator(v.end()), 0, hf1,
hf1, eq1); eq1);
T y(test::copy_iterator(x.begin()), test::copy_iterator(x.end()), 0, T y(test::copy_iterator(x.begin()), test::copy_iterator(x.end()), 0, hf2,
hf2, eq2); eq2);
test::check_container(x, v); test::check_container(x, v);
test::check_container(y, x); test::check_container(y, x);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
} }
UNORDERED_SUB_TEST("Construct 9") UNORDERED_SUB_TEST("Construct 9")
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<T> v(100, generator); test::random_values<T> v(100, generator);
T x(50); T x(50);
BOOST_TEST(x.bucket_count() >= 50); BOOST_TEST(x.bucket_count() >= 50);
x.max_load_factor(10); x.max_load_factor(10);
BOOST_TEST(x.bucket_count() >= 50); BOOST_TEST(x.bucket_count() >= 50);
x.insert(v.begin(), v.end()); x.insert(v.begin(), v.end());
BOOST_TEST(x.bucket_count() >= 50); BOOST_TEST(x.bucket_count() >= 50);
test::check_container(x, v); test::check_container(x, v);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
@ -322,126 +324,126 @@ void constructor_tests2(T*, test::random_generator const& generator)
UNORDERED_SUB_TEST("Initializer list construct 1") UNORDERED_SUB_TEST("Initializer list construct 1")
{ {
test::check_instances check_; test::check_instances check_;
T x(list); T x(list);
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::equivalent(x.get_allocator(), al)); BOOST_TEST(test::equivalent(x.get_allocator(), al));
} }
UNORDERED_SUB_TEST("Initializer list construct 2") UNORDERED_SUB_TEST("Initializer list construct 2")
{ {
test::check_instances check_; test::check_instances check_;
T x(list, 1000); T x(list, 1000);
BOOST_TEST(x.empty()); BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 1000); BOOST_TEST(x.bucket_count() >= 1000);
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));
} }
UNORDERED_SUB_TEST("Initializer list construct 3") UNORDERED_SUB_TEST("Initializer list construct 3")
{ {
test::check_instances check_; test::check_instances check_;
T x(list, 10, hf1); T x(list, 10, hf1);
BOOST_TEST(x.empty()); BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 10); BOOST_TEST(x.bucket_count() >= 10);
BOOST_TEST(test::equivalent(x.hash_function(), hf1)); BOOST_TEST(test::equivalent(x.hash_function(), hf1));
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));
} }
UNORDERED_SUB_TEST("Initializer list construct 4") UNORDERED_SUB_TEST("Initializer list construct 4")
{ {
test::check_instances check_; test::check_instances check_;
T x(list, 10, hf1, eq1); T x(list, 10, hf1, eq1);
BOOST_TEST(x.empty()); BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 10); BOOST_TEST(x.bucket_count() >= 10);
BOOST_TEST(test::equivalent(x.hash_function(), hf1)); BOOST_TEST(test::equivalent(x.hash_function(), hf1));
BOOST_TEST(test::equivalent(x.key_eq(), eq1)); BOOST_TEST(test::equivalent(x.key_eq(), eq1));
BOOST_TEST(test::equivalent(x.get_allocator(), al)); BOOST_TEST(test::equivalent(x.get_allocator(), al));
} }
UNORDERED_SUB_TEST("Initializer list construct 5") UNORDERED_SUB_TEST("Initializer list construct 5")
{ {
test::check_instances check_; test::check_instances check_;
T x(list, 10, hf1, eq1, al1); T x(list, 10, hf1, eq1, al1);
BOOST_TEST(x.empty()); BOOST_TEST(x.empty());
BOOST_TEST(x.bucket_count() >= 10); BOOST_TEST(x.bucket_count() >= 10);
BOOST_TEST(test::equivalent(x.hash_function(), hf1)); BOOST_TEST(test::equivalent(x.hash_function(), hf1));
BOOST_TEST(test::equivalent(x.key_eq(), eq1)); BOOST_TEST(test::equivalent(x.key_eq(), eq1));
BOOST_TEST(test::equivalent(x.get_allocator(), al1)); BOOST_TEST(test::equivalent(x.get_allocator(), al1));
} }
#endif #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)
{ {
typedef test::list<std::pair<BOOST_DEDUCED_TYPENAME T::key_type, typedef test::list<std::pair<BOOST_DEDUCED_TYPENAME T::key_type,
BOOST_DEDUCED_TYPENAME T::mapped_type> > BOOST_DEDUCED_TYPENAME T::mapped_type> >
list; list;
test::random_values<T> v(1000, generator); test::random_values<T> v(1000, generator);
list l(v.begin(), v.end()); list l(v.begin(), v.end());
T x(l.begin(), l.end()); T x(l.begin(), l.end());
test::check_container(x, v); test::check_container(x, v);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
boost::unordered_map<test::object, test::object, test::hash, test::equal_to, boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
std::allocator<test::object> >* test_map_std_alloc; std::allocator<test::object> >* test_map_std_alloc;
boost::unordered_set<test::object, test::hash, test::equal_to, boost::unordered_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set; test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to, boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset; test::allocator2<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to, boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_map; test::allocator2<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash, boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator1<test::object> >* test_multimap; test::equal_to, test::allocator1<test::object> >* test_multimap;
using test::default_generator; using test::default_generator;
using test::generate_collisions; using test::generate_collisions;
using test::limited_range; using test::limited_range;
UNORDERED_TEST(constructor_tests1, UNORDERED_TEST(constructor_tests1,
((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap))( ((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range))) (default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(constructor_tests2, UNORDERED_TEST(constructor_tests2,
((test_set)(test_multiset)(test_map)(test_multimap))( ((test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range))) (default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(map_constructor_test, UNORDERED_TEST(map_constructor_test,
((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)))
#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)
{ {
std::initializer_list<int> init; std::initializer_list<int> init;
boost::unordered_set<int> x1 = init; boost::unordered_set<int> x1 = init;
BOOST_TEST(x1.empty()); BOOST_TEST(x1.empty());
} }
#endif #endif
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
UNORDERED_AUTO_TEST(test_initializer_list) UNORDERED_AUTO_TEST(test_initializer_list)
{ {
boost::unordered_set<int> x1 = {2, 10, 45, -5}; boost::unordered_set<int> x1 = {2, 10, 45, -5};
BOOST_TEST(x1.find(10) != x1.end()); BOOST_TEST(x1.find(10) != x1.end());
BOOST_TEST(x1.find(46) == x1.end()); BOOST_TEST(x1.find(46) == x1.end());
} }
#endif #endif
} }

View File

@ -22,9 +22,9 @@ test::seed_t initialize_seed(9063);
namespace copy_tests { namespace copy_tests {
template <class T> template <class T>
void copy_construct_tests1(T*, test::random_generator const& generator) void copy_construct_tests1(T*, test::random_generator const& generator)
{ {
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type; typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
BOOST_DEDUCED_TYPENAME T::hasher hf; BOOST_DEDUCED_TYPENAME T::hasher hf;
@ -32,58 +32,58 @@ void copy_construct_tests1(T*, test::random_generator const& generator)
BOOST_DEDUCED_TYPENAME T::allocator_type al; BOOST_DEDUCED_TYPENAME T::allocator_type al;
{ {
test::check_instances check_; test::check_instances check_;
T x; T x;
T y(x); T y(x);
BOOST_TEST(y.empty()); BOOST_TEST(y.empty());
BOOST_TEST(test::equivalent(y.hash_function(), hf)); BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq)); BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al)); BOOST_TEST(test::equivalent(y.get_allocator(), al));
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));
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
} }
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<T> v(1000, generator); test::random_values<T> v(1000, generator);
T x(v.begin(), v.end()); T x(v.begin(), v.end());
T y(x); T y(x);
test::unordered_equivalence_tester<T> equivalent(x); test::unordered_equivalence_tester<T> equivalent(x);
BOOST_TEST(equivalent(y)); BOOST_TEST(equivalent(y));
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));
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
} }
{ {
test::check_instances check_; test::check_instances check_;
// In this test I drop the original containers max load factor, so it // In this test I drop the original containers max load factor, so it
// is much lower than the load factor. The hash table is not allowed // is much lower than the load factor. The hash table is not allowed
// to rehash, but the destination container should probably allocate // to rehash, but the destination container should probably allocate
// enough buckets to decrease the load factor appropriately. // enough buckets to decrease the load factor appropriately.
test::random_values<T> v(1000, generator); test::random_values<T> v(1000, generator);
T x(v.begin(), v.end()); T x(v.begin(), v.end());
x.max_load_factor(x.load_factor() / 4); x.max_load_factor(x.load_factor() / 4);
T y(x); T y(x);
test::unordered_equivalence_tester<T> equivalent(x); test::unordered_equivalence_tester<T> equivalent(x);
BOOST_TEST(equivalent(y)); BOOST_TEST(equivalent(y));
// This isn't guaranteed: // This isn't guaranteed:
BOOST_TEST(y.load_factor() < y.max_load_factor()); BOOST_TEST(y.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));
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
} }
} }
template <class T> template <class T>
void copy_construct_tests2(T*, test::random_generator const& generator) void copy_construct_tests2(T*, test::random_generator const& generator)
{ {
BOOST_DEDUCED_TYPENAME T::hasher hf(1); BOOST_DEDUCED_TYPENAME T::hasher hf(1);
BOOST_DEDUCED_TYPENAME T::key_equal eq(1); BOOST_DEDUCED_TYPENAME T::key_equal eq(1);
BOOST_DEDUCED_TYPENAME T::allocator_type al(1); BOOST_DEDUCED_TYPENAME T::allocator_type al(1);
@ -92,117 +92,117 @@ void copy_construct_tests2(T*, test::random_generator const& generator)
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type; typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
{ {
test::check_instances check_; test::check_instances check_;
T x(10000, hf, eq, al); T x(10000, hf, eq, al);
T y(x); T y(x);
BOOST_TEST(y.empty()); BOOST_TEST(y.empty());
BOOST_TEST(test::equivalent(y.hash_function(), hf)); BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq)); BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al)); BOOST_TEST(test::equivalent(y.get_allocator(), al));
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));
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
} }
{ {
test::check_instances check_; test::check_instances check_;
T x(1000, hf, eq, al); T x(1000, hf, eq, al);
T y(x, al2); T y(x, al2);
BOOST_TEST(y.empty()); BOOST_TEST(y.empty());
BOOST_TEST(test::equivalent(y.hash_function(), hf)); BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq)); BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al2)); BOOST_TEST(test::equivalent(y.get_allocator(), al2));
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()) == 0); BOOST_TEST(test::selected_count(y.get_allocator()) == 0);
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
} }
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<T> v(1000, generator); test::random_values<T> v(1000, generator);
T x(v.begin(), v.end(), 0, hf, eq, al); T x(v.begin(), v.end(), 0, hf, eq, al);
T y(x); T y(x);
test::unordered_equivalence_tester<T> equivalent(x); test::unordered_equivalence_tester<T> equivalent(x);
BOOST_TEST(equivalent(y)); BOOST_TEST(equivalent(y));
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
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::equivalent(y.get_allocator(), al)); BOOST_TEST(test::equivalent(y.get_allocator(), al));
} }
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<T> v(500, generator); test::random_values<T> v(500, generator);
T x(v.begin(), v.end(), 0, hf, eq, al); T x(v.begin(), v.end(), 0, hf, eq, al);
T y(x, al2); T y(x, al2);
test::unordered_equivalence_tester<T> equivalent(x); test::unordered_equivalence_tester<T> equivalent(x);
BOOST_TEST(equivalent(y)); BOOST_TEST(equivalent(y));
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
BOOST_TEST(test::selected_count(y.get_allocator()) == 0); BOOST_TEST(test::selected_count(y.get_allocator()) == 0);
BOOST_TEST(test::equivalent(y.get_allocator(), al2)); BOOST_TEST(test::equivalent(y.get_allocator(), al2));
} }
} }
boost::unordered_set<test::object, test::hash, test::equal_to, boost::unordered_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set; test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to, boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset; test::allocator2<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to, boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_map; test::allocator1<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash, boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator2<test::object> >* test_multimap; test::equal_to, test::allocator2<test::object> >* test_multimap;
boost::unordered_set<test::object, test::hash, test::equal_to, boost::unordered_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::select_copy> >* test::cxx11_allocator<test::object, test::select_copy> >*
test_set_select_copy; test_set_select_copy;
boost::unordered_multiset<test::object, test::hash, test::equal_to, boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::select_copy> >* test::cxx11_allocator<test::object, test::select_copy> >*
test_multiset_select_copy; test_multiset_select_copy;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to, boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::select_copy> >* test::cxx11_allocator<test::object, test::select_copy> >*
test_map_select_copy; test_map_select_copy;
boost::unordered_multimap<test::object, test::object, test::hash, boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::cxx11_allocator<test::object, test::select_copy> >* test::equal_to, test::cxx11_allocator<test::object, test::select_copy> >*
test_multimap_select_copy; test_multimap_select_copy;
boost::unordered_set<test::object, test::hash, test::equal_to, boost::unordered_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_select_copy> >* test::cxx11_allocator<test::object, test::no_select_copy> >*
test_set_no_select_copy; test_set_no_select_copy;
boost::unordered_multiset<test::object, test::hash, test::equal_to, boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_select_copy> >* test::cxx11_allocator<test::object, test::no_select_copy> >*
test_multiset_no_select_copy; test_multiset_no_select_copy;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to, boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_select_copy> >* test::cxx11_allocator<test::object, test::no_select_copy> >*
test_map_no_select_copy; test_map_no_select_copy;
boost::unordered_multimap<test::object, test::object, test::hash, boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::cxx11_allocator<test::object, test::no_select_copy> >* test::equal_to, test::cxx11_allocator<test::object, test::no_select_copy> >*
test_multimap_no_select_copy; test_multimap_no_select_copy;
using test::default_generator; using test::default_generator;
using test::generate_collisions; using test::generate_collisions;
using test::limited_range; using test::limited_range;
UNORDERED_TEST(copy_construct_tests1, UNORDERED_TEST(copy_construct_tests1,
((test_set)(test_multiset)(test_map)(test_multimap)(test_set_select_copy)( ((test_set)(test_multiset)(test_map)(test_multimap)(test_set_select_copy)(
test_multiset_select_copy)(test_map_select_copy)( test_multiset_select_copy)(test_map_select_copy)(
test_multimap_select_copy)(test_set_no_select_copy)( test_multimap_select_copy)(test_set_no_select_copy)(
test_multiset_no_select_copy)(test_map_no_select_copy)( test_multiset_no_select_copy)(test_map_no_select_copy)(
test_multimap_no_select_copy))( test_multimap_no_select_copy))(
(default_generator)(generate_collisions)(limited_range))) (default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(copy_construct_tests2, UNORDERED_TEST(copy_construct_tests2,
((test_set)(test_multiset)(test_map)(test_multimap)(test_set_select_copy)( ((test_set)(test_multiset)(test_map)(test_multimap)(test_set_select_copy)(
test_multiset_select_copy)(test_map_select_copy)( test_multiset_select_copy)(test_map_select_copy)(
test_multimap_select_copy)(test_set_no_select_copy)( test_multimap_select_copy)(test_set_no_select_copy)(
test_multiset_no_select_copy)(test_map_no_select_copy)( test_multiset_no_select_copy)(test_map_no_select_copy)(
test_multimap_no_select_copy))( test_multimap_no_select_copy))(
(default_generator)(generate_collisions)(limited_range))) (default_generator)(generate_collisions)(limited_range)))
} }

View File

@ -17,86 +17,86 @@
// Might be too slow if we had larger primes? // Might be too slow if we had larger primes?
bool is_prime(std::size_t x) bool is_prime(std::size_t x)
{ {
if (x == 2) { if (x == 2) {
return true; return true;
} else if (x == 1 || x % 2 == 0) { } else if (x == 1 || x % 2 == 0) {
return false;
} else {
// y*y <= x had rounding errors, so instead use y <= (x/y).
for (std::size_t y = 3; y <= (x / y); y += 2) {
if (x % y == 0) {
return false; return false;
} else { break;
// y*y <= x had rounding errors, so instead use y <= (x/y). }
for (std::size_t y = 3; y <= (x / y); y += 2) {
if (x % y == 0) {
return false;
break;
}
}
return true;
} }
return true;
}
} }
void test_next_prime(std::size_t value) void test_next_prime(std::size_t value)
{ {
std::size_t x = boost::unordered::detail::next_prime(value); std::size_t x = boost::unordered::detail::next_prime(value);
BOOST_TEST(is_prime(x)); BOOST_TEST(is_prime(x));
BOOST_TEST(x >= value); BOOST_TEST(x >= value);
} }
void test_prev_prime(std::size_t value) void test_prev_prime(std::size_t value)
{ {
std::size_t x = boost::unordered::detail::prev_prime(value); std::size_t x = boost::unordered::detail::prev_prime(value);
BOOST_TEST(is_prime(x)); BOOST_TEST(is_prime(x));
BOOST_TEST(x <= value); BOOST_TEST(x <= value);
if (x > value) { if (x > value) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << x << "," << value << std::endl; BOOST_LIGHTWEIGHT_TEST_OSTREAM << x << "," << value << std::endl;
} }
} }
UNORDERED_AUTO_TEST(next_prime_test) UNORDERED_AUTO_TEST(next_prime_test)
{ {
BOOST_TEST(!is_prime(0)); BOOST_TEST(!is_prime(0));
BOOST_TEST(!is_prime(1)); BOOST_TEST(!is_prime(1));
BOOST_TEST(is_prime(2)); BOOST_TEST(is_prime(2));
BOOST_TEST(is_prime(3)); BOOST_TEST(is_prime(3));
BOOST_TEST(is_prime(13)); BOOST_TEST(is_prime(13));
BOOST_TEST(!is_prime(4)); BOOST_TEST(!is_prime(4));
BOOST_TEST(!is_prime(100)); BOOST_TEST(!is_prime(100));
BOOST_TEST(boost::unordered::detail::next_prime(0) > 0); BOOST_TEST(boost::unordered::detail::next_prime(0) > 0);
// test_prev_prime doesn't work for values less than 17. // test_prev_prime doesn't work for values less than 17.
// Which should be okay, unless an allocator has a really tiny // Which should be okay, unless an allocator has a really tiny
// max_size? // max_size?
const std::size_t min_prime = 17; const std::size_t min_prime = 17;
// test_next_prime doesn't work for values greater than this, // test_next_prime doesn't work for values greater than this,
// which might be a problem if you've got terrabytes of memory? // which might be a problem if you've got terrabytes of memory?
// I seriously doubt the container would work well at such sizes // I seriously doubt the container would work well at such sizes
// regardless. // regardless.
const std::size_t max_prime = 4294967291ul; const std::size_t max_prime = 4294967291ul;
std::size_t i; std::size_t i;
BOOST_TEST(is_prime(min_prime)); BOOST_TEST(is_prime(min_prime));
BOOST_TEST(is_prime(max_prime)); BOOST_TEST(is_prime(max_prime));
for (i = 0; i < 10000; ++i) { for (i = 0; i < 10000; ++i) {
if (i < min_prime) { if (i < min_prime) {
BOOST_TEST(boost::unordered::detail::prev_prime(i) == min_prime); BOOST_TEST(boost::unordered::detail::prev_prime(i) == min_prime);
} else { } else {
test_prev_prime(i); test_prev_prime(i);
}
test_next_prime(i);
} }
test_next_prime(i);
}
std::size_t last = i - 1; std::size_t last = i - 1;
for (; i > last; last = i, i += i / 5) { for (; i > last; last = i, i += i / 5) {
if (i > max_prime) { if (i > max_prime) {
BOOST_TEST(boost::unordered::detail::next_prime(i) == max_prime); BOOST_TEST(boost::unordered::detail::next_prime(i) == max_prime);
} else { } else {
test_next_prime(i); test_next_prime(i);
}
test_prev_prime(i);
} }
test_prev_prime(i);
}
} }
RUN_TESTS() RUN_TESTS()

View File

@ -19,9 +19,9 @@
// arguments. // arguments.
namespace emplace_tests { namespace emplace_tests {
// Constructible with 2 to 10 arguments // Constructible with 2 to 10 arguments
struct emplace_value : private test::counted_object struct emplace_value : private test::counted_object
{ {
typedef int A0; typedef int A0;
typedef std::string A1; typedef std::string A1;
typedef char A2; typedef char A2;
@ -59,40 +59,40 @@ struct emplace_value : private test::counted_object
} }
emplace_value( emplace_value(
A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3, A4 const& b4) A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3, A4 const& b4)
: arg_count(5), a0(b0), a1(b1), a2(b2), a3(b3), a4(b4) : arg_count(5), a0(b0), a1(b1), a2(b2), a3(b3), a4(b4)
{ {
} }
emplace_value(A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3, emplace_value(A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3,
A4 const& b4, A5 const& b5) A4 const& b4, A5 const& b5)
: arg_count(6), a0(b0), a1(b1), a2(b2), a3(b3), a4(b4), a5(b5) : arg_count(6), a0(b0), a1(b1), a2(b2), a3(b3), a4(b4), a5(b5)
{ {
} }
emplace_value(A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3, emplace_value(A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3,
A4 const& b4, A5 const& b5, A6 const& b6) A4 const& b4, A5 const& b5, A6 const& b6)
: arg_count(7), a0(b0), a1(b1), a2(b2), a3(b3), a4(b4), a5(b5), a6(b6) : arg_count(7), a0(b0), a1(b1), a2(b2), a3(b3), a4(b4), a5(b5), a6(b6)
{ {
} }
emplace_value(A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3, emplace_value(A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3,
A4 const& b4, A5 const& b5, A6 const& b6, A7 const& b7) A4 const& b4, A5 const& b5, A6 const& b6, A7 const& b7)
: arg_count(8), a0(b0), a1(b1), a2(b2), a3(b3), a4(b4), a5(b5), a6(b6), : arg_count(8), a0(b0), a1(b1), a2(b2), a3(b3), a4(b4), a5(b5), a6(b6),
a7(b7) a7(b7)
{ {
} }
emplace_value(A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3, emplace_value(A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3,
A4 const& b4, A5 const& b5, A6 const& b6, A7 const& b7, A8 const& b8) A4 const& b4, A5 const& b5, A6 const& b6, A7 const& b7, A8 const& b8)
: arg_count(9), a0(b0), a1(b1), a2(b2), a3(b3), a4(b4), a5(b5), a6(b6), : arg_count(9), a0(b0), a1(b1), a2(b2), a3(b3), a4(b4), a5(b5), a6(b6),
a7(b7), a8(b8) a7(b7), a8(b8)
{ {
} }
emplace_value(A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3, emplace_value(A0 const& b0, A1 const& b1, A2 const& b2, A3 const& b3,
A4 const& b4, A5 const& b5, A6 const& b6, A7 const& b7, A8 const& b8, A4 const& b4, A5 const& b5, A6 const& b6, A7 const& b7, A8 const& b8,
A9 const& b9) A9 const& b9)
: arg_count(10), a0(b0), a1(b1), a2(b2), a3(b3), a4(b4), a5(b5), a6(b6), : arg_count(10), a0(b0), a1(b1), a2(b2), a3(b3), a4(b4), a5(b5), a6(b6),
a7(b7), a8(b8), a9(b9) a7(b7), a8(b8), a9(b9)
{ {
@ -100,79 +100,79 @@ struct emplace_value : private test::counted_object
friend std::size_t hash_value(emplace_value const& x) friend std::size_t hash_value(emplace_value const& x)
{ {
std::size_t r1 = 23894278u; std::size_t r1 = 23894278u;
if (x.arg_count >= 1) if (x.arg_count >= 1)
boost::hash_combine(r1, x.a0); boost::hash_combine(r1, x.a0);
if (x.arg_count >= 2) if (x.arg_count >= 2)
boost::hash_combine(r1, x.a1); boost::hash_combine(r1, x.a1);
if (x.arg_count >= 3) if (x.arg_count >= 3)
boost::hash_combine(r1, x.a2); boost::hash_combine(r1, x.a2);
if (x.arg_count >= 4) if (x.arg_count >= 4)
boost::hash_combine(r1, x.a3); boost::hash_combine(r1, x.a3);
if (x.arg_count >= 5) if (x.arg_count >= 5)
boost::hash_combine(r1, x.a4); boost::hash_combine(r1, x.a4);
if (x.arg_count >= 6) if (x.arg_count >= 6)
boost::hash_combine(r1, x.a5); boost::hash_combine(r1, x.a5);
if (x.arg_count >= 7) if (x.arg_count >= 7)
boost::hash_combine(r1, x.a6); boost::hash_combine(r1, x.a6);
if (x.arg_count >= 8) if (x.arg_count >= 8)
boost::hash_combine(r1, x.a7); boost::hash_combine(r1, x.a7);
if (x.arg_count >= 9) if (x.arg_count >= 9)
boost::hash_combine(r1, x.a8); boost::hash_combine(r1, x.a8);
if (x.arg_count >= 10) if (x.arg_count >= 10)
boost::hash_combine(r1, x.a9); boost::hash_combine(r1, x.a9);
return r1; return r1;
} }
friend bool operator==(emplace_value const& x, emplace_value const& y) friend bool operator==(emplace_value const& x, emplace_value const& y)
{ {
if (x.arg_count != y.arg_count) { if (x.arg_count != y.arg_count) {
return false; return false;
} }
if (x.arg_count >= 1 && x.a0 != y.a0) { if (x.arg_count >= 1 && x.a0 != y.a0) {
return false; return false;
} }
if (x.arg_count >= 2 && x.a1 != y.a1) { if (x.arg_count >= 2 && x.a1 != y.a1) {
return false; return false;
} }
if (x.arg_count >= 3 && x.a2 != y.a2) { if (x.arg_count >= 3 && x.a2 != y.a2) {
return false; return false;
} }
if (x.arg_count >= 4 && x.a3 != y.a3) { if (x.arg_count >= 4 && x.a3 != y.a3) {
return false; return false;
} }
if (x.arg_count >= 5 && x.a4 != y.a4) { if (x.arg_count >= 5 && x.a4 != y.a4) {
return false; return false;
} }
if (x.arg_count >= 6 && x.a5 != y.a5) { if (x.arg_count >= 6 && x.a5 != y.a5) {
return false; return false;
} }
if (x.arg_count >= 7 && x.a6 != y.a6) { if (x.arg_count >= 7 && x.a6 != y.a6) {
return false; return false;
} }
if (x.arg_count >= 8 && x.a7 != y.a7) { if (x.arg_count >= 8 && x.a7 != y.a7) {
return false; return false;
} }
if (x.arg_count >= 9 && x.a8 != y.a8) { if (x.arg_count >= 9 && x.a8 != y.a8) {
return false; return false;
} }
if (x.arg_count >= 10 && x.a9 != y.a9) { if (x.arg_count >= 10 && x.a9 != y.a9) {
return false; return false;
} }
return true; return true;
} }
private: private:
emplace_value(); emplace_value();
emplace_value(emplace_value const&); emplace_value(emplace_value const&);
}; };
UNORDERED_AUTO_TEST(emplace_set) UNORDERED_AUTO_TEST(emplace_set)
{ {
test::check_instances check_; test::check_instances check_;
typedef boost::unordered_set<emplace_value, boost::hash<emplace_value> > typedef boost::unordered_set<emplace_value, boost::hash<emplace_value> >
container; container;
typedef container::iterator iterator; typedef container::iterator iterator;
typedef std::pair<iterator, bool> return_type; typedef std::pair<iterator, bool> return_type;
container x(10); container x(10);
@ -233,12 +233,12 @@ UNORDERED_AUTO_TEST(emplace_set)
BOOST_TEST_EQ(check_.instances(), 8); BOOST_TEST_EQ(check_.instances(), 8);
BOOST_TEST_EQ(check_.constructions(), 9); BOOST_TEST_EQ(check_.constructions(), 9);
BOOST_TEST(r1.first ==
x.emplace_hint(r1.first, 10, "", 'a', 4, 5, 6, 7, 8, 9, 10));
BOOST_TEST(r1.first ==
x.emplace_hint(r2.first, 10, "", 'a', 4, 5, 6, 7, 8, 9, 10));
BOOST_TEST( BOOST_TEST(
r1.first == x.emplace_hint(x.end(), 10, "", 'a', 4, 5, 6, 7, 8, 9, 10)); r1.first == x.emplace_hint(r1.first, 10, "", 'a', 4, 5, 6, 7, 8, 9, 10));
BOOST_TEST(
r1.first == x.emplace_hint(r2.first, 10, "", 'a', 4, 5, 6, 7, 8, 9, 10));
BOOST_TEST(
r1.first == x.emplace_hint(x.end(), 10, "", 'a', 4, 5, 6, 7, 8, 9, 10));
BOOST_TEST_EQ(check_.instances(), 8); BOOST_TEST_EQ(check_.instances(), 8);
BOOST_TEST_EQ(check_.constructions(), 12); BOOST_TEST_EQ(check_.constructions(), 12);
@ -247,15 +247,15 @@ UNORDERED_AUTO_TEST(emplace_set)
BOOST_TEST(x.count(v2) == 1); BOOST_TEST(x.count(v2) == 1);
BOOST_TEST(x.count(v3) == 1); BOOST_TEST(x.count(v3) == 1);
BOOST_TEST(x.count(v4) == 1); BOOST_TEST(x.count(v4) == 1);
} }
UNORDERED_AUTO_TEST(emplace_multiset) UNORDERED_AUTO_TEST(emplace_multiset)
{ {
test::check_instances check_; test::check_instances check_;
typedef boost::unordered_multiset<emplace_value, typedef boost::unordered_multiset<emplace_value,
boost::hash<emplace_value> > boost::hash<emplace_value> >
container; container;
typedef container::iterator iterator; typedef container::iterator iterator;
container x(10); container x(10);
iterator i1, i2; iterator i1, i2;
@ -326,15 +326,15 @@ UNORDERED_AUTO_TEST(emplace_multiset)
BOOST_TEST_EQ(x.count(v1), 1u); BOOST_TEST_EQ(x.count(v1), 1u);
BOOST_TEST_EQ(x.count(v2), 2u); BOOST_TEST_EQ(x.count(v2), 2u);
BOOST_TEST_EQ(x.count(v3), 2u); BOOST_TEST_EQ(x.count(v3), 2u);
} }
UNORDERED_AUTO_TEST(emplace_map) UNORDERED_AUTO_TEST(emplace_map)
{ {
test::check_instances check_; test::check_instances check_;
typedef boost::unordered_map<emplace_value, emplace_value, typedef boost::unordered_map<emplace_value, emplace_value,
boost::hash<emplace_value> > boost::hash<emplace_value> >
container; container;
typedef container::iterator iterator; typedef container::iterator iterator;
typedef std::pair<iterator, bool> return_type; typedef std::pair<iterator, bool> return_type;
container x(10); container x(10);
@ -345,8 +345,8 @@ UNORDERED_AUTO_TEST(emplace_map)
emplace_value k1(5, "", 'b', 4, 5); emplace_value k1(5, "", 'b', 4, 5);
emplace_value m1(8, "xxx", 'z', 4, 5, 6, 7, 8); emplace_value m1(8, "xxx", 'z', 4, 5, 6, 7, 8);
r1 = x.emplace(boost::unordered::piecewise_construct, r1 = x.emplace(boost::unordered::piecewise_construct,
boost::make_tuple(5, "", 'b', 4, 5), boost::make_tuple(5, "", 'b', 4, 5),
boost::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8)); boost::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8));
BOOST_TEST_EQ(x.size(), 1u); BOOST_TEST_EQ(x.size(), 1u);
BOOST_TEST(r1.second); BOOST_TEST(r1.second);
BOOST_TEST(x.find(k1) == r1.first); BOOST_TEST(x.find(k1) == r1.first);
@ -355,8 +355,8 @@ UNORDERED_AUTO_TEST(emplace_map)
BOOST_TEST_EQ(check_.constructions(), 4); BOOST_TEST_EQ(check_.constructions(), 4);
r2 = x.emplace(boost::unordered::piecewise_construct, r2 = x.emplace(boost::unordered::piecewise_construct,
boost::make_tuple(5, "", 'b', 4, 5), boost::make_tuple(5, "", 'b', 4, 5),
boost::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8)); boost::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8));
BOOST_TEST_EQ(x.size(), 1u); BOOST_TEST_EQ(x.size(), 1u);
BOOST_TEST(!r2.second); BOOST_TEST(!r2.second);
BOOST_TEST(r1.first == r2.first); BOOST_TEST(r1.first == r2.first);
@ -371,8 +371,8 @@ UNORDERED_AUTO_TEST(emplace_map)
emplace_value k2(9, "", 'b', 4, 5, 6, 7, 8, 9); emplace_value k2(9, "", 'b', 4, 5, 6, 7, 8, 9);
emplace_value m2(3, "aaa", 'm'); emplace_value m2(3, "aaa", 'm');
r1 = x.emplace(boost::unordered::piecewise_construct, r1 = x.emplace(boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9), boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(3, "aaa", 'm')); boost::make_tuple(3, "aaa", 'm'));
BOOST_TEST_EQ(x.size(), 2u); BOOST_TEST_EQ(x.size(), 2u);
BOOST_TEST(r1.second); BOOST_TEST(r1.second);
BOOST_TEST(r1.first->first.arg_count == 9); BOOST_TEST(r1.first->first.arg_count == 9);
@ -384,29 +384,29 @@ UNORDERED_AUTO_TEST(emplace_map)
BOOST_TEST(r1.first == BOOST_TEST(r1.first ==
x.emplace_hint(r1.first, boost::unordered::piecewise_construct, x.emplace_hint(r1.first, boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9), boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(15, "jkjk"))); boost::make_tuple(15, "jkjk")));
BOOST_TEST(r1.first == BOOST_TEST(r1.first ==
x.emplace_hint(r2.first, boost::unordered::piecewise_construct, x.emplace_hint(r2.first, boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9), boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(275, "xxx", 'm', 6))); boost::make_tuple(275, "xxx", 'm', 6)));
BOOST_TEST(r1.first == BOOST_TEST(r1.first ==
x.emplace_hint(x.end(), boost::unordered::piecewise_construct, x.emplace_hint(x.end(), boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9), boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(-10, "blah blah", '\0'))); boost::make_tuple(-10, "blah blah", '\0')));
BOOST_TEST_EQ(x.size(), 2u); BOOST_TEST_EQ(x.size(), 2u);
BOOST_TEST(x.find(k2)->second == m2); BOOST_TEST(x.find(k2)->second == m2);
BOOST_TEST_EQ(check_.instances(), 8); BOOST_TEST_EQ(check_.instances(), 8);
BOOST_TEST_EQ(check_.constructions(), 16); BOOST_TEST_EQ(check_.constructions(), 16);
} }
UNORDERED_AUTO_TEST(emplace_multimap) UNORDERED_AUTO_TEST(emplace_multimap)
{ {
test::check_instances check_; test::check_instances check_;
typedef boost::unordered_multimap<emplace_value, emplace_value, typedef boost::unordered_multimap<emplace_value, emplace_value,
boost::hash<emplace_value> > boost::hash<emplace_value> >
container; container;
typedef container::iterator iterator; typedef container::iterator iterator;
container x(10); container x(10);
iterator i1, i2, i3, i4; iterator i1, i2, i3, i4;
@ -416,8 +416,8 @@ UNORDERED_AUTO_TEST(emplace_multimap)
emplace_value k1(5, "", 'b', 4, 5); emplace_value k1(5, "", 'b', 4, 5);
emplace_value m1(8, "xxx", 'z', 4, 5, 6, 7, 8); emplace_value m1(8, "xxx", 'z', 4, 5, 6, 7, 8);
i1 = x.emplace(boost::unordered::piecewise_construct, i1 = x.emplace(boost::unordered::piecewise_construct,
boost::make_tuple(5, "", 'b', 4, 5), boost::make_tuple(5, "", 'b', 4, 5),
boost::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8)); boost::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8));
BOOST_TEST_EQ(x.size(), 1u); BOOST_TEST_EQ(x.size(), 1u);
BOOST_TEST(x.find(k1) == i1); BOOST_TEST(x.find(k1) == i1);
BOOST_TEST(x.find(k1)->second == m1); BOOST_TEST(x.find(k1)->second == m1);
@ -426,8 +426,8 @@ UNORDERED_AUTO_TEST(emplace_multimap)
emplace_value m1a(8, "xxx", 'z', 4, 5, 6, 7, 8); emplace_value m1a(8, "xxx", 'z', 4, 5, 6, 7, 8);
i2 = x.emplace(boost::unordered::piecewise_construct, i2 = x.emplace(boost::unordered::piecewise_construct,
boost::make_tuple(5, "", 'b', 4, 5), boost::make_tuple(5, "", 'b', 4, 5),
boost::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8)); boost::make_tuple(8, "xxx", 'z', 4, 5, 6, 7, 8));
BOOST_TEST_EQ(x.size(), 2u); BOOST_TEST_EQ(x.size(), 2u);
BOOST_TEST(i1 != i2); BOOST_TEST(i1 != i2);
BOOST_TEST(i1->second == m1); BOOST_TEST(i1->second == m1);
@ -440,8 +440,8 @@ UNORDERED_AUTO_TEST(emplace_multimap)
emplace_value k2(9, "", 'b', 4, 5, 6, 7, 8, 9); emplace_value k2(9, "", 'b', 4, 5, 6, 7, 8, 9);
emplace_value m2(3, "aaa", 'm'); emplace_value m2(3, "aaa", 'm');
i1 = x.emplace(boost::unordered::piecewise_construct, i1 = x.emplace(boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9), boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(3, "aaa", 'm')); boost::make_tuple(3, "aaa", 'm'));
BOOST_TEST_EQ(x.size(), 3u); BOOST_TEST_EQ(x.size(), 3u);
BOOST_TEST(i1->first.arg_count == 9); BOOST_TEST(i1->first.arg_count == 9);
BOOST_TEST(i1->second.arg_count == 3); BOOST_TEST(i1->second.arg_count == 3);
@ -450,24 +450,24 @@ UNORDERED_AUTO_TEST(emplace_multimap)
emplace_value m2a(15, "jkjk"); emplace_value m2a(15, "jkjk");
i2 = x.emplace_hint(i2, boost::unordered::piecewise_construct, i2 = x.emplace_hint(i2, boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9), boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(15, "jkjk")); boost::make_tuple(15, "jkjk"));
emplace_value m2b(275, "xxx", 'm', 6); emplace_value m2b(275, "xxx", 'm', 6);
i3 = x.emplace_hint(i1, boost::unordered::piecewise_construct, i3 = x.emplace_hint(i1, boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9), boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(275, "xxx", 'm', 6)); boost::make_tuple(275, "xxx", 'm', 6));
emplace_value m2c(-10, "blah blah", '\0'); emplace_value m2c(-10, "blah blah", '\0');
i4 = x.emplace_hint(x.end(), boost::unordered::piecewise_construct, i4 = x.emplace_hint(x.end(), boost::unordered::piecewise_construct,
boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9), boost::make_tuple(9, "", 'b', 4, 5, 6, 7, 8, 9),
boost::make_tuple(-10, "blah blah", '\0')); boost::make_tuple(-10, "blah blah", '\0'));
BOOST_TEST_EQ(x.size(), 6u); BOOST_TEST_EQ(x.size(), 6u);
BOOST_TEST(x.find(k2)->second == m2); BOOST_TEST(x.find(k2)->second == m2);
BOOST_TEST_EQ(check_.instances(), 20); BOOST_TEST_EQ(check_.instances(), 20);
BOOST_TEST_EQ(check_.constructions(), 20); BOOST_TEST_EQ(check_.constructions(), 20);
} }
UNORDERED_AUTO_TEST(try_emplace) UNORDERED_AUTO_TEST(try_emplace)
{ {
test::check_instances check_; test::check_instances check_;
typedef boost::unordered_map<int, emplace_value> container; typedef boost::unordered_map<int, emplace_value> container;
@ -509,11 +509,11 @@ UNORDERED_AUTO_TEST(try_emplace)
BOOST_TEST(r2.first == x.try_emplace(r2.first, k2, 808709, "what")); BOOST_TEST(r2.first == x.try_emplace(r2.first, k2, 808709, "what"));
BOOST_TEST( BOOST_TEST(
r2.first == r2.first ==
x.try_emplace(r2.first, k2, 10, "xxx", 'a', 4, 5, 6, 7, 8, 9, 10)); x.try_emplace(r2.first, k2, 10, "xxx", 'a', 4, 5, 6, 7, 8, 9, 10));
BOOST_TEST(r2.first->second == m2); BOOST_TEST(r2.first->second == m2);
BOOST_TEST_EQ(x.size(), 2u); BOOST_TEST_EQ(x.size(), 2u);
} }
} }
RUN_TESTS() RUN_TESTS()

View File

@ -15,8 +15,8 @@
#include "../helpers/test.hpp" #include "../helpers/test.hpp"
namespace equality_tests { namespace equality_tests {
struct mod_compare struct mod_compare
{ {
bool alt_hash_; bool alt_hash_;
explicit mod_compare(bool alt_hash = false) : alt_hash_(alt_hash) {} explicit mod_compare(bool alt_hash = false) : alt_hash_(alt_hash) {}
@ -25,50 +25,49 @@ struct mod_compare
std::size_t operator()(int x) const std::size_t operator()(int x) const
{ {
return alt_hash_ ? static_cast<std::size_t>(x % 250) return alt_hash_ ? static_cast<std::size_t>(x % 250)
: static_cast<std::size_t>((x + 5) % 250); : static_cast<std::size_t>((x + 5) % 250);
} }
}; };
#define UNORDERED_EQUALITY_SET_TEST(seq1, op, seq2) \ #define UNORDERED_EQUALITY_SET_TEST(seq1, op, seq2) \
{ \ { \
boost::unordered_set<int, mod_compare, mod_compare> set1, set2; \ boost::unordered_set<int, mod_compare, mod_compare> set1, set2; \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set1, seq1) \ BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set1, seq1) \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set2, seq2) \ BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set2, seq2) \
BOOST_TEST(set1 op set2); \ BOOST_TEST(set1 op set2); \
} }
#define UNORDERED_EQUALITY_MULTISET_TEST(seq1, op, seq2) \ #define UNORDERED_EQUALITY_MULTISET_TEST(seq1, op, seq2) \
{ \ { \
boost::unordered_multiset<int, mod_compare, mod_compare> set1, set2; \ boost::unordered_multiset<int, mod_compare, mod_compare> set1, set2; \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set1, seq1) \ BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set1, seq1) \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set2, seq2) \ BOOST_PP_SEQ_FOR_EACH(UNORDERED_SET_INSERT, set2, seq2) \
BOOST_TEST(set1 op set2); \ BOOST_TEST(set1 op set2); \
} }
#define UNORDERED_EQUALITY_MAP_TEST(seq1, op, seq2) \ #define UNORDERED_EQUALITY_MAP_TEST(seq1, op, seq2) \
{ \ { \
boost::unordered_map<int, int, mod_compare, mod_compare> map1, map2; \ boost::unordered_map<int, int, mod_compare, mod_compare> map1, map2; \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map1, seq1) \ BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map1, seq1) \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map2, seq2) \ BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map2, seq2) \
BOOST_TEST(map1 op map2); \ BOOST_TEST(map1 op map2); \
} }
#define UNORDERED_EQUALITY_MULTIMAP_TEST(seq1, op, seq2) \ #define UNORDERED_EQUALITY_MULTIMAP_TEST(seq1, op, seq2) \
{ \ { \
boost::unordered_multimap<int, int, mod_compare, mod_compare> map1, \ boost::unordered_multimap<int, int, mod_compare, mod_compare> map1, map2; \
map2; \ BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map1, seq1) \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map1, seq1) \ BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map2, seq2) \
BOOST_PP_SEQ_FOR_EACH(UNORDERED_MAP_INSERT, map2, seq2) \ BOOST_TEST(map1 op map2); \
BOOST_TEST(map1 op map2); \ }
}
#define UNORDERED_SET_INSERT(r, set, item) set.insert(item); #define UNORDERED_SET_INSERT(r, set, item) set.insert(item);
#define UNORDERED_MAP_INSERT(r, map, item) \ #define UNORDERED_MAP_INSERT(r, map, item) \
map.insert(std::pair<int const, int> BOOST_PP_SEQ_TO_TUPLE(item)); map.insert(std::pair<int const, int> BOOST_PP_SEQ_TO_TUPLE(item));
UNORDERED_AUTO_TEST(equality_size_tests) UNORDERED_AUTO_TEST(equality_size_tests)
{ {
boost::unordered_set<int> x1, x2; boost::unordered_set<int> x1, x2;
BOOST_TEST(x1 == x2); BOOST_TEST(x1 == x2);
BOOST_TEST(!(x1 != x2)); BOOST_TEST(!(x1 != x2));
@ -88,61 +87,61 @@ UNORDERED_AUTO_TEST(equality_size_tests)
BOOST_TEST(!(x1 == x2)); BOOST_TEST(!(x1 == x2));
BOOST_TEST(x2 != x1); BOOST_TEST(x2 != x1);
BOOST_TEST(!(x2 == x1)); BOOST_TEST(!(x2 == x1));
} }
UNORDERED_AUTO_TEST(equality_key_value_tests) UNORDERED_AUTO_TEST(equality_key_value_tests)
{ {
UNORDERED_EQUALITY_MULTISET_TEST((1), !=, (2)) UNORDERED_EQUALITY_MULTISET_TEST((1), !=, (2))
UNORDERED_EQUALITY_SET_TEST((2), ==, (2)) UNORDERED_EQUALITY_SET_TEST((2), ==, (2))
UNORDERED_EQUALITY_MAP_TEST(((1)(1))((2)(1)), !=, ((1)(1))((3)(1))) UNORDERED_EQUALITY_MAP_TEST(((1)(1))((2)(1)), !=, ((1)(1))((3)(1)))
} }
UNORDERED_AUTO_TEST(equality_collision_test) UNORDERED_AUTO_TEST(equality_collision_test)
{ {
UNORDERED_EQUALITY_MULTISET_TEST((1), !=, (501)) UNORDERED_EQUALITY_MULTISET_TEST((1), !=, (501))
UNORDERED_EQUALITY_MULTISET_TEST((1)(251), !=, (1)(501)) UNORDERED_EQUALITY_MULTISET_TEST((1)(251), !=, (1)(501))
UNORDERED_EQUALITY_MULTIMAP_TEST(((251)(1))((1)(1)), !=, ((501)(1))((1)(1))) UNORDERED_EQUALITY_MULTIMAP_TEST(((251)(1))((1)(1)), !=, ((501)(1))((1)(1)))
UNORDERED_EQUALITY_MULTISET_TEST((1)(501), ==, (1)(501)) UNORDERED_EQUALITY_MULTISET_TEST((1)(501), ==, (1)(501))
UNORDERED_EQUALITY_SET_TEST((1)(501), ==, (501)(1)) UNORDERED_EQUALITY_SET_TEST((1)(501), ==, (501)(1))
} }
UNORDERED_AUTO_TEST(equality_group_size_test) UNORDERED_AUTO_TEST(equality_group_size_test)
{ {
UNORDERED_EQUALITY_MULTISET_TEST((10)(20)(20), !=, (10)(10)(20)) UNORDERED_EQUALITY_MULTISET_TEST((10)(20)(20), !=, (10)(10)(20))
UNORDERED_EQUALITY_MULTIMAP_TEST( UNORDERED_EQUALITY_MULTIMAP_TEST(
((10)(1))((20)(1))((20)(1)), !=, ((10)(1))((20)(1))((10)(1))) ((10)(1))((20)(1))((20)(1)), !=, ((10)(1))((20)(1))((10)(1)))
UNORDERED_EQUALITY_MULTIMAP_TEST( UNORDERED_EQUALITY_MULTIMAP_TEST(
((20)(1))((10)(1))((10)(1)), ==, ((10)(1))((20)(1))((10)(1))) ((20)(1))((10)(1))((10)(1)), ==, ((10)(1))((20)(1))((10)(1)))
} }
UNORDERED_AUTO_TEST(equality_map_value_test) UNORDERED_AUTO_TEST(equality_map_value_test)
{ {
UNORDERED_EQUALITY_MAP_TEST(((1)(1)), !=, ((1)(2))) UNORDERED_EQUALITY_MAP_TEST(((1)(1)), !=, ((1)(2)))
UNORDERED_EQUALITY_MAP_TEST(((1)(1)), ==, ((1)(1))) UNORDERED_EQUALITY_MAP_TEST(((1)(1)), ==, ((1)(1)))
UNORDERED_EQUALITY_MULTIMAP_TEST(((1)(1)), !=, ((1)(2))) UNORDERED_EQUALITY_MULTIMAP_TEST(((1)(1)), !=, ((1)(2)))
UNORDERED_EQUALITY_MULTIMAP_TEST(((1)(1))((1)(1)), !=, ((1)(1))((1)(2))) UNORDERED_EQUALITY_MULTIMAP_TEST(((1)(1))((1)(1)), !=, ((1)(1))((1)(2)))
UNORDERED_EQUALITY_MULTIMAP_TEST(((1)(2))((1)(1)), ==, ((1)(1))((1)(2))) UNORDERED_EQUALITY_MULTIMAP_TEST(((1)(2))((1)(1)), ==, ((1)(1))((1)(2)))
UNORDERED_EQUALITY_MULTIMAP_TEST(((1)(2))((1)(1)), !=, ((1)(1))((1)(3))) UNORDERED_EQUALITY_MULTIMAP_TEST(((1)(2))((1)(1)), !=, ((1)(1))((1)(3)))
} }
UNORDERED_AUTO_TEST(equality_predicate_test) UNORDERED_AUTO_TEST(equality_predicate_test)
{ {
UNORDERED_EQUALITY_SET_TEST((1), !=, (1001)) UNORDERED_EQUALITY_SET_TEST((1), !=, (1001))
UNORDERED_EQUALITY_MAP_TEST(((1)(2))((1001)(1)), !=, ((1001)(2))((1)(1))) UNORDERED_EQUALITY_MAP_TEST(((1)(2))((1001)(1)), !=, ((1001)(2))((1)(1)))
} }
UNORDERED_AUTO_TEST(equality_multiple_group_test) UNORDERED_AUTO_TEST(equality_multiple_group_test)
{ {
UNORDERED_EQUALITY_MULTISET_TEST( UNORDERED_EQUALITY_MULTISET_TEST(
(1)(1)(1)(1001)(2001)(2001)(2)(1002)(3)(1003)(2003), ==, (1)(1)(1)(1001)(2001)(2001)(2)(1002)(3)(1003)(2003), ==,
(3)(1003)(2003)(1002)(2)(2001)(2001)(1)(1001)(1)(1)); (3)(1003)(2003)(1002)(2)(2001)(2001)(1)(1001)(1)(1));
} }
// Test that equality still works when the two containers have // Test that equality still works when the two containers have
// different hash functions but the same equality predicate. // different hash functions but the same equality predicate.
UNORDERED_AUTO_TEST(equality_different_hash_test) UNORDERED_AUTO_TEST(equality_different_hash_test)
{ {
typedef boost::unordered_set<int, mod_compare, mod_compare> set; typedef boost::unordered_set<int, mod_compare, mod_compare> set;
set set1(0, mod_compare(false), mod_compare(false)); set set1(0, mod_compare(false), mod_compare(false));
set set2(0, mod_compare(true), mod_compare(true)); set set2(0, mod_compare(true), mod_compare(true));
@ -159,7 +158,7 @@ UNORDERED_AUTO_TEST(equality_different_hash_test)
set1.insert(20); set1.insert(20);
set2.insert(10); set2.insert(10);
BOOST_TEST(set1 == set2); BOOST_TEST(set1 == set2);
} }
} }
RUN_TESTS() RUN_TESTS()

View File

@ -20,60 +20,60 @@
template <class Container, class Iterator> template <class Container, class Iterator>
void test_equal_insertion(Iterator begin, Iterator end) void test_equal_insertion(Iterator begin, Iterator end)
{ {
typedef test::ordered<Container> tracker; typedef test::ordered<Container> tracker;
Container x1; Container x1;
tracker x2 = test::create_ordered(x1); tracker x2 = test::create_ordered(x1);
for (Iterator it = begin; it != end; ++it) { for (Iterator it = begin; it != end; ++it) {
x1.insert(*it); x1.insert(*it);
x2.insert(*it); x2.insert(*it);
x2.compare_key(x1, *it); x2.compare_key(x1, *it);
} }
x2.compare(x1); x2.compare(x1);
test::check_equivalent_keys(x1); test::check_equivalent_keys(x1);
} }
UNORDERED_AUTO_TEST(set_tests) UNORDERED_AUTO_TEST(set_tests)
{ {
int values[][5] = {{1}, {54, 23}, {-13, 65}, {77, 77}, {986, 25, 986}}; int values[][5] = {{1}, {54, 23}, {-13, 65}, {77, 77}, {986, 25, 986}};
typedef boost::unordered_set<int> set; typedef boost::unordered_set<int> set;
typedef boost::unordered_multiset<int> multiset; typedef boost::unordered_multiset<int> multiset;
test_equal_insertion<set>(values[0], values[0] + 1); test_equal_insertion<set>(values[0], values[0] + 1);
test_equal_insertion<set>(values[1], values[1] + 2); test_equal_insertion<set>(values[1], values[1] + 2);
test_equal_insertion<set>(values[2], values[2] + 2); test_equal_insertion<set>(values[2], values[2] + 2);
test_equal_insertion<set>(values[3], values[3] + 2); test_equal_insertion<set>(values[3], values[3] + 2);
test_equal_insertion<set>(values[4], values[4] + 3); test_equal_insertion<set>(values[4], values[4] + 3);
test_equal_insertion<multiset>(values[0], values[0] + 1); test_equal_insertion<multiset>(values[0], values[0] + 1);
test_equal_insertion<multiset>(values[1], values[1] + 2); test_equal_insertion<multiset>(values[1], values[1] + 2);
test_equal_insertion<multiset>(values[2], values[2] + 2); test_equal_insertion<multiset>(values[2], values[2] + 2);
test_equal_insertion<multiset>(values[3], values[3] + 2); test_equal_insertion<multiset>(values[3], values[3] + 2);
test_equal_insertion<multiset>(values[4], values[4] + 3); test_equal_insertion<multiset>(values[4], values[4] + 3);
} }
UNORDERED_AUTO_TEST(map_tests) UNORDERED_AUTO_TEST(map_tests)
{ {
typedef test::list<std::pair<int const, int> > values_type; typedef test::list<std::pair<int const, int> > values_type;
values_type v[5]; values_type v[5];
v[0].push_back(std::pair<int const, int>(1, 1)); v[0].push_back(std::pair<int const, int>(1, 1));
v[1].push_back(std::pair<int const, int>(28, 34)); v[1].push_back(std::pair<int const, int>(28, 34));
v[1].push_back(std::pair<int const, int>(16, 58)); v[1].push_back(std::pair<int const, int>(16, 58));
v[1].push_back(std::pair<int const, int>(-124, 62)); v[1].push_back(std::pair<int const, int>(-124, 62));
v[2].push_back(std::pair<int const, int>(432, 12)); v[2].push_back(std::pair<int const, int>(432, 12));
v[2].push_back(std::pair<int const, int>(9, 13)); v[2].push_back(std::pair<int const, int>(9, 13));
v[2].push_back(std::pair<int const, int>(432, 24)); v[2].push_back(std::pair<int const, int>(432, 24));
for (int i = 0; i < 5; ++i) for (int i = 0; i < 5; ++i)
test_equal_insertion<boost::unordered_map<int, int> >( test_equal_insertion<boost::unordered_map<int, int> >(
v[i].begin(), v[i].end()); v[i].begin(), v[i].end());
for (int i2 = 0; i2 < 5; ++i2) for (int i2 = 0; i2 < 5; ++i2)
test_equal_insertion<boost::unordered_multimap<int, int> >( test_equal_insertion<boost::unordered_multimap<int, int> >(
v[i2].begin(), v[i2].end()); v[i2].begin(), v[i2].end());
} }
RUN_TESTS() RUN_TESTS()

View File

@ -27,109 +27,108 @@
struct write_pair_type struct write_pair_type
{ {
template <class X1, class X2> template <class X1, class X2>
void operator()(std::pair<X1, X2> const& x) const void operator()(std::pair<X1, X2> const& x) const
{ {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "(" << x.first << "," << x.second BOOST_LIGHTWEIGHT_TEST_OSTREAM << "(" << x.first << "," << x.second << ")";
<< ")"; }
}
} write_pair; } write_pair;
template <class Container> void write_container(Container const& x) template <class Container> void write_container(Container const& x)
{ {
std::for_each(x.begin(), x.end(), write_pair); std::for_each(x.begin(), x.end(), write_pair);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
} }
// Make everything collide - for testing erase in a single bucket. // Make everything collide - for testing erase in a single bucket.
struct collision_hash struct collision_hash
{ {
std::size_t operator()(int) const { return 0; } std::size_t operator()(int) const { return 0; }
}; };
// For testing erase in 2 buckets. // For testing erase in 2 buckets.
struct collision2_hash struct collision2_hash
{ {
std::size_t operator()(int x) const std::size_t operator()(int x) const
{ {
return static_cast<std::size_t>(x & 1); return static_cast<std::size_t>(x & 1);
} }
}; };
// For testing erase in lots of buckets. // For testing erase in lots of buckets.
struct collision3_hash struct collision3_hash
{ {
std::size_t operator()(int x) const { return static_cast<std::size_t>(x); } std::size_t operator()(int x) const { return static_cast<std::size_t>(x); }
}; };
typedef boost::unordered_multimap<int, int, collision_hash, std::equal_to<int>, typedef boost::unordered_multimap<int, int, collision_hash, std::equal_to<int>,
test::allocator1<std::pair<int const, int> > > test::allocator1<std::pair<int const, int> > >
collide_map; collide_map;
typedef boost::unordered_multimap<int, int, collision2_hash, std::equal_to<int>, typedef boost::unordered_multimap<int, int, collision2_hash, std::equal_to<int>,
test::allocator2<std::pair<int const, int> > > test::allocator2<std::pair<int const, int> > >
collide_map2; collide_map2;
typedef boost::unordered_multimap<int, int, collision3_hash, std::equal_to<int>, typedef boost::unordered_multimap<int, int, collision3_hash, std::equal_to<int>,
test::allocator2<std::pair<int const, int> > > test::allocator2<std::pair<int const, int> > >
collide_map3; collide_map3;
typedef collide_map::value_type collide_value; typedef collide_map::value_type collide_value;
typedef test::list<collide_value> collide_list; typedef test::list<collide_value> collide_list;
UNORDERED_AUTO_TEST(empty_range_tests) UNORDERED_AUTO_TEST(empty_range_tests)
{ {
collide_map x; collide_map x;
x.erase(x.begin(), x.end()); x.erase(x.begin(), x.end());
x.erase(x.begin(), x.begin()); x.erase(x.begin(), x.begin());
x.erase(x.end(), x.end()); x.erase(x.end(), x.end());
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
UNORDERED_AUTO_TEST(single_item_tests) UNORDERED_AUTO_TEST(single_item_tests)
{ {
collide_list init; collide_list init;
init.push_back(collide_value(1, 1)); init.push_back(collide_value(1, 1));
collide_map x(init.begin(), init.end()); collide_map x(init.begin(), init.end());
x.erase(x.begin(), x.begin()); x.erase(x.begin(), x.begin());
BOOST_TEST(x.count(1) == 1 && x.size() == 1); BOOST_TEST(x.count(1) == 1 && x.size() == 1);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
x.erase(x.end(), x.end()); x.erase(x.end(), x.end());
BOOST_TEST(x.count(1) == 1 && x.size() == 1); BOOST_TEST(x.count(1) == 1 && x.size() == 1);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
x.erase(x.begin(), x.end()); x.erase(x.begin(), x.end());
BOOST_TEST(x.count(1) == 0 && x.size() == 0); BOOST_TEST(x.count(1) == 0 && x.size() == 0);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
UNORDERED_AUTO_TEST(two_equivalent_item_tests) UNORDERED_AUTO_TEST(two_equivalent_item_tests)
{ {
collide_list init; collide_list init;
init.push_back(collide_value(1, 1)); init.push_back(collide_value(1, 1));
init.push_back(collide_value(1, 2)); init.push_back(collide_value(1, 2));
{ {
collide_map x(init.begin(), init.end()); collide_map x(init.begin(), init.end());
x.erase(x.begin(), x.end()); x.erase(x.begin(), x.end());
BOOST_TEST(x.count(1) == 0 && x.size() == 0); BOOST_TEST(x.count(1) == 0 && x.size() == 0);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
{ {
collide_map x(init.begin(), init.end()); collide_map x(init.begin(), init.end());
int value = test::next(x.begin())->second; int value = test::next(x.begin())->second;
x.erase(x.begin(), test::next(x.begin())); x.erase(x.begin(), test::next(x.begin()));
BOOST_TEST(x.count(1) == 1 && x.size() == 1 && x.begin()->first == 1 && BOOST_TEST(x.count(1) == 1 && x.size() == 1 && x.begin()->first == 1 &&
x.begin()->second == value); x.begin()->second == value);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
{ {
collide_map x(init.begin(), init.end()); collide_map x(init.begin(), init.end());
int value = x.begin()->second; int value = x.begin()->second;
x.erase(test::next(x.begin()), x.end()); x.erase(test::next(x.begin()), x.end());
BOOST_TEST(x.count(1) == 1 && x.size() == 1 && x.begin()->first == 1 && BOOST_TEST(x.count(1) == 1 && x.size() == 1 && x.begin()->first == 1 &&
x.begin()->second == value); x.begin()->second == value);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
} }
// More automated tests... // More automated tests...
@ -137,89 +136,88 @@ UNORDERED_AUTO_TEST(two_equivalent_item_tests)
template <class Range1, class Range2> template <class Range1, class Range2>
bool compare(Range1 const& x, Range2 const& y) bool compare(Range1 const& x, Range2 const& y)
{ {
collide_list a(x.begin(), x.end()); collide_list a(x.begin(), x.end());
collide_list b(y.begin(), y.end()); collide_list b(y.begin(), y.end());
a.sort(); a.sort();
b.sort(); b.sort();
return a == b; return a == b;
} }
template <class Container> template <class Container>
bool general_erase_range_test(Container& x, std::size_t start, std::size_t end) bool general_erase_range_test(Container& x, std::size_t start, std::size_t end)
{ {
collide_list l(x.begin(), x.end()); collide_list l(x.begin(), x.end());
l.erase(test::next(l.begin(), start), test::next(l.begin(), end)); l.erase(test::next(l.begin(), start), test::next(l.begin(), end));
x.erase(test::next(x.begin(), start), test::next(x.begin(), end)); x.erase(test::next(x.begin(), start), test::next(x.begin(), end));
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
return compare(l, x); return compare(l, x);
} }
template <class Container> void erase_subrange_tests(Container const& x) template <class Container> void erase_subrange_tests(Container const& x)
{ {
for (std::size_t length = 0; length < x.size(); ++length) { for (std::size_t length = 0; length < x.size(); ++length) {
for (std::size_t position = 0; position < x.size() - length; for (std::size_t position = 0; position < x.size() - length; ++position) {
++position) { Container y(x);
Container y(x); collide_list init(y.begin(), y.end());
collide_list init(y.begin(), y.end()); if (!general_erase_range_test(y, position, position + length)) {
if (!general_erase_range_test(y, position, position + length)) { BOOST_ERROR("general_erase_range_test failed.");
BOOST_ERROR("general_erase_range_test failed."); BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Erase: [" << position << ","
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Erase: [" << position << "," << position + length << ")\n";
<< position + length << ")\n"; write_container(init);
write_container(init); write_container(y);
write_container(y); }
}
}
} }
}
} }
template <class Container> template <class Container>
void x_by_y_erase_range_tests(Container*, int values, int duplicates) void x_by_y_erase_range_tests(Container*, int values, int duplicates)
{ {
Container y; Container y;
for (int i = 0; i < values; ++i) { for (int i = 0; i < values; ++i) {
for (int j = 0; j < duplicates; ++j) { for (int j = 0; j < duplicates; ++j) {
y.insert(collide_value(i, j)); y.insert(collide_value(i, j));
}
} }
}
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Values: " << values BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Values: " << values
<< ", Duplicates: " << duplicates << "\n"; << ", Duplicates: " << duplicates << "\n";
erase_subrange_tests(y); erase_subrange_tests(y);
} }
template <class Container> template <class Container>
void exhaustive_erase_tests(Container* x, int num_values, int num_duplicated) void exhaustive_erase_tests(Container* x, int num_values, int num_duplicated)
{ {
for (int i = 0; i < num_values; ++i) { for (int i = 0; i < num_values; ++i) {
for (int j = 0; j < num_duplicated; ++j) { for (int j = 0; j < num_duplicated; ++j) {
x_by_y_erase_range_tests(x, i, j); x_by_y_erase_range_tests(x, i, j);
}
} }
}
} }
UNORDERED_AUTO_TEST(exhaustive_collide_tests) UNORDERED_AUTO_TEST(exhaustive_collide_tests)
{ {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "exhaustive_collide_tests:\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "exhaustive_collide_tests:\n";
collide_map m; collide_map m;
exhaustive_erase_tests((collide_map*)0, 4, 4); exhaustive_erase_tests((collide_map*)0, 4, 4);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
} }
UNORDERED_AUTO_TEST(exhaustive_collide2_tests) UNORDERED_AUTO_TEST(exhaustive_collide2_tests)
{ {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "exhaustive_collide2_tests:\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "exhaustive_collide2_tests:\n";
exhaustive_erase_tests((collide_map2*)0, 8, 4); exhaustive_erase_tests((collide_map2*)0, 8, 4);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
} }
UNORDERED_AUTO_TEST(exhaustive_collide3_tests) UNORDERED_AUTO_TEST(exhaustive_collide3_tests)
{ {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "exhaustive_collide3_tests:\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "exhaustive_collide3_tests:\n";
exhaustive_erase_tests((collide_map3*)0, 8, 4); exhaustive_erase_tests((collide_map3*)0, 8, 4);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
} }
RUN_TESTS() RUN_TESTS()

View File

@ -22,254 +22,251 @@
namespace erase_tests { namespace erase_tests {
test::seed_t initialize_seed(85638); test::seed_t initialize_seed(85638);
template <class Container> template <class Container>
void erase_tests1(Container*, test::random_generator generator) void erase_tests1(Container*, test::random_generator generator)
{ {
typedef BOOST_DEDUCED_TYPENAME Container::iterator iterator; typedef BOOST_DEDUCED_TYPENAME Container::iterator iterator;
typedef BOOST_DEDUCED_TYPENAME Container::const_iterator c_iterator; typedef BOOST_DEDUCED_TYPENAME Container::const_iterator c_iterator;
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Erase by key.\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Erase by key.\n";
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<Container> v(1000, generator); test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end()); Container x(v.begin(), v.end());
int iterations = 0; int iterations = 0;
for (BOOST_DEDUCED_TYPENAME test::random_values<Container>::iterator for (BOOST_DEDUCED_TYPENAME test::random_values<Container>::iterator it =
it = v.begin(); v.begin();
it != v.end(); ++it) { it != v.end(); ++it) {
std::size_t count = x.count(test::get_key<Container>(*it)); std::size_t count = x.count(test::get_key<Container>(*it));
std::size_t old_size = x.size(); std::size_t old_size = x.size();
BOOST_TEST(count == x.erase(test::get_key<Container>(*it))); BOOST_TEST(count == x.erase(test::get_key<Container>(*it)));
BOOST_TEST(x.size() == old_size - count); BOOST_TEST(x.size() == old_size - count);
BOOST_TEST(x.count(test::get_key<Container>(*it)) == 0); BOOST_TEST(x.count(test::get_key<Container>(*it)) == 0);
BOOST_TEST(x.find(test::get_key<Container>(*it)) == x.end()); BOOST_TEST(x.find(test::get_key<Container>(*it)) == x.end());
if (++iterations % 20 == 0) if (++iterations % 20 == 0)
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
} }
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "erase(begin()).\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "erase(begin()).\n";
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<Container> v(1000, generator); test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end()); Container x(v.begin(), v.end());
std::size_t size = x.size(); std::size_t size = x.size();
int iterations = 0; int iterations = 0;
while (size > 0 && !x.empty()) { while (size > 0 && !x.empty()) {
BOOST_DEDUCED_TYPENAME Container::key_type key = BOOST_DEDUCED_TYPENAME Container::key_type key =
test::get_key<Container>(*x.begin()); test::get_key<Container>(*x.begin());
std::size_t count = x.count(key); std::size_t count = x.count(key);
iterator pos = x.erase(x.begin()); iterator pos = x.erase(x.begin());
--size; --size;
BOOST_TEST(pos == x.begin()); BOOST_TEST(pos == x.begin());
BOOST_TEST(x.count(key) == count - 1); BOOST_TEST(x.count(key) == count - 1);
BOOST_TEST(x.size() == size); BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0) if (++iterations % 20 == 0)
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
BOOST_TEST(x.empty()); BOOST_TEST(x.empty());
} }
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "erase(random position).\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "erase(random position).\n";
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<Container> v(1000, generator); test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end()); Container x(v.begin(), v.end());
std::size_t size = x.size(); std::size_t size = x.size();
int iterations = 0; int iterations = 0;
while (size > 0 && !x.empty()) { while (size > 0 && !x.empty()) {
std::size_t index = test::random_value(x.size()); std::size_t index = test::random_value(x.size());
c_iterator prev, pos, next; c_iterator prev, pos, next;
if (index == 0) { if (index == 0) {
prev = pos = x.begin(); prev = pos = x.begin();
} else { } else {
prev = test::next(x.begin(), index - 1); prev = test::next(x.begin(), index - 1);
pos = test::next(prev); pos = test::next(prev);
}
next = test::next(pos);
BOOST_DEDUCED_TYPENAME Container::key_type key =
test::get_key<Container>(*pos);
std::size_t count = x.count(key);
BOOST_TEST(count > 0);
BOOST_TEST(next == x.erase(pos));
--size;
if (size > 0)
BOOST_TEST(
index == 0 ? next == x.begin() : next == test::next(prev));
BOOST_TEST(x.count(key) == count - 1);
if (x.count(key) != count - 1) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << count << " => "
<< x.count(key) << std::endl;
}
BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
} }
BOOST_TEST(x.empty()); next = test::next(pos);
BOOST_DEDUCED_TYPENAME Container::key_type key =
test::get_key<Container>(*pos);
std::size_t count = x.count(key);
BOOST_TEST(count > 0);
BOOST_TEST(next == x.erase(pos));
--size;
if (size > 0)
BOOST_TEST(index == 0 ? next == x.begin() : next == test::next(prev));
BOOST_TEST(x.count(key) == count - 1);
if (x.count(key) != count - 1) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << count << " => " << x.count(key)
<< std::endl;
}
BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
} }
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "erase(ranges).\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "erase(ranges).\n";
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<Container> v(500, generator); test::random_values<Container> v(500, generator);
Container x(v.begin(), v.end()); Container x(v.begin(), v.end());
std::size_t size = x.size(); std::size_t size = x.size();
// I'm actually stretching it a little here, as the standard says it // I'm actually stretching it a little here, as the standard says it
// returns 'the iterator immediately following the erase elements' // returns 'the iterator immediately following the erase elements'
// and if nothing is erased, then there's nothing to follow. But I // and if nothing is erased, then there's nothing to follow. But I
// think this is the only sensible option... // think this is the only sensible option...
BOOST_TEST(x.erase(x.end(), x.end()) == x.end()); BOOST_TEST(x.erase(x.end(), x.end()) == x.end());
BOOST_TEST(x.erase(x.begin(), x.begin()) == x.begin()); BOOST_TEST(x.erase(x.begin(), x.begin()) == x.begin());
BOOST_TEST(x.size() == size); BOOST_TEST(x.size() == size);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
BOOST_TEST(x.erase(x.begin(), x.end()) == x.end()); BOOST_TEST(x.erase(x.begin(), x.end()) == x.end());
BOOST_TEST(x.empty()); BOOST_TEST(x.empty());
BOOST_TEST(x.begin() == x.end()); BOOST_TEST(x.begin() == x.end());
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
BOOST_TEST(x.erase(x.begin(), x.end()) == x.begin()); BOOST_TEST(x.erase(x.begin(), x.end()) == x.begin());
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "erase(random ranges).\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "erase(random ranges).\n";
{ {
test::check_instances check_; test::check_instances check_;
Container x; Container x;
for (int i = 0; i < 100; ++i) { for (int i = 0; i < 100; ++i) {
test::random_values<Container> v(1000, generator); test::random_values<Container> v(1000, generator);
x.insert(v.begin(), v.end()); x.insert(v.begin(), v.end());
// Note that erase only invalidates the erased iterators. // Note that erase only invalidates the erased iterators.
std::vector<c_iterator> iterators; std::vector<c_iterator> iterators;
for (c_iterator it = x.cbegin(); it != x.cend(); ++it) { for (c_iterator it = x.cbegin(); it != x.cend(); ++it) {
iterators.push_back(it); iterators.push_back(it);
}
iterators.push_back(x.cend());
while (iterators.size() > 1) {
std::size_t start = test::random_value(iterators.size());
std::size_t length =
test::random_value(iterators.size() - start);
x.erase(iterators[start], iterators[start + length]);
iterators.erase(test::next(iterators.begin(), start),
test::next(iterators.begin(), start + length));
BOOST_TEST(x.size() == iterators.size() - 1);
BOOST_DEDUCED_TYPENAME std::vector<c_iterator>::const_iterator
i2 = iterators.begin();
for (c_iterator i1 = x.cbegin(); i1 != x.cend(); ++i1) {
BOOST_TEST(i1 == *i2);
++i2;
}
BOOST_TEST(x.cend() == *i2);
test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
} }
iterators.push_back(x.cend());
while (iterators.size() > 1) {
std::size_t start = test::random_value(iterators.size());
std::size_t length = test::random_value(iterators.size() - start);
x.erase(iterators[start], iterators[start + length]);
iterators.erase(test::next(iterators.begin(), start),
test::next(iterators.begin(), start + length));
BOOST_TEST(x.size() == iterators.size() - 1);
BOOST_DEDUCED_TYPENAME std::vector<c_iterator>::const_iterator i2 =
iterators.begin();
for (c_iterator i1 = x.cbegin(); i1 != x.cend(); ++i1) {
BOOST_TEST(i1 == *i2);
++i2;
}
BOOST_TEST(x.cend() == *i2);
test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
}
} }
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "quick_erase(begin()).\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "quick_erase(begin()).\n";
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<Container> v(1000, generator); test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end()); Container x(v.begin(), v.end());
std::size_t size = x.size(); std::size_t size = x.size();
int iterations = 0; int iterations = 0;
while (size > 0 && !x.empty()) { while (size > 0 && !x.empty()) {
BOOST_DEDUCED_TYPENAME Container::key_type key = BOOST_DEDUCED_TYPENAME Container::key_type key =
test::get_key<Container>(*x.begin()); test::get_key<Container>(*x.begin());
std::size_t count = x.count(key); std::size_t count = x.count(key);
x.quick_erase(x.begin()); x.quick_erase(x.begin());
--size; --size;
BOOST_TEST(x.count(key) == count - 1); BOOST_TEST(x.count(key) == count - 1);
BOOST_TEST(x.size() == size); BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0) if (++iterations % 20 == 0)
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
BOOST_TEST(x.empty()); BOOST_TEST(x.empty());
} }
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "quick_erase(random position).\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "quick_erase(random position).\n";
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<Container> v(1000, generator); test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end()); Container x(v.begin(), v.end());
std::size_t size = x.size(); std::size_t size = x.size();
int iterations = 0; int iterations = 0;
while (size > 0 && !x.empty()) { while (size > 0 && !x.empty()) {
std::size_t index = test::random_value(x.size()); std::size_t index = test::random_value(x.size());
BOOST_DEDUCED_TYPENAME Container::const_iterator prev, pos, next; BOOST_DEDUCED_TYPENAME Container::const_iterator prev, pos, next;
if (index == 0) { if (index == 0) {
prev = pos = x.begin(); prev = pos = x.begin();
} else { } else {
prev = test::next(x.begin(), index - 1); prev = test::next(x.begin(), index - 1);
pos = test::next(prev); pos = test::next(prev);
}
next = test::next(pos);
BOOST_DEDUCED_TYPENAME Container::key_type key =
test::get_key<Container>(*pos);
std::size_t count = x.count(key);
BOOST_TEST(count > 0);
x.quick_erase(pos);
--size;
if (size > 0)
BOOST_TEST(
index == 0 ? next == x.begin() : next == test::next(prev));
BOOST_TEST(x.count(key) == count - 1);
if (x.count(key) != count - 1) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << count << " => "
<< x.count(key) << std::endl;
}
BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
} }
BOOST_TEST(x.empty()); next = test::next(pos);
BOOST_DEDUCED_TYPENAME Container::key_type key =
test::get_key<Container>(*pos);
std::size_t count = x.count(key);
BOOST_TEST(count > 0);
x.quick_erase(pos);
--size;
if (size > 0)
BOOST_TEST(index == 0 ? next == x.begin() : next == test::next(prev));
BOOST_TEST(x.count(key) == count - 1);
if (x.count(key) != count - 1) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << count << " => " << x.count(key)
<< std::endl;
}
BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
} }
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "clear().\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "clear().\n";
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<Container> v(500, generator); test::random_values<Container> v(500, generator);
Container x(v.begin(), v.end()); Container x(v.begin(), v.end());
x.clear(); x.clear();
BOOST_TEST(x.empty()); BOOST_TEST(x.empty());
BOOST_TEST(x.begin() == x.end()); BOOST_TEST(x.begin() == x.end());
} }
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
} }
boost::unordered_set<test::object, test::hash, test::equal_to, boost::unordered_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set; test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to, boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset; test::allocator2<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to, boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_map; test::allocator1<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash, boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator2<test::object> >* test_multimap; test::equal_to, test::allocator2<test::object> >* test_multimap;
using test::default_generator; using test::default_generator;
using test::generate_collisions; using test::generate_collisions;
using test::limited_range; using test::limited_range;
UNORDERED_TEST( UNORDERED_TEST(
erase_tests1, ((test_set)(test_multiset)(test_map)(test_multimap))( erase_tests1, ((test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range))) (default_generator)(generate_collisions)(limited_range)))
} }
RUN_TESTS() RUN_TESTS()

View File

@ -21,118 +21,118 @@
namespace extract_tests { namespace extract_tests {
test::seed_t initialize_seed(85638); test::seed_t initialize_seed(85638);
template <class Container> template <class Container>
void extract_tests1(Container*, test::random_generator generator) void extract_tests1(Container*, test::random_generator generator)
{ {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Extract by key.\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Extract by key.\n";
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<Container> v(1000, generator); test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end()); Container x(v.begin(), v.end());
int iterations = 0; int iterations = 0;
for (BOOST_DEDUCED_TYPENAME test::random_values<Container>::iterator for (BOOST_DEDUCED_TYPENAME test::random_values<Container>::iterator it =
it = v.begin(); v.begin();
it != v.end(); ++it) { it != v.end(); ++it) {
std::size_t count = x.count(test::get_key<Container>(*it)); std::size_t count = x.count(test::get_key<Container>(*it));
std::size_t old_size = x.size(); std::size_t old_size = x.size();
std::size_t new_count = count ? count - 1 : count; std::size_t new_count = count ? count - 1 : count;
std::size_t new_size = count ? old_size - 1 : old_size; std::size_t new_size = count ? old_size - 1 : old_size;
typename Container::node_type n = typename Container::node_type n =
x.extract(test::get_key<Container>(*it)); x.extract(test::get_key<Container>(*it));
BOOST_TEST((n ? true : false) == (count ? true : false)); BOOST_TEST((n ? true : false) == (count ? true : false));
BOOST_TEST(x.size() == new_size); BOOST_TEST(x.size() == new_size);
BOOST_TEST(x.count(test::get_key<Container>(*it)) == new_count); BOOST_TEST(x.count(test::get_key<Container>(*it)) == new_count);
if (!new_count) { if (!new_count) {
BOOST_TEST(x.find(test::get_key<Container>(*it)) == x.end()); BOOST_TEST(x.find(test::get_key<Container>(*it)) == x.end());
} else { } else {
BOOST_TEST(x.find(test::get_key<Container>(*it)) != x.end()); BOOST_TEST(x.find(test::get_key<Container>(*it)) != x.end());
}
if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
} }
BOOST_TEST(x.empty()); if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
} }
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "extract(begin()).\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "extract(begin()).\n";
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<Container> v(1000, generator); test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end()); Container x(v.begin(), v.end());
std::size_t size = x.size(); std::size_t size = x.size();
int iterations = 0; int iterations = 0;
while (size > 0 && !x.empty()) { while (size > 0 && !x.empty()) {
BOOST_DEDUCED_TYPENAME Container::key_type key = BOOST_DEDUCED_TYPENAME Container::key_type key =
test::get_key<Container>(*x.begin()); test::get_key<Container>(*x.begin());
std::size_t count = x.count(key); std::size_t count = x.count(key);
typename Container::node_type n = x.extract(x.begin()); typename Container::node_type n = x.extract(x.begin());
BOOST_TEST(n); BOOST_TEST(n);
--size; --size;
BOOST_TEST(x.count(key) == count - 1); BOOST_TEST(x.count(key) == count - 1);
BOOST_TEST(x.size() == size); BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0) if (++iterations % 20 == 0)
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
BOOST_TEST(x.empty()); BOOST_TEST(x.empty());
} }
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "extract(random position).\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "extract(random position).\n";
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<Container> v(1000, generator); test::random_values<Container> v(1000, generator);
Container x(v.begin(), v.end()); Container x(v.begin(), v.end());
std::size_t size = x.size(); std::size_t size = x.size();
int iterations = 0; int iterations = 0;
while (size > 0 && !x.empty()) { while (size > 0 && !x.empty()) {
using namespace std; using namespace std;
int index = rand() % (int)x.size(); int index = rand() % (int)x.size();
BOOST_DEDUCED_TYPENAME Container::const_iterator prev, pos, next; BOOST_DEDUCED_TYPENAME Container::const_iterator prev, pos, next;
if (index == 0) { if (index == 0) {
prev = pos = x.begin(); prev = pos = x.begin();
} else { } else {
prev = boost::next(x.begin(), index - 1); prev = boost::next(x.begin(), index - 1);
pos = boost::next(prev); pos = boost::next(prev);
}
next = boost::next(pos);
BOOST_DEDUCED_TYPENAME Container::key_type key =
test::get_key<Container>(*pos);
std::size_t count = x.count(key);
typename Container::node_type n = x.extract(pos);
BOOST_TEST(n);
--size;
if (size > 0)
BOOST_TEST(
index == 0 ? next == x.begin() : next == boost::next(prev));
BOOST_TEST(x.count(key) == count - 1);
BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
} }
BOOST_TEST(x.empty()); next = boost::next(pos);
BOOST_DEDUCED_TYPENAME Container::key_type key =
test::get_key<Container>(*pos);
std::size_t count = x.count(key);
typename Container::node_type n = x.extract(pos);
BOOST_TEST(n);
--size;
if (size > 0)
BOOST_TEST(
index == 0 ? next == x.begin() : next == boost::next(prev));
BOOST_TEST(x.count(key) == count - 1);
BOOST_TEST(x.size() == size);
if (++iterations % 20 == 0)
test::check_equivalent_keys(x);
}
BOOST_TEST(x.empty());
} }
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\n";
} }
boost::unordered_set<test::object, test::hash, test::equal_to, boost::unordered_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set; test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to, boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset; test::allocator2<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to, boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_map; test::allocator1<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash, boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator2<test::object> >* test_multimap; test::equal_to, test::allocator2<test::object> >* test_multimap;
using test::default_generator; using test::default_generator;
using test::generate_collisions; using test::generate_collisions;
UNORDERED_TEST( UNORDERED_TEST(
extract_tests1, ((test_set)(test_multiset)(test_map)(test_multimap))( extract_tests1, ((test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions))) (default_generator)(generate_collisions)))
} }
RUN_TESTS() RUN_TESTS()

View File

@ -18,109 +18,106 @@
namespace find_tests { namespace find_tests {
test::seed_t initialize_seed(78937); test::seed_t initialize_seed(78937);
template <class X> void find_tests1(X*, test::random_generator generator) template <class X> void find_tests1(X*, test::random_generator generator)
{ {
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator; typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<X> v(500, generator); test::random_values<X> v(500, generator);
X x(v.begin(), v.end()); X x(v.begin(), v.end());
X const& x_const = x; X const& x_const = x;
test::ordered<X> tracker = test::create_ordered(x); test::ordered<X> tracker = test::create_ordered(x);
tracker.insert_range(v.begin(), v.end()); tracker.insert_range(v.begin(), v.end());
for (BOOST_DEDUCED_TYPENAME test::ordered<X>::const_iterator it1 = for (BOOST_DEDUCED_TYPENAME test::ordered<X>::const_iterator it1 =
tracker.begin(); tracker.begin();
it1 != tracker.end(); ++it1) { it1 != tracker.end(); ++it1) {
BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key<X>(*it1); BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key<X>(*it1);
BOOST_DEDUCED_TYPENAME X::const_iterator const_pos = BOOST_DEDUCED_TYPENAME X::const_iterator const_pos = x_const.find(key);
x_const.find(key); iterator pos = x.find(key);
iterator pos = x.find(key); BOOST_TEST(const_pos != x_const.end());
BOOST_TEST(const_pos != x_const.end()); BOOST_TEST(const_pos != x_const.end() &&
BOOST_TEST(const_pos != x_const.end() && x_const.key_eq()(key, test::get_key<X>(*const_pos)));
x_const.key_eq()(key, test::get_key<X>(*const_pos))); BOOST_TEST(pos != x.end());
BOOST_TEST(pos != x.end()); BOOST_TEST(pos != x.end() && x.key_eq()(key, test::get_key<X>(*pos)));
BOOST_TEST(
pos != x.end() && x.key_eq()(key, test::get_key<X>(*pos)));
BOOST_TEST(x.count(key) == tracker.count(key)); BOOST_TEST(x.count(key) == tracker.count(key));
test::compare_pairs(x.equal_range(key), tracker.equal_range(key), test::compare_pairs(x.equal_range(key), tracker.equal_range(key),
(BOOST_DEDUCED_TYPENAME X::value_type*)0); (BOOST_DEDUCED_TYPENAME X::value_type*)0);
test::compare_pairs(x_const.equal_range(key), test::compare_pairs(x_const.equal_range(key), tracker.equal_range(key),
tracker.equal_range(key), (BOOST_DEDUCED_TYPENAME X::value_type*)0);
(BOOST_DEDUCED_TYPENAME X::value_type*)0); }
}
test::random_values<X> v2(500, generator);
test::random_values<X> v2(500, generator); for (BOOST_DEDUCED_TYPENAME test::random_values<X>::const_iterator it2 =
for (BOOST_DEDUCED_TYPENAME test::random_values<X>::const_iterator it2 = v2.begin();
v2.begin(); it2 != v2.end(); ++it2) {
it2 != v2.end(); ++it2) { BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key<X>(*it2);
BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key<X>(*it2); if (tracker.find(test::get_key<X>(key)) == tracker.end()) {
if (tracker.find(test::get_key<X>(key)) == tracker.end()) { BOOST_TEST(x.find(key) == x.end());
BOOST_TEST(x.find(key) == x.end()); BOOST_TEST(x_const.find(key) == x_const.end());
BOOST_TEST(x_const.find(key) == x_const.end()); BOOST_TEST(x.count(key) == 0);
BOOST_TEST(x.count(key) == 0); std::pair<iterator, iterator> range = x.equal_range(key);
std::pair<iterator, iterator> range = x.equal_range(key); BOOST_TEST(range.first == range.second);
BOOST_TEST(range.first == range.second);
}
} }
}
} }
{ {
test::check_instances check_; test::check_instances check_;
X x; X x;
test::random_values<X> v2(5, generator); test::random_values<X> v2(5, generator);
for (BOOST_DEDUCED_TYPENAME test::random_values<X>::const_iterator it3 = for (BOOST_DEDUCED_TYPENAME test::random_values<X>::const_iterator it3 =
v2.begin(); v2.begin();
it3 != v2.end(); ++it3) { it3 != v2.end(); ++it3) {
BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key<X>(*it3); BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key<X>(*it3);
BOOST_TEST(x.find(key) == x.end()); BOOST_TEST(x.find(key) == x.end());
BOOST_TEST(x.count(key) == 0); BOOST_TEST(x.count(key) == 0);
std::pair<iterator, iterator> range = x.equal_range(key); std::pair<iterator, iterator> range = x.equal_range(key);
BOOST_TEST(range.first == range.second); BOOST_TEST(range.first == range.second);
} }
} }
} }
struct compatible_key struct compatible_key
{ {
test::object o_; test::object o_;
compatible_key(test::object const& o) : o_(o) {} compatible_key(test::object const& o) : o_(o) {}
}; };
struct compatible_hash struct compatible_hash
{ {
test::hash hash_; test::hash hash_;
std::size_t operator()(compatible_key const& k) const std::size_t operator()(compatible_key const& k) const
{ {
return hash_(k.o_); return hash_(k.o_);
} }
}; };
struct compatible_predicate struct compatible_predicate
{ {
test::equal_to equal_; test::equal_to equal_;
bool operator()(compatible_key const& k1, compatible_key const& k2) const bool operator()(compatible_key const& k1, compatible_key const& k2) const
{ {
return equal_(k1.o_, k2.o_); return equal_(k1.o_, k2.o_);
} }
}; };
template <class X> template <class X>
void find_compatible_keys_test(X*, test::random_generator generator) void find_compatible_keys_test(X*, test::random_generator generator)
{ {
typedef BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator typedef BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator
value_iterator; value_iterator;
test::random_values<X> v(500, generator); test::random_values<X> v(500, generator);
X x(v.begin(), v.end()); X x(v.begin(), v.end());
@ -128,35 +125,35 @@ void find_compatible_keys_test(X*, test::random_generator generator)
compatible_predicate eq; compatible_predicate eq;
for (value_iterator it = v.begin(), end = v.end(); it != end; ++it) { for (value_iterator it = v.begin(), end = v.end(); it != end; ++it) {
BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key<X>(*it); BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key<X>(*it);
BOOST_TEST(x.find(key) == x.find(compatible_key(key), h, eq)); BOOST_TEST(x.find(key) == x.find(compatible_key(key), h, eq));
} }
test::random_values<X> v2(20, generator); test::random_values<X> v2(20, generator);
for (value_iterator it = v2.begin(), end = v2.end(); it != end; ++it) { for (value_iterator it = v2.begin(), end = v2.end(); it != end; ++it) {
BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key<X>(*it); BOOST_DEDUCED_TYPENAME X::key_type key = test::get_key<X>(*it);
BOOST_TEST(x.find(key) == x.find(compatible_key(key), h, eq)); BOOST_TEST(x.find(key) == x.find(compatible_key(key), h, eq));
} }
} }
boost::unordered_set<test::object, test::hash, test::equal_to, boost::unordered_set<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_set; test::allocator2<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to, boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_multiset; test::allocator1<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to, boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_map; test::allocator2<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash, boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator1<test::object> >* test_multimap; test::equal_to, test::allocator1<test::object> >* test_multimap;
using test::default_generator; using test::default_generator;
using test::generate_collisions; using test::generate_collisions;
using test::limited_range; using test::limited_range;
UNORDERED_TEST( UNORDERED_TEST(
find_tests1, ((test_set)(test_multiset)(test_map)(test_multimap))( find_tests1, ((test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range))) (default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(find_compatible_keys_test, UNORDERED_TEST(find_compatible_keys_test,
((test_set)(test_multiset)(test_map)(test_multimap))( ((test_set)(test_multiset)(test_map)(test_multimap))(
(default_generator)(generate_collisions)(limited_range))) (default_generator)(generate_collisions)(limited_range)))
} }

View File

@ -12,41 +12,41 @@
template <typename T> template <typename T>
void call_swap(boost::unordered_map<T, T>& x, boost::unordered_map<T, T>& y) void call_swap(boost::unordered_map<T, T>& x, boost::unordered_map<T, T>& y)
{ {
swap(x, y); swap(x, y);
} }
template <typename T> template <typename T>
bool call_equals(boost::unordered_map<T, T>& x, boost::unordered_map<T, T>& y) bool call_equals(boost::unordered_map<T, T>& x, boost::unordered_map<T, T>& y)
{ {
return x == y; return x == y;
} }
template <typename T> template <typename T>
bool call_not_equals( bool call_not_equals(
boost::unordered_map<T, T>& x, boost::unordered_map<T, T>& y) boost::unordered_map<T, T>& x, boost::unordered_map<T, T>& y)
{ {
return x != y; return x != y;
} }
template <typename T> template <typename T>
void call_swap( void call_swap(
boost::unordered_multimap<T, T>& x, boost::unordered_multimap<T, T>& y) boost::unordered_multimap<T, T>& x, boost::unordered_multimap<T, T>& y)
{ {
swap(x, y); swap(x, y);
} }
template <typename T> template <typename T>
bool call_equals( bool call_equals(
boost::unordered_multimap<T, T>& x, boost::unordered_multimap<T, T>& y) boost::unordered_multimap<T, T>& x, boost::unordered_multimap<T, T>& y)
{ {
return x == y; return x == y;
} }
template <typename T> template <typename T>
bool call_not_equals( bool call_not_equals(
boost::unordered_multimap<T, T>& x, boost::unordered_multimap<T, T>& y) boost::unordered_multimap<T, T>& x, boost::unordered_multimap<T, T>& y)
{ {
return x != y; return x != y;
} }
#include <boost/unordered_map.hpp> #include <boost/unordered_map.hpp>
@ -57,27 +57,27 @@ typedef boost::unordered_multimap<int, int> int_multimap;
UNORDERED_AUTO_TEST(use_map_fwd_declared_function) UNORDERED_AUTO_TEST(use_map_fwd_declared_function)
{ {
int_map x, y; int_map x, y;
x[1] = 2; x[1] = 2;
y[2] = 1; y[2] = 1;
call_swap(x, y); call_swap(x, y);
BOOST_TEST(y.find(1) != y.end() && y.find(1)->second == 2); BOOST_TEST(y.find(1) != y.end() && y.find(1)->second == 2);
BOOST_TEST(y.find(2) == y.end()); BOOST_TEST(y.find(2) == y.end());
BOOST_TEST(x.find(1) == x.end()); BOOST_TEST(x.find(1) == x.end());
BOOST_TEST(x.find(2) != x.end() && x.find(2)->second == 1); BOOST_TEST(x.find(2) != x.end() && x.find(2)->second == 1);
BOOST_TEST(!call_equals(x, y)); BOOST_TEST(!call_equals(x, y));
BOOST_TEST(call_not_equals(x, y)); BOOST_TEST(call_not_equals(x, y));
} }
UNORDERED_AUTO_TEST(use_multimap_fwd_declared_function) UNORDERED_AUTO_TEST(use_multimap_fwd_declared_function)
{ {
int_multimap x, y; int_multimap x, y;
call_swap(x, y); call_swap(x, y);
BOOST_TEST(call_equals(x, y)); BOOST_TEST(call_equals(x, y));
BOOST_TEST(!call_not_equals(x, y)); BOOST_TEST(!call_not_equals(x, y));
} }
RUN_TESTS() RUN_TESTS()

View File

@ -11,55 +11,55 @@
struct true_type struct true_type
{ {
char x[100]; char x[100];
}; };
struct false_type struct false_type
{ {
char x; char x;
}; };
false_type is_unordered_set_impl(void*); false_type is_unordered_set_impl(void*);
template <class Value, class Hash, class Pred, class Alloc> template <class Value, class Hash, class Pred, class Alloc>
true_type is_unordered_set_impl( true_type is_unordered_set_impl(
boost::unordered_set<Value, Hash, Pred, Alloc>*); boost::unordered_set<Value, Hash, Pred, Alloc>*);
template <typename T> template <typename T>
void call_swap(boost::unordered_set<T>& x, boost::unordered_set<T>& y) void call_swap(boost::unordered_set<T>& x, boost::unordered_set<T>& y)
{ {
swap(x, y); swap(x, y);
} }
template <typename T> template <typename T>
bool call_equals(boost::unordered_set<T>& x, boost::unordered_set<T>& y) bool call_equals(boost::unordered_set<T>& x, boost::unordered_set<T>& y)
{ {
return x == y; return x == y;
} }
template <typename T> template <typename T>
bool call_not_equals(boost::unordered_set<T>& x, boost::unordered_set<T>& y) bool call_not_equals(boost::unordered_set<T>& x, boost::unordered_set<T>& y)
{ {
return x != y; return x != y;
} }
template <typename T> template <typename T>
void call_swap(boost::unordered_multiset<T>& x, boost::unordered_multiset<T>& y) void call_swap(boost::unordered_multiset<T>& x, boost::unordered_multiset<T>& y)
{ {
swap(x, y); swap(x, y);
} }
template <typename T> template <typename T>
bool call_equals( bool call_equals(
boost::unordered_multiset<T>& x, boost::unordered_multiset<T>& y) boost::unordered_multiset<T>& x, boost::unordered_multiset<T>& y)
{ {
return x == y; return x == y;
} }
template <typename T> template <typename T>
bool call_not_equals( bool call_not_equals(
boost::unordered_multiset<T>& x, boost::unordered_multiset<T>& y) boost::unordered_multiset<T>& x, boost::unordered_multiset<T>& y)
{ {
return x != y; return x != y;
} }
#include "../helpers/test.hpp" #include "../helpers/test.hpp"
@ -69,42 +69,42 @@ typedef boost::unordered_multiset<int> int_multiset;
UNORDERED_AUTO_TEST(use_fwd_declared_trait_without_definition) UNORDERED_AUTO_TEST(use_fwd_declared_trait_without_definition)
{ {
BOOST_TEST(sizeof(is_unordered_set_impl((int_set*)0)) == sizeof(true_type)); BOOST_TEST(sizeof(is_unordered_set_impl((int_set*)0)) == sizeof(true_type));
} }
#include <boost/unordered_set.hpp> #include <boost/unordered_set.hpp>
UNORDERED_AUTO_TEST(use_fwd_declared_trait) UNORDERED_AUTO_TEST(use_fwd_declared_trait)
{ {
boost::unordered_set<int> x; boost::unordered_set<int> x;
BOOST_TEST(sizeof(is_unordered_set_impl(&x)) == sizeof(true_type)); BOOST_TEST(sizeof(is_unordered_set_impl(&x)) == sizeof(true_type));
BOOST_TEST(sizeof(is_unordered_set_impl((int*)0)) == sizeof(false_type)); BOOST_TEST(sizeof(is_unordered_set_impl((int*)0)) == sizeof(false_type));
} }
UNORDERED_AUTO_TEST(use_set_fwd_declared_function) UNORDERED_AUTO_TEST(use_set_fwd_declared_function)
{ {
int_set x, y; int_set x, y;
x.insert(1); x.insert(1);
y.insert(2); y.insert(2);
call_swap(x, y); call_swap(x, y);
BOOST_TEST(y.find(1) != y.end()); BOOST_TEST(y.find(1) != y.end());
BOOST_TEST(y.find(2) == y.end()); BOOST_TEST(y.find(2) == y.end());
BOOST_TEST(x.find(1) == x.end()); BOOST_TEST(x.find(1) == x.end());
BOOST_TEST(x.find(2) != x.end()); BOOST_TEST(x.find(2) != x.end());
BOOST_TEST(!call_equals(x, y)); BOOST_TEST(!call_equals(x, y));
BOOST_TEST(call_not_equals(x, y)); BOOST_TEST(call_not_equals(x, y));
} }
UNORDERED_AUTO_TEST(use_multiset_fwd_declared_function) UNORDERED_AUTO_TEST(use_multiset_fwd_declared_function)
{ {
int_multiset x, y; int_multiset x, y;
call_swap(x, y); call_swap(x, y);
BOOST_TEST(call_equals(x, y)); BOOST_TEST(call_equals(x, y));
BOOST_TEST(!call_not_equals(x, y)); BOOST_TEST(!call_not_equals(x, y));
} }
RUN_TESTS() RUN_TESTS()

View File

@ -13,52 +13,52 @@
#include <utility> #include <utility>
namespace x { namespace x {
struct D struct D
{ {
boost::unordered_map<D, D> x; boost::unordered_map<D, D> x;
}; };
} }
namespace incomplete_test { namespace incomplete_test {
// Declare, but don't define some types. // Declare, but don't define some types.
struct value; struct value;
struct hash; struct hash;
struct equals; struct equals;
template <class T> struct allocator; template <class T> struct allocator;
// Declare some instances // Declare some instances
typedef boost::unordered_map<value, value, hash, equals, typedef boost::unordered_map<value, value, hash, equals,
allocator<std::pair<value const, value> > > allocator<std::pair<value const, value> > >
map; map;
typedef boost::unordered_multimap<value, value, hash, equals, typedef boost::unordered_multimap<value, value, hash, equals,
allocator<std::pair<value const, value> > > allocator<std::pair<value const, value> > >
multimap; multimap;
typedef boost::unordered_set<value, hash, equals, allocator<value> > set; typedef boost::unordered_set<value, hash, equals, allocator<value> > set;
typedef boost::unordered_multiset<value, hash, equals, allocator<value> > typedef boost::unordered_multiset<value, hash, equals, allocator<value> >
multiset; multiset;
// Now define the types which are stored as members, as they are needed for // Now define the types which are stored as members, as they are needed for
// declaring struct members. // declaring struct members.
struct hash struct hash
{ {
template <typename T> std::size_t operator()(T const&) const { return 0; } template <typename T> std::size_t operator()(T const&) const { return 0; }
}; };
struct equals struct equals
{ {
template <typename T> bool operator()(T const&, T const&) const template <typename T> bool operator()(T const&, T const&) const
{ {
return true; return true;
} }
}; };
// This is a dubious way to implement an allocator, but good enough // This is a dubious way to implement an allocator, but good enough
// for this test. // for this test.
template <typename T> struct allocator : std::allocator<T> template <typename T> struct allocator : std::allocator<T>
{ {
allocator() {} allocator() {}
template <typename T2> template <typename T2>
@ -70,72 +70,72 @@ template <typename T> struct allocator : std::allocator<T>
allocator(const std::allocator<T2>& other) : std::allocator<T>(other) allocator(const std::allocator<T2>& other) : std::allocator<T>(other)
{ {
} }
}; };
// Declare some members of a structs. // Declare some members of a structs.
// //
// Incomplete hash, equals and allocator aren't here supported at the // Incomplete hash, equals and allocator aren't here supported at the
// moment. // moment.
struct struct1 struct struct1
{ {
boost::unordered_map<struct1, struct1, hash, equals, boost::unordered_map<struct1, struct1, hash, equals,
allocator<std::pair<struct1 const, struct1> > > allocator<std::pair<struct1 const, struct1> > >
x; x;
}; };
struct struct2 struct struct2
{ {
boost::unordered_multimap<struct2, struct2, hash, equals, boost::unordered_multimap<struct2, struct2, hash, equals,
allocator<std::pair<struct2 const, struct2> > > allocator<std::pair<struct2 const, struct2> > >
x; x;
}; };
struct struct3 struct struct3
{ {
boost::unordered_set<struct3, hash, equals, allocator<struct3> > x; boost::unordered_set<struct3, hash, equals, allocator<struct3> > x;
}; };
struct struct4 struct struct4
{ {
boost::unordered_multiset<struct4, hash, equals, allocator<struct4> > x; boost::unordered_multiset<struct4, hash, equals, allocator<struct4> > x;
}; };
// Now define the value type. // Now define the value type.
struct value struct value
{ {
}; };
// Create some instances. // Create some instances.
incomplete_test::map m1; incomplete_test::map m1;
incomplete_test::multimap m2; incomplete_test::multimap m2;
incomplete_test::set s1; incomplete_test::set s1;
incomplete_test::multiset s2; incomplete_test::multiset s2;
incomplete_test::struct1 c1; incomplete_test::struct1 c1;
incomplete_test::struct2 c2; incomplete_test::struct2 c2;
incomplete_test::struct3 c3; incomplete_test::struct3 c3;
incomplete_test::struct4 c4; incomplete_test::struct4 c4;
// Now declare, but don't define, the operators required for comparing // Now declare, but don't define, the operators required for comparing
// elements. // elements.
std::size_t hash_value(value const&); std::size_t hash_value(value const&);
bool operator==(value const&, value const&); bool operator==(value const&, value const&);
std::size_t hash_value(struct1 const&); std::size_t hash_value(struct1 const&);
std::size_t hash_value(struct2 const&); std::size_t hash_value(struct2 const&);
std::size_t hash_value(struct3 const&); std::size_t hash_value(struct3 const&);
std::size_t hash_value(struct4 const&); std::size_t hash_value(struct4 const&);
bool operator==(struct1 const&, struct1 const&); bool operator==(struct1 const&, struct1 const&);
bool operator==(struct2 const&, struct2 const&); bool operator==(struct2 const&, struct2 const&);
bool operator==(struct3 const&, struct3 const&); bool operator==(struct3 const&, struct3 const&);
bool operator==(struct4 const&, struct4 const&); bool operator==(struct4 const&, struct4 const&);
// And finally use these // And finally use these
void use_types() void use_types()
{ {
incomplete_test::value x; incomplete_test::value x;
m1[x] = x; m1[x] = x;
m2.insert(std::make_pair(x, x)); m2.insert(std::make_pair(x, x));
@ -146,28 +146,28 @@ void use_types()
c2.x.insert(std::make_pair(c2, c2)); c2.x.insert(std::make_pair(c2, c2));
c3.x.insert(c3); c3.x.insert(c3);
c4.x.insert(c4); c4.x.insert(c4);
} }
// And finally define the operators required for comparing elements. // And finally define the operators required for comparing elements.
std::size_t hash_value(value const&) { return 0; } std::size_t hash_value(value const&) { return 0; }
bool operator==(value const&, value const&) { return true; } bool operator==(value const&, value const&) { return true; }
std::size_t hash_value(struct1 const&) { return 0; } std::size_t hash_value(struct1 const&) { return 0; }
std::size_t hash_value(struct2 const&) { return 0; } std::size_t hash_value(struct2 const&) { return 0; }
std::size_t hash_value(struct3 const&) { return 0; } std::size_t hash_value(struct3 const&) { return 0; }
std::size_t hash_value(struct4 const&) { return 0; } std::size_t hash_value(struct4 const&) { return 0; }
bool operator==(struct1 const&, struct1 const&) { return true; } bool operator==(struct1 const&, struct1 const&) { return true; }
bool operator==(struct2 const&, struct2 const&) { return true; } bool operator==(struct2 const&, struct2 const&) { return true; }
bool operator==(struct3 const&, struct3 const&) { return true; } bool operator==(struct3 const&, struct3 const&) { return true; }
bool operator==(struct4 const&, struct4 const&) { return true; } bool operator==(struct4 const&, struct4 const&) { return true; }
} }
int main() int main()
{ {
// This could just be a compile test, but I like to be able to run these // This could just be a compile test, but I like to be able to run these
// things. It's probably irrational, but I find it reassuring. // things. It's probably irrational, but I find it reassuring.
incomplete_test::use_types(); incomplete_test::use_types();
} }

View File

@ -17,18 +17,18 @@
#include <set> #include <set>
namespace insert_hint { namespace insert_hint {
UNORDERED_AUTO_TEST(insert_hint_empty) UNORDERED_AUTO_TEST(insert_hint_empty)
{ {
typedef boost::unordered_multiset<int> container; typedef boost::unordered_multiset<int> container;
container x; container x;
x.insert(x.cbegin(), 10); x.insert(x.cbegin(), 10);
BOOST_TEST_EQ(x.size(), 1u); BOOST_TEST_EQ(x.size(), 1u);
BOOST_TEST_EQ(x.count(10), 1u); BOOST_TEST_EQ(x.count(10), 1u);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
UNORDERED_AUTO_TEST(insert_hint_empty2) UNORDERED_AUTO_TEST(insert_hint_empty2)
{ {
typedef boost::unordered_multimap<std::string, int> container; typedef boost::unordered_multimap<std::string, int> container;
container x; container x;
x.emplace_hint(x.cbegin(), "hello", 50); x.emplace_hint(x.cbegin(), "hello", 50);
@ -36,10 +36,10 @@ UNORDERED_AUTO_TEST(insert_hint_empty2)
BOOST_TEST_EQ(x.count("hello"), 1u); BOOST_TEST_EQ(x.count("hello"), 1u);
BOOST_TEST_EQ(x.find("hello")->second, 50); BOOST_TEST_EQ(x.find("hello")->second, 50);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
UNORDERED_AUTO_TEST(insert_hint_single) UNORDERED_AUTO_TEST(insert_hint_single)
{ {
typedef boost::unordered_multiset<std::string> container; typedef boost::unordered_multiset<std::string> container;
container x; container x;
x.insert("equal"); x.insert("equal");
@ -47,10 +47,10 @@ UNORDERED_AUTO_TEST(insert_hint_single)
BOOST_TEST_EQ(x.size(), 2u); BOOST_TEST_EQ(x.size(), 2u);
BOOST_TEST_EQ(x.count("equal"), 2u); BOOST_TEST_EQ(x.count("equal"), 2u);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
UNORDERED_AUTO_TEST(insert_hint_single2) UNORDERED_AUTO_TEST(insert_hint_single2)
{ {
typedef boost::unordered_multimap<int, std::string> container; typedef boost::unordered_multimap<int, std::string> container;
container x; container x;
x.emplace(10, "one"); x.emplace(10, "one");
@ -67,47 +67,47 @@ UNORDERED_AUTO_TEST(insert_hint_single2)
BOOST_TEST(v0 != v1); BOOST_TEST(v0 != v1);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
UNORDERED_AUTO_TEST(insert_hint_multiple) UNORDERED_AUTO_TEST(insert_hint_multiple)
{ {
for (unsigned int size = 0; size < 10; ++size) { for (unsigned int size = 0; size < 10; ++size) {
for (unsigned int offset = 0; offset <= size; ++offset) { for (unsigned int offset = 0; offset <= size; ++offset) {
typedef boost::unordered_multiset<std::string> container; typedef boost::unordered_multiset<std::string> container;
container x; container x;
for (unsigned int i = 0; i < size; ++i) { for (unsigned int i = 0; i < size; ++i) {
x.insert("multiple"); x.insert("multiple");
}
BOOST_TEST_EQ(x.size(), size);
container::const_iterator position = x.cbegin();
for (unsigned int i = 0; i < offset; ++i) {
++position;
}
x.insert(position, "multiple");
BOOST_TEST_EQ(x.size(), size + 1u);
BOOST_TEST_EQ(x.count("multiple"), size + 1u);
test::check_equivalent_keys(x);
} }
}
}
UNORDERED_AUTO_TEST(insert_hint_unique) BOOST_TEST_EQ(x.size(), size);
{
container::const_iterator position = x.cbegin();
for (unsigned int i = 0; i < offset; ++i) {
++position;
}
x.insert(position, "multiple");
BOOST_TEST_EQ(x.size(), size + 1u);
BOOST_TEST_EQ(x.count("multiple"), size + 1u);
test::check_equivalent_keys(x);
}
}
}
UNORDERED_AUTO_TEST(insert_hint_unique)
{
typedef boost::unordered_set<int> container; typedef boost::unordered_set<int> container;
container x; container x;
x.insert(x.cbegin(), 10); x.insert(x.cbegin(), 10);
BOOST_TEST_EQ(x.size(), 1u); BOOST_TEST_EQ(x.size(), 1u);
BOOST_TEST_EQ(x.count(10), 1u); BOOST_TEST_EQ(x.count(10), 1u);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
UNORDERED_AUTO_TEST(insert_hint_unique_single) UNORDERED_AUTO_TEST(insert_hint_unique_single)
{ {
typedef boost::unordered_set<int> container; typedef boost::unordered_set<int> container;
container x; container x;
x.insert(10); x.insert(10);
@ -122,7 +122,7 @@ UNORDERED_AUTO_TEST(insert_hint_unique_single)
BOOST_TEST_EQ(x.count(10), 1u); BOOST_TEST_EQ(x.count(10), 1u);
BOOST_TEST_EQ(x.count(20), 1u); BOOST_TEST_EQ(x.count(20), 1u);
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
} }
} }
RUN_TESTS() RUN_TESTS()

View File

@ -9,26 +9,26 @@
int main() int main()
{ {
#if defined(UNORDERED_TEST_MAP) #if defined(UNORDERED_TEST_MAP)
typedef boost::unordered_map<int, int> container; typedef boost::unordered_map<int, int> container;
container x; container x;
x.emplace(1, 1); x.emplace(1, 1);
#elif defined(UNORDERED_TEST_MULTIMAP) #elif defined(UNORDERED_TEST_MULTIMAP)
typedef boost::unordered_multimap<int, int> container; typedef boost::unordered_multimap<int, int> container;
container x; container x;
#elif defined(UNORDERED_TEST_SET) #elif defined(UNORDERED_TEST_SET)
typedef boost::unordered_set<int> container; typedef boost::unordered_set<int> container;
container x; container x;
x.emplace(1); x.emplace(1);
#elif defined(UNORDERED_TEST_MULTISET) #elif defined(UNORDERED_TEST_MULTISET)
typedef boost::unordered_multiset<int> container; typedef boost::unordered_multiset<int> container;
container x; container x;
x.emplace(1); x.emplace(1);
#else #else
#define UNORDERED_ERROR #define UNORDERED_ERROR
#endif #endif
#if !defined(UNORDERED_ERROR) #if !defined(UNORDERED_ERROR)
container::node_type n = x.extract(x.begin()); container::node_type n = x.extract(x.begin());
x.insert(n); x.insert(n);
#endif #endif
} }

View File

@ -13,8 +13,8 @@
#include "../helpers/test.hpp" #include "../helpers/test.hpp"
namespace insert_stable { namespace insert_stable {
struct member struct member
{ {
int tag1_; int tag1_;
int tag2_; int tag2_;
@ -23,14 +23,14 @@ struct member
friend bool operator==(member const& x, member const& y) friend bool operator==(member const& x, member const& y)
{ {
return x.tag1_ == y.tag1_; return x.tag1_ == y.tag1_;
} }
friend bool operator!=(member const& x, member const& y) friend bool operator!=(member const& x, member const& y)
{ {
return x.tag1_ != y.tag1_; return x.tag1_ != y.tag1_;
} }
}; };
} }
#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
@ -39,10 +39,10 @@ namespace boost
namespace insert_stable namespace insert_stable
#endif #endif
{ {
std::size_t hash_value(insert_stable::member const& x) std::size_t hash_value(insert_stable::member const& x)
{ {
return static_cast<std::size_t>(x.tag1_); return static_cast<std::size_t>(x.tag1_);
} }
} }
// This is no longer supported, as there's no longer an efficient way to get to // This is no longer supported, as there's no longer an efficient way to get to

File diff suppressed because it is too large Load Diff

View File

@ -11,16 +11,16 @@
// clang-format on // clang-format on
void foo(boost::unordered_set<int>&, boost::unordered_map<int, int>&, void foo(boost::unordered_set<int>&, boost::unordered_map<int, int>&,
boost::unordered_multiset<int>&, boost::unordered_multimap<int, int>&); boost::unordered_multiset<int>&, boost::unordered_multimap<int, int>&);
int main() int main()
{ {
boost::unordered_set<int> x1; boost::unordered_set<int> x1;
boost::unordered_map<int, int> x2; boost::unordered_map<int, int> x2;
boost::unordered_multiset<int> x3; boost::unordered_multiset<int> x3;
boost::unordered_multimap<int, int> x4; boost::unordered_multimap<int, int> x4;
foo(x1, x2, x3, x4); foo(x1, x2, x3, x4);
return 0; return 0;
} }

View File

@ -11,20 +11,20 @@
// clang-format on // clang-format on
void foo(boost::unordered_set<int>& x1, boost::unordered_map<int, int>& x2, void foo(boost::unordered_set<int>& x1, boost::unordered_map<int, int>& x2,
boost::unordered_multiset<int>& x3, boost::unordered_multimap<int, int>& x4) boost::unordered_multiset<int>& x3, boost::unordered_multimap<int, int>& x4)
{ {
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613)) #if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x0613))
struct dummy struct dummy
{ {
boost::unordered_set<int> x1; boost::unordered_set<int> x1;
boost::unordered_map<int, int> x2; boost::unordered_map<int, int> x2;
boost::unordered_multiset<int> x3; boost::unordered_multiset<int> x3;
boost::unordered_multimap<int, int> x4; boost::unordered_multimap<int, int> x4;
}; };
#endif #endif
x1.insert(1); x1.insert(1);
x2[2] = 2; x2[2] = 2;
x3.insert(3); x3.insert(3);
x4.insert(std::make_pair(4, 5)); x4.insert(std::make_pair(4, 5));
} }

View File

@ -21,10 +21,10 @@
namespace load_factor_tests { namespace load_factor_tests {
test::seed_t initialize_seed(783656); test::seed_t initialize_seed(783656);
template <class X> void set_load_factor_tests(X*) template <class X> void set_load_factor_tests(X*)
{ {
X x; X x;
BOOST_TEST(x.max_load_factor() == 1.0); BOOST_TEST(x.max_load_factor() == 1.0);
@ -36,11 +36,11 @@ template <class X> void set_load_factor_tests(X*)
BOOST_TEST(x.max_load_factor() == 2.0); BOOST_TEST(x.max_load_factor() == 2.0);
x.max_load_factor(0.5); x.max_load_factor(0.5);
BOOST_TEST(x.max_load_factor() == 0.5); BOOST_TEST(x.max_load_factor() == 0.5);
} }
template <class X> template <class X>
void insert_test(X*, float mlf, test::random_generator generator) void insert_test(X*, float mlf, test::random_generator generator)
{ {
X x; X x;
x.max_load_factor(mlf); x.max_load_factor(mlf);
float b = x.max_load_factor(); float b = x.max_load_factor();
@ -48,21 +48,21 @@ void insert_test(X*, float mlf, test::random_generator generator)
test::random_values<X> values(1000, generator); test::random_values<X> values(1000, generator);
for (BOOST_DEDUCED_TYPENAME test::random_values<X>::const_iterator for (BOOST_DEDUCED_TYPENAME test::random_values<X>::const_iterator
it = values.begin(), it = values.begin(),
end = values.end(); end = values.end();
it != end; ++it) { it != end; ++it) {
BOOST_DEDUCED_TYPENAME X::size_type old_size = x.size(), BOOST_DEDUCED_TYPENAME X::size_type old_size = x.size(),
old_bucket_count = x.bucket_count(); old_bucket_count = x.bucket_count();
x.insert(*it); x.insert(*it);
if (static_cast<double>(old_size + 1) <= if (static_cast<double>(old_size + 1) <=
b * static_cast<double>(old_bucket_count)) b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count); BOOST_TEST(x.bucket_count() == old_bucket_count);
} }
} }
template <class X> template <class X>
void load_factor_insert_tests(X* ptr, test::random_generator generator) void load_factor_insert_tests(X* ptr, test::random_generator generator)
{ {
insert_test(ptr, 1.0f, generator); insert_test(ptr, 1.0f, generator);
insert_test(ptr, 0.1f, generator); insert_test(ptr, 0.1f, generator);
insert_test(ptr, 100.0f, generator); insert_test(ptr, 100.0f, generator);
@ -70,22 +70,22 @@ void load_factor_insert_tests(X* ptr, test::random_generator generator)
insert_test(ptr, (std::numeric_limits<float>::min)(), generator); insert_test(ptr, (std::numeric_limits<float>::min)(), generator);
if (std::numeric_limits<float>::has_infinity) if (std::numeric_limits<float>::has_infinity)
insert_test(ptr, std::numeric_limits<float>::infinity(), generator); insert_test(ptr, std::numeric_limits<float>::infinity(), generator);
} }
boost::unordered_set<int>* int_set_ptr; boost::unordered_set<int>* int_set_ptr;
boost::unordered_multiset<int>* int_multiset_ptr; boost::unordered_multiset<int>* int_multiset_ptr;
boost::unordered_map<int, int>* int_map_ptr; boost::unordered_map<int, int>* int_map_ptr;
boost::unordered_multimap<int, int>* int_multimap_ptr; boost::unordered_multimap<int, int>* int_multimap_ptr;
using test::default_generator; using test::default_generator;
using test::generate_collisions; using test::generate_collisions;
using test::limited_range; using test::limited_range;
UNORDERED_TEST(set_load_factor_tests, UNORDERED_TEST(set_load_factor_tests,
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))) ((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr)))
UNORDERED_TEST(load_factor_insert_tests, UNORDERED_TEST(load_factor_insert_tests,
((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))( ((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr))(
(default_generator)(generate_collisions)(limited_range))) (default_generator)(generate_collisions)(limited_range)))
} }

View File

@ -19,8 +19,8 @@
namespace merge_tests { namespace merge_tests {
UNORDERED_AUTO_TEST(merge_set) UNORDERED_AUTO_TEST(merge_set)
{ {
boost::unordered_set<int> x; boost::unordered_set<int> x;
boost::unordered_set<int> y; boost::unordered_set<int> y;
@ -57,10 +57,10 @@ UNORDERED_AUTO_TEST(merge_set)
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
} }
UNORDERED_AUTO_TEST(merge_multiset) UNORDERED_AUTO_TEST(merge_multiset)
{ {
boost::unordered_multiset<int> x; boost::unordered_multiset<int> x;
boost::unordered_multiset<int> y; boost::unordered_multiset<int> y;
@ -97,10 +97,10 @@ UNORDERED_AUTO_TEST(merge_multiset)
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
} }
UNORDERED_AUTO_TEST(merge_set_and_multiset) UNORDERED_AUTO_TEST(merge_set_and_multiset)
{ {
boost::unordered_set<int> x; boost::unordered_set<int> x;
boost::unordered_multiset<int> y; boost::unordered_multiset<int> y;
@ -137,11 +137,11 @@ UNORDERED_AUTO_TEST(merge_set_and_multiset)
test::check_equivalent_keys(x); test::check_equivalent_keys(x);
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
} }
template <class X1, class X2> template <class X1, class X2>
void merge_empty_test(X1*, X2*, test::random_generator generator) void merge_empty_test(X1*, X2*, test::random_generator generator)
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<X1> v(1000, generator); test::random_values<X1> v(1000, generator);
@ -152,11 +152,11 @@ void merge_empty_test(X1*, X2*, test::random_generator generator)
BOOST_TEST(x2.empty()); BOOST_TEST(x2.empty());
test::check_equivalent_keys(x1); test::check_equivalent_keys(x1);
test::check_equivalent_keys(x2); test::check_equivalent_keys(x2);
} }
template <class X> template <class X>
void merge_into_empty_test(X*, test::random_generator generator) void merge_into_empty_test(X*, test::random_generator generator)
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<X> v(1000, generator); test::random_values<X> v(1000, generator);
@ -167,12 +167,12 @@ void merge_into_empty_test(X*, test::random_generator generator)
BOOST_TEST(x2.empty()); BOOST_TEST(x2.empty());
test::check_equivalent_keys(x1); test::check_equivalent_keys(x1);
test::check_equivalent_keys(x2); test::check_equivalent_keys(x2);
} }
template <class X1, class X2> template <class X1, class X2>
void merge_into_unique_keys_test(X1*, X2*, int hash_equal1, int hash_equal2, void merge_into_unique_keys_test(X1*, X2*, int hash_equal1, int hash_equal2,
test::random_generator generator) test::random_generator generator)
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<X1> v1(1000, generator); test::random_values<X1> v1(1000, generator);
@ -181,17 +181,17 @@ void merge_into_unique_keys_test(X1*, X2*, int hash_equal1, int hash_equal2,
v2.insert(v1.begin(), boost::next(v1.begin(), 100)); v2.insert(v1.begin(), boost::next(v1.begin(), 100));
X1 x1(v1.begin(), v1.end(), 0, test::hash(hash_equal1), X1 x1(v1.begin(), v1.end(), 0, test::hash(hash_equal1),
test::equal_to(hash_equal1)); test::equal_to(hash_equal1));
X2 x2(v2.begin(), v2.end(), 0, test::hash(hash_equal2), X2 x2(v2.begin(), v2.end(), 0, test::hash(hash_equal2),
test::equal_to(hash_equal2)); test::equal_to(hash_equal2));
test::ordered<X1> tracker1 = test::create_ordered(x1); test::ordered<X1> tracker1 = test::create_ordered(x1);
test::ordered<X2> tracker2 = test::create_ordered(x2); test::ordered<X2> tracker2 = test::create_ordered(x2);
tracker1.insert(v1.begin(), v1.end()); tracker1.insert(v1.begin(), v1.end());
for (typename X2::iterator it = x2.begin(); it != x2.end(); ++it) { for (typename X2::iterator it = x2.begin(); it != x2.end(); ++it) {
if (!tracker1.insert(*it).second) { if (!tracker1.insert(*it).second) {
tracker2.insert(*it); tracker2.insert(*it);
} }
} }
x1.merge(x2); x1.merge(x2);
@ -200,12 +200,12 @@ void merge_into_unique_keys_test(X1*, X2*, int hash_equal1, int hash_equal2,
tracker2.compare(x2); tracker2.compare(x2);
test::check_equivalent_keys(x1); test::check_equivalent_keys(x1);
test::check_equivalent_keys(x2); test::check_equivalent_keys(x2);
} }
template <class X1, class X2> template <class X1, class X2>
void merge_into_equiv_keys_test(X1*, X2*, int hash_equal1, int hash_equal2, void merge_into_equiv_keys_test(X1*, X2*, int hash_equal1, int hash_equal2,
test::random_generator generator) test::random_generator generator)
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<X1> v1(1000, generator); test::random_values<X1> v1(1000, generator);
@ -214,9 +214,9 @@ void merge_into_equiv_keys_test(X1*, X2*, int hash_equal1, int hash_equal2,
v2.insert(v1.begin(), boost::next(v1.begin(), 100)); v2.insert(v1.begin(), boost::next(v1.begin(), 100));
X1 x1(v1.begin(), v1.end(), 0, test::hash(hash_equal1), X1 x1(v1.begin(), v1.end(), 0, test::hash(hash_equal1),
test::equal_to(hash_equal1)); test::equal_to(hash_equal1));
X2 x2(v2.begin(), v2.end(), 0, test::hash(hash_equal2), X2 x2(v2.begin(), v2.end(), 0, test::hash(hash_equal2),
test::equal_to(hash_equal2)); test::equal_to(hash_equal2));
x1.merge(x2); x1.merge(x2);
test::ordered<X1> tracker1 = test::create_ordered(x1); test::ordered<X1> tracker1 = test::create_ordered(x1);
@ -230,32 +230,32 @@ void merge_into_equiv_keys_test(X1*, X2*, int hash_equal1, int hash_equal2,
tracker2.compare(x2); tracker2.compare(x2);
test::check_equivalent_keys(x1); test::check_equivalent_keys(x1);
test::check_equivalent_keys(x2); test::check_equivalent_keys(x2);
} }
boost::unordered_set<test::movable, test::hash, test::equal_to, boost::unordered_set<test::movable, test::hash, test::equal_to,
std::allocator<test::movable> >* test_set_std_alloc; std::allocator<test::movable> >* test_set_std_alloc;
boost::unordered_multiset<test::movable, test::hash, test::equal_to, boost::unordered_multiset<test::movable, test::hash, test::equal_to,
std::allocator<test::movable> >* test_multiset_std_alloc; std::allocator<test::movable> >* test_multiset_std_alloc;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to, boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
std::allocator<test::object> >* test_map_std_alloc; std::allocator<test::object> >* test_map_std_alloc;
boost::unordered_multimap<test::object, test::object, test::hash, boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, std::allocator<test::object> >* test_multimap_std_alloc; test::equal_to, std::allocator<test::object> >* test_multimap_std_alloc;
boost::unordered_set<test::object, test::hash, test::equal_to, boost::unordered_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set; test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to, boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_multiset; test::allocator1<test::object> >* test_multiset;
boost::unordered_map<test::movable, test::movable, test::hash, test::equal_to, boost::unordered_map<test::movable, test::movable, test::hash, test::equal_to,
test::allocator2<test::movable> >* test_map; test::allocator2<test::movable> >* test_map;
boost::unordered_multimap<test::movable, test::movable, test::hash, boost::unordered_multimap<test::movable, test::movable, test::hash,
test::equal_to, test::allocator2<test::movable> >* test_multimap; test::equal_to, test::allocator2<test::movable> >* test_multimap;
using test::default_generator; using test::default_generator;
using test::generate_collisions; using test::generate_collisions;
// clang-format off // clang-format off
UNORDERED_TEST(merge_empty_test, UNORDERED_TEST(merge_empty_test,
((test_set_std_alloc)(test_multiset_std_alloc)) ((test_set_std_alloc)(test_multiset_std_alloc))
((test_set_std_alloc)(test_multiset_std_alloc)) ((test_set_std_alloc)(test_multiset_std_alloc))
@ -335,7 +335,7 @@ UNORDERED_TEST(merge_into_equiv_keys_test,
((0)(1)(2)) ((0)(1)(2))
((0)(1)(2)) ((0)(1)(2))
((default_generator)(generate_collisions))) ((default_generator)(generate_collisions)))
// clang-format on // clang-format on
} }
RUN_TESTS() RUN_TESTS()

View File

@ -11,83 +11,82 @@
template <class Tp> struct SimpleAllocator template <class Tp> struct SimpleAllocator
{ {
typedef Tp value_type; typedef Tp value_type;
SimpleAllocator() {} SimpleAllocator() {}
template <class T> SimpleAllocator(const SimpleAllocator<T>&) {} template <class T> SimpleAllocator(const SimpleAllocator<T>&) {}
Tp* allocate(std::size_t n) Tp* allocate(std::size_t n)
{ {
return static_cast<Tp*>(::operator new(n * sizeof(Tp))); return static_cast<Tp*>(::operator new(n * sizeof(Tp)));
} }
void deallocate(Tp* p, std::size_t) { ::operator delete((void*)p); } void deallocate(Tp* p, std::size_t) { ::operator delete((void*)p); }
}; };
template <typename T> void test_simple_allocator() template <typename T> void test_simple_allocator()
{ {
test::check_instances check_; test::check_instances check_;
typedef boost::unordered::detail::allocator_traits<SimpleAllocator<T> > typedef boost::unordered::detail::allocator_traits<SimpleAllocator<T> >
traits; traits;
BOOST_STATIC_ASSERT((boost::is_same<typename traits::allocator_type, BOOST_STATIC_ASSERT((boost::is_same<typename traits::allocator_type,
SimpleAllocator<T> >::value)); SimpleAllocator<T> >::value));
BOOST_STATIC_ASSERT( BOOST_STATIC_ASSERT((boost::is_same<typename traits::value_type, T>::value));
(boost::is_same<typename traits::value_type, T>::value));
BOOST_STATIC_ASSERT((boost::is_same<typename traits::pointer, T*>::value)); BOOST_STATIC_ASSERT((boost::is_same<typename traits::pointer, T*>::value));
BOOST_STATIC_ASSERT( BOOST_STATIC_ASSERT(
(boost::is_same<typename traits::const_pointer, T const*>::value)); (boost::is_same<typename traits::const_pointer, T const*>::value));
// BOOST_STATIC_ASSERT((boost::is_same<typename traits::void_pointer, void* // BOOST_STATIC_ASSERT((boost::is_same<typename traits::void_pointer, void*
// >::value)); // >::value));
// BOOST_STATIC_ASSERT((boost::is_same<typename traits::const_void_pointer, // BOOST_STATIC_ASSERT((boost::is_same<typename traits::const_void_pointer,
// void const*>::value)); // void const*>::value));
BOOST_STATIC_ASSERT((boost::is_same<typename traits::difference_type, BOOST_STATIC_ASSERT(
std::ptrdiff_t>::value)); (boost::is_same<typename traits::difference_type, std::ptrdiff_t>::value));
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1 #if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
BOOST_STATIC_ASSERT((boost::is_same<typename traits::size_type, BOOST_STATIC_ASSERT((boost::is_same<typename traits::size_type,
std::make_unsigned<std::ptrdiff_t>::type>::value)); std::make_unsigned<std::ptrdiff_t>::type>::value));
#else #else
BOOST_STATIC_ASSERT( BOOST_STATIC_ASSERT(
(boost::is_same<typename traits::size_type, std::size_t>::value)); (boost::is_same<typename traits::size_type, std::size_t>::value));
#endif #endif
BOOST_TEST(!traits::propagate_on_container_copy_assignment::value); BOOST_TEST(!traits::propagate_on_container_copy_assignment::value);
BOOST_TEST(!traits::propagate_on_container_move_assignment::value); BOOST_TEST(!traits::propagate_on_container_move_assignment::value);
BOOST_TEST(!traits::propagate_on_container_swap::value); BOOST_TEST(!traits::propagate_on_container_swap::value);
// rebind_alloc // rebind_alloc
// rebind_traits // rebind_traits
SimpleAllocator<T> a; SimpleAllocator<T> a;
T* ptr1 = traits::allocate(a, 1); T* ptr1 = traits::allocate(a, 1);
// T* ptr2 = traits::allocate(a, 1, static_cast<void const*>(ptr1)); // T* ptr2 = traits::allocate(a, 1, static_cast<void const*>(ptr1));
traits::construct(a, ptr1, T(10)); traits::construct(a, ptr1, T(10));
// traits::construct(a, ptr2, T(30), ptr1); // traits::construct(a, ptr2, T(30), ptr1);
BOOST_TEST(*ptr1 == T(10)); BOOST_TEST(*ptr1 == T(10));
// BOOST_TEST(*ptr2 == T(30)); // BOOST_TEST(*ptr2 == T(30));
traits::destroy(a, ptr1); traits::destroy(a, ptr1);
// traits::destroy(a, ptr2); // traits::destroy(a, ptr2);
// traits::deallocate(a, ptr2, 1); // traits::deallocate(a, ptr2, 1);
traits::deallocate(a, ptr1, 1); traits::deallocate(a, ptr1, 1);
traits::max_size(a); traits::max_size(a);
} }
int main() int main()
{ {
test_simple_allocator<int>(); test_simple_allocator<int>();
test_simple_allocator<test::object>(); test_simple_allocator<test::object>();
return boost::report_errors(); return boost::report_errors();
} }

View File

@ -23,90 +23,90 @@
#endif #endif
namespace move_tests { namespace move_tests {
test::seed_t initialize_seed(98624); test::seed_t initialize_seed(98624);
#if defined(BOOST_UNORDERED_USE_MOVE) || \ #if defined(BOOST_UNORDERED_USE_MOVE) || \
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES) !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
#define BOOST_UNORDERED_TEST_MOVING 1 #define BOOST_UNORDERED_TEST_MOVING 1
#else #else
#define BOOST_UNORDERED_TEST_MOVING 0 #define BOOST_UNORDERED_TEST_MOVING 0
#endif #endif
template <class T> T empty(T*) { return T(); } template <class T> T empty(T*) { return T(); }
template <class T> template <class T>
T create(test::random_values<T> const& v, test::object_count& count) T create(test::random_values<T> const& v, test::object_count& count)
{ {
T x(v.begin(), v.end()); T x(v.begin(), v.end());
count = test::global_object_count; count = test::global_object_count;
return x; return x;
} }
template <class T> template <class T>
T create(test::random_values<T> const& v, test::object_count& count, T create(test::random_values<T> const& v, test::object_count& count,
BOOST_DEDUCED_TYPENAME T::hasher hf, BOOST_DEDUCED_TYPENAME T::key_equal eq, BOOST_DEDUCED_TYPENAME T::hasher hf, BOOST_DEDUCED_TYPENAME T::key_equal eq,
BOOST_DEDUCED_TYPENAME T::allocator_type al, float mlf) BOOST_DEDUCED_TYPENAME T::allocator_type al, float mlf)
{ {
T x(0, hf, eq, al); T x(0, hf, eq, al);
x.max_load_factor(mlf); x.max_load_factor(mlf);
x.insert(v.begin(), v.end()); x.insert(v.begin(), v.end());
count = test::global_object_count; count = test::global_object_count;
return x; return x;
} }
template <class T> template <class T>
void move_construct_tests1(T* ptr, test::random_generator const& generator) void move_construct_tests1(T* ptr, test::random_generator const& generator)
{ {
BOOST_DEDUCED_TYPENAME T::hasher hf; BOOST_DEDUCED_TYPENAME T::hasher hf;
BOOST_DEDUCED_TYPENAME T::key_equal eq; BOOST_DEDUCED_TYPENAME T::key_equal eq;
BOOST_DEDUCED_TYPENAME T::allocator_type al; BOOST_DEDUCED_TYPENAME T::allocator_type al;
{ {
test::check_instances check_; test::check_instances check_;
T y(empty(ptr)); T y(empty(ptr));
BOOST_TEST(y.empty()); BOOST_TEST(y.empty());
BOOST_TEST(test::equivalent(y.hash_function(), hf)); BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq)); BOOST_TEST(test::equivalent(y.key_eq(), eq));
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);
} }
{ {
test::check_instances check_; test::check_instances check_;
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));
#if defined(BOOST_HAS_NRVO) #if defined(BOOST_HAS_NRVO)
BOOST_TEST(count == test::global_object_count); BOOST_TEST(count == test::global_object_count);
#endif #endif
test::check_container(y, v); test::check_container(y, v);
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
} }
} }
template <class T> template <class T>
void move_assign_tests1(T*, test::random_generator const& generator) void move_assign_tests1(T*, test::random_generator const& generator)
{ {
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<T> v(500, generator); test::random_values<T> v(500, generator);
test::object_count count; test::object_count count;
T y; T y;
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 #endif
test::check_container(y, v); test::check_container(y, v);
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
} }
} }
template <class T> template <class T>
void move_construct_tests2(T*, test::random_generator const& generator) void move_construct_tests2(T*, test::random_generator const& generator)
{ {
BOOST_DEDUCED_TYPENAME T::hasher hf(1); BOOST_DEDUCED_TYPENAME T::hasher hf(1);
BOOST_DEDUCED_TYPENAME T::key_equal eq(1); BOOST_DEDUCED_TYPENAME T::key_equal eq(1);
BOOST_DEDUCED_TYPENAME T::allocator_type al(1); BOOST_DEDUCED_TYPENAME T::allocator_type al(1);
@ -115,71 +115,71 @@ void move_construct_tests2(T*, test::random_generator const& generator)
test::object_count count; test::object_count count;
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<T> v(500, generator); test::random_values<T> v(500, generator);
T y(create(v, count, hf, eq, al, 0.5)); T y(create(v, count, hf, eq, al, 0.5));
#if defined(BOOST_HAS_NRVO) #if defined(BOOST_HAS_NRVO)
BOOST_TEST(count == test::global_object_count); BOOST_TEST(count == test::global_object_count);
#endif #endif
test::check_container(y, v); test::check_container(y, v);
BOOST_TEST(test::equivalent(y.hash_function(), hf)); BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq)); BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al)); BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(y.max_load_factor() == 0.5); // Not necessarily required. BOOST_TEST(y.max_load_factor() == 0.5); // Not necessarily required.
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
} }
{ {
test::check_instances check_; test::check_instances check_;
// TODO: To do this correctly requires the fancy new allocator // TODO: To do this correctly requires the fancy new allocator
// stuff. // stuff.
test::random_values<T> v(500, generator); test::random_values<T> v(500, generator);
T y(create(v, count, hf, eq, al, 2.0), al2); T y(create(v, count, hf, eq, al, 2.0), al2);
BOOST_TEST(count != test::global_object_count); BOOST_TEST(count != test::global_object_count);
test::check_container(y, v); test::check_container(y, v);
BOOST_TEST(test::equivalent(y.hash_function(), hf)); BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq)); BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al2)); BOOST_TEST(test::equivalent(y.get_allocator(), al2));
BOOST_TEST(y.max_load_factor() == 2.0); // Not necessarily required. BOOST_TEST(y.max_load_factor() == 2.0); // Not necessarily required.
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
} }
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<T> v(25, generator); test::random_values<T> v(25, generator);
T y(create(v, count, hf, eq, al, 1.0), al); T y(create(v, count, hf, eq, al, 1.0), al);
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
BOOST_TEST(count == test::global_object_count); BOOST_TEST(count == test::global_object_count);
#elif defined(BOOST_HAS_NRVO) #elif defined(BOOST_HAS_NRVO)
BOOST_TEST( BOOST_TEST(
static_cast<std::size_t>(test::global_object_count.constructions - static_cast<std::size_t>(
count.constructions) <= test::global_object_count.constructions - count.constructions) <=
(test::is_set<T>::value ? 1 : 2) * (test::is_set<T>::value ? 1 : 2) *
(test::has_unique_keys<T>::value ? 25 : v.size())); (test::has_unique_keys<T>::value ? 25 : v.size()));
BOOST_TEST(count.instances == test::global_object_count.instances); BOOST_TEST(count.instances == test::global_object_count.instances);
#else #else
BOOST_TEST( BOOST_TEST(
static_cast<std::size_t>(test::global_object_count.constructions - static_cast<std::size_t>(
count.constructions) <= test::global_object_count.constructions - count.constructions) <=
(test::is_set<T>::value ? 2 : 4) * (test::is_set<T>::value ? 2 : 4) *
(test::has_unique_keys<T>::value ? 25 : v.size())); (test::has_unique_keys<T>::value ? 25 : v.size()));
BOOST_TEST(count.instances == test::global_object_count.instances); BOOST_TEST(count.instances == test::global_object_count.instances);
#endif #endif
test::check_container(y, v); test::check_container(y, v);
BOOST_TEST(test::equivalent(y.hash_function(), hf)); BOOST_TEST(test::equivalent(y.hash_function(), hf));
BOOST_TEST(test::equivalent(y.key_eq(), eq)); BOOST_TEST(test::equivalent(y.key_eq(), eq));
BOOST_TEST(test::equivalent(y.get_allocator(), al)); BOOST_TEST(test::equivalent(y.get_allocator(), al));
BOOST_TEST(y.max_load_factor() == 1.0); // Not necessarily required. BOOST_TEST(y.max_load_factor() == 1.0); // Not necessarily required.
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
} }
} }
template <class T> template <class T>
void move_assign_tests2(T*, test::random_generator const& generator) void move_assign_tests2(T*, test::random_generator const& generator)
{ {
BOOST_DEDUCED_TYPENAME T::hasher hf(1); BOOST_DEDUCED_TYPENAME T::hasher hf(1);
BOOST_DEDUCED_TYPENAME T::key_equal eq(1); BOOST_DEDUCED_TYPENAME T::key_equal eq(1);
BOOST_DEDUCED_TYPENAME T::allocator_type al1(1); BOOST_DEDUCED_TYPENAME T::allocator_type al1(1);
@ -187,188 +187,185 @@ void move_assign_tests2(T*, test::random_generator const& generator)
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type; typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
{ {
test::random_values<T> v(500, generator); test::random_values<T> v(500, generator);
test::random_values<T> v2(0, generator); test::random_values<T> v2(0, generator);
T y(v.begin(), v.end(), 0, hf, eq, al1); T y(v.begin(), v.end(), 0, hf, eq, al1);
test::object_count count; test::object_count count;
y = create(v2, count, hf, eq, al2, 2.0); y = create(v2, count, hf, eq, al2, 2.0);
BOOST_TEST(y.empty()); BOOST_TEST(y.empty());
test::check_container(y, v2); test::check_container(y, v2);
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
BOOST_TEST(y.max_load_factor() == 2.0); BOOST_TEST(y.max_load_factor() == 2.0);
#if defined(BOOST_HAS_NRVO) #if defined(BOOST_HAS_NRVO)
if (BOOST_UNORDERED_TEST_MOVING if (BOOST_UNORDERED_TEST_MOVING
? (bool)allocator_type::is_propagate_on_move ? (bool)allocator_type::is_propagate_on_move
: (bool)allocator_type::is_propagate_on_assign) { : (bool)allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(y.get_allocator(), al2)); BOOST_TEST(test::equivalent(y.get_allocator(), al2));
} else { } else {
BOOST_TEST(test::equivalent(y.get_allocator(), al1)); BOOST_TEST(test::equivalent(y.get_allocator(), al1));
} }
#endif #endif
} }
{ {
test::random_values<T> v(500, generator); test::random_values<T> v(500, generator);
test::object_count count; test::object_count count;
T y(0, hf, eq, al1); T y(0, hf, eq, al1);
y = create(v, count, hf, eq, al2, 0.5); y = create(v, count, hf, eq, al2, 0.5);
#if defined(BOOST_HAS_NRVO) #if defined(BOOST_HAS_NRVO)
if (BOOST_UNORDERED_TEST_MOVING && if (BOOST_UNORDERED_TEST_MOVING && allocator_type::is_propagate_on_move) {
allocator_type::is_propagate_on_move) { BOOST_TEST(count == test::global_object_count);
BOOST_TEST(count == test::global_object_count); }
}
#endif #endif
test::check_container(y, v); test::check_container(y, v);
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
BOOST_TEST(y.max_load_factor() == 0.5); BOOST_TEST(y.max_load_factor() == 0.5);
#if defined(BOOST_HAS_NRVO) #if defined(BOOST_HAS_NRVO)
if (BOOST_UNORDERED_TEST_MOVING if (BOOST_UNORDERED_TEST_MOVING
? (bool)allocator_type::is_propagate_on_move ? (bool)allocator_type::is_propagate_on_move
: (bool)allocator_type::is_propagate_on_assign) { : (bool)allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(y.get_allocator(), al2)); BOOST_TEST(test::equivalent(y.get_allocator(), al2));
} else { } else {
BOOST_TEST(test::equivalent(y.get_allocator(), al1)); BOOST_TEST(test::equivalent(y.get_allocator(), al1));
} }
#endif #endif
} }
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<T> v(500, generator); test::random_values<T> v(500, generator);
T y(0, hf, eq, al1); T y(0, hf, eq, al1);
T x(0, hf, eq, al2); T x(0, hf, eq, al2);
x.max_load_factor(0.25); x.max_load_factor(0.25);
x.insert(v.begin(), v.end()); x.insert(v.begin(), v.end());
test::object_count count = test::global_object_count; test::object_count count = test::global_object_count;
y = boost::move(x); y = boost::move(x);
if (BOOST_UNORDERED_TEST_MOVING && if (BOOST_UNORDERED_TEST_MOVING && allocator_type::is_propagate_on_move) {
allocator_type::is_propagate_on_move) { BOOST_TEST(count == test::global_object_count);
BOOST_TEST(count == test::global_object_count); }
} test::check_container(y, v);
test::check_container(y, v); test::check_equivalent_keys(y);
test::check_equivalent_keys(y); BOOST_TEST(y.max_load_factor() == 0.25);
BOOST_TEST(y.max_load_factor() == 0.25);
if (BOOST_UNORDERED_TEST_MOVING if (BOOST_UNORDERED_TEST_MOVING
? (bool)allocator_type::is_propagate_on_move ? (bool)allocator_type::is_propagate_on_move
: (bool)allocator_type::is_propagate_on_assign) { : (bool)allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(y.get_allocator(), al2)); BOOST_TEST(test::equivalent(y.get_allocator(), al2));
} else { } else {
BOOST_TEST(test::equivalent(y.get_allocator(), al1)); BOOST_TEST(test::equivalent(y.get_allocator(), al1));
} }
} }
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<T> v1(1000, generator); test::random_values<T> v1(1000, generator);
test::random_values<T> v2(200, generator); test::random_values<T> v2(200, generator);
T x(0, hf, eq, al2); T x(0, hf, eq, al2);
x.max_load_factor(0.5); x.max_load_factor(0.5);
x.insert(v2.begin(), v2.end()); x.insert(v2.begin(), v2.end());
test::object_count count1 = test::global_object_count; test::object_count count1 = test::global_object_count;
T y(v1.begin(), v1.end(), 0, hf, eq, al1); T y(v1.begin(), v1.end(), 0, hf, eq, al1);
y = boost::move(x); y = boost::move(x);
test::object_count count2 = test::global_object_count; test::object_count count2 = test::global_object_count;
if (BOOST_UNORDERED_TEST_MOVING && if (BOOST_UNORDERED_TEST_MOVING && allocator_type::is_propagate_on_move) {
allocator_type::is_propagate_on_move) { BOOST_TEST(count1.instances == test::global_object_count.instances);
BOOST_TEST(count1.instances == test::global_object_count.instances); BOOST_TEST(
BOOST_TEST(count2.constructions == count2.constructions == test::global_object_count.constructions);
test::global_object_count.constructions); }
}
test::check_container(y, v2); test::check_container(y, v2);
test::check_equivalent_keys(y); test::check_equivalent_keys(y);
BOOST_TEST(y.max_load_factor() == 0.5); BOOST_TEST(y.max_load_factor() == 0.5);
if (BOOST_UNORDERED_TEST_MOVING if (BOOST_UNORDERED_TEST_MOVING
? (bool)allocator_type::is_propagate_on_move ? (bool)allocator_type::is_propagate_on_move
: (bool)allocator_type::is_propagate_on_assign) { : (bool)allocator_type::is_propagate_on_assign) {
BOOST_TEST(test::equivalent(y.get_allocator(), al2)); BOOST_TEST(test::equivalent(y.get_allocator(), al2));
} else { } else {
BOOST_TEST(test::equivalent(y.get_allocator(), al1)); BOOST_TEST(test::equivalent(y.get_allocator(), al1));
} }
} }
} }
boost::unordered_map<test::object, test::object, test::hash, test::equal_to, boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
std::allocator<test::object> >* test_map_std_alloc; std::allocator<test::object> >* test_map_std_alloc;
boost::unordered_set<test::object, test::hash, test::equal_to, boost::unordered_set<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_set; test::allocator2<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to, boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_multiset; test::allocator1<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to, boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_map; test::allocator1<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash, boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator2<test::object> >* test_multimap; test::equal_to, test::allocator2<test::object> >* test_multimap;
boost::unordered_set<test::object, test::hash, test::equal_to, boost::unordered_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_move> >* test::cxx11_allocator<test::object, test::propagate_move> >*
test_set_prop_move; test_set_prop_move;
boost::unordered_multiset<test::object, test::hash, test::equal_to, boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_move> >* test::cxx11_allocator<test::object, test::propagate_move> >*
test_multiset_prop_move; test_multiset_prop_move;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to, boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_move> >* test::cxx11_allocator<test::object, test::propagate_move> >*
test_map_prop_move; test_map_prop_move;
boost::unordered_multimap<test::object, test::object, test::hash, boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::cxx11_allocator<test::object, test::propagate_move> >* test::equal_to, test::cxx11_allocator<test::object, test::propagate_move> >*
test_multimap_prop_move; test_multimap_prop_move;
boost::unordered_set<test::object, test::hash, test::equal_to, boost::unordered_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_move> >* test::cxx11_allocator<test::object, test::no_propagate_move> >*
test_set_no_prop_move; test_set_no_prop_move;
boost::unordered_multiset<test::object, test::hash, test::equal_to, boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_move> >* test::cxx11_allocator<test::object, test::no_propagate_move> >*
test_multiset_no_prop_move; test_multiset_no_prop_move;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to, boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_move> >* test::cxx11_allocator<test::object, test::no_propagate_move> >*
test_map_no_prop_move; test_map_no_prop_move;
boost::unordered_multimap<test::object, test::object, test::hash, boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_move> >* test::cxx11_allocator<test::object, test::no_propagate_move> >*
test_multimap_no_prop_move; test_multimap_no_prop_move;
using test::default_generator; using test::default_generator;
using test::generate_collisions; using test::generate_collisions;
using test::limited_range; using test::limited_range;
UNORDERED_TEST(move_construct_tests1, UNORDERED_TEST(move_construct_tests1,
((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap)( ((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap)(
test_set_prop_move)(test_multiset_prop_move)(test_map_prop_move)( test_set_prop_move)(test_multiset_prop_move)(test_map_prop_move)(
test_multimap_prop_move)(test_set_no_prop_move)( test_multimap_prop_move)(test_set_no_prop_move)(
test_multiset_no_prop_move)(test_map_no_prop_move)( test_multiset_no_prop_move)(test_map_no_prop_move)(
test_multimap_no_prop_move))( test_multimap_no_prop_move))(
(default_generator)(generate_collisions)(limited_range))) (default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(move_assign_tests1, UNORDERED_TEST(move_assign_tests1,
((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap)( ((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap)(
test_set_prop_move)(test_multiset_prop_move)(test_map_prop_move)( test_set_prop_move)(test_multiset_prop_move)(test_map_prop_move)(
test_multimap_prop_move)(test_set_no_prop_move)( test_multimap_prop_move)(test_set_no_prop_move)(
test_multiset_no_prop_move)(test_map_no_prop_move)( test_multiset_no_prop_move)(test_map_no_prop_move)(
test_multimap_no_prop_move))( test_multimap_no_prop_move))(
(default_generator)(generate_collisions)(limited_range))) (default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(move_construct_tests2, UNORDERED_TEST(move_construct_tests2,
((test_set)(test_multiset)(test_map)(test_multimap)(test_set_prop_move)( ((test_set)(test_multiset)(test_map)(test_multimap)(test_set_prop_move)(
test_multiset_prop_move)(test_map_prop_move)(test_multimap_prop_move)( test_multiset_prop_move)(test_map_prop_move)(test_multimap_prop_move)(
test_set_no_prop_move)(test_multiset_no_prop_move)( test_set_no_prop_move)(test_multiset_no_prop_move)(test_map_no_prop_move)(
test_map_no_prop_move)(test_multimap_no_prop_move))( test_multimap_no_prop_move))(
(default_generator)(generate_collisions)(limited_range))) (default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(move_assign_tests2, UNORDERED_TEST(move_assign_tests2,
((test_set)(test_multiset)(test_map)(test_multimap)(test_set_prop_move)( ((test_set)(test_multiset)(test_map)(test_multimap)(test_set_prop_move)(
test_multiset_prop_move)(test_map_prop_move)(test_multimap_prop_move)( test_multiset_prop_move)(test_map_prop_move)(test_multimap_prop_move)(
test_set_no_prop_move)(test_multiset_no_prop_move)( test_set_no_prop_move)(test_multiset_no_prop_move)(test_map_no_prop_move)(
test_map_no_prop_move)(test_multimap_no_prop_move))( test_multimap_no_prop_move))(
(default_generator)(generate_collisions)(limited_range))) (default_generator)(generate_collisions)(limited_range)))
} }

View File

@ -18,419 +18,418 @@
UNORDERED_AUTO_TEST(example1) UNORDERED_AUTO_TEST(example1)
{ {
typedef boost::unordered_map<int, std::string>::insert_return_type typedef boost::unordered_map<int, std::string>::insert_return_type
insert_return_type; insert_return_type;
boost::unordered_map<int, std::string> src; boost::unordered_map<int, std::string> src;
src.emplace(1, "one"); src.emplace(1, "one");
src.emplace(2, "two"); src.emplace(2, "two");
src.emplace(3, "buckle my shoe"); src.emplace(3, "buckle my shoe");
boost::unordered_map<int, std::string> dst; boost::unordered_map<int, std::string> dst;
dst.emplace(3, "three"); dst.emplace(3, "three");
dst.insert(src.extract(src.find(1))); dst.insert(src.extract(src.find(1)));
dst.insert(src.extract(2)); dst.insert(src.extract(2));
insert_return_type r = dst.insert(src.extract(3)); insert_return_type r = dst.insert(src.extract(3));
BOOST_TEST(src.empty()); BOOST_TEST(src.empty());
BOOST_TEST(dst.size() == 3); BOOST_TEST(dst.size() == 3);
BOOST_TEST(dst[1] == "one"); BOOST_TEST(dst[1] == "one");
BOOST_TEST(dst[2] == "two"); BOOST_TEST(dst[2] == "two");
BOOST_TEST(dst[3] == "three"); BOOST_TEST(dst[3] == "three");
BOOST_TEST(!r.inserted); BOOST_TEST(!r.inserted);
BOOST_TEST(r.position == dst.find(3)); BOOST_TEST(r.position == dst.find(3));
BOOST_TEST(r.node.mapped() == "buckle my shoe"); BOOST_TEST(r.node.mapped() == "buckle my shoe");
} }
UNORDERED_AUTO_TEST(example2) UNORDERED_AUTO_TEST(example2)
{ {
boost::unordered_set<int> src; boost::unordered_set<int> src;
src.insert(1); src.insert(1);
src.insert(3); src.insert(3);
src.insert(5); src.insert(5);
boost::unordered_set<int> dst; boost::unordered_set<int> dst;
dst.insert(2); dst.insert(2);
dst.insert(4); dst.insert(4);
dst.insert(5); dst.insert(5);
// dst.merge(src); // dst.merge(src);
// Merge src into dst. // Merge src into dst.
// src == {5} // src == {5}
// dst == {1, 2, 3, 4, 5} // dst == {1, 2, 3, 4, 5}
} }
UNORDERED_AUTO_TEST(example3) UNORDERED_AUTO_TEST(example3)
{ {
typedef boost::unordered_set<int>::iterator iterator; typedef boost::unordered_set<int>::iterator iterator;
boost::unordered_set<int> src; boost::unordered_set<int> src;
src.insert(1); src.insert(1);
src.insert(3); src.insert(3);
src.insert(5); src.insert(5);
boost::unordered_set<int> dst; boost::unordered_set<int> dst;
dst.insert(2); dst.insert(2);
dst.insert(4); dst.insert(4);
dst.insert(5); dst.insert(5);
for (iterator i = src.begin(); i != src.end();) { for (iterator i = src.begin(); i != src.end();) {
std::pair<iterator, iterator> p = dst.equal_range(*i); std::pair<iterator, iterator> p = dst.equal_range(*i);
if (p.first == p.second) if (p.first == p.second)
dst.insert(p.first, src.extract(i++)); dst.insert(p.first, src.extract(i++));
else else
++i; ++i;
} }
BOOST_TEST(src.size() == 1); BOOST_TEST(src.size() == 1);
BOOST_TEST(*src.begin() == 5); BOOST_TEST(*src.begin() == 5);
std::set<int> dst2(dst.begin(), dst.end()); std::set<int> dst2(dst.begin(), dst.end());
std::set<int>::iterator it = dst2.begin(); std::set<int>::iterator it = dst2.begin();
BOOST_TEST(*it++ == 1); BOOST_TEST(*it++ == 1);
BOOST_TEST(*it++ == 2); BOOST_TEST(*it++ == 2);
BOOST_TEST(*it++ == 3); BOOST_TEST(*it++ == 3);
BOOST_TEST(*it++ == 4); BOOST_TEST(*it++ == 4);
BOOST_TEST(*it++ == 5); BOOST_TEST(*it++ == 5);
BOOST_TEST(it == dst2.end()); BOOST_TEST(it == dst2.end());
} }
UNORDERED_AUTO_TEST(failed_insertion_with_hint) UNORDERED_AUTO_TEST(failed_insertion_with_hint)
{ {
{ {
boost::unordered_set<int> src; boost::unordered_set<int> src;
boost::unordered_set<int> dst; boost::unordered_set<int> dst;
src.emplace(10); src.emplace(10);
src.emplace(20); src.emplace(20);
dst.emplace(10); dst.emplace(10);
dst.emplace(20); dst.emplace(20);
boost::unordered_set<int>::node_type nh = src.extract(10); boost::unordered_set<int>::node_type nh = src.extract(10);
BOOST_TEST(dst.insert(dst.find(10), boost::move(nh)) == dst.find(10)); BOOST_TEST(dst.insert(dst.find(10), boost::move(nh)) == dst.find(10));
BOOST_TEST(nh); BOOST_TEST(nh);
BOOST_TEST(!nh.empty()); BOOST_TEST(!nh.empty());
BOOST_TEST(nh.value() == 10); BOOST_TEST(nh.value() == 10);
BOOST_TEST(dst.insert(dst.find(20), boost::move(nh)) == dst.find(10)); BOOST_TEST(dst.insert(dst.find(20), boost::move(nh)) == dst.find(10));
BOOST_TEST(nh); BOOST_TEST(nh);
BOOST_TEST(!nh.empty()); BOOST_TEST(!nh.empty());
BOOST_TEST(nh.value() == 10); BOOST_TEST(nh.value() == 10);
BOOST_TEST(src.count(10) == 0); BOOST_TEST(src.count(10) == 0);
BOOST_TEST(src.count(20) == 1); BOOST_TEST(src.count(20) == 1);
BOOST_TEST(dst.count(10) == 1); BOOST_TEST(dst.count(10) == 1);
BOOST_TEST(dst.count(20) == 1); BOOST_TEST(dst.count(20) == 1);
} }
{ {
boost::unordered_map<int, int> src; boost::unordered_map<int, int> src;
boost::unordered_map<int, int> dst; boost::unordered_map<int, int> dst;
src.emplace(10, 30); src.emplace(10, 30);
src.emplace(20, 5); src.emplace(20, 5);
dst.emplace(10, 20); dst.emplace(10, 20);
dst.emplace(20, 2); dst.emplace(20, 2);
boost::unordered_map<int, int>::node_type nh = src.extract(10); boost::unordered_map<int, int>::node_type nh = src.extract(10);
BOOST_TEST(dst.insert(dst.find(10), boost::move(nh)) == dst.find(10)); BOOST_TEST(dst.insert(dst.find(10), boost::move(nh)) == dst.find(10));
BOOST_TEST(nh); BOOST_TEST(nh);
BOOST_TEST(!nh.empty()); BOOST_TEST(!nh.empty());
BOOST_TEST(nh.key() == 10); BOOST_TEST(nh.key() == 10);
BOOST_TEST(nh.mapped() == 30); BOOST_TEST(nh.mapped() == 30);
BOOST_TEST(dst[10] == 20); BOOST_TEST(dst[10] == 20);
BOOST_TEST(dst.insert(dst.find(20), boost::move(nh)) == dst.find(10)); BOOST_TEST(dst.insert(dst.find(20), boost::move(nh)) == dst.find(10));
BOOST_TEST(nh); BOOST_TEST(nh);
BOOST_TEST(!nh.empty()); BOOST_TEST(!nh.empty());
BOOST_TEST(nh.key() == 10); BOOST_TEST(nh.key() == 10);
BOOST_TEST(nh.mapped() == 30); BOOST_TEST(nh.mapped() == 30);
BOOST_TEST(dst[10] == 20); BOOST_TEST(dst[10] == 20);
BOOST_TEST(src.count(10) == 0); BOOST_TEST(src.count(10) == 0);
BOOST_TEST(src.count(20) == 1); BOOST_TEST(src.count(20) == 1);
BOOST_TEST(dst.count(10) == 1); BOOST_TEST(dst.count(10) == 1);
BOOST_TEST(dst.count(20) == 1); BOOST_TEST(dst.count(20) == 1);
} }
}
template <typename NodeHandle>
bool node_handle_compare(NodeHandle const& nh,
BOOST_DEDUCED_TYPENAME NodeHandle::value_type const& x)
{
return x == nh.value();
} }
template <typename NodeHandle> template <typename NodeHandle>
bool node_handle_compare( bool node_handle_compare(
NodeHandle const& nh, NodeHandle const& nh, BOOST_DEDUCED_TYPENAME NodeHandle::value_type const& x)
std::pair<BOOST_DEDUCED_TYPENAME NodeHandle::key_type const,
BOOST_DEDUCED_TYPENAME NodeHandle::mapped_type> const& x)
{ {
return x.first == nh.key() && x.second == nh.mapped(); return x == nh.value();
}
template <typename NodeHandle>
bool node_handle_compare(
NodeHandle const& nh,
std::pair<BOOST_DEDUCED_TYPENAME NodeHandle::key_type const,
BOOST_DEDUCED_TYPENAME NodeHandle::mapped_type> const& x)
{
return x.first == nh.key() && x.second == nh.mapped();
} }
template <typename Container> void node_handle_tests_impl(Container& c) template <typename Container> void node_handle_tests_impl(Container& c)
{ {
typedef BOOST_DEDUCED_TYPENAME Container::node_type node_type; typedef BOOST_DEDUCED_TYPENAME Container::node_type node_type;
BOOST_DEDUCED_TYPENAME Container::value_type value = *c.begin(); BOOST_DEDUCED_TYPENAME Container::value_type value = *c.begin();
node_type n1; node_type n1;
BOOST_TEST(!n1); BOOST_TEST(!n1);
BOOST_TEST(n1.empty()); BOOST_TEST(n1.empty());
node_type n2 = c.extract(c.begin()); node_type n2 = c.extract(c.begin());
BOOST_TEST(n2); BOOST_TEST(n2);
BOOST_TEST(!n2.empty()); BOOST_TEST(!n2.empty());
node_handle_compare(n2, value); node_handle_compare(n2, value);
node_type n3 = boost::move(n2); node_type n3 = boost::move(n2);
BOOST_TEST(n3); BOOST_TEST(n3);
BOOST_TEST(!n2); BOOST_TEST(!n2);
node_handle_compare(n3, value); node_handle_compare(n3, value);
// TODO: Check that n2 doesn't have an allocator? // TODO: Check that n2 doesn't have an allocator?
// Maybe by swapping and observing that the allocator is // Maybe by swapping and observing that the allocator is
// swapped rather than moved? // swapped rather than moved?
n1 = boost::move(n3); n1 = boost::move(n3);
BOOST_TEST(n1); BOOST_TEST(n1);
BOOST_TEST(!n3); BOOST_TEST(!n3);
node_handle_compare(n1, value); node_handle_compare(n1, value);
// Self move-assignment empties the node_handle. // Self move-assignment empties the node_handle.
n1 = boost::move(n1); n1 = boost::move(n1);
BOOST_TEST(!n1); BOOST_TEST(!n1);
n3 = boost::move(n3); n3 = boost::move(n3);
BOOST_TEST(!n3); BOOST_TEST(!n3);
BOOST_DEDUCED_TYPENAME Container::value_type value1 = *c.begin(); BOOST_DEDUCED_TYPENAME Container::value_type value1 = *c.begin();
n1 = c.extract(c.begin()); n1 = c.extract(c.begin());
BOOST_DEDUCED_TYPENAME Container::value_type value2 = *c.begin(); BOOST_DEDUCED_TYPENAME Container::value_type value2 = *c.begin();
n2 = c.extract(c.begin()); n2 = c.extract(c.begin());
n3 = node_type(); n3 = node_type();
node_handle_compare(n1, value1); node_handle_compare(n1, value1);
node_handle_compare(n2, value2); node_handle_compare(n2, value2);
n1.swap(n2); n1.swap(n2);
BOOST_TEST(n1); BOOST_TEST(n1);
BOOST_TEST(n2); BOOST_TEST(n2);
node_handle_compare(n1, value2); node_handle_compare(n1, value2);
node_handle_compare(n2, value1); node_handle_compare(n2, value1);
BOOST_TEST(n1); BOOST_TEST(n1);
BOOST_TEST(!n3); BOOST_TEST(!n3);
n1.swap(n3); n1.swap(n3);
BOOST_TEST(!n1); BOOST_TEST(!n1);
BOOST_TEST(n3); BOOST_TEST(n3);
node_handle_compare(n3, value2); node_handle_compare(n3, value2);
BOOST_TEST(!n1); BOOST_TEST(!n1);
BOOST_TEST(n2); BOOST_TEST(n2);
n1.swap(n2); n1.swap(n2);
BOOST_TEST(n1); BOOST_TEST(n1);
BOOST_TEST(!n2); BOOST_TEST(!n2);
node_handle_compare(n1, value1); node_handle_compare(n1, value1);
node_type n4; node_type n4;
BOOST_TEST(!n2); BOOST_TEST(!n2);
BOOST_TEST(!n4); BOOST_TEST(!n4);
n2.swap(n4); n2.swap(n4);
BOOST_TEST(!n2); BOOST_TEST(!n2);
BOOST_TEST(!n4); BOOST_TEST(!n4);
} }
UNORDERED_AUTO_TEST(node_handle_tests) UNORDERED_AUTO_TEST(node_handle_tests)
{ {
boost::unordered_set<int> x1; boost::unordered_set<int> x1;
x1.emplace(100); x1.emplace(100);
x1.emplace(140); x1.emplace(140);
x1.emplace(-55); x1.emplace(-55);
node_handle_tests_impl(x1); node_handle_tests_impl(x1);
boost::unordered_map<int, std::string> x2; boost::unordered_map<int, std::string> x2;
x2.emplace(10, "ten"); x2.emplace(10, "ten");
x2.emplace(-23, "twenty"); x2.emplace(-23, "twenty");
x2.emplace(-76, "thirty"); x2.emplace(-76, "thirty");
node_handle_tests_impl(x2); node_handle_tests_impl(x2);
} }
template <typename Container1, typename Container2> template <typename Container1, typename Container2>
void insert_node_handle_unique(Container1& c1, Container2& c2) void insert_node_handle_unique(Container1& c1, Container2& c2)
{ {
typedef BOOST_DEDUCED_TYPENAME Container1::node_type node_type; typedef BOOST_DEDUCED_TYPENAME Container1::node_type node_type;
typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_type; typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_type;
BOOST_STATIC_ASSERT(boost::is_same<node_type, BOOST_STATIC_ASSERT(boost::is_same<node_type,
BOOST_DEDUCED_TYPENAME Container2::node_type>::value); BOOST_DEDUCED_TYPENAME Container2::node_type>::value);
typedef BOOST_DEDUCED_TYPENAME Container1::insert_return_type typedef BOOST_DEDUCED_TYPENAME Container1::insert_return_type
insert_return_type1; insert_return_type1;
typedef BOOST_DEDUCED_TYPENAME Container2::insert_return_type typedef BOOST_DEDUCED_TYPENAME Container2::insert_return_type
insert_return_type2; insert_return_type2;
insert_return_type1 r1 = c1.insert(node_type()); insert_return_type1 r1 = c1.insert(node_type());
insert_return_type2 r2 = c2.insert(node_type()); insert_return_type2 r2 = c2.insert(node_type());
BOOST_TEST(!r1.inserted); BOOST_TEST(!r1.inserted);
BOOST_TEST(!r1.node); BOOST_TEST(!r1.node);
BOOST_TEST(r1.position == c1.end()); BOOST_TEST(r1.position == c1.end());
BOOST_TEST(!r2.inserted); BOOST_TEST(!r2.inserted);
BOOST_TEST(!r2.node); BOOST_TEST(!r2.node);
BOOST_TEST(r2.position == c2.end()); BOOST_TEST(r2.position == c2.end());
while (!c1.empty()) { while (!c1.empty()) {
value_type v = *c1.begin(); value_type v = *c1.begin();
value_type const* v_ptr = boost::addressof(*c1.begin()); value_type const* v_ptr = boost::addressof(*c1.begin());
std::size_t count = c2.count(test::get_key<Container1>(v)); std::size_t count = c2.count(test::get_key<Container1>(v));
insert_return_type2 r = c2.insert(c1.extract(c1.begin())); insert_return_type2 r = c2.insert(c1.extract(c1.begin()));
if (!count) { if (!count) {
BOOST_TEST(r.inserted); BOOST_TEST(r.inserted);
BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count + 1); BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count + 1);
BOOST_TEST(r.position != c2.end()); BOOST_TEST(r.position != c2.end());
BOOST_TEST(boost::addressof(*r.position) == v_ptr); BOOST_TEST(boost::addressof(*r.position) == v_ptr);
BOOST_TEST(!r.node); BOOST_TEST(!r.node);
} else { } else {
BOOST_TEST(!r.inserted); BOOST_TEST(!r.inserted);
BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count); BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count);
BOOST_TEST(r.position != c2.end()); BOOST_TEST(r.position != c2.end());
BOOST_TEST(test::get_key<Container2>(*r.position) == BOOST_TEST(
test::get_key<Container2>(v)); test::get_key<Container2>(*r.position) == test::get_key<Container2>(v));
BOOST_TEST(r.node); BOOST_TEST(r.node);
node_handle_compare(r.node, v); node_handle_compare(r.node, v);
}
} }
}
} }
template <typename Container1, typename Container2> template <typename Container1, typename Container2>
void insert_node_handle_unique2(Container1& c1, Container2& c2) void insert_node_handle_unique2(Container1& c1, Container2& c2)
{ {
typedef BOOST_DEDUCED_TYPENAME Container1::node_type node_type; typedef BOOST_DEDUCED_TYPENAME Container1::node_type node_type;
typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_type; typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_type;
BOOST_STATIC_ASSERT(boost::is_same<node_type, BOOST_STATIC_ASSERT(boost::is_same<node_type,
BOOST_DEDUCED_TYPENAME Container2::node_type>::value); BOOST_DEDUCED_TYPENAME Container2::node_type>::value);
// typedef BOOST_DEDUCED_TYPENAME Container1::insert_return_type // typedef BOOST_DEDUCED_TYPENAME Container1::insert_return_type
// insert_return_type1; // insert_return_type1;
typedef BOOST_DEDUCED_TYPENAME Container2::insert_return_type typedef BOOST_DEDUCED_TYPENAME Container2::insert_return_type
insert_return_type2; insert_return_type2;
while (!c1.empty()) { while (!c1.empty()) {
value_type v = *c1.begin(); value_type v = *c1.begin();
value_type const* v_ptr = boost::addressof(*c1.begin()); value_type const* v_ptr = boost::addressof(*c1.begin());
std::size_t count = c2.count(test::get_key<Container1>(v)); std::size_t count = c2.count(test::get_key<Container1>(v));
insert_return_type2 r = insert_return_type2 r = c2.insert(c1.extract(test::get_key<Container1>(v)));
c2.insert(c1.extract(test::get_key<Container1>(v))); if (r.inserted) {
if (r.inserted) { BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count + 1);
BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count + 1); BOOST_TEST(r.position != c2.end());
BOOST_TEST(r.position != c2.end()); BOOST_TEST(boost::addressof(*r.position) == v_ptr);
BOOST_TEST(boost::addressof(*r.position) == v_ptr); BOOST_TEST(!r.node);
BOOST_TEST(!r.node); } else {
} else { BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count);
BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count); BOOST_TEST(r.position != c2.end());
BOOST_TEST(r.position != c2.end()); BOOST_TEST(
BOOST_TEST(test::get_key<Container2>(*r.position) == test::get_key<Container2>(*r.position) == test::get_key<Container2>(v));
test::get_key<Container2>(v)); BOOST_TEST(r.node);
BOOST_TEST(r.node); node_handle_compare(r.node, v);
node_handle_compare(r.node, v);
}
} }
}
} }
template <typename Container1, typename Container2> template <typename Container1, typename Container2>
void insert_node_handle_equiv(Container1& c1, Container2& c2) void insert_node_handle_equiv(Container1& c1, Container2& c2)
{ {
typedef BOOST_DEDUCED_TYPENAME Container1::node_type node_type; typedef BOOST_DEDUCED_TYPENAME Container1::node_type node_type;
typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_type; typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_type;
BOOST_STATIC_ASSERT(boost::is_same<node_type, BOOST_STATIC_ASSERT(boost::is_same<node_type,
BOOST_DEDUCED_TYPENAME Container2::node_type>::value); BOOST_DEDUCED_TYPENAME Container2::node_type>::value);
typedef BOOST_DEDUCED_TYPENAME Container1::iterator iterator1; typedef BOOST_DEDUCED_TYPENAME Container1::iterator iterator1;
typedef BOOST_DEDUCED_TYPENAME Container2::iterator iterator2; typedef BOOST_DEDUCED_TYPENAME Container2::iterator iterator2;
iterator1 r1 = c1.insert(node_type()); iterator1 r1 = c1.insert(node_type());
iterator2 r2 = c2.insert(node_type()); iterator2 r2 = c2.insert(node_type());
BOOST_TEST(r1 == c1.end()); BOOST_TEST(r1 == c1.end());
BOOST_TEST(r2 == c2.end()); BOOST_TEST(r2 == c2.end());
while (!c1.empty()) { while (!c1.empty()) {
value_type v = *c1.begin(); value_type v = *c1.begin();
value_type const* v_ptr = boost::addressof(*c1.begin()); value_type const* v_ptr = boost::addressof(*c1.begin());
std::size_t count = c2.count(test::get_key<Container1>(v)); std::size_t count = c2.count(test::get_key<Container1>(v));
iterator2 r = c2.insert(c1.extract(c1.begin())); iterator2 r = c2.insert(c1.extract(c1.begin()));
BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count + 1); BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count + 1);
BOOST_TEST(r != c2.end()); BOOST_TEST(r != c2.end());
BOOST_TEST(boost::addressof(*r) == v_ptr); BOOST_TEST(boost::addressof(*r) == v_ptr);
} }
} }
struct hash_thing struct hash_thing
{ {
std::size_t operator()(int x) const std::size_t operator()(int x) const
{ {
return static_cast<std::size_t>(x * 13 + 5); return static_cast<std::size_t>(x * 13 + 5);
} }
}; };
UNORDERED_AUTO_TEST(insert_node_handle_unique_tests) UNORDERED_AUTO_TEST(insert_node_handle_unique_tests)
{ {
{ {
boost::unordered_set<int> x1; boost::unordered_set<int> x1;
boost::unordered_set<int> x2; boost::unordered_set<int> x2;
x1.emplace(100); x1.emplace(100);
x1.emplace(140); x1.emplace(140);
x1.emplace(-55); x1.emplace(-55);
x2.emplace(140); x2.emplace(140);
insert_node_handle_unique(x1, x2); insert_node_handle_unique(x1, x2);
BOOST_TEST(x2.size() == 3); BOOST_TEST(x2.size() == 3);
} }
{ {
boost::unordered_map<int, int, hash_thing> x1; boost::unordered_map<int, int, hash_thing> x1;
boost::unordered_map<int, int> x2; boost::unordered_map<int, int> x2;
x1.emplace(67, 50); x1.emplace(67, 50);
x1.emplace(23, 45); x1.emplace(23, 45);
x1.emplace(18, 19); x1.emplace(18, 19);
x2.emplace(23, 50); x2.emplace(23, 50);
x2.emplace(12, 49); x2.emplace(12, 49);
insert_node_handle_unique(x1, x2); insert_node_handle_unique(x1, x2);
BOOST_TEST(x2.size() == 4); BOOST_TEST(x2.size() == 4);
} }
} }
UNORDERED_AUTO_TEST(insert_node_handle_equiv_tests) UNORDERED_AUTO_TEST(insert_node_handle_equiv_tests)
{ {
{ {
boost::unordered_multimap<int, int, hash_thing> x1; boost::unordered_multimap<int, int, hash_thing> x1;
boost::unordered_multimap<int, int> x2; boost::unordered_multimap<int, int> x2;
x1.emplace(67, 50); x1.emplace(67, 50);
x1.emplace(67, 100); x1.emplace(67, 100);
x1.emplace(23, 45); x1.emplace(23, 45);
x1.emplace(18, 19); x1.emplace(18, 19);
x2.emplace(23, 50); x2.emplace(23, 50);
x2.emplace(12, 49); x2.emplace(12, 49);
insert_node_handle_equiv(x1, x2); insert_node_handle_equiv(x1, x2);
BOOST_TEST(x2.size() == 6); BOOST_TEST(x2.size() == 6);
} }
} }
UNORDERED_AUTO_TEST(insert_node_handle_unique_tests2) UNORDERED_AUTO_TEST(insert_node_handle_unique_tests2)
{ {
{ {
boost::unordered_set<int> x1; boost::unordered_set<int> x1;
boost::unordered_set<int> x2; boost::unordered_set<int> x2;
x1.emplace(100); x1.emplace(100);
x1.emplace(140); x1.emplace(140);
x1.emplace(-55); x1.emplace(-55);
x2.emplace(140); x2.emplace(140);
insert_node_handle_unique2(x1, x2); insert_node_handle_unique2(x1, x2);
BOOST_TEST(x2.size() == 3); BOOST_TEST(x2.size() == 3);
} }
{ {
boost::unordered_map<int, int, hash_thing> x1; boost::unordered_map<int, int, hash_thing> x1;
boost::unordered_map<int, int> x2; boost::unordered_map<int, int> x2;
x1.emplace(67, 50); x1.emplace(67, 50);
x1.emplace(23, 45); x1.emplace(23, 45);
x1.emplace(18, 19); x1.emplace(18, 19);
x2.emplace(23, 50); x2.emplace(23, 50);
x2.emplace(12, 49); x2.emplace(12, 49);
insert_node_handle_unique2(x1, x2); insert_node_handle_unique2(x1, x2);
BOOST_TEST(x2.size() == 4); BOOST_TEST(x2.size() == 4);
} }
} }
RUN_TESTS() RUN_TESTS()

View File

@ -13,37 +13,37 @@
#include "../helpers/test.hpp" #include "../helpers/test.hpp"
namespace noexcept_tests { namespace noexcept_tests {
// Test the noexcept is set correctly for the move constructor. // Test the noexcept is set correctly for the move constructor.
struct hash_possible_exception : boost::hash<int> struct hash_possible_exception : boost::hash<int>
{ {
hash_possible_exception(hash_possible_exception const&) {} hash_possible_exception(hash_possible_exception const&) {}
}; };
struct equal_to_possible_exception : std::equal_to<int> struct equal_to_possible_exception : std::equal_to<int>
{ {
equal_to_possible_exception(equal_to_possible_exception const&) {} equal_to_possible_exception(equal_to_possible_exception const&) {}
}; };
// Test that the move constructor does actually move without throwing // Test that the move constructor does actually move without throwing
// an exception when it claims to. // an exception when it claims to.
struct test_exception struct test_exception
{ {
}; };
bool throwing_test_exception = false; bool throwing_test_exception = false;
void test_throw(char const* name) void test_throw(char const* name)
{ {
if (throwing_test_exception) { if (throwing_test_exception) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Throw exception in: " << name BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Throw exception in: " << name
<< std::endl; << std::endl;
throw test_exception(); throw test_exception();
} }
} }
class hash_nothrow_move : boost::hash<int> class hash_nothrow_move : boost::hash<int>
{ {
BOOST_COPYABLE_AND_MOVABLE(hash_nothrow_move) BOOST_COPYABLE_AND_MOVABLE(hash_nothrow_move)
typedef boost::hash<int> base; typedef boost::hash<int> base;
@ -55,23 +55,23 @@ class hash_nothrow_move : boost::hash<int>
hash_nothrow_move(hash_nothrow_move const&) { test_throw("Copy"); } hash_nothrow_move(hash_nothrow_move const&) { test_throw("Copy"); }
hash_nothrow_move& operator=(BOOST_COPY_ASSIGN_REF(hash_nothrow_move)) hash_nothrow_move& operator=(BOOST_COPY_ASSIGN_REF(hash_nothrow_move))
{ {
test_throw("Assign"); test_throw("Assign");
return *this; return *this;
} }
hash_nothrow_move& operator=(BOOST_RV_REF(hash_nothrow_move)) hash_nothrow_move& operator=(BOOST_RV_REF(hash_nothrow_move))
{ {
test_throw("Move Assign"); test_throw("Move Assign");
return *this; return *this;
} }
std::size_t operator()(int x) const std::size_t operator()(int x) const
{ {
test_throw("Operator"); test_throw("Operator");
return static_cast<base const&>(*this)(x); return static_cast<base const&>(*this)(x);
} }
}; };
class equal_to_nothrow_move : std::equal_to<int> class equal_to_nothrow_move : std::equal_to<int>
{ {
BOOST_COPYABLE_AND_MOVABLE(equal_to_nothrow_move) BOOST_COPYABLE_AND_MOVABLE(equal_to_nothrow_move)
typedef std::equal_to<int> base; typedef std::equal_to<int> base;
@ -81,31 +81,31 @@ class equal_to_nothrow_move : std::equal_to<int>
equal_to_nothrow_move() { test_throw("Constructor"); } equal_to_nothrow_move() { test_throw("Constructor"); }
equal_to_nothrow_move(equal_to_nothrow_move const&) { test_throw("Copy"); } equal_to_nothrow_move(equal_to_nothrow_move const&) { test_throw("Copy"); }
equal_to_nothrow_move& operator=( equal_to_nothrow_move& operator=(
BOOST_COPY_ASSIGN_REF(equal_to_nothrow_move)) BOOST_COPY_ASSIGN_REF(equal_to_nothrow_move))
{ {
test_throw("Assign"); test_throw("Assign");
return *this; return *this;
} }
equal_to_nothrow_move& operator=(BOOST_RV_REF(equal_to_nothrow_move)) equal_to_nothrow_move& operator=(BOOST_RV_REF(equal_to_nothrow_move))
{ {
test_throw("Move Assign"); test_throw("Move Assign");
return *this; return *this;
} }
std::size_t operator()(int x, int y) const std::size_t operator()(int x, int y) const
{ {
test_throw("Operator"); test_throw("Operator");
return static_cast<base const&>(*this)(x, y); return static_cast<base const&>(*this)(x, y);
} }
}; };
bool have_is_nothrow_move = false; bool have_is_nothrow_move = false;
UNORDERED_AUTO_TEST(check_is_nothrow_move) UNORDERED_AUTO_TEST(check_is_nothrow_move)
{ {
BOOST_TEST( BOOST_TEST(
!boost::is_nothrow_move_constructible<hash_possible_exception>::value); !boost::is_nothrow_move_constructible<hash_possible_exception>::value);
have_is_nothrow_move = have_is_nothrow_move =
boost::is_nothrow_move_constructible<hash_nothrow_move>::value; boost::is_nothrow_move_constructible<hash_nothrow_move>::value;
// Copied from boost::is_nothrow_move_constructible implementation // Copied from boost::is_nothrow_move_constructible implementation
// to make sure this does actually detect it when expected. // to make sure this does actually detect it when expected.
@ -114,58 +114,58 @@ UNORDERED_AUTO_TEST(check_is_nothrow_move)
// is defined (for some versions of Visual C++?) but detects 'throw()', // is defined (for some versions of Visual C++?) but detects 'throw()',
// not noexcept. // not noexcept.
#if !defined(BOOST_NO_CXX11_NOEXCEPT) && !defined(BOOST_NO_SFINAE_EXPR) && \ #if !defined(BOOST_NO_CXX11_NOEXCEPT) && !defined(BOOST_NO_SFINAE_EXPR) && \
!BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800) !BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
BOOST_TEST(have_is_nothrow_move); BOOST_TEST(have_is_nothrow_move);
#endif #endif
} }
UNORDERED_AUTO_TEST(test_noexcept) UNORDERED_AUTO_TEST(test_noexcept)
{ {
if (have_is_nothrow_move) { if (have_is_nothrow_move) {
BOOST_TEST((boost::is_nothrow_move_constructible< BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_set<int> >::value)); boost::unordered_set<int> >::value));
BOOST_TEST((boost::is_nothrow_move_constructible< BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_multiset<int> >::value)); boost::unordered_multiset<int> >::value));
BOOST_TEST((boost::is_nothrow_move_constructible< BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_map<int, int> >::value)); boost::unordered_map<int, int> >::value));
BOOST_TEST((boost::is_nothrow_move_constructible< BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_multimap<int, int> >::value)); boost::unordered_multimap<int, int> >::value));
} }
BOOST_TEST((!boost::is_nothrow_move_constructible< BOOST_TEST((!boost::is_nothrow_move_constructible<
boost::unordered_set<int, hash_possible_exception> >::value)); boost::unordered_set<int, hash_possible_exception> >::value));
BOOST_TEST( BOOST_TEST(
(!boost::is_nothrow_move_constructible<boost::unordered_multiset<int, (!boost::is_nothrow_move_constructible<boost::unordered_multiset<int,
boost::hash<int>, equal_to_possible_exception> >::value)); boost::hash<int>, equal_to_possible_exception> >::value));
} }
UNORDERED_AUTO_TEST(test_no_throw_when_noexcept) UNORDERED_AUTO_TEST(test_no_throw_when_noexcept)
{ {
typedef boost::unordered_set<int, hash_nothrow_move, equal_to_nothrow_move> typedef boost::unordered_set<int, hash_nothrow_move, equal_to_nothrow_move>
throwing_set; throwing_set;
if (have_is_nothrow_move) { if (have_is_nothrow_move) {
BOOST_TEST(boost::is_nothrow_move_constructible<throwing_set>::value); BOOST_TEST(boost::is_nothrow_move_constructible<throwing_set>::value);
throwing_test_exception = false; throwing_test_exception = false;
throwing_set x1; throwing_set x1;
x1.insert(10); x1.insert(10);
x1.insert(50); x1.insert(50);
try { try {
throwing_test_exception = true; throwing_test_exception = true;
throwing_set x2 = boost::move(x1); throwing_set x2 = boost::move(x1);
BOOST_TEST(x2.size() == 2); BOOST_TEST(x2.size() == 2);
BOOST_TEST(*x2.begin() == 10 || *x2.begin() == 50); BOOST_TEST(*x2.begin() == 10 || *x2.begin() == 50);
} catch (test_exception) { } catch (test_exception) {
BOOST_TEST(false); BOOST_TEST(false);
} }
throwing_test_exception = false; throwing_test_exception = false;
} }
} }
} }
RUN_TESTS() RUN_TESTS()

View File

@ -18,18 +18,18 @@
namespace rehash_tests { namespace rehash_tests {
test::seed_t initialize_seed(2974); test::seed_t initialize_seed(2974);
template <class X> template <class X>
bool postcondition(X const& x, BOOST_DEDUCED_TYPENAME X::size_type n) bool postcondition(X const& x, BOOST_DEDUCED_TYPENAME X::size_type n)
{ {
return static_cast<double>(x.bucket_count()) >= return static_cast<double>(x.bucket_count()) >=
static_cast<double>(x.size()) / x.max_load_factor() && static_cast<double>(x.size()) / x.max_load_factor() &&
x.bucket_count() >= n; x.bucket_count() >= n;
} }
template <class X> void rehash_empty_test1(X*) template <class X> void rehash_empty_test1(X*)
{ {
X x; X x;
x.rehash(10000); x.rehash(10000);
@ -40,10 +40,11 @@ template <class X> void rehash_empty_test1(X*)
x.rehash(10000000); x.rehash(10000000);
BOOST_TEST(postcondition(x, 10000000)); BOOST_TEST(postcondition(x, 10000000));
} }
template <class X> void rehash_empty_test2(X*, test::random_generator generator) template <class X>
{ void rehash_empty_test2(X*, test::random_generator generator)
{
test::random_values<X> v(1000, generator); test::random_values<X> v(1000, generator);
test::ordered<X> tracker; test::ordered<X> tracker;
@ -61,10 +62,11 @@ template <class X> void rehash_empty_test2(X*, test::random_generator generator)
x.rehash(10000000); x.rehash(10000000);
tracker.compare(x); tracker.compare(x);
BOOST_TEST(postcondition(x, 10000000)); BOOST_TEST(postcondition(x, 10000000));
} }
template <class X> void rehash_empty_test3(X*, test::random_generator generator) template <class X>
{ void rehash_empty_test3(X*, test::random_generator generator)
{
test::random_values<X> v(1000, generator); test::random_values<X> v(1000, generator);
test::ordered<X> tracker; test::ordered<X> tracker;
@ -78,10 +80,10 @@ template <class X> void rehash_empty_test3(X*, test::random_generator generator)
tracker.compare(x); tracker.compare(x);
BOOST_TEST(postcondition(x, 0)); BOOST_TEST(postcondition(x, 0));
} }
template <class X> void rehash_test1(X*, test::random_generator generator) template <class X> void rehash_test1(X*, test::random_generator generator)
{ {
test::random_values<X> v(1000, generator); test::random_values<X> v(1000, generator);
test::ordered<X> tracker; test::ordered<X> tracker;
tracker.insert_range(v.begin(), v.end()); tracker.insert_range(v.begin(), v.end());
@ -104,10 +106,10 @@ template <class X> void rehash_test1(X*, test::random_generator generator)
x.rehash(1000); x.rehash(1000);
BOOST_TEST(postcondition(x, 1000)); BOOST_TEST(postcondition(x, 1000));
tracker.compare(x); tracker.compare(x);
} }
template <class X> void reserve_empty_test1(X*) template <class X> void reserve_empty_test1(X*)
{ {
X x; X x;
x.reserve(10000); x.reserve(10000);
@ -117,10 +119,10 @@ template <class X> void reserve_empty_test1(X*)
x.reserve(10000000); x.reserve(10000000);
BOOST_TEST(x.bucket_count() >= 10000000); BOOST_TEST(x.bucket_count() >= 10000000);
} }
template <class X> void reserve_empty_test2(X*) template <class X> void reserve_empty_test2(X*)
{ {
X x; X x;
x.max_load_factor(0.25); x.max_load_factor(0.25);
@ -131,98 +133,96 @@ template <class X> void reserve_empty_test2(X*)
x.reserve(10000000); x.reserve(10000000);
BOOST_TEST(x.bucket_count() >= 40000000); BOOST_TEST(x.bucket_count() >= 40000000);
} }
template <class X> void reserve_test1(X*, test::random_generator generator) template <class X> void reserve_test1(X*, test::random_generator generator)
{ {
for (int random_mlf = 0; random_mlf < 2; ++random_mlf) { for (int random_mlf = 0; random_mlf < 2; ++random_mlf) {
for (std::size_t i = 1; i < 2000; i += i < 50 ? 1 : 13) { for (std::size_t i = 1; i < 2000; i += i < 50 ? 1 : 13) {
test::random_values<X> v(i, generator); test::random_values<X> v(i, generator);
test::ordered<X> tracker; test::ordered<X> tracker;
tracker.insert_range(v.begin(), v.end()); tracker.insert_range(v.begin(), v.end());
X x; X x;
x.max_load_factor( x.max_load_factor(
random_mlf random_mlf ? static_cast<float>(std::rand() % 1000) / 500.0f + 0.5f
? static_cast<float>(std::rand() % 1000) / 500.0f + 0.5f : 1.0f);
: 1.0f); x.reserve(test::has_unique_keys<X>::value ? i : v.size());
x.reserve(test::has_unique_keys<X>::value ? i : v.size());
// Insert an element before the range insert, otherwise there are // Insert an element before the range insert, otherwise there are
// no iterators to invalidate in the range insert, and it can // no iterators to invalidate in the range insert, and it can
// rehash. // rehash.
typename test::random_values<X>::iterator it = v.begin(); typename test::random_values<X>::iterator it = v.begin();
x.insert(*it); x.insert(*it);
++it; ++it;
std::size_t bucket_count = x.bucket_count(); std::size_t bucket_count = x.bucket_count();
x.insert(it, v.end()); x.insert(it, v.end());
BOOST_TEST(bucket_count == x.bucket_count()); BOOST_TEST(bucket_count == x.bucket_count());
tracker.compare(x); tracker.compare(x);
} }
} }
} }
template <class X> void reserve_test2(X*, test::random_generator generator) template <class X> void reserve_test2(X*, test::random_generator generator)
{ {
for (int random_mlf = 0; random_mlf < 2; ++random_mlf) { for (int random_mlf = 0; random_mlf < 2; ++random_mlf) {
for (std::size_t i = 0; i < 2000; i += i < 50 ? 1 : 13) { for (std::size_t i = 0; i < 2000; i += i < 50 ? 1 : 13) {
test::random_values<X> v(i, generator); test::random_values<X> v(i, generator);
test::ordered<X> tracker; test::ordered<X> tracker;
tracker.insert_range(v.begin(), v.end()); tracker.insert_range(v.begin(), v.end());
X x; X x;
x.max_load_factor( x.max_load_factor(
random_mlf random_mlf ? static_cast<float>(std::rand() % 1000) / 500.0f + 0.5f
? static_cast<float>(std::rand() % 1000) / 500.0f + 0.5f : 1.0f);
: 1.0f);
x.reserve(test::has_unique_keys<X>::value ? i : v.size()); x.reserve(test::has_unique_keys<X>::value ? i : v.size());
std::size_t bucket_count = x.bucket_count(); std::size_t bucket_count = x.bucket_count();
for (typename test::random_values<X>::iterator it = v.begin(); for (typename test::random_values<X>::iterator it = v.begin();
it != v.end(); ++it) { it != v.end(); ++it) {
x.insert(*it); x.insert(*it);
}
BOOST_TEST(bucket_count == x.bucket_count());
tracker.compare(x);
} }
}
}
boost::unordered_set<int>* int_set_ptr; BOOST_TEST(bucket_count == x.bucket_count());
boost::unordered_multiset<test::object, test::hash, test::equal_to, tracker.compare(x);
}
}
}
boost::unordered_set<int>* int_set_ptr;
boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset_ptr; test::allocator2<test::object> >* test_multiset_ptr;
boost::unordered_map<test::movable, test::movable, test::hash, test::equal_to, boost::unordered_map<test::movable, test::movable, test::hash, test::equal_to,
test::allocator2<test::movable> >* test_map_ptr; test::allocator2<test::movable> >* test_map_ptr;
boost::unordered_multimap<int, int>* int_multimap_ptr; boost::unordered_multimap<int, int>* int_multimap_ptr;
using test::default_generator; using test::default_generator;
using test::generate_collisions; using test::generate_collisions;
using test::limited_range; using test::limited_range;
UNORDERED_TEST(rehash_empty_test1, UNORDERED_TEST(rehash_empty_test1,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))) ((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr)))
UNORDERED_TEST(rehash_empty_test2, UNORDERED_TEST(rehash_empty_test2,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))( ((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))(
(default_generator)(generate_collisions)(limited_range))) (default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(rehash_empty_test3, UNORDERED_TEST(rehash_empty_test3,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))( ((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))(
(default_generator)(generate_collisions)(limited_range))) (default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(rehash_test1, UNORDERED_TEST(rehash_test1,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))( ((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))(
(default_generator)(generate_collisions)(limited_range))) (default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(reserve_empty_test1, UNORDERED_TEST(reserve_empty_test1,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))) ((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr)))
UNORDERED_TEST(reserve_empty_test2, UNORDERED_TEST(reserve_empty_test2,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))) ((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr)))
UNORDERED_TEST(reserve_test1, UNORDERED_TEST(reserve_test1,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))( ((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))(
(default_generator)(generate_collisions)(limited_range))) (default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(reserve_test2, UNORDERED_TEST(reserve_test2,
((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))( ((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr))(
(default_generator)(generate_collisions)(limited_range))) (default_generator)(generate_collisions)(limited_range)))
} }

View File

@ -19,117 +19,117 @@
template <class X> void simple_test(X const& a) template <class X> void simple_test(X const& a)
{ {
test::unordered_equivalence_tester<X> equivalent(a); test::unordered_equivalence_tester<X> equivalent(a);
{ {
X u; X u;
BOOST_TEST(u.size() == 0); BOOST_TEST(u.size() == 0);
BOOST_TEST(X().size() == 0); BOOST_TEST(X().size() == 0);
} }
{ {
BOOST_TEST(equivalent(X(a))); BOOST_TEST(equivalent(X(a)));
} }
{ {
X u(a); X u(a);
BOOST_TEST(equivalent(u)); BOOST_TEST(equivalent(u));
} }
{ {
X u = a; X u = a;
BOOST_TEST(equivalent(u)); BOOST_TEST(equivalent(u));
} }
{ {
X b(a); X b(a);
BOOST_TEST(b.begin() == const_cast<X const&>(b).cbegin()); BOOST_TEST(b.begin() == const_cast<X const&>(b).cbegin());
BOOST_TEST(b.end() == const_cast<X const&>(b).cend()); BOOST_TEST(b.end() == const_cast<X const&>(b).cend());
} }
{ {
X b(a); X b(a);
X c; X c;
BOOST_TEST(equivalent(b)); BOOST_TEST(equivalent(b));
BOOST_TEST(c.empty()); BOOST_TEST(c.empty());
b.swap(c); b.swap(c);
BOOST_TEST(b.empty()); BOOST_TEST(b.empty());
BOOST_TEST(equivalent(c)); BOOST_TEST(equivalent(c));
b.swap(c); b.swap(c);
BOOST_TEST(c.empty()); BOOST_TEST(c.empty());
BOOST_TEST(equivalent(b)); BOOST_TEST(equivalent(b));
} }
{ {
X u; X u;
X& r = u; X& r = u;
BOOST_TEST(&(r = r) == &r); BOOST_TEST(&(r = r) == &r);
BOOST_TEST(r.empty()); BOOST_TEST(r.empty());
BOOST_TEST(&(r = a) == &r); BOOST_TEST(&(r = a) == &r);
BOOST_TEST(equivalent(r)); BOOST_TEST(equivalent(r));
BOOST_TEST(&(r = r) == &r); BOOST_TEST(&(r = r) == &r);
BOOST_TEST(equivalent(r)); BOOST_TEST(equivalent(r));
} }
{ {
BOOST_TEST(a.size() == static_cast<BOOST_DEDUCED_TYPENAME X::size_type>( BOOST_TEST(a.size() == static_cast<BOOST_DEDUCED_TYPENAME X::size_type>(
std::distance(a.begin(), a.end()))); std::distance(a.begin(), a.end())));
} }
{ {
BOOST_TEST(a.empty() == (a.size() == 0)); BOOST_TEST(a.empty() == (a.size() == 0));
} }
{ {
BOOST_TEST(a.empty() == (a.begin() == a.end())); BOOST_TEST(a.empty() == (a.begin() == a.end()));
X u; X u;
BOOST_TEST(u.begin() == u.end()); BOOST_TEST(u.begin() == u.end());
} }
} }
UNORDERED_AUTO_TEST(simple_tests) UNORDERED_AUTO_TEST(simple_tests)
{ {
using namespace std; using namespace std;
srand(14878); srand(14878);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_set.\n";
boost::unordered_set<int> set; boost::unordered_set<int> set;
simple_test(set); simple_test(set);
set.insert(1); set.insert(1);
set.insert(2); set.insert(2);
set.insert(1456); set.insert(1456);
simple_test(set); simple_test(set);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multiset.\n";
boost::unordered_multiset<int> multiset; boost::unordered_multiset<int> multiset;
simple_test(multiset); simple_test(multiset);
for (int i1 = 0; i1 < 1000; ++i1) { for (int i1 = 0; i1 < 1000; ++i1) {
int count = rand() % 10, index = rand(); int count = rand() % 10, index = rand();
for (int j = 0; j < count; ++j) for (int j = 0; j < count; ++j)
multiset.insert(index); multiset.insert(index);
} }
simple_test(multiset); simple_test(multiset);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_map.\n";
boost::unordered_map<int, int> map; boost::unordered_map<int, int> map;
for (int i2 = 0; i2 < 1000; ++i2) { for (int i2 = 0; i2 < 1000; ++i2) {
map.insert(std::pair<const int, int>(rand(), rand())); map.insert(std::pair<const int, int>(rand(), rand()));
} }
simple_test(map); simple_test(map);
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multimap.\n"; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Test unordered_multimap.\n";
boost::unordered_multimap<int, int> multimap; boost::unordered_multimap<int, int> multimap;
for (int i3 = 0; i3 < 1000; ++i3) { for (int i3 = 0; i3 < 1000; ++i3) {
int count = rand() % 10, index = rand(); int count = rand() % 10, index = rand();
for (int j = 0; j < count; ++j) for (int j = 0; j < count; ++j)
multimap.insert(std::pair<const int, int>(index, rand())); multimap.insert(std::pair<const int, int>(index, rand()));
} }
simple_test(multimap); simple_test(multimap);
} }
RUN_TESTS() RUN_TESTS()

View File

@ -26,10 +26,10 @@
namespace swap_tests { namespace swap_tests {
test::seed_t initialize_seed(783472); test::seed_t initialize_seed(783472);
template <class X> void swap_test_impl(X& x1, X& x2) template <class X> void swap_test_impl(X& x1, X& x2)
{ {
test::ordered<X> tracker1 = test::create_ordered(x1); test::ordered<X> tracker1 = test::create_ordered(x1);
test::ordered<X> tracker2 = test::create_ordered(x2); test::ordered<X> tracker2 = test::create_ordered(x2);
tracker1.insert_range(x1.begin(), x1.end()); tracker1.insert_range(x1.begin(), x1.end());
@ -37,45 +37,45 @@ template <class X> void swap_test_impl(X& x1, X& x2)
x1.swap(x2); x1.swap(x2);
tracker1.compare(x2); tracker1.compare(x2);
tracker2.compare(x1); tracker2.compare(x1);
} }
template <class X> void swap_tests1(X*, test::random_generator generator) template <class X> void swap_tests1(X*, test::random_generator generator)
{ {
{ {
test::check_instances check_; test::check_instances check_;
X x; X x;
swap_test_impl(x, x); swap_test_impl(x, x);
} }
{ {
test::check_instances check_; test::check_instances check_;
X x, y; X x, y;
swap_test_impl(x, y); swap_test_impl(x, y);
} }
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<X> v(1000, generator); test::random_values<X> v(1000, generator);
X x, y(v.begin(), v.end()); X x, y(v.begin(), v.end());
swap_test_impl(x, y); swap_test_impl(x, y);
swap_test_impl(x, y); swap_test_impl(x, y);
} }
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<X> vx(1000, generator), vy(1000, generator); test::random_values<X> vx(1000, generator), vy(1000, generator);
X x(vx.begin(), vx.end()), y(vy.begin(), vy.end()); X x(vx.begin(), vx.end()), y(vy.begin(), vy.end());
swap_test_impl(x, y); swap_test_impl(x, y);
swap_test_impl(x, y); swap_test_impl(x, y);
} }
} }
template <class X> void swap_tests2(X* ptr, test::random_generator generator) template <class X> void swap_tests2(X* ptr, test::random_generator generator)
{ {
swap_tests1(ptr, generator); swap_tests1(ptr, generator);
typedef BOOST_DEDUCED_TYPENAME X::hasher hasher; typedef BOOST_DEDUCED_TYPENAME X::hasher hasher;
@ -83,134 +83,130 @@ template <class X> void swap_tests2(X* ptr, test::random_generator generator)
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type; typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
{ {
test::check_instances check_; test::check_instances check_;
X x(0, hasher(1), key_equal(1)); X x(0, hasher(1), key_equal(1));
X y(0, hasher(2), key_equal(2)); X y(0, hasher(2), key_equal(2));
swap_test_impl(x, y); swap_test_impl(x, y);
} }
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<X> v(1000, generator); test::random_values<X> v(1000, generator);
X x(v.begin(), v.end(), 0, hasher(1), key_equal(1)); X x(v.begin(), v.end(), 0, hasher(1), key_equal(1));
X y(0, hasher(2), key_equal(2)); X y(0, hasher(2), key_equal(2));
swap_test_impl(x, y); swap_test_impl(x, y);
} }
{ {
test::check_instances check_; test::check_instances check_;
test::random_values<X> vx(100, generator), vy(50, generator); test::random_values<X> vx(100, generator), vy(50, generator);
X x(vx.begin(), vx.end(), 0, hasher(1), key_equal(1)); X x(vx.begin(), vx.end(), 0, hasher(1), key_equal(1));
X y(vy.begin(), vy.end(), 0, hasher(2), key_equal(2)); X y(vy.begin(), vy.end(), 0, hasher(2), key_equal(2));
swap_test_impl(x, y); swap_test_impl(x, y);
swap_test_impl(x, y); swap_test_impl(x, y);
} }
{ {
test::force_equal_allocator force_( test::force_equal_allocator force_(!allocator_type::is_propagate_on_swap);
!allocator_type::is_propagate_on_swap); test::check_instances check_;
test::check_instances check_;
test::random_values<X> vx(50, generator), vy(100, generator); test::random_values<X> vx(50, generator), vy(100, generator);
X x(vx.begin(), vx.end(), 0, hasher(), key_equal(), allocator_type(1)); X x(vx.begin(), vx.end(), 0, hasher(), key_equal(), allocator_type(1));
X y(vy.begin(), vy.end(), 0, hasher(), key_equal(), allocator_type(2)); X y(vy.begin(), vy.end(), 0, hasher(), key_equal(), allocator_type(2));
if (allocator_type::is_propagate_on_swap || if (allocator_type::is_propagate_on_swap ||
x.get_allocator() == y.get_allocator()) { x.get_allocator() == y.get_allocator()) {
swap_test_impl(x, y); swap_test_impl(x, y);
} }
} }
{ {
test::force_equal_allocator force_( test::force_equal_allocator force_(!allocator_type::is_propagate_on_swap);
!allocator_type::is_propagate_on_swap); test::check_instances check_;
test::check_instances check_;
test::random_values<X> vx(100, generator), vy(100, generator); test::random_values<X> vx(100, generator), vy(100, generator);
X x(vx.begin(), vx.end(), 0, hasher(1), key_equal(1), X x(vx.begin(), vx.end(), 0, hasher(1), key_equal(1), allocator_type(1));
allocator_type(1)); X y(vy.begin(), vy.end(), 0, hasher(2), key_equal(2), allocator_type(2));
X y(vy.begin(), vy.end(), 0, hasher(2), key_equal(2),
allocator_type(2));
if (allocator_type::is_propagate_on_swap || if (allocator_type::is_propagate_on_swap ||
x.get_allocator() == y.get_allocator()) { x.get_allocator() == y.get_allocator()) {
swap_test_impl(x, y); swap_test_impl(x, y);
swap_test_impl(x, y); swap_test_impl(x, y);
} }
} }
} }
boost::unordered_map<test::object, test::object, test::hash, test::equal_to, boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
std::allocator<test::object> >* test_map_std_alloc; std::allocator<test::object> >* test_map_std_alloc;
boost::unordered_set<test::object, test::hash, test::equal_to, boost::unordered_set<test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_set; test::allocator1<test::object> >* test_set;
boost::unordered_multiset<test::object, test::hash, test::equal_to, boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::allocator2<test::object> >* test_multiset; test::allocator2<test::object> >* test_multiset;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to, boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::allocator1<test::object> >* test_map; test::allocator1<test::object> >* test_map;
boost::unordered_multimap<test::object, test::object, test::hash, boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::allocator2<test::object> >* test_multimap; test::equal_to, test::allocator2<test::object> >* test_multimap;
boost::unordered_set<test::object, test::hash, test::equal_to, boost::unordered_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_swap> >* test::cxx11_allocator<test::object, test::propagate_swap> >*
test_set_prop_swap; test_set_prop_swap;
boost::unordered_multiset<test::object, test::hash, test::equal_to, boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_swap> >* test::cxx11_allocator<test::object, test::propagate_swap> >*
test_multiset_prop_swap; test_multiset_prop_swap;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to, boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::propagate_swap> >* test::cxx11_allocator<test::object, test::propagate_swap> >*
test_map_prop_swap; test_map_prop_swap;
boost::unordered_multimap<test::object, test::object, test::hash, boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::cxx11_allocator<test::object, test::propagate_swap> >* test::equal_to, test::cxx11_allocator<test::object, test::propagate_swap> >*
test_multimap_prop_swap; test_multimap_prop_swap;
boost::unordered_set<test::object, test::hash, test::equal_to, boost::unordered_set<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_swap> >* test::cxx11_allocator<test::object, test::no_propagate_swap> >*
test_set_no_prop_swap; test_set_no_prop_swap;
boost::unordered_multiset<test::object, test::hash, test::equal_to, boost::unordered_multiset<test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_swap> >* test::cxx11_allocator<test::object, test::no_propagate_swap> >*
test_multiset_no_prop_swap; test_multiset_no_prop_swap;
boost::unordered_map<test::object, test::object, test::hash, test::equal_to, boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_swap> >* test::cxx11_allocator<test::object, test::no_propagate_swap> >*
test_map_no_prop_swap; test_map_no_prop_swap;
boost::unordered_multimap<test::object, test::object, test::hash, boost::unordered_multimap<test::object, test::object, test::hash,
test::equal_to, test::equal_to,
test::cxx11_allocator<test::object, test::no_propagate_swap> >* test::cxx11_allocator<test::object, test::no_propagate_swap> >*
test_multimap_no_prop_swap; test_multimap_no_prop_swap;
template <typename T> bool is_propagate(T*) template <typename T> bool is_propagate(T*)
{ {
return T::allocator_type::is_propagate_on_swap; return T::allocator_type::is_propagate_on_swap;
} }
using test::default_generator; using test::default_generator;
using test::generate_collisions; using test::generate_collisions;
using test::limited_range; using test::limited_range;
UNORDERED_AUTO_TEST(check_traits) UNORDERED_AUTO_TEST(check_traits)
{ {
BOOST_TEST(!is_propagate(test_set)); BOOST_TEST(!is_propagate(test_set));
BOOST_TEST(is_propagate(test_set_prop_swap)); BOOST_TEST(is_propagate(test_set_prop_swap));
BOOST_TEST(!is_propagate(test_set_no_prop_swap)); BOOST_TEST(!is_propagate(test_set_no_prop_swap));
} }
UNORDERED_TEST(swap_tests1, UNORDERED_TEST(
((test_map_std_alloc)(test_set)(test_multiset)(test_map)(test_multimap)( swap_tests1, ((test_map_std_alloc)(test_set)(test_multiset)(test_map)(
test_set_prop_swap)(test_multiset_prop_swap)(test_map_prop_swap)( test_multimap)(test_set_prop_swap)(test_multiset_prop_swap)(
test_multimap_prop_swap)(test_set_no_prop_swap)( test_map_prop_swap)(test_multimap_prop_swap)(
test_multiset_no_prop_swap)(test_map_no_prop_swap)( test_set_no_prop_swap)(test_multiset_no_prop_swap)(
test_multimap_no_prop_swap))( test_map_no_prop_swap)(test_multimap_no_prop_swap))(
(default_generator)(generate_collisions)(limited_range))) (default_generator)(generate_collisions)(limited_range)))
UNORDERED_TEST(swap_tests2, UNORDERED_TEST(swap_tests2,
((test_set)(test_multiset)(test_map)(test_multimap)(test_set_prop_swap)( ((test_set)(test_multiset)(test_map)(test_multimap)(test_set_prop_swap)(
test_multiset_prop_swap)(test_map_prop_swap)(test_multimap_prop_swap)( test_multiset_prop_swap)(test_map_prop_swap)(test_multimap_prop_swap)(
test_set_no_prop_swap)(test_multiset_no_prop_swap)( test_set_no_prop_swap)(test_multiset_no_prop_swap)(test_map_no_prop_swap)(
test_map_no_prop_swap)(test_multimap_no_prop_swap))( test_multimap_no_prop_swap))(
(default_generator)(generate_collisions)(limited_range))) (default_generator)(generate_collisions)(limited_range)))
} }
RUN_TESTS() RUN_TESTS()

View File

@ -13,8 +13,8 @@
#include "../helpers/test.hpp" #include "../helpers/test.hpp"
namespace unnecessary_copy_tests { namespace unnecessary_copy_tests {
struct count_copies struct count_copies
{ {
private: private:
BOOST_COPYABLE_AND_MOVABLE(count_copies) BOOST_COPYABLE_AND_MOVABLE(count_copies)
public: public:
@ -24,14 +24,14 @@ struct count_copies
count_copies() : tag_(0), id_(++id_count) count_copies() : tag_(0), id_(++id_count)
{ {
++copies; ++copies;
trace_op("Default construct"); trace_op("Default construct");
} }
explicit count_copies(int tag) : tag_(tag), id_(++id_count) explicit count_copies(int tag) : tag_(tag), id_(++id_count)
{ {
++copies; ++copies;
trace_op("Tag construct"); trace_op("Tag construct");
} }
// This bizarre constructor is an attempt to confuse emplace. // This bizarre constructor is an attempt to confuse emplace.
@ -46,66 +46,66 @@ struct count_copies
count_copies(count_copies const&, count_copies const& x) count_copies(count_copies const&, count_copies const& x)
: tag_(x.tag_), id_(++id_count) : tag_(x.tag_), id_(++id_count)
{ {
++copies; ++copies;
trace_op("Pair construct"); trace_op("Pair construct");
} }
count_copies(count_copies const& x) : tag_(x.tag_), id_(++id_count) count_copies(count_copies const& x) : tag_(x.tag_), id_(++id_count)
{ {
++copies; ++copies;
trace_op("Copy construct"); trace_op("Copy construct");
} }
count_copies(BOOST_RV_REF(count_copies) x) : tag_(x.tag_), id_(++id_count) count_copies(BOOST_RV_REF(count_copies) x) : tag_(x.tag_), id_(++id_count)
{ {
x.tag_ = -1; x.tag_ = -1;
++moves; ++moves;
trace_op("Move construct"); trace_op("Move construct");
} }
count_copies& operator=( count_copies& operator=(
BOOST_COPY_ASSIGN_REF(count_copies) p) // Copy assignment BOOST_COPY_ASSIGN_REF(count_copies) p) // Copy assignment
{ {
tag_ = p.tag_; tag_ = p.tag_;
++copies; ++copies;
trace_op("Copy assign"); trace_op("Copy assign");
return *this; return *this;
} }
count_copies& operator=(BOOST_RV_REF(count_copies) p) // Move assignment count_copies& operator=(BOOST_RV_REF(count_copies) p) // Move assignment
{ {
tag_ = p.tag_; tag_ = p.tag_;
++moves; ++moves;
trace_op("Move assign"); trace_op("Move assign");
return *this; return *this;
} }
~count_copies() { trace_op("Destruct"); } ~count_copies() { trace_op("Destruct"); }
void trace_op(char const* str) void trace_op(char const* str)
{ {
BOOST_LIGHTWEIGHT_TEST_OSTREAM << str << ": " << tag_ << " (#" << id_ BOOST_LIGHTWEIGHT_TEST_OSTREAM << str << ": " << tag_ << " (#" << id_
<< ")" << std::endl; << ")" << std::endl;
} }
int tag_; int tag_;
int id_; int id_;
}; };
bool operator==(count_copies const& x, count_copies const& y) bool operator==(count_copies const& x, count_copies const& y)
{ {
return x.tag_ == y.tag_; return x.tag_ == y.tag_;
} }
template <class T> T source() { return T(); } template <class T> T source() { return T(); }
void reset() void reset()
{ {
count_copies::copies = 0; count_copies::copies = 0;
count_copies::moves = 0; count_copies::moves = 0;
BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\nReset\n" << std::endl; BOOST_LIGHTWEIGHT_TEST_OSTREAM << "\nReset\n" << std::endl;
} }
} }
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
@ -114,10 +114,10 @@ namespace boost
namespace unnecessary_copy_tests namespace unnecessary_copy_tests
#endif #endif
{ {
std::size_t hash_value(unnecessary_copy_tests::count_copies const& x) std::size_t hash_value(unnecessary_copy_tests::count_copies const& x)
{ {
return static_cast<std::size_t>(x.tag_); return static_cast<std::size_t>(x.tag_);
} }
} }
// Boost.Move doesn't seem to work very well on this compiler. // Boost.Move doesn't seem to work very well on this compiler.
@ -135,59 +135,57 @@ std::size_t hash_value(unnecessary_copy_tests::count_copies const& x)
#endif #endif
#define COPY_COUNT(n) \ #define COPY_COUNT(n) \
if (::unnecessary_copy_tests::count_copies::copies != n) { \ if (::unnecessary_copy_tests::count_copies::copies != n) { \
BOOST_ERROR("Wrong number of copies."); \ BOOST_ERROR("Wrong number of copies."); \
BOOST_LIGHTWEIGHT_TEST_OSTREAM \ BOOST_LIGHTWEIGHT_TEST_OSTREAM \
<< "Number of copies: " \ << "Number of copies: " \
<< ::unnecessary_copy_tests::count_copies::copies \ << ::unnecessary_copy_tests::count_copies::copies << " expecting: " << n \
<< " expecting: " << n << std::endl; \ << std::endl; \
} }
#define MOVE_COUNT(n) \ #define MOVE_COUNT(n) \
if (::unnecessary_copy_tests::count_copies::moves != n) { \ if (::unnecessary_copy_tests::count_copies::moves != n) { \
BOOST_ERROR("Wrong number of moves."); \ BOOST_ERROR("Wrong number of moves."); \
BOOST_LIGHTWEIGHT_TEST_OSTREAM \ BOOST_LIGHTWEIGHT_TEST_OSTREAM \
<< "Number of moves: " \ << "Number of moves: " << ::unnecessary_copy_tests::count_copies::moves \
<< ::unnecessary_copy_tests::count_copies::moves \ << " expecting: " << n << std::endl; \
<< " expecting: " << n << std::endl; \ }
}
#define COPY_COUNT_RANGE(a, b) \ #define COPY_COUNT_RANGE(a, b) \
if (::unnecessary_copy_tests::count_copies::copies < a || \ if (::unnecessary_copy_tests::count_copies::copies < a || \
::unnecessary_copy_tests::count_copies::copies > b) { \ ::unnecessary_copy_tests::count_copies::copies > b) { \
BOOST_ERROR("Wrong number of copies."); \ BOOST_ERROR("Wrong number of copies."); \
BOOST_LIGHTWEIGHT_TEST_OSTREAM \ BOOST_LIGHTWEIGHT_TEST_OSTREAM \
<< "Number of copies: " \ << "Number of copies: " \
<< ::unnecessary_copy_tests::count_copies::copies \ << ::unnecessary_copy_tests::count_copies::copies << " expecting: [" \
<< " expecting: [" << a << ", " << b << "]" << std::endl; \ << a << ", " << b << "]" << std::endl; \
} }
#define MOVE_COUNT_RANGE(a, b) \ #define MOVE_COUNT_RANGE(a, b) \
if (::unnecessary_copy_tests::count_copies::moves < a || \ if (::unnecessary_copy_tests::count_copies::moves < a || \
::unnecessary_copy_tests::count_copies::moves > b) { \ ::unnecessary_copy_tests::count_copies::moves > b) { \
BOOST_ERROR("Wrong number of moves."); \ BOOST_ERROR("Wrong number of moves."); \
BOOST_LIGHTWEIGHT_TEST_OSTREAM \ BOOST_LIGHTWEIGHT_TEST_OSTREAM \
<< "Number of moves: " \ << "Number of moves: " << ::unnecessary_copy_tests::count_copies::moves \
<< ::unnecessary_copy_tests::count_copies::moves \ << " expecting: [" << a << ", " << b << "]" << std::endl; \
<< " expecting: [" << a << ", " << b << "]" << std::endl; \ }
}
#define COPY_COUNT_EXTRA(a, b) COPY_COUNT_RANGE(a, a + b * EXTRA_CONSTRUCT_COST) #define COPY_COUNT_EXTRA(a, b) COPY_COUNT_RANGE(a, a + b * EXTRA_CONSTRUCT_COST)
#define MOVE_COUNT_EXTRA(a, b) MOVE_COUNT_RANGE(a, a + b * EXTRA_CONSTRUCT_COST) #define MOVE_COUNT_EXTRA(a, b) MOVE_COUNT_RANGE(a, a + b * EXTRA_CONSTRUCT_COST)
namespace unnecessary_copy_tests { namespace unnecessary_copy_tests {
int count_copies::copies; int count_copies::copies;
int count_copies::moves; int count_copies::moves;
int count_copies::id_count; int count_copies::id_count;
template <class T> void unnecessary_copy_insert_test(T*) template <class T> void unnecessary_copy_insert_test(T*)
{ {
T x; T x;
BOOST_DEDUCED_TYPENAME T::value_type a; BOOST_DEDUCED_TYPENAME T::value_type a;
reset(); reset();
x.insert(a); x.insert(a);
COPY_COUNT(1); COPY_COUNT(1);
MOVE_COUNT(0); MOVE_COUNT(0);
} }
template <class T> void unnecessary_copy_insert_rvalue_set_test(T*) template <class T> void unnecessary_copy_insert_rvalue_set_test(T*)
{ {
T x; T x;
BOOST_DEDUCED_TYPENAME T::value_type a; BOOST_DEDUCED_TYPENAME T::value_type a;
reset(); reset();
@ -200,10 +198,10 @@ template <class T> void unnecessary_copy_insert_rvalue_set_test(T*)
x.insert(boost::move(a)); x.insert(boost::move(a));
COPY_COUNT(0); COPY_COUNT(0);
MOVE_COUNT((x.size() == 2 ? 1 : 0)); MOVE_COUNT((x.size() == 2 ? 1 : 0));
} }
template <class T> void unnecessary_copy_insert_rvalue_map_test(T*) template <class T> void unnecessary_copy_insert_rvalue_map_test(T*)
{ {
// Doesn't currently try to emulate std::pair move construction, // Doesn't currently try to emulate std::pair move construction,
// so std::pair's require a copy. Could try emulating it in // so std::pair's require a copy. Could try emulating it in
// construct_from_args. // construct_from_args.
@ -230,29 +228,29 @@ template <class T> void unnecessary_copy_insert_rvalue_map_test(T*)
COPY_COUNT(0); COPY_COUNT(0);
MOVE_COUNT((x.size() == 2 ? 1 : 0)); MOVE_COUNT((x.size() == 2 ? 1 : 0));
#endif #endif
} }
boost::unordered_set<count_copies>* set; boost::unordered_set<count_copies>* set;
boost::unordered_multiset<count_copies>* multiset; boost::unordered_multiset<count_copies>* multiset;
boost::unordered_map<int, count_copies>* map; boost::unordered_map<int, count_copies>* map;
boost::unordered_multimap<int, count_copies>* multimap; boost::unordered_multimap<int, count_copies>* multimap;
UNORDERED_TEST(unnecessary_copy_insert_test, ((set)(multiset)(map)(multimap))) UNORDERED_TEST(unnecessary_copy_insert_test, ((set)(multiset)(map)(multimap)))
UNORDERED_TEST(unnecessary_copy_insert_rvalue_set_test, ((set)(multiset))) UNORDERED_TEST(unnecessary_copy_insert_rvalue_set_test, ((set)(multiset)))
UNORDERED_TEST(unnecessary_copy_insert_rvalue_map_test, ((map)(multimap))) UNORDERED_TEST(unnecessary_copy_insert_rvalue_map_test, ((map)(multimap)))
template <class T> void unnecessary_copy_emplace_test(T*) template <class T> void unnecessary_copy_emplace_test(T*)
{ {
reset(); reset();
T x; T x;
BOOST_DEDUCED_TYPENAME T::value_type a; BOOST_DEDUCED_TYPENAME T::value_type a;
COPY_COUNT(1); COPY_COUNT(1);
x.emplace(a); x.emplace(a);
COPY_COUNT(2); COPY_COUNT(2);
} }
template <class T> void unnecessary_copy_emplace_rvalue_test(T*) template <class T> void unnecessary_copy_emplace_rvalue_test(T*)
{ {
reset(); reset();
T x; T x;
x.emplace(source<BOOST_DEDUCED_TYPENAME T::value_type>()); x.emplace(source<BOOST_DEDUCED_TYPENAME T::value_type>());
@ -261,15 +259,16 @@ template <class T> void unnecessary_copy_emplace_rvalue_test(T*)
#else #else
COPY_COUNT(2); COPY_COUNT(2);
#endif #endif
} }
UNORDERED_TEST(unnecessary_copy_emplace_test, ((set)(multiset)(map)(multimap))) UNORDERED_TEST(
UNORDERED_TEST( unnecessary_copy_emplace_test, ((set)(multiset)(map)(multimap)))
UNORDERED_TEST(
unnecessary_copy_emplace_rvalue_test, ((set)(multiset)(map)(multimap))) unnecessary_copy_emplace_rvalue_test, ((set)(multiset)(map)(multimap)))
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <class T> void unnecessary_copy_emplace_std_move_test(T*) template <class T> void unnecessary_copy_emplace_std_move_test(T*)
{ {
reset(); reset();
T x; T x;
BOOST_DEDUCED_TYPENAME T::value_type a; BOOST_DEDUCED_TYPENAME T::value_type a;
@ -278,14 +277,14 @@ template <class T> void unnecessary_copy_emplace_std_move_test(T*)
x.emplace(std::move(a)); x.emplace(std::move(a));
COPY_COUNT(1); COPY_COUNT(1);
MOVE_COUNT(1); MOVE_COUNT(1);
} }
UNORDERED_TEST( UNORDERED_TEST(
unnecessary_copy_emplace_std_move_test, ((set)(multiset)(map)(multimap))) unnecessary_copy_emplace_std_move_test, ((set)(multiset)(map)(multimap)))
#endif #endif
template <class T> void unnecessary_copy_emplace_boost_move_test(T*) template <class T> void unnecessary_copy_emplace_boost_move_test(T*)
{ {
reset(); reset();
T x; T x;
BOOST_DEDUCED_TYPENAME T::value_type a; BOOST_DEDUCED_TYPENAME T::value_type a;
@ -300,13 +299,13 @@ template <class T> void unnecessary_copy_emplace_boost_move_test(T*)
COPY_COUNT_RANGE(1, 2); COPY_COUNT_RANGE(1, 2);
MOVE_COUNT_RANGE(0, 1); MOVE_COUNT_RANGE(0, 1);
#endif #endif
} }
UNORDERED_TEST( UNORDERED_TEST(
unnecessary_copy_emplace_boost_move_test, ((set)(multiset)(map)(multimap))) unnecessary_copy_emplace_boost_move_test, ((set)(multiset)(map)(multimap)))
template <class T> void unnecessary_copy_emplace_boost_move_set_test(T*) template <class T> void unnecessary_copy_emplace_boost_move_set_test(T*)
{ {
reset(); reset();
T x; T x;
BOOST_DEDUCED_TYPENAME T::value_type a; BOOST_DEDUCED_TYPENAME T::value_type a;
@ -315,12 +314,13 @@ template <class T> void unnecessary_copy_emplace_boost_move_set_test(T*)
x.emplace(boost::move(a)); x.emplace(boost::move(a));
COPY_COUNT(1); COPY_COUNT(1);
MOVE_COUNT(1); MOVE_COUNT(1);
} }
UNORDERED_TEST(unnecessary_copy_emplace_boost_move_set_test, ((set)(multiset))) UNORDERED_TEST(
unnecessary_copy_emplace_boost_move_set_test, ((set)(multiset)))
template <class T> void unnecessary_copy_emplace_boost_move_map_test(T*) template <class T> void unnecessary_copy_emplace_boost_move_map_test(T*)
{ {
reset(); reset();
T x; T x;
COPY_COUNT(0); COPY_COUNT(0);
@ -336,12 +336,13 @@ template <class T> void unnecessary_copy_emplace_boost_move_map_test(T*)
COPY_COUNT(1); COPY_COUNT(1);
MOVE_COUNT(1); MOVE_COUNT(1);
#endif #endif
} }
UNORDERED_TEST(unnecessary_copy_emplace_boost_move_map_test, ((map)(multimap))) UNORDERED_TEST(
unnecessary_copy_emplace_boost_move_map_test, ((map)(multimap)))
UNORDERED_AUTO_TEST(unnecessary_copy_emplace_set_test) UNORDERED_AUTO_TEST(unnecessary_copy_emplace_set_test)
{ {
// When calling 'source' the object is moved on some compilers, but not // When calling 'source' the object is moved on some compilers, but not
// others. So count that here to adjust later. // others. So count that here to adjust later.
@ -422,10 +423,10 @@ UNORDERED_AUTO_TEST(unnecessary_copy_emplace_set_test)
x.emplace(b, b); x.emplace(b, b);
COPY_COUNT(1); COPY_COUNT(1);
MOVE_COUNT(0); MOVE_COUNT(0);
} }
UNORDERED_AUTO_TEST(unnecessary_copy_emplace_map_test) UNORDERED_AUTO_TEST(unnecessary_copy_emplace_map_test)
{ {
// When calling 'source' the object is moved on some compilers, but not // When calling 'source' the object is moved on some compilers, but not
// others. So count that here to adjust later. // others. So count that here to adjust later.
@ -471,7 +472,7 @@ UNORDERED_AUTO_TEST(unnecessary_copy_emplace_map_test)
reset(); reset();
x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(), x.emplace(boost::unordered::piecewise_construct, boost::make_tuple(),
boost::make_tuple()); boost::make_tuple());
COPY_COUNT(2); COPY_COUNT(2);
MOVE_COUNT(0); MOVE_COUNT(0);
@ -492,7 +493,7 @@ UNORDERED_AUTO_TEST(unnecessary_copy_emplace_map_test)
MOVE_COUNT(source_pair_cost); MOVE_COUNT(source_pair_cost);
#if !(defined(__GNUC__) && __cplusplus < 199900L) && \ #if !(defined(__GNUC__) && __cplusplus < 199900L) && \
!(defined(_MSC_VER) && _MSC_VER < 1600) !(defined(_MSC_VER) && _MSC_VER < 1600)
count_copies part; count_copies part;
reset(); reset();
std::pair<count_copies const&, count_copies const&> a_ref(part, part); std::pair<count_copies const&, count_copies const&> a_ref(part, part);
@ -538,8 +539,8 @@ UNORDERED_AUTO_TEST(unnecessary_copy_emplace_map_test)
reset(); reset();
x.emplace(boost::unordered::piecewise_construct, x.emplace(boost::unordered::piecewise_construct,
boost::make_tuple(boost::ref(b.first)), boost::make_tuple(boost::ref(b.first)),
boost::make_tuple(boost::ref(b.second))); boost::make_tuple(boost::ref(b.second)));
COPY_COUNT(0); COPY_COUNT(0);
MOVE_COUNT(0); MOVE_COUNT(0);
@ -547,8 +548,7 @@ UNORDERED_AUTO_TEST(unnecessary_copy_emplace_map_test)
reset(); reset();
x.emplace(boost::unordered::piecewise_construct, x.emplace(boost::unordered::piecewise_construct,
std::make_tuple(std::ref(b.first)), std::make_tuple(std::ref(b.first)), std::make_tuple(std::ref(b.second)));
std::make_tuple(std::ref(b.second)));
COPY_COUNT(0); COPY_COUNT(0);
MOVE_COUNT(0); MOVE_COUNT(0);
@ -562,23 +562,23 @@ UNORDERED_AUTO_TEST(unnecessary_copy_emplace_map_test)
std::pair<count_copies const, count_copies> move_source; std::pair<count_copies const, count_copies> move_source;
reset(); reset();
x.emplace(boost::unordered::piecewise_construct, x.emplace(boost::unordered::piecewise_construct,
std::make_tuple(std::move(move_source.first)), std::make_tuple(std::move(move_source.first)),
std::make_tuple(std::move(move_source.second))); std::make_tuple(std::move(move_source.second)));
COPY_COUNT(tuple_copy_cost); COPY_COUNT(tuple_copy_cost);
MOVE_COUNT(tuple_move_cost); MOVE_COUNT(tuple_move_cost);
#if !defined(BOOST_NO_CXX11_HDR_TUPLE) && \ #if !defined(BOOST_NO_CXX11_HDR_TUPLE) && \
!(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ < 6) && \ !(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ < 6) && \
!(defined(BOOST_MSVC) && BOOST_MSVC < 1700) !(defined(BOOST_MSVC) && BOOST_MSVC < 1700)
reset(); reset();
x.emplace(boost::unordered::piecewise_construct, x.emplace(boost::unordered::piecewise_construct,
std::forward_as_tuple(b.first), std::forward_as_tuple(b.second)); std::forward_as_tuple(b.first), std::forward_as_tuple(b.second));
COPY_COUNT(0); COPY_COUNT(0);
MOVE_COUNT(0); MOVE_COUNT(0);
#endif #endif
#endif #endif
} }
} }
RUN_TESTS() RUN_TESTS()