Compare commits

..

1 Commits

Author SHA1 Message Date
Marshall Clow b1c1e96476 Release 1.55.0
[SVN r86621]
2013-11-11 19:45:21 +00:00
31 changed files with 186 additions and 487 deletions
-1
View File
@@ -1 +0,0 @@
/doc/html/
+1 -30
View File
@@ -47,7 +47,7 @@ First official release.
[h2 Boost 1.38.0]
* Use [@boost:/libs/core/swap.html `boost::swap`].
* Use [@boost:/libs/utility/swap.html `boost::swap`].
* [@https://svn.boost.org/trac/boost/ticket/2237 Ticket 2237]:
Document that the equality and inequality operators are undefined for two
objects if their equality predicates aren't equivalent. Thanks to Daniel
@@ -239,34 +239,5 @@ C++11 support has resulted in some breaking changes:
* Avoid some warnings ([ticket 8851], [ticket 8874]).
* Avoid exposing some detail functions via. ADL on the iterators.
* Follow the standard by only using the allocators' construct and destroy
methods to construct and destroy stored elements. Don't use them for internal
data like pointers.
[h2 Boost 1.56.0]
* Fix some shadowed variable warnings ([ticket 9377]).
* Fix allocator use in documentation ([ticket 9719]).
* Always use prime number of buckets for integers. Fixes performance
regression when inserting consecutive integers, although makes other
uses slower ([ticket 9282]).
* Only construct elements using allocators, as specified in C++11 standard.
[h2 Boost 1.57.0]
* Fix the `pointer` typedef in iterators ([ticket 10672]).
* Fix Coverity warning
([@https://github.com/boostorg/unordered/pull/2 GitHub #2]).
[h2 Boost 1.58.0]
* Remove unnecessary template parameter from const iterators.
* Rename private `iterator` typedef in some iterator classes, as it
confuses some traits classes.
* Fix move assignment with stateful, propagate_on_container_move_assign
allocators ([ticket 10777]).
* Fix rare exception safety issue in move assignment.
* Fix potential overflow when calculating number of buckets to allocate
([@https://github.com/boostorg/unordered/pull/4 GitHub #4]).
[endsect]
+2 -2
View File
@@ -54,14 +54,14 @@ order to work with non-C++11 compilers and libraries.
class Key, class Mapped,
class Hash = ``[classref boost::hash]``<Key>,
class Pred = std::equal_to<Key>,
class Alloc = std::allocator<std::pair<Key const, Mapped> > >
class Alloc = std::allocator<Key> >
class ``[classref boost::unordered_map unordered_map]``;
template<
class Key, class Mapped,
class Hash = ``[classref boost::hash]``<Key>,
class Pred = std::equal_to<Key>,
class Alloc = std::allocator<std::pair<Key const, Mapped> > >
class Alloc = std::allocator<Key> >
class ``[classref boost::unordered_multimap unordered_multimap]``;
}
+8 -13
View File
@@ -3,7 +3,7 @@
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
[def __wang__
[@http://web.archive.org/web/20121102023700/http://www.concentric.net/~Ttwang/tech/inthash.htm
[@http://www.concentric.net/~Ttwang/tech/inthash.htm
Thomas Wang's article on integer hash functions]]
[section:rationale Implementation Rationale]
@@ -85,8 +85,7 @@ of 2.
Using a prime number of buckets, and choosing a bucket by using the modulus
of the hash function's result will usually give a good result. The downside
is that the required modulus operation is fairly expensive. This is what the
containers do in most cases.
is that the required modulus operation is fairly expensive.
Using a power of 2 allows for much quicker selection of the bucket
to use, but at the expense of loosing the upper bits of the hash value.
@@ -96,16 +95,12 @@ functions this can't be relied on.
To avoid this a transformation could be applied to the hash function, for an
example see __wang__. Unfortunately, a transformation like Wang's requires
knowledge of the number of bits in the hash value, so it isn't portable enough
to use as a default. It can applicable in certain cases so the containers
have a policy based implementation that can use this alternative technique.
knowledge of the number of bits in the hash value, so it isn't portable enough.
This leaves more expensive methods, such as Knuth's Multiplicative Method
(mentioned in Wang's article). These don't tend to work as well as taking the
modulus of a prime, and the extra computation required might negate
efficiency advantage of power of 2 hash tables.
Currently this is only done on 64 bit architecures, where prime number
modulus can be expensive. Although this varies depending on the architecture,
so I probably should revisit it.
I'm also thinking of introducing a mechanism whereby a hash function can
indicate that it's safe to be used directly with power of 2 buckets, in
which case a faster plain power of 2 implementation can be used.
So, this implementation uses a prime number for the hash table size.
[endsect]
+9 -13
View File
@@ -9,9 +9,8 @@
#ifndef BOOST_UNORDERED_ALLOCATE_HPP
#define BOOST_UNORDERED_ALLOCATE_HPP
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/unordered/detail/fwd.hpp>
@@ -880,7 +879,7 @@ namespace boost { namespace unordered { namespace detail { namespace func {
# define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \
template<typename Alloc, typename T> \
void construct_from_tuple_impl( \
boost::unordered::detail::func::length<0>, Alloc&, T* ptr, \
boost::unordered::detail::length<0>, Alloc&, T* ptr, \
namespace_ tuple<>) \
{ \
new ((void*) ptr) T(); \
@@ -893,7 +892,7 @@ namespace boost { namespace unordered { namespace detail { namespace func {
template<typename Alloc, typename T, \
BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
void construct_from_tuple_impl( \
boost::unordered::detail::func::length<n>, Alloc&, T* ptr, \
boost::unordered::detail::length<n>, Alloc&, T* ptr, \
namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
{ \
new ((void*) ptr) T( \
@@ -922,7 +921,7 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
void construct_from_tuple(Alloc& alloc, T* ptr, Tuple const& x)
{
construct_from_tuple_impl(
boost::unordered::detail::func::length<
boost::unordered::detail::length<
boost::tuples::length<Tuple>::value>(),
alloc, ptr, x);
}
@@ -1081,10 +1080,8 @@ namespace boost { namespace unordered { namespace detail {
~array_constructor() {
if (ptr_) {
for(pointer p = ptr_; p != constructed_; ++p) {
boost::unordered::detail::func::destroy(
boost::addressof(*p));
}
for(pointer p = ptr_; p != constructed_; ++p)
traits::destroy(alloc_, boost::addressof(*p));
traits::deallocate(alloc_, ptr_, length_);
}
@@ -1097,9 +1094,8 @@ namespace boost { namespace unordered { namespace detail {
length_ = l;
ptr_ = traits::allocate(alloc_, length_);
pointer end = ptr_ + static_cast<std::ptrdiff_t>(length_);
for(constructed_ = ptr_; constructed_ != end; ++constructed_) {
new ((void*) boost::addressof(*constructed_)) V(v);
}
for(constructed_ = ptr_; constructed_ != end; ++constructed_)
traits::construct(alloc_, boost::addressof(*constructed_), v);
}
pointer get() const
+25 -65
View File
@@ -7,9 +7,8 @@
#ifndef BOOST_UNORDERED_DETAIL_MANAGER_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_MANAGER_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/unordered/detail/util.hpp>
@@ -45,9 +44,9 @@ namespace boost { namespace unordered { namespace iterator_detail {
// all no throw
template <typename Node> struct iterator;
template <typename Node> struct c_iterator;
template <typename Node, typename ConstNodePointer> struct c_iterator;
template <typename Node, typename Policy> struct l_iterator;
template <typename Node, typename Policy>
template <typename Node, typename ConstNodePointer, typename Policy>
struct cl_iterator;
// Local Iterators
@@ -60,16 +59,16 @@ namespace boost { namespace unordered { namespace iterator_detail {
std::forward_iterator_tag,
typename Node::value_type,
std::ptrdiff_t,
typename Node::value_type*,
typename Node::node_pointer,
typename Node::value_type&>
{
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename Node2, typename Policy2>
template <typename Node2, typename ConstNodePointer, typename Policy2>
friend struct boost::unordered::iterator_detail::cl_iterator;
private:
#endif
typedef typename Node::node_pointer node_pointer;
typedef boost::unordered::iterator_detail::iterator<Node> n_iterator;
typedef boost::unordered::iterator_detail::iterator<Node> iterator;
node_pointer ptr_;
std::size_t bucket_;
std::size_t bucket_count_;
@@ -80,7 +79,7 @@ namespace boost { namespace unordered { namespace iterator_detail {
l_iterator() BOOST_NOEXCEPT : ptr_() {}
l_iterator(n_iterator x, std::size_t b, std::size_t c) BOOST_NOEXCEPT
l_iterator(iterator x, std::size_t b, std::size_t c) BOOST_NOEXCEPT
: ptr_(x.node_), bucket_(b), bucket_count_(c) {}
value_type& operator*() const {
@@ -114,13 +113,13 @@ namespace boost { namespace unordered { namespace iterator_detail {
}
};
template <typename Node, typename Policy>
template <typename Node, typename ConstNodePointer, typename Policy>
struct cl_iterator
: public boost::iterator<
std::forward_iterator_tag,
typename Node::value_type,
std::ptrdiff_t,
typename Node::value_type const*,
ConstNodePointer,
typename Node::value_type const&>
{
friend struct boost::unordered::iterator_detail::l_iterator
@@ -128,7 +127,7 @@ namespace boost { namespace unordered { namespace iterator_detail {
private:
typedef typename Node::node_pointer node_pointer;
typedef boost::unordered::iterator_detail::iterator<Node> n_iterator;
typedef boost::unordered::iterator_detail::iterator<Node> iterator;
node_pointer ptr_;
std::size_t bucket_;
std::size_t bucket_count_;
@@ -139,7 +138,7 @@ namespace boost { namespace unordered { namespace iterator_detail {
cl_iterator() BOOST_NOEXCEPT : ptr_() {}
cl_iterator(n_iterator x, std::size_t b, std::size_t c) BOOST_NOEXCEPT :
cl_iterator(iterator x, std::size_t b, std::size_t c) BOOST_NOEXCEPT :
ptr_(x.node_), bucket_(b), bucket_count_(c) {}
cl_iterator(boost::unordered::iterator_detail::l_iterator<
@@ -188,15 +187,15 @@ namespace boost { namespace unordered { namespace iterator_detail {
std::forward_iterator_tag,
typename Node::value_type,
std::ptrdiff_t,
typename Node::value_type*,
typename Node::node_pointer,
typename Node::value_type&>
{
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template <typename>
template <typename, typename>
friend struct boost::unordered::iterator_detail::c_iterator;
template <typename, typename>
friend struct boost::unordered::iterator_detail::l_iterator;
template <typename, typename>
template <typename, typename, typename>
friend struct boost::unordered::iterator_detail::cl_iterator;
template <typename>
friend struct boost::unordered::detail::table;
@@ -223,7 +222,7 @@ namespace boost { namespace unordered { namespace iterator_detail {
}
value_type* operator->() const {
return node_->value_ptr();
return &node_->value();
}
iterator& operator++() {
@@ -246,13 +245,13 @@ namespace boost { namespace unordered { namespace iterator_detail {
}
};
template <typename Node>
template <typename Node, typename ConstNodePointer>
struct c_iterator
: public boost::iterator<
std::forward_iterator_tag,
typename Node::value_type,
std::ptrdiff_t,
typename Node::value_type const*,
ConstNodePointer,
typename Node::value_type const&>
{
friend struct boost::unordered::iterator_detail::iterator<Node>;
@@ -268,7 +267,7 @@ namespace boost { namespace unordered { namespace iterator_detail {
private:
#endif
typedef typename Node::node_pointer node_pointer;
typedef boost::unordered::iterator_detail::iterator<Node> n_iterator;
typedef boost::unordered::iterator_detail::iterator<Node> iterator;
node_pointer node_;
public:
@@ -280,14 +279,14 @@ namespace boost { namespace unordered { namespace iterator_detail {
explicit c_iterator(typename Node::link_pointer x) BOOST_NOEXCEPT :
node_(static_cast<node_pointer>(x)) {}
c_iterator(n_iterator const& x) BOOST_NOEXCEPT : node_(x.node_) {}
c_iterator(iterator const& x) BOOST_NOEXCEPT : node_(x.node_) {}
value_type const& operator*() const {
return node_->value();
}
value_type const* operator->() const {
return node_->value_ptr();
return &node_->value();
}
c_iterator& operator++() {
@@ -402,7 +401,7 @@ namespace boost { namespace unordered { namespace detail {
}
if (node_constructed_) {
boost::unordered::detail::func::destroy(
node_allocator_traits::destroy(alloc_,
boost::addressof(*node_));
}
@@ -419,7 +418,8 @@ namespace boost { namespace unordered { namespace detail {
node_ = node_allocator_traits::allocate(alloc_, 1);
new ((void*) boost::addressof(*node_)) node();
node_allocator_traits::construct(alloc_,
boost::addressof(*node_), node());
node_->init(node_);
node_constructed_ = true;
}
@@ -547,7 +547,7 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::func::destroy_value_impl(this->alloc_,
p->value_ptr());
boost::unordered::detail::func::destroy(boost::addressof(*p));
node_allocator_traits::destroy(this->alloc_, boost::addressof(*p));
node_allocator_traits::deallocate(this->alloc_, p, 1);
}
}
@@ -665,51 +665,11 @@ namespace boost { namespace unordered { namespace detail {
typedef mix64_policy<std::size_t> type;
};
template <typename T>
struct pick_policy :
pick_policy_impl<
std::numeric_limits<std::size_t>::digits,
std::numeric_limits<std::size_t>::radix> {};
// While the mix policy is generally faster, the prime policy is a lot
// faster when a large number consecutive integers are used, because
// there are no collisions. Since that is probably quite common, use
// prime policy for integeral types. But not the smaller ones, as they
// don't have enough unique values for this to be an issue.
template <>
struct pick_policy<int> {
typedef prime_policy<std::size_t> type;
};
template <>
struct pick_policy<unsigned int> {
typedef prime_policy<std::size_t> type;
};
template <>
struct pick_policy<long> {
typedef prime_policy<std::size_t> type;
};
template <>
struct pick_policy<unsigned long> {
typedef prime_policy<std::size_t> type;
};
// TODO: Maybe not if std::size_t is smaller than long long.
#if !defined(BOOST_NO_LONG_LONG)
template <>
struct pick_policy<long long> {
typedef prime_policy<std::size_t> type;
};
template <>
struct pick_policy<unsigned long long> {
typedef prime_policy<std::size_t> type;
};
#endif
////////////////////////////////////////////////////////////////////////////
// Functions
+24 -30
View File
@@ -7,9 +7,8 @@
#ifndef BOOST_UNORDERED_DETAIL_EQUIVALENT_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_EQUIVALENT_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/unordered/detail/table.hpp>
@@ -52,16 +51,15 @@ namespace boost { namespace unordered { namespace detail {
template <typename T>
struct grouped_ptr_node :
boost::unordered::detail::value_base<T>,
boost::unordered::detail::ptr_bucket
{
typedef T value_type;
typedef boost::unordered::detail::ptr_bucket bucket_base;
typedef grouped_ptr_node<T>* node_pointer;
typedef ptr_bucket* link_pointer;
node_pointer group_prev_;
std::size_t hash_;
boost::unordered::detail::value_base<T> value_base_;
grouped_ptr_node() :
bucket_base(),
@@ -74,10 +72,6 @@ namespace boost { namespace unordered { namespace detail {
group_prev_ = self;
}
void* address() { return value_base_.address(); }
value_type& value() { return value_base_.value(); }
value_type* value_ptr() { return value_base_.value_ptr(); }
private:
grouped_ptr_node& operator=(grouped_ptr_node const&);
};
@@ -151,7 +145,7 @@ namespace boost { namespace unordered { namespace detail {
typedef boost::unordered::detail::grouped_table_impl<types> table;
typedef boost::unordered::detail::set_extractor<value_type> extractor;
typedef typename boost::unordered::detail::pick_policy<T>::type policy;
typedef boost::unordered::detail::pick_policy::type policy;
};
template <typename A, typename K, typename M, typename H, typename P>
@@ -176,7 +170,7 @@ namespace boost { namespace unordered { namespace detail {
typedef boost::unordered::detail::map_extractor<key_type, value_type>
extractor;
typedef typename boost::unordered::detail::pick_policy<K>::type policy;
typedef boost::unordered::detail::pick_policy::type policy;
};
template <typename Types>
@@ -542,9 +536,9 @@ namespace boost { namespace unordered { namespace detail {
node_pointer first_node = static_cast<node_pointer>(prev->next_);
link_pointer end = first_node->group_prev_->next_;
std::size_t deleted_count = this->delete_nodes(prev, end);
std::size_t count = this->delete_nodes(prev, end);
this->fix_bucket(bucket_index, prev);
return deleted_count;
return count;
}
iterator erase(c_iterator r)
@@ -563,21 +557,21 @@ namespace boost { namespace unordered { namespace detail {
return iterator(r2.node_);
}
link_pointer erase_nodes(node_pointer i, node_pointer j)
link_pointer erase_nodes(node_pointer begin, node_pointer end)
{
std::size_t bucket_index = this->hash_to_bucket(i->hash_);
std::size_t bucket_index = this->hash_to_bucket(begin->hash_);
// Split the groups containing 'i' and 'j'.
// And get the pointer to the node before i while
// Split the groups containing 'begin' and 'end'.
// And get the pointer to the node before begin while
// we're at it.
link_pointer prev = split_groups(i, j);
link_pointer prev = split_groups(begin, end);
// If we don't have a 'prev' it means that i is at the
// If we don't have a 'prev' it means that begin is at the
// beginning of a block, so search through the blocks in the
// same bucket.
if (!prev) {
prev = this->get_previous_start(bucket_index);
while (prev->next_ != i)
while (prev->next_ != begin)
prev = static_cast<node_pointer>(prev->next_)->group_prev_;
}
@@ -587,24 +581,24 @@ namespace boost { namespace unordered { namespace detail {
static_cast<node_pointer>(prev->next_)->group_prev_->next_;
this->delete_nodes(prev, group_end);
bucket_index = this->fix_bucket(bucket_index, prev);
} while(prev->next_ != j);
} while(prev->next_ != end);
return prev;
}
static link_pointer split_groups(node_pointer i, node_pointer j)
static link_pointer split_groups(node_pointer begin, node_pointer end)
{
node_pointer prev = i->group_prev_;
if (prev->next_ != i) prev = node_pointer();
node_pointer prev = begin->group_prev_;
if (prev->next_ != begin) prev = node_pointer();
if (j) {
node_pointer first = j;
while (first != i && first->group_prev_->next_ == first) {
if (end) {
node_pointer first = end;
while (first != begin && first->group_prev_->next_ == first) {
first = first->group_prev_;
}
boost::swap(first->group_prev_, j->group_prev_);
if (first == i) return prev;
boost::swap(first->group_prev_, end->group_prev_);
if (first == begin) return prev;
}
if (prev) {
@@ -612,7 +606,7 @@ namespace boost { namespace unordered { namespace detail {
while (first->group_prev_->next_ == first) {
first = first->group_prev_;
}
boost::swap(first->group_prev_, i->group_prev_);
boost::swap(first->group_prev_, begin->group_prev_);
}
return prev;
@@ -6,11 +6,6 @@
#ifndef BOOST_UNORDERED_DETAIL_EXTRACT_KEY_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_EXTRACT_KEY_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
#include <boost/unordered/detail/table.hpp>
namespace boost {
+3 -3
View File
@@ -6,11 +6,11 @@
#ifndef BOOST_UNORDERED_FWD_HPP_INCLUDED
#define BOOST_UNORDERED_FWD_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
namespace boost
{
namespace unordered
+32 -42
View File
@@ -7,11 +7,6 @@
#ifndef BOOST_UNORDERED_DETAIL_ALL_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_ALL_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
#include <boost/unordered/detail/buckets.hpp>
#include <boost/unordered/detail/util.hpp>
#include <boost/type_traits/aligned_storage.hpp>
@@ -59,10 +54,6 @@ namespace boost { namespace unordered { namespace detail {
sizeof(value_type),
boost::alignment_of<value_type>::value>::type data_;
value_base() :
data_()
{}
void* address() {
return this;
}
@@ -191,11 +182,11 @@ namespace boost { namespace unordered { namespace detail {
typedef boost::unordered::iterator_detail::
iterator<node> iterator;
typedef boost::unordered::iterator_detail::
c_iterator<node> c_iterator;
c_iterator<node, const_node_pointer> c_iterator;
typedef boost::unordered::iterator_detail::
l_iterator<node, policy> l_iterator;
typedef boost::unordered::iterator_detail::
cl_iterator<node, policy> cl_iterator;
cl_iterator<node, const_node_pointer, policy> cl_iterator;
////////////////////////////////////////////////////////////////////////
// Members
@@ -266,9 +257,9 @@ namespace boost { namespace unordered { namespace detail {
return prev ? iterator(prev->next_) : iterator();
}
std::size_t hash_to_bucket(std::size_t hash_value) const
std::size_t hash_to_bucket(std::size_t hash) const
{
return policy::to_bucket(bucket_count_, hash_value);
return policy::to_bucket(bucket_count_, hash);
}
float load_factor() const
@@ -343,7 +334,7 @@ namespace boost { namespace unordered { namespace detail {
return policy::new_bucket_count(
boost::unordered::detail::double_to_size(floor(
static_cast<double>(size) /
static_cast<double>(mlf_)) + 1));
static_cast<double>(mlf_))) + 1);
}
////////////////////////////////////////////////////////////////////////
@@ -404,8 +395,8 @@ namespace boost { namespace unordered { namespace detail {
{
if (x.size_) {
create_buckets(bucket_count_);
copy_nodes<node_allocator> node_creator(node_alloc());
table_impl::fill_buckets(x.begin(), *this, node_creator);
copy_nodes<node_allocator> copy(node_alloc());
table_impl::fill_buckets(x.begin(), *this, copy);
}
}
@@ -418,9 +409,9 @@ namespace boost { namespace unordered { namespace detail {
// TODO: Could pick new bucket size?
create_buckets(bucket_count_);
move_nodes<node_allocator> node_creator(node_alloc());
move_nodes<node_allocator> move(node_alloc());
node_holder<node_allocator> nodes(x);
table_impl::fill_buckets(nodes.begin(), *this, node_creator);
table_impl::fill_buckets(nodes.begin(), *this, move);
}
}
@@ -500,11 +491,9 @@ namespace boost { namespace unordered { namespace detail {
op2.commit();
}
// Only call with nodes allocated with the currect allocator, or
// one that is equal to it. (Can't assert because other's
// allocators might have already been moved).
void move_buckets_from(table& other)
{
BOOST_ASSERT(node_alloc() == other.node_alloc());
BOOST_ASSERT(!buckets_);
buckets_ = other.buckets_;
bucket_count_ = other.bucket_count_;
@@ -529,7 +518,8 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::func::destroy_value_impl(node_alloc(),
n->value_ptr());
boost::unordered::detail::func::destroy(boost::addressof(*n));
node_allocator_traits::destroy(node_alloc(),
boost::addressof(*n));
node_allocator_traits::deallocate(node_alloc(), n, 1);
--size_;
}
@@ -556,7 +546,7 @@ namespace boost { namespace unordered { namespace detail {
if (bucket::extra_node) {
node_pointer n = static_cast<node_pointer>(
get_bucket(bucket_count_)->next_);
boost::unordered::detail::func::destroy(
node_allocator_traits::destroy(node_alloc(),
boost::addressof(*n));
node_allocator_traits::deallocate(node_alloc(), n, 1);
}
@@ -593,7 +583,7 @@ namespace boost { namespace unordered { namespace detail {
bucket_pointer end = get_bucket(bucket_count_ + 1);
for(bucket_pointer it = buckets_; it != end; ++it)
{
boost::unordered::detail::func::destroy(
bucket_allocator_traits::destroy(bucket_alloc(),
boost::addressof(*it));
}
@@ -665,8 +655,8 @@ namespace boost { namespace unordered { namespace detail {
// assign_nodes takes ownership of the container's elements,
// assigning to them if possible, and deleting any that are
// left over.
assign_nodes<table> node_creator(*this);
table_impl::fill_buckets(x.begin(), *this, node_creator);
assign_nodes<table> assign(*this);
table_impl::fill_buckets(x.begin(), *this, assign);
}
void assign(table const& x, true_type)
@@ -692,8 +682,8 @@ namespace boost { namespace unordered { namespace detail {
// Finally copy the elements.
if (x.size_) {
create_buckets(bucket_count_);
copy_nodes<node_allocator> node_creator(node_alloc());
table_impl::fill_buckets(x.begin(), *this, node_creator);
copy_nodes<node_allocator> copy(node_alloc());
table_impl::fill_buckets(x.begin(), *this, copy);
}
}
}
@@ -712,25 +702,15 @@ namespace boost { namespace unordered { namespace detail {
void move_assign(table& x, true_type)
{
delete_buckets();
set_hash_functions new_func_this(*this, x);
allocators_.move_assign(x.allocators_);
// No throw from here.
mlf_ = x.mlf_;
max_load_ = x.max_load_;
move_buckets_from(x);
new_func_this.commit();
move_assign_no_alloc(x);
}
void move_assign(table& x, false_type)
{
if (node_alloc() == x.node_alloc()) {
delete_buckets();
set_hash_functions new_func_this(*this, x);
// No throw from here.
mlf_ = x.mlf_;
max_load_ = x.max_load_;
move_buckets_from(x);
new_func_this.commit();
move_assign_no_alloc(x);
}
else {
set_hash_functions new_func_this(*this, x);
@@ -750,11 +730,21 @@ namespace boost { namespace unordered { namespace detail {
// move_assign_nodes takes ownership of the container's
// elements, assigning to them if possible, and deleting
// any that are left over.
move_assign_nodes<table> node_creator(*this);
move_assign_nodes<table> assign(*this);
node_holder<node_allocator> nodes(x);
table_impl::fill_buckets(nodes.begin(), *this, node_creator);
table_impl::fill_buckets(nodes.begin(), *this, assign);
}
}
void move_assign_no_alloc(table& x)
{
set_hash_functions new_func_this(*this, x);
// No throw from here.
mlf_ = x.mlf_;
max_load_ = x.max_load_;
move_buckets_from(x);
new_func_this.commit();
}
// Accessors
+13 -21
View File
@@ -7,9 +7,8 @@
#ifndef BOOST_UNORDERED_DETAIL_UNIQUE_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_UNIQUE_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/unordered/detail/table.hpp>
@@ -28,9 +27,7 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::value_base<T>
{
typedef typename ::boost::unordered::detail::rebind_wrap<
A, unique_node<A, T> >::type allocator;
typedef typename ::boost::unordered::detail::
allocator_traits<allocator>::pointer node_pointer;
A, unique_node<A, T> >::type::pointer node_pointer;
typedef node_pointer link_pointer;
link_pointer next_;
@@ -51,15 +48,14 @@ namespace boost { namespace unordered { namespace detail {
template <typename T>
struct ptr_node :
boost::unordered::detail::value_base<T>,
boost::unordered::detail::ptr_bucket
{
typedef T value_type;
typedef boost::unordered::detail::ptr_bucket bucket_base;
typedef ptr_node<T>* node_pointer;
typedef ptr_bucket* link_pointer;
std::size_t hash_;
boost::unordered::detail::value_base<T> value_base_;
ptr_node() :
bucket_base(),
@@ -70,10 +66,6 @@ namespace boost { namespace unordered { namespace detail {
{
}
void* address() { return value_base_.address(); }
value_type& value() { return value_base_.value(); }
value_type* value_ptr() { return value_base_.value_ptr(); }
private:
ptr_node& operator=(ptr_node const&);
};
@@ -146,7 +138,7 @@ namespace boost { namespace unordered { namespace detail {
typedef boost::unordered::detail::table_impl<types> table;
typedef boost::unordered::detail::set_extractor<value_type> extractor;
typedef typename boost::unordered::detail::pick_policy<T>::type policy;
typedef boost::unordered::detail::pick_policy::type policy;
};
template <typename A, typename K, typename M, typename H, typename P>
@@ -171,7 +163,7 @@ namespace boost { namespace unordered { namespace detail {
typedef boost::unordered::detail::map_extractor<key_type, value_type>
extractor;
typedef typename boost::unordered::detail::pick_policy<K>::type policy;
typedef boost::unordered::detail::pick_policy::type policy;
};
template <typename Types>
@@ -537,9 +529,9 @@ namespace boost { namespace unordered { namespace detail {
link_pointer end = static_cast<node_pointer>(prev->next_)->next_;
std::size_t deleted_count = this->delete_nodes(prev, end);
std::size_t count = this->delete_nodes(prev, end);
this->fix_bucket(bucket_index, prev);
return deleted_count;
return count;
}
iterator erase(c_iterator r)
@@ -558,19 +550,19 @@ namespace boost { namespace unordered { namespace detail {
return iterator(r2.node_);
}
void erase_nodes(node_pointer i, node_pointer j)
void erase_nodes(node_pointer begin, node_pointer end)
{
std::size_t bucket_index = this->hash_to_bucket(i->hash_);
std::size_t bucket_index = this->hash_to_bucket(begin->hash_);
// Find the node before i.
// Find the node before begin.
link_pointer prev = this->get_previous_start(bucket_index);
while(prev->next_ != i) prev = prev->next_;
while(prev->next_ != begin) prev = prev->next_;
// Delete the nodes.
do {
this->delete_node(prev);
bucket_index = this->fix_bucket(bucket_index, prev);
} while (prev->next_ != j);
} while (prev->next_ != end);
}
////////////////////////////////////////////////////////////////////////
+2 -3
View File
@@ -7,9 +7,8 @@
#ifndef BOOST_UNORDERED_DETAIL_UTIL_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_UTIL_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/type_traits/is_convertible.hpp>
+2 -3
View File
@@ -9,9 +9,8 @@
#ifndef BOOST_UNORDERED_UNORDERED_MAP_HPP_INCLUDED
#define BOOST_UNORDERED_UNORDERED_MAP_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/unordered/unordered_map_fwd.hpp>
@@ -6,11 +6,11 @@
#ifndef BOOST_UNORDERED_MAP_FWD_HPP_INCLUDED
#define BOOST_UNORDERED_MAP_FWD_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/config.hpp>
#include <memory>
#include <functional>
#include <boost/functional/hash_fwd.hpp>
+2 -3
View File
@@ -9,9 +9,8 @@
#ifndef BOOST_UNORDERED_UNORDERED_SET_HPP_INCLUDED
#define BOOST_UNORDERED_UNORDERED_SET_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/unordered/unordered_set_fwd.hpp>
@@ -6,11 +6,11 @@
#ifndef BOOST_UNORDERED_SET_FWD_HPP_INCLUDED
#define BOOST_UNORDERED_SET_FWD_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/config.hpp>
#include <memory>
#include <functional>
#include <boost/functional/hash_fwd.hpp>
+2 -3
View File
@@ -9,9 +9,8 @@
#ifndef BOOST_UNORDERED_MAP_HPP_INCLUDED
#define BOOST_UNORDERED_MAP_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/unordered/unordered_map.hpp>
+2 -3
View File
@@ -9,9 +9,8 @@
#ifndef BOOST_UNORDERED_SET_HPP_INCLUDED
#define BOOST_UNORDERED_SET_HPP_INCLUDED
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/unordered/unordered_set.hpp>
-17
View File
@@ -1,17 +0,0 @@
{
"key": "unordered",
"name": "Unordered",
"authors": [
"Daniel James"
],
"maintainers": [
"Daniel James <dnljms -at- gmail.com>"
],
"description": "Unordered associative containers.",
"std": [
"tr1"
],
"category": [
"Containers"
]
}
+7 -2
View File
@@ -12,8 +12,13 @@ project unordered-test/exception-tests
: requirements
<warnings>all
<toolset>intel:<warnings>on
<toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow -Wno-long-long"
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow"
<toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter"
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter"
#<toolset>gcc:<define>_GLIBCXX_DEBUG
#<toolset>darwin:<define>_GLIBCXX_DEBUG
#<toolset>msvc:<warnings-as-errors>on
#<toolset>gcc:<warnings-as-errors>on
#<toolset>darwin:<warnings-as-errors>on
;
test-suite unordered-exception
+1 -2
View File
@@ -105,8 +105,7 @@ namespace test
i = 0; i < x1.bucket_count(); ++i)
{
for (BOOST_DEDUCED_TYPENAME X::const_local_iterator
begin2 = x1.begin(i), end2 = x1.end(i);
begin2 != end2; ++begin2)
begin = x1.begin(i), end = x1.end(i); begin != end; ++begin)
{
++bucket_size;
}
+2 -2
View File
@@ -41,7 +41,7 @@ namespace test
int count = type_ == generate_collisions ?
1 + (generate(int_ptr) % 5) : 1;
for(int j = 0; j < count; ++j) {
for(int i = 0; i < count; ++i) {
x.push_back(value);
}
}
@@ -71,7 +71,7 @@ namespace test
int count = type_ == generate_collisions ?
1 + (generate(int_ptr) % 5) : 1;
for(int j = 0; j < count; ++j) {
for(int i = 0; i < count; ++i) {
x.push_back(std::pair<key_type const, mapped_type>(
key, generate(mapped_ptr)));
}
+18 -47
View File
@@ -19,12 +19,6 @@
#pragma warning(disable:4100) // unreferenced formal parameter
#endif
#if !BOOST_WORKAROUND(BOOST_MSVC, == 1500)
#define BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED 1
#else
#define BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED 0
#endif
namespace test
{
namespace minimal
@@ -35,9 +29,7 @@ namespace minimal
class default_assignable;
class assignable;
struct ampersand_operator_used {
ampersand_operator_used() { BOOST_TEST(false); }
};
struct ampersand_operator_used {};
template <class T> class hash;
template <class T> class equal_to;
@@ -56,7 +48,6 @@ namespace minimal
public:
destructible(constructor_param const&) {}
~destructible() {}
void dummy_member() const {}
private:
destructible(destructible const&);
destructible& operator=(destructible const&);
@@ -68,7 +59,6 @@ namespace minimal
copy_constructible(constructor_param const&) {}
copy_constructible(copy_constructible const&) {}
~copy_constructible() {}
void dummy_member() const {}
private:
copy_constructible& operator=(copy_constructible const&);
copy_constructible() {}
@@ -88,15 +78,11 @@ namespace minimal
{
}
void dummy_member() const {}
private:
copy_constructible_equality_comparable& operator=(
copy_constructible_equality_comparable const&);
copy_constructible_equality_comparable() {}
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
ampersand_operator_used operator&() const { return ampersand_operator_used(); }
};
bool operator==(
@@ -135,12 +121,9 @@ namespace minimal
{
}
void dummy_member() const {}
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
private:
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
};
class assignable
@@ -150,13 +133,11 @@ namespace minimal
assignable(assignable const&) {}
assignable& operator=(assignable const&) { return *this; }
~assignable() {}
void dummy_member() const {}
private:
assignable() {}
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
// TODO: This messes up a concept check in the tests.
//ampersand_operator_used operator&() const { return ampersand_operator_used(); }
};
struct movable_init {};
@@ -172,7 +153,6 @@ namespace minimal
movable1(BOOST_RV_REF(movable1)) {}
movable1& operator=(BOOST_RV_REF(movable1)) { return *this; }
~movable1() {}
void dummy_member() const {}
};
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
@@ -184,7 +164,6 @@ namespace minimal
movable2(movable2&&) {}
~movable2() {}
movable2& operator=(movable2&&) { return *this; }
void dummy_member() const {}
private:
movable2() {}
movable2(movable2 const&);
@@ -205,10 +184,8 @@ namespace minimal
~hash() {}
std::size_t operator()(T const&) const { return 0; }
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
private:
ampersand_operator_used operator&() const { return ampersand_operator_used(); }
};
template <class T>
@@ -222,10 +199,8 @@ namespace minimal
~equal_to() {}
bool operator()(T const&, T const&) const { return true; }
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
private:
ampersand_operator_used operator&() const { return ampersand_operator_used(); }
};
template <class T> class ptr;
@@ -313,10 +288,9 @@ namespace minimal
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_; }
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
private:
// TODO:
//ampersand_operator_used operator&() const { return ampersand_operator_used(); }
};
template <class T>
@@ -351,10 +325,9 @@ namespace minimal
bool operator>(const_ptr const& x) const { return ptr_ > x.ptr_; }
bool operator<=(const_ptr const& x) const { return ptr_ <= x.ptr_; }
bool operator>=(const_ptr const& x) const { return ptr_ >= x.ptr_; }
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
private:
// TODO:
//ampersand_operator_used operator&() const { return ampersand_operator_used(); }
};
template <class T>
@@ -414,10 +387,8 @@ namespace minimal
#else
private: allocator& operator=(allocator const&);
#endif
#if BOOST_UNORDERED_CHECK_ADDR_OPERATOR_NOT_USED
ampersand_operator_used operator&() const {
return ampersand_operator_used(); }
#endif
private:
ampersand_operator_used operator&() const { return ampersand_operator_used(); }
};
template <class T>
+4 -2
View File
@@ -11,8 +11,10 @@ project unordered-test/unordered
<toolset>intel:<warnings>on
# Would be nice to define -Wundef, but I'm getting warnings from
# Boost.Preprocessor on trunk.
<toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow -Wno-long-long"
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow"
<toolset>gcc:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wno-long-long -Wfloat-equal"
<toolset>darwin:<cxxflags>"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal"
#<toolset>gcc:<define>_GLIBCXX_DEBUG
#<toolset>darwin:<define>_GLIBCXX_DEBUG
;
test-suite unordered
-2
View File
@@ -202,7 +202,6 @@ UNORDERED_AUTO_TEST(test2)
unordered_unique_test(map, map_value);
unordered_map_test(map, assignable, assignable);
unordered_copyable_test(map, assignable, map_value, hash, equal_to);
unordered_map_member_test(map, map_value);
boost::unordered_map<
test::minimal::assignable,
@@ -227,7 +226,6 @@ UNORDERED_AUTO_TEST(test2)
unordered_equivalent_test(multimap, map_value);
unordered_map_test(multimap, assignable, assignable);
unordered_copyable_test(multimap, assignable, map_value, hash, equal_to);
unordered_map_member_test(multimap, map_value);
}
RUN_TESTS()
-2
View File
@@ -183,7 +183,6 @@ UNORDERED_AUTO_TEST(test2)
unordered_unique_test(set, assignable);
unordered_set_test(set, assignable);
unordered_copyable_test(set, assignable, assignable, hash, equal_to);
unordered_set_member_test(set, assignable);
std::cout<<"Test unordered_multiset.\n";
@@ -196,7 +195,6 @@ UNORDERED_AUTO_TEST(test2)
unordered_equivalent_test(multiset, assignable);
unordered_set_test(multiset, assignable);
unordered_copyable_test(multiset, assignable, assignable, hash, equal_to);
unordered_set_member_test(multiset, assignable);
}
UNORDERED_AUTO_TEST(movable1_tests)
-66
View File
@@ -180,28 +180,6 @@ void unordered_set_test(X&, Key const&)
typedef BOOST_DEDUCED_TYPENAME X::key_type key_type;
BOOST_STATIC_ASSERT((boost::is_same<value_type, key_type>::value));
// iterator pointer / const_pointer_type
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
typedef BOOST_DEDUCED_TYPENAME X::local_iterator local_iterator;
typedef BOOST_DEDUCED_TYPENAME X::const_local_iterator const_local_iterator;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<iterator>::type iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<const_iterator>::type
const_iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<local_iterator>::type local_iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<const_local_iterator>::type
const_local_iterator_pointer;
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, const_iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, local_iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, const_local_iterator_pointer>::value));
}
template <class X, class Key, class T>
@@ -213,30 +191,6 @@ void unordered_map_test(X& r, Key const& k, T const& v)
BOOST_STATIC_ASSERT((
boost::is_same<value_type, std::pair<key_type const, T> >::value));
// iterator pointer / const_pointer_type
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator;
typedef BOOST_DEDUCED_TYPENAME X::local_iterator local_iterator;
typedef BOOST_DEDUCED_TYPENAME X::const_local_iterator const_local_iterator;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<iterator>::type iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<const_iterator>::type
const_iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<local_iterator>::type local_iterator_pointer;
typedef BOOST_DEDUCED_TYPENAME
boost::iterator_pointer<const_local_iterator>::type
const_local_iterator_pointer;
BOOST_STATIC_ASSERT((boost::is_same<value_type*, iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, const_iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<value_type*, local_iterator_pointer>::value));
BOOST_STATIC_ASSERT((boost::is_same<value_type const*, const_local_iterator_pointer>::value));
// Calling functions
r.insert(std::pair<Key const, T>(k, v));
Key k_lvalue(k);
@@ -554,23 +508,3 @@ void unordered_movable_test(X& x, Key& k, T& /* t */, Hash& hf, Pred& eq)
sink(a8);
sink(a10);
}
template <class X, class T>
void unordered_set_member_test(X& x, T& t)
{
X x1(x);
x1.insert(t);
x1.begin()->dummy_member();
x1.cbegin()->dummy_member();
}
template <class X, class T>
void unordered_map_member_test(X& x, T& t)
{
X x1(x);
x1.insert(t);
x1.begin()->first.dummy_member();
x1.cbegin()->first.dummy_member();
x1.begin()->second.dummy_member();
x1.cbegin()->second.dummy_member();
}
+1
View File
@@ -117,6 +117,7 @@ struct compatible_predicate
template <class X>
void find_compatible_keys_test(X*, test::random_generator generator)
{
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
typedef BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator
value_iterator;
test::random_values<X> v(500, generator);
+5 -50
View File
@@ -9,7 +9,6 @@
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
#include <boost/predef.h>
#include <boost/next_prior.hpp>
#include "../objects/test.hpp"
#include "../helpers/random_values.hpp"
@@ -364,6 +363,9 @@ void equivalent_emplace_tests1(X*, test::random_generator generator)
template <class X>
void move_emplace_tests(X*, test::random_generator generator)
{
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
typedef test::ordered<X> ordered;
std::cerr<<"emplace(move(value)) tests for containers with unique keys.\n";
X x;
@@ -574,21 +576,6 @@ UNORDERED_TEST(map_insert_range_test2,
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
struct initialize_from_two_ints
{
int a, b;
friend std::size_t hash_value(initialize_from_two_ints const& x)
{
return x.a + x.b;
}
bool operator==(initialize_from_two_ints const& x) const
{
return a == x.a && b == x.b;
}
};
UNORDERED_AUTO_TEST(insert_initializer_list_set)
{
boost::unordered_set<int> set;
@@ -596,38 +583,8 @@ UNORDERED_AUTO_TEST(insert_initializer_list_set)
BOOST_TEST_EQ(set.size(), 3u);
BOOST_TEST(set.find(1) != set.end());
BOOST_TEST(set.find(4) == set.end());
boost::unordered_set<initialize_from_two_ints> set2;
#if BOOST_COMP_GNUC && BOOST_COMP_GNUC < BOOST_VERSION_NUMBER(4,5,0)
set2.insert({{1, 2}});
#else
set2.insert({1, 2});
#endif
BOOST_TEST(set2.size() == 1);
BOOST_TEST(set2.find({1,2}) != set2.end());
BOOST_TEST(set2.find({2,1}) == set2.end());
set2.insert({{3,4},{5,6},{7,8}});
BOOST_TEST(set2.size() == 4);
BOOST_TEST(set2.find({1,2}) != set2.end());
BOOST_TEST(set2.find({3,4}) != set2.end());
BOOST_TEST(set2.find({5,6}) != set2.end());
BOOST_TEST(set2.find({7,8}) != set2.end());
BOOST_TEST(set2.find({8,7}) == set2.end());
set2.insert({{2, 1}, {3,4}});
BOOST_TEST(set2.size() == 5);
BOOST_TEST(set2.find({1,2}) != set2.end());
BOOST_TEST(set2.find({2,1}) != set2.end());
BOOST_TEST(set2.find({3,4}) != set2.end());
BOOST_TEST(set2.find({5,6}) != set2.end());
BOOST_TEST(set2.find({7,8}) != set2.end());
BOOST_TEST(set2.find({8,7}) == set2.end());
}
#if !BOOST_WORKAROUND(BOOST_MSVC, == 1800)
UNORDERED_AUTO_TEST(insert_initializer_list_multiset)
{
boost::unordered_multiset<std::string> multiset;
@@ -644,8 +601,6 @@ UNORDERED_AUTO_TEST(insert_initializer_list_multiset)
BOOST_TEST_EQ(multiset.count("c"), 0u);
}
#endif
UNORDERED_AUTO_TEST(insert_initializer_list_map)
{
boost::unordered_map<std::string, std::string> map;
@@ -669,8 +624,8 @@ UNORDERED_AUTO_TEST(insert_initializer_list_multimap)
struct overloaded_constructor
{
overloaded_constructor(int x1_ = 1, int x2_ = 2, int x3_ = 3, int x4_ = 4)
: x1(x1_), x2(x2_), x3(x3_), x4(x4_) {}
overloaded_constructor(int x1 = 1, int x2 = 2, int x3 = 3, int x4 = 4)
: x1(x1), x2(x2), x3(x3), x4(x4) {}
int x1, x2, x3, x4;
+2 -2
View File
@@ -69,7 +69,7 @@ namespace noexcept_tests
BOOST_NOEXCEPT {}
hash_nothrow_move() { test_throw("Constructor"); }
hash_nothrow_move(hash_nothrow_move const&) { test_throw("Copy"); }
hash_nothrow_move(hash_nothrow_move const& x) { test_throw("Copy"); }
hash_nothrow_move& operator=(hash_nothrow_move const&)
{ test_throw("Assign"); return *this; }
std::size_t operator()(int x) const
@@ -85,7 +85,7 @@ namespace noexcept_tests
equal_to_nothrow_move(BOOST_RV_REF(equal_to_nothrow_move))
BOOST_NOEXCEPT {}
equal_to_nothrow_move() { test_throw("Constructor"); }
equal_to_nothrow_move(equal_to_nothrow_move const&)
equal_to_nothrow_move(equal_to_nothrow_move const& x)
{ test_throw("Copy"); }
equal_to_nothrow_move& operator=(equal_to_nothrow_move const&)
{ test_throw("Assign"); return *this; }
+13 -47
View File
@@ -119,20 +119,6 @@ namespace unnecessary_copy_tests
}
}
// Boost.Move doesn't seem to work very well on this compiler.
// For example for:
//
// T x;
//
// It will default construct T, and then move it in.
// For 'T const' it seems to copy.
#if defined(__IBMCPP__) && __IBMCPP__ <= 1210
#define EXTRA_CONSTRUCT_COST 1
#else
#define EXTRA_CONSTRUCT_COST 0
#endif
#define COPY_COUNT(n) \
if(::unnecessary_copy_tests::count_copies::copies != n) { \
BOOST_ERROR("Wrong number of copies."); \
@@ -164,13 +150,9 @@ namespace unnecessary_copy_tests
BOOST_ERROR("Wrong number of moves."); \
std::cerr \
<< "Number of moves: " \
<< ::unnecessary_copy_tests::count_copies::moves \
<< ::unnecessary_copy_tests::count_copies::copies \
<< " expecting: [" << a << ", " << b << "]" << std::endl; \
}
#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)
namespace unnecessary_copy_tests
{
@@ -225,29 +207,13 @@ namespace unnecessary_copy_tests
UNORDERED_TEST(unnecessary_copy_emplace_rvalue_test,
((set)(multiset)(map)(multimap)))
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template <class T>
void unnecessary_copy_emplace_std_move_test(T*)
void unnecessary_copy_emplace_move_test(T*)
{
reset();
T x;
BOOST_DEDUCED_TYPENAME T::value_type a;
COPY_COUNT(1); MOVE_COUNT(0);
x.emplace(std::move(a));
COPY_COUNT(1); MOVE_COUNT(1);
}
UNORDERED_TEST(unnecessary_copy_emplace_std_move_test,
((set)(multiset)(map)(multimap)))
#endif
template <class T>
void unnecessary_copy_emplace_boost_move_test(T*)
{
reset();
T x;
BOOST_DEDUCED_TYPENAME T::value_type a;
COPY_COUNT(1); MOVE_COUNT_EXTRA(0, 1);
x.emplace(boost::move(a));
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
COPY_COUNT(1); MOVE_COUNT(1);
@@ -257,7 +223,7 @@ namespace unnecessary_copy_tests
#endif
}
UNORDERED_TEST(unnecessary_copy_emplace_boost_move_test,
UNORDERED_TEST(unnecessary_copy_emplace_move_test,
((set)(multiset)(map)(multimap)))
template <class T>
@@ -281,10 +247,10 @@ namespace unnecessary_copy_tests
T x;
COPY_COUNT(0); MOVE_COUNT(0);
BOOST_DEDUCED_TYPENAME T::value_type a;
COPY_COUNT(1); MOVE_COUNT_EXTRA(0, 1);
COPY_COUNT(1); MOVE_COUNT(0);
x.emplace(boost::move(a));
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
COPY_COUNT(2); MOVE_COUNT_EXTRA(0, 1);
COPY_COUNT(2); MOVE_COUNT(0);
#else
COPY_COUNT(1); MOVE_COUNT(1);
#endif
@@ -398,7 +364,7 @@ namespace unnecessary_copy_tests
// TODO: Run tests for pairs without const etc.
std::pair<count_copies const, count_copies> a;
x.emplace(a);
COPY_COUNT_EXTRA(4, 1); MOVE_COUNT_EXTRA(0, 1);
COPY_COUNT(4); MOVE_COUNT(0);
//
// 0 arguments
@@ -408,7 +374,7 @@ namespace unnecessary_copy_tests
// COPY_COUNT(1) would be okay here.
reset();
x.emplace();
# if BOOST_WORKAROUND(BOOST_MSVC, == 1700)
# if BOOST_WORKAROUND(BOOST_MSVC, >= 1700)
// This is a little odd, Visual C++ 11 seems to move the pair, which
// results in one copy (for the const key) and one move (for the
// non-const mapped value). Since 'emplace(boost::move(a))' (see below)
@@ -416,7 +382,7 @@ namespace unnecessary_copy_tests
// Visual C++ 11 handles calling move for default arguments.
COPY_COUNT(3); MOVE_COUNT(1);
# else
COPY_COUNT_EXTRA(2, 1); MOVE_COUNT_EXTRA(0, 1);
COPY_COUNT(2); MOVE_COUNT(0);
# endif
#endif
@@ -441,8 +407,9 @@ namespace unnecessary_copy_tests
x.emplace(source<std::pair<count_copies, count_copies> >());
COPY_COUNT(2); MOVE_COUNT(source_pair_cost);
#if !(defined(__GNUC__) && __cplusplus < 199900L) && \
!(defined(_MSC_VER) && _MSC_VER < 1600)
#if (defined(__GNUC__) && __GNUC__ > 4) || \
(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ > 2) || \
(defined(BOOST_MSVC) && BOOST_MSVC >= 1600 )
count_copies part;
reset();
std::pair<count_copies const&, count_copies const&> a_ref(part, part);
@@ -509,9 +476,8 @@ namespace unnecessary_copy_tests
COPY_COUNT(tuple_copy_cost);
MOVE_COUNT(tuple_move_cost);
#if !defined(BOOST_NO_CXX11_HDR_TUPLE) && \
!(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ < 6) && \
!(defined(BOOST_MSVC) && BOOST_MSVC < 1700)
#if defined(__GNUC__) && __GNUC__ > 4 || \
defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 6
reset();
x.emplace(boost::unordered::piecewise_construct,
std::forward_as_tuple(b.first),