forked from boostorg/unordered
Unordered: Merge from trunk.
- Some changes to the internals, including reverting some of the recent changes to constructing values which turned out to be more bother than it was worth. - On C++11 compilers, better use of `construct` and `destroy`. - Better testing. [SVN r80350]
This commit is contained in:
@@ -39,26 +39,40 @@ template <class T>
|
||||
struct assign_base : public test::exception_base
|
||||
{
|
||||
const test::random_values<T> x_values, y_values;
|
||||
const T x,y;
|
||||
T x,y;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME T::hasher hasher;
|
||||
typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal;
|
||||
typedef BOOST_DEDUCED_TYPENAME T::allocator_type allocator_type;
|
||||
|
||||
assign_base(unsigned int count1, unsigned int count2, int tag1, int tag2) :
|
||||
assign_base(unsigned int count1, unsigned int count2, int tag1, int tag2,
|
||||
float mlf1 = 1.0, float mlf2 = 1.0) :
|
||||
x_values(count1),
|
||||
y_values(count2),
|
||||
x(x_values.begin(), x_values.end(), 0, hasher(tag1), key_equal(tag1),
|
||||
allocator_type(tag1)),
|
||||
y(y_values.begin(), y_values.end(), 0, hasher(tag2), key_equal(tag2),
|
||||
allocator_type(tag2))
|
||||
{}
|
||||
{
|
||||
x.max_load_factor(mlf1);
|
||||
y.max_load_factor(mlf2);
|
||||
}
|
||||
|
||||
typedef T data_type;
|
||||
T init() const { return T(x); }
|
||||
void run(T& x1) const { x1 = y; }
|
||||
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
|
||||
// internal structure is hidden, this exposes it.
|
||||
T& y = const_cast<T&>(x1);
|
||||
if (x_values.size()) {
|
||||
y.emplace(*x_values.begin());
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
@@ -85,7 +99,13 @@ struct assign_test4 : assign_base<T>
|
||||
assign_test4() : assign_base<T>(10, 10, 1, 2) {}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct assign_test5 : assign_base<T>
|
||||
{
|
||||
assign_test5() : assign_base<T>(5, 60, 0, 0, 1.0, 0.1) {}
|
||||
};
|
||||
|
||||
RUN_EXCEPTION_TESTS(
|
||||
(self_assign_test1)(self_assign_test2)
|
||||
(assign_test1)(assign_test2)(assign_test3)(assign_test4),
|
||||
(assign_test1)(assign_test2)(assign_test3)(assign_test4)(assign_test5),
|
||||
CONTAINER_SEQ)
|
||||
|
||||
@@ -18,13 +18,13 @@ typedef boost::unordered_multiset<
|
||||
test::exception::object,
|
||||
test::exception::hash,
|
||||
test::exception::equal_to,
|
||||
test::exception::allocator<test::exception::object> > test_multiset;
|
||||
test::exception::allocator2<test::exception::object> > test_multiset;
|
||||
typedef boost::unordered_map<
|
||||
test::exception::object,
|
||||
test::exception::object,
|
||||
test::exception::hash,
|
||||
test::exception::equal_to,
|
||||
test::exception::allocator<test::exception::object> > test_map;
|
||||
test::exception::allocator2<test::exception::object> > test_map;
|
||||
typedef boost::unordered_multimap<
|
||||
test::exception::object,
|
||||
test::exception::object,
|
||||
|
||||
@@ -60,7 +60,9 @@ struct swap_base : public test::exception_base
|
||||
initial_x(x_values.begin(), x_values.end(), 0, hasher(tag1),
|
||||
key_equal(tag1), allocator_type(tag1)),
|
||||
initial_y(y_values.begin(), y_values.end(), 0, hasher(tag2),
|
||||
key_equal(tag2), allocator_type(tag2))
|
||||
key_equal(tag2), allocator_type(
|
||||
T::allocator_type::propagate_on_container_swap::value ?
|
||||
tag2 : tag1))
|
||||
{}
|
||||
|
||||
struct data_type {
|
||||
@@ -71,6 +73,7 @@ struct swap_base : public test::exception_base
|
||||
};
|
||||
|
||||
data_type init() const { return data_type(initial_x, initial_y); }
|
||||
|
||||
void run(data_type& d) const {
|
||||
try {
|
||||
d.x.swap(d.y);
|
||||
|
||||
@@ -82,16 +82,39 @@ namespace test
|
||||
}
|
||||
};
|
||||
|
||||
// Finally, check that size matches up.
|
||||
// Check that size matches up.
|
||||
|
||||
if(x1.size() != size) {
|
||||
BOOST_ERROR("x1.size() doesn't match actual size.");
|
||||
std::cout<<x1.size()<<"/"<<size<<std::endl;
|
||||
}
|
||||
|
||||
// Check the load factor.
|
||||
|
||||
float load_factor =
|
||||
static_cast<float>(size) / static_cast<float>(x1.bucket_count());
|
||||
using namespace std;
|
||||
if(fabs(x1.load_factor() - load_factor) > x1.load_factor() / 64)
|
||||
BOOST_ERROR("x1.load_factor() doesn't match actual load_factor.");
|
||||
|
||||
// Check that size in the buckets matches up.
|
||||
|
||||
BOOST_DEDUCED_TYPENAME X::size_type bucket_size = 0;
|
||||
|
||||
for (BOOST_DEDUCED_TYPENAME X::size_type
|
||||
i = 0; i < x1.bucket_count(); ++i)
|
||||
{
|
||||
for (BOOST_DEDUCED_TYPENAME X::const_local_iterator
|
||||
begin = x1.begin(i), end = x1.end(i); begin != end; ++begin)
|
||||
{
|
||||
++bucket_size;
|
||||
}
|
||||
}
|
||||
|
||||
if(x1.size() != bucket_size) {
|
||||
BOOST_ERROR("x1.size() doesn't match bucket size.");
|
||||
std::cout<<x1.size()<<"/"<<bucket_size<<std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -401,6 +401,186 @@ namespace exception
|
||||
//}
|
||||
return x.tag_ != y.tag_;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
class allocator2
|
||||
{
|
||||
public:
|
||||
int tag_;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef T* pointer;
|
||||
typedef T const* const_pointer;
|
||||
typedef T& reference;
|
||||
typedef T const& const_reference;
|
||||
typedef T value_type;
|
||||
|
||||
template <class U> struct rebind { typedef allocator2<U> other; };
|
||||
|
||||
explicit allocator2(int t = 0) : tag_(t)
|
||||
{
|
||||
UNORDERED_SCOPE(allocator2::allocator2()) {
|
||||
UNORDERED_EPOINT("Mock allocator2 default constructor.");
|
||||
}
|
||||
test::detail::tracker.allocator_ref();
|
||||
}
|
||||
|
||||
allocator2(allocator<T> const& x) : tag_(x.tag_)
|
||||
{
|
||||
UNORDERED_SCOPE(allocator2::allocator2()) {
|
||||
UNORDERED_EPOINT("Mock allocator2 constructor from allocator.");
|
||||
}
|
||||
test::detail::tracker.allocator_ref();
|
||||
}
|
||||
|
||||
template <class Y> allocator2(allocator2<Y> const& x) : tag_(x.tag_)
|
||||
{
|
||||
UNORDERED_SCOPE(allocator2::allocator2()) {
|
||||
UNORDERED_EPOINT("Mock allocator2 template copy constructor.");
|
||||
}
|
||||
test::detail::tracker.allocator_ref();
|
||||
}
|
||||
|
||||
allocator2(allocator2 const& x) : tag_(x.tag_)
|
||||
{
|
||||
UNORDERED_SCOPE(allocator2::allocator2()) {
|
||||
UNORDERED_EPOINT("Mock allocator2 copy constructor.");
|
||||
}
|
||||
test::detail::tracker.allocator_ref();
|
||||
}
|
||||
|
||||
~allocator2() {
|
||||
test::detail::tracker.allocator_unref();
|
||||
}
|
||||
|
||||
allocator2& operator=(allocator2 const& x) {
|
||||
UNORDERED_SCOPE(allocator2::allocator2()) {
|
||||
UNORDERED_EPOINT("Mock allocator2 assignment operator.");
|
||||
tag_ = x.tag_;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// If address throws, then it can't be used in erase or the
|
||||
// destructor, which is very limiting. I need to check up on
|
||||
// this.
|
||||
|
||||
pointer address(reference r) {
|
||||
//UNORDERED_SCOPE(allocator2::address(reference)) {
|
||||
// UNORDERED_EPOINT("Mock allocator2 address function.");
|
||||
//}
|
||||
return pointer(&r);
|
||||
}
|
||||
|
||||
const_pointer address(const_reference r) {
|
||||
//UNORDERED_SCOPE(allocator2::address(const_reference)) {
|
||||
// UNORDERED_EPOINT("Mock allocator2 const address function.");
|
||||
//}
|
||||
return const_pointer(&r);
|
||||
}
|
||||
|
||||
pointer allocate(size_type n) {
|
||||
T* ptr = 0;
|
||||
UNORDERED_SCOPE(allocator2::allocate(size_type)) {
|
||||
UNORDERED_EPOINT("Mock allocator2 allocate function.");
|
||||
|
||||
using namespace std;
|
||||
ptr = (T*) malloc(n * sizeof(T));
|
||||
if(!ptr) throw std::bad_alloc();
|
||||
}
|
||||
test::detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
|
||||
return pointer(ptr);
|
||||
|
||||
//return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
|
||||
}
|
||||
|
||||
pointer allocate(size_type n, void const* u)
|
||||
{
|
||||
T* ptr = 0;
|
||||
UNORDERED_SCOPE(allocator2::allocate(size_type, const_pointer)) {
|
||||
UNORDERED_EPOINT("Mock allocator2 allocate function.");
|
||||
|
||||
using namespace std;
|
||||
ptr = (T*) malloc(n * sizeof(T));
|
||||
if(!ptr) throw std::bad_alloc();
|
||||
}
|
||||
test::detail::tracker.track_allocate((void*) ptr, n, sizeof(T), tag_);
|
||||
return pointer(ptr);
|
||||
|
||||
//return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
|
||||
}
|
||||
|
||||
void deallocate(pointer p, size_type n)
|
||||
{
|
||||
//::operator delete((void*) p);
|
||||
if(p) {
|
||||
test::detail::tracker.track_deallocate((void*) p, n, sizeof(T), tag_);
|
||||
using namespace std;
|
||||
free(p);
|
||||
}
|
||||
}
|
||||
|
||||
void construct(pointer p, T const& t) {
|
||||
UNORDERED_SCOPE(allocator2::construct(T*, T)) {
|
||||
UNORDERED_EPOINT("Mock allocator2 construct function.");
|
||||
new(p) T(t);
|
||||
}
|
||||
test::detail::tracker.track_construct((void*) p, sizeof(T), tag_);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
|
||||
template<class... Args> void construct(T* p, BOOST_FWD_REF(Args)... args) {
|
||||
UNORDERED_SCOPE(allocator2::construct(pointer, BOOST_FWD_REF(Args)...)) {
|
||||
UNORDERED_EPOINT("Mock allocator2 construct function.");
|
||||
new(p) T(boost::forward<Args>(args)...);
|
||||
}
|
||||
test::detail::tracker.track_construct((void*) p, sizeof(T), tag_);
|
||||
}
|
||||
#endif
|
||||
|
||||
void destroy(T* p) {
|
||||
test::detail::tracker.track_destroy((void*) p, sizeof(T), tag_);
|
||||
p->~T();
|
||||
}
|
||||
|
||||
size_type max_size() const {
|
||||
UNORDERED_SCOPE(allocator2::construct(pointer, T)) {
|
||||
UNORDERED_EPOINT("Mock allocator2 max_size function.");
|
||||
}
|
||||
return (std::numeric_limits<std::size_t>::max)();
|
||||
}
|
||||
|
||||
typedef false_type propagate_on_container_copy_assignment;
|
||||
typedef false_type propagate_on_container_move_assignment;
|
||||
typedef false_type propagate_on_container_swap;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void swap(allocator2<T>& x, allocator2<T>& y)
|
||||
{
|
||||
std::swap(x.tag_, y.tag_);
|
||||
}
|
||||
|
||||
// It's pretty much impossible to write a compliant swap when these
|
||||
// two can throw. So they don't.
|
||||
|
||||
template <class T>
|
||||
inline bool operator==(allocator2<T> const& x, allocator2<T> const& y)
|
||||
{
|
||||
//UNORDERED_SCOPE(operator==(allocator2, allocator2)) {
|
||||
// UNORDERED_EPOINT("Mock allocator2 equality operator.");
|
||||
//}
|
||||
return x.tag_ == y.tag_;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline bool operator!=(allocator2<T> const& x, allocator2<T> const& y)
|
||||
{
|
||||
//UNORDERED_SCOPE(operator!=(allocator2, allocator2)) {
|
||||
// UNORDERED_EPOINT("Mock allocator2 inequality operator.");
|
||||
//}
|
||||
return x.tag_ != y.tag_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace minimal
|
||||
class destructible;
|
||||
class copy_constructible;
|
||||
class copy_constructible_equality_comparable;
|
||||
class default_copy_constructible;
|
||||
class default_assignable;
|
||||
class assignable;
|
||||
|
||||
struct ampersand_operator_used {};
|
||||
@@ -99,26 +99,29 @@ namespace minimal
|
||||
return false;
|
||||
}
|
||||
|
||||
class default_copy_constructible
|
||||
class default_assignable
|
||||
{
|
||||
public:
|
||||
default_copy_constructible(constructor_param const&) {}
|
||||
default_assignable(constructor_param const&) {}
|
||||
|
||||
default_copy_constructible()
|
||||
default_assignable()
|
||||
{
|
||||
}
|
||||
|
||||
default_copy_constructible(default_copy_constructible const&)
|
||||
default_assignable(default_assignable const&)
|
||||
{
|
||||
}
|
||||
|
||||
~default_copy_constructible()
|
||||
default_assignable& operator=(default_assignable const&)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
~default_assignable()
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
default_copy_constructible& operator=(
|
||||
default_copy_constructible const&);
|
||||
ampersand_operator_used operator&() const {
|
||||
return ampersand_operator_used(); }
|
||||
};
|
||||
@@ -148,7 +151,7 @@ namespace minimal
|
||||
movable1() {}
|
||||
explicit movable1(movable_init) {}
|
||||
movable1(BOOST_RV_REF(movable1)) {}
|
||||
movable1& operator=(BOOST_RV_REF(movable1));
|
||||
movable1& operator=(BOOST_RV_REF(movable1)) { return *this; }
|
||||
~movable1() {}
|
||||
};
|
||||
|
||||
@@ -160,6 +163,7 @@ namespace minimal
|
||||
explicit movable2(movable_init) {}
|
||||
movable2(movable2&&) {}
|
||||
~movable2() {}
|
||||
movable2& operator=(movable2&&) { return *this; }
|
||||
private:
|
||||
movable2() {}
|
||||
movable2(movable2 const&);
|
||||
|
||||
@@ -63,6 +63,7 @@ void assign_tests1(T*,
|
||||
tracker.compare(y);
|
||||
BOOST_TEST(x.max_load_factor() == mlf);
|
||||
BOOST_TEST(y.max_load_factor() == mlf);
|
||||
BOOST_TEST(y.load_factor() <= y.max_load_factor());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,9 +88,31 @@ void assign_tests2(T*,
|
||||
T x1(v.begin(), v.end(), 0, hf1, eq1);
|
||||
T x2(0, hf2, eq2);
|
||||
x2 = x1;
|
||||
BOOST_TEST(test::equivalent(x1.hash_function(), hf1));
|
||||
BOOST_TEST(test::equivalent(x1.key_eq(), eq1));
|
||||
BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
|
||||
BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
|
||||
test::check_container(x1, v);
|
||||
test::check_container(x2, v);
|
||||
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
|
||||
}
|
||||
|
||||
std::cerr<<"assign_tests2.1a\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
test::random_values<T> v1(0, generator);
|
||||
test::random_values<T> v2(1000, generator);
|
||||
T x1(0, hf2, eq2);
|
||||
T x2(v2.begin(), v2.end(), 0, hf1, eq1);
|
||||
x2 = x1;
|
||||
BOOST_TEST(test::equivalent(x1.hash_function(), hf2));
|
||||
BOOST_TEST(test::equivalent(x1.key_eq(), eq2));
|
||||
BOOST_TEST(test::equivalent(x2.hash_function(), hf2));
|
||||
BOOST_TEST(test::equivalent(x2.key_eq(), eq2));
|
||||
test::check_container(x1, v1);
|
||||
test::check_container(x2, v1);
|
||||
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
|
||||
}
|
||||
|
||||
std::cerr<<"assign_tests2.2\n";
|
||||
@@ -110,7 +133,55 @@ void assign_tests2(T*,
|
||||
BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
|
||||
BOOST_TEST(!test::equivalent(x2.get_allocator(), al1));
|
||||
}
|
||||
test::check_container(x1, v1);
|
||||
test::check_container(x2, v1);
|
||||
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
|
||||
}
|
||||
|
||||
std::cerr<<"assign_tests2.3\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
test::random_values<T> v1(100, generator), v2(1000, generator);
|
||||
T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1);
|
||||
T x2(v2.begin(), v2.end(), 0, hf2, eq2, al2);
|
||||
x2 = x1;
|
||||
BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
|
||||
BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
|
||||
if (allocator_type::is_propagate_on_assign) {
|
||||
BOOST_TEST(test::equivalent(x2.get_allocator(), al1));
|
||||
BOOST_TEST(!test::equivalent(x2.get_allocator(), al2));
|
||||
}
|
||||
else {
|
||||
BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
|
||||
BOOST_TEST(!test::equivalent(x2.get_allocator(), al1));
|
||||
}
|
||||
test::check_container(x1, v1);
|
||||
test::check_container(x2, v1);
|
||||
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
|
||||
}
|
||||
|
||||
std::cerr<<"assign_tests2.4\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
test::random_values<T> v1(1000, generator), v2(100, generator);
|
||||
T x1(v1.begin(), v1.end(), 0, hf1, eq1, al1);
|
||||
T x2(v2.begin(), v2.end(), 0, hf2, eq2, al2);
|
||||
x2 = x1;
|
||||
BOOST_TEST(test::equivalent(x2.hash_function(), hf1));
|
||||
BOOST_TEST(test::equivalent(x2.key_eq(), eq1));
|
||||
if (allocator_type::is_propagate_on_assign) {
|
||||
BOOST_TEST(test::equivalent(x2.get_allocator(), al1));
|
||||
BOOST_TEST(!test::equivalent(x2.get_allocator(), al2));
|
||||
}
|
||||
else {
|
||||
BOOST_TEST(test::equivalent(x2.get_allocator(), al2));
|
||||
BOOST_TEST(!test::equivalent(x2.get_allocator(), al1));
|
||||
}
|
||||
test::check_container(x1, v1);
|
||||
test::check_container(x2, v1);
|
||||
BOOST_TEST(x2.load_factor() <= x2.max_load_factor());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,13 +32,13 @@ template class boost::unordered_multimap<
|
||||
|
||||
template class boost::unordered_map<
|
||||
test::minimal::assignable,
|
||||
test::minimal::default_copy_constructible,
|
||||
test::minimal::default_assignable,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
test::minimal::equal_to<test::minimal::assignable>,
|
||||
test::minimal::allocator<test::minimal::assignable> >;
|
||||
template class boost::unordered_multimap<
|
||||
test::minimal::assignable,
|
||||
test::minimal::copy_constructible,
|
||||
test::minimal::assignable,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
test::minimal::equal_to<test::minimal::assignable>,
|
||||
test::minimal::allocator<test::minimal::assignable> >;
|
||||
@@ -48,7 +48,7 @@ UNORDERED_AUTO_TEST(test0)
|
||||
test::minimal::constructor_param x;
|
||||
|
||||
typedef std::pair<test::minimal::assignable const,
|
||||
test::minimal::copy_constructible> value_type;
|
||||
test::minimal::assignable> value_type;
|
||||
value_type value(x, x);
|
||||
|
||||
std::cout<<"Test unordered_map.\n";
|
||||
@@ -62,7 +62,7 @@ UNORDERED_AUTO_TEST(test0)
|
||||
|
||||
boost::unordered_map<
|
||||
test::minimal::assignable,
|
||||
test::minimal::copy_constructible,
|
||||
test::minimal::assignable,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
test::minimal::equal_to<test::minimal::assignable>,
|
||||
test::minimal::allocator<value_type> > map;
|
||||
@@ -82,7 +82,7 @@ UNORDERED_AUTO_TEST(test0)
|
||||
|
||||
boost::unordered_multimap<
|
||||
test::minimal::assignable,
|
||||
test::minimal::copy_constructible,
|
||||
test::minimal::assignable,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
test::minimal::equal_to<test::minimal::assignable>,
|
||||
test::minimal::allocator<value_type> > multimap;
|
||||
@@ -95,7 +95,7 @@ UNORDERED_AUTO_TEST(test0)
|
||||
UNORDERED_AUTO_TEST(equality_tests) {
|
||||
typedef std::pair<
|
||||
test::minimal::copy_constructible_equality_comparable const,
|
||||
test::minimal::copy_constructible> value_type;
|
||||
test::minimal::copy_constructible_equality_comparable> value_type;
|
||||
|
||||
boost::unordered_map<int, int> int_map;
|
||||
|
||||
@@ -187,44 +187,44 @@ UNORDERED_AUTO_TEST(test2)
|
||||
test::minimal::equal_to<test::minimal::assignable> equal_to(x);
|
||||
|
||||
typedef std::pair<test::minimal::assignable const,
|
||||
test::minimal::copy_constructible> map_value_type;
|
||||
map_value_type map_value(assignable, copy_constructible);
|
||||
test::minimal::assignable> map_value_type;
|
||||
map_value_type map_value(assignable, assignable);
|
||||
|
||||
std::cout<<"Test unordered_map.\n";
|
||||
|
||||
boost::unordered_map<
|
||||
test::minimal::assignable,
|
||||
test::minimal::copy_constructible,
|
||||
test::minimal::assignable,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
test::minimal::equal_to<test::minimal::assignable>,
|
||||
test::minimal::allocator<map_value_type> > map;
|
||||
|
||||
unordered_unique_test(map, map_value);
|
||||
unordered_map_test(map, assignable, copy_constructible);
|
||||
unordered_map_test(map, assignable, assignable);
|
||||
unordered_copyable_test(map, assignable, map_value, hash, equal_to);
|
||||
|
||||
boost::unordered_map<
|
||||
test::minimal::assignable,
|
||||
test::minimal::default_copy_constructible,
|
||||
test::minimal::default_assignable,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
test::minimal::equal_to<test::minimal::assignable>,
|
||||
test::minimal::allocator<map_value_type> > map2;
|
||||
|
||||
test::minimal::default_copy_constructible default_copy_constructible;
|
||||
test::minimal::default_assignable default_assignable;
|
||||
|
||||
unordered_map_functions(map2, assignable, default_copy_constructible);
|
||||
unordered_map_functions(map2, assignable, default_assignable);
|
||||
|
||||
std::cout<<"Test unordered_multimap.\n";
|
||||
|
||||
boost::unordered_multimap<
|
||||
test::minimal::assignable,
|
||||
test::minimal::copy_constructible,
|
||||
test::minimal::assignable,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
test::minimal::equal_to<test::minimal::assignable>,
|
||||
test::minimal::allocator<map_value_type> > multimap;
|
||||
|
||||
unordered_equivalent_test(multimap, map_value);
|
||||
unordered_map_test(multimap, assignable, copy_constructible);
|
||||
unordered_map_test(multimap, assignable, assignable);
|
||||
unordered_copyable_test(multimap, assignable, map_value, hash, equal_to);
|
||||
}
|
||||
|
||||
|
||||
@@ -170,7 +170,6 @@ namespace unnecessary_copy_tests
|
||||
UNORDERED_TEST(unnecessary_copy_emplace_rvalue_test,
|
||||
((set)(multiset)(map)(multimap)))
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
|
||||
template <class T>
|
||||
void unnecessary_copy_emplace_move_test(T*)
|
||||
{
|
||||
@@ -178,13 +177,17 @@ namespace unnecessary_copy_tests
|
||||
T x;
|
||||
BOOST_DEDUCED_TYPENAME T::value_type a;
|
||||
COPY_COUNT(1); MOVE_COUNT(0);
|
||||
x.emplace(std::move(a));
|
||||
x.emplace(boost::move(a));
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
COPY_COUNT(1); MOVE_COUNT(1);
|
||||
#else
|
||||
// Since std::pair isn't movable, move only works for sets.
|
||||
COPY_COUNT_RANGE(1, 2); MOVE_COUNT_RANGE(0, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
UNORDERED_TEST(unnecessary_copy_emplace_move_test,
|
||||
((set)(multiset)(map)(multimap)))
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
void unnecessary_copy_emplace_boost_move_set_test(T*)
|
||||
@@ -270,14 +273,16 @@ namespace unnecessary_copy_tests
|
||||
x.emplace(source<count_copies>());
|
||||
COPY_COUNT(1); MOVE_COUNT(source_cost);
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
|
||||
// No move should take place.
|
||||
reset();
|
||||
x.emplace(std::move(a));
|
||||
x.emplace(boost::move(a));
|
||||
#if !defined(BOOST_NO_RVALUE_REFERENCES)
|
||||
COPY_COUNT(0); MOVE_COUNT(0);
|
||||
#else
|
||||
COPY_COUNT(0); MOVE_COUNT(1);
|
||||
#endif
|
||||
|
||||
// Just in case a did get moved...
|
||||
// Use a new value for cases where a did get moved...
|
||||
count_copies b;
|
||||
|
||||
// The container will have to create a copy in order to compare with
|
||||
@@ -367,16 +372,12 @@ namespace unnecessary_copy_tests
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_UNORDERED_STD_FORWARD_MOVE)
|
||||
|
||||
// No move should take place.
|
||||
// (since a is already in the container)
|
||||
reset();
|
||||
x.emplace(std::move(a));
|
||||
x.emplace(boost::move(a));
|
||||
COPY_COUNT(0); MOVE_COUNT(0);
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
// 2 arguments
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user