Compare commits

..

1 Commits

Author SHA1 Message Date
Marshall Clow 68db81064b Release 1.53.0
[SVN r82734]
2013-02-04 18:11:49 +00:00
12 changed files with 176 additions and 410 deletions
-12
View File
@@ -228,16 +228,4 @@ C++11 support has resulted in some breaking changes:
* More internal implementation changes, including a much simpler
implementation of `erase`.
[h2 Boost 1.54.0]
* Mark methods specified in standard as `noexpect`. More to come in the next
release.
* If the hash function and equality predicate are known to both have nothrow
move assignment or construction then use them.
[h2 Boost 1.55.0]
* Avoid some warnings ([ticket 8851], [ticket 8874]).
* Avoid exposing some detail functions via. ADL on the iterators.
[endsect]
+4 -5
View File
@@ -8,12 +8,11 @@
Support for move semantics is implemented using Boost.Move. If rvalue
references are available it will use them, but if not it uses a close,
but imperfect emulation. On such compilers:
but imperfect emulation. On such compilers you'll need to use Boost.Move
to take advantage of using movable container elements, also note that:
* Non-copyable objects can be stored in the containers.
They can be constructed in place using `emplace`, or if they support
Boost.Move, moved into place.
* The containers themselves are not movable.
* Non-copyable objects can be stored in the containers, but without support
for rvalue references the container will not be movable.
* Argument forwarding is not perfect.
[endsect]
+25 -29
View File
@@ -234,11 +234,9 @@ namespace boost { namespace unordered { namespace detail {
#pragma warning(disable:4100) // unreferenced formal parameter
#endif
namespace func {
template <class T>
inline void destroy(T* x) {
x->~T();
}
template <class T>
inline void destroy(T* x) {
x->~T();
}
#if defined(BOOST_MSVC)
@@ -259,12 +257,13 @@ namespace boost { namespace unordered { namespace detail {
template <typename T, unsigned int> struct expr_test;
template <typename T> struct expr_test<T, sizeof(char)> : T {};
template <typename U> static char for_expr_test(U const&);
# define BOOST_UNORDERED_CHECK_EXPRESSION(count, result, expression) \
template <typename U> \
static typename boost::unordered::detail::expr_test< \
BOOST_PP_CAT(choice, result), \
sizeof(for_expr_test(( \
sizeof(boost::unordered::detail::for_expr_test(( \
(expression), \
0)))>::type test( \
BOOST_PP_CAT(choice, count))
@@ -277,7 +276,6 @@ namespace boost { namespace unordered { namespace detail {
# define BOOST_UNORDERED_HAS_FUNCTION(name, thing, args, _) \
struct BOOST_PP_CAT(has_, name) \
{ \
template <typename U> static char for_expr_test(U const&); \
BOOST_UNORDERED_CHECK_EXPRESSION(1, 1, \
boost::unordered::detail::make< thing >().name args); \
BOOST_UNORDERED_DEFAULT_EXPRESSION(2, 2); \
@@ -475,9 +473,6 @@ namespace boost { namespace unordered { namespace detail {
# endif
namespace func
{
template <typename Alloc>
inline Alloc call_select_on_container_copy_construction(const Alloc& rhs,
typename boost::enable_if_c<
@@ -515,8 +510,6 @@ namespace boost { namespace unordered { namespace detail {
return (std::numeric_limits<SizeType>::max)();
}
} // namespace func.
template <typename Alloc>
struct allocator_traits
{
@@ -596,7 +589,7 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::has_destroy<Alloc, T>::value>::type
destroy(Alloc&, T* p)
{
boost::unordered::detail::func::destroy(p);
boost::unordered::detail::destroy(p);
}
# elif !defined(BOOST_NO_SFINAE_EXPR)
@@ -630,7 +623,7 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::has_destroy<Alloc, T>::value>::type
destroy(Alloc&, T* p)
{
boost::unordered::detail::func::destroy(p);
boost::unordered::detail::destroy(p);
}
# else
@@ -676,22 +669,21 @@ namespace boost { namespace unordered { namespace detail {
boost::is_same<T, value_type>::value,
void*>::type = 0)
{
boost::unordered::detail::func::destroy(p);
boost::unordered::detail::destroy(p);
}
# endif
static size_type max_size(const Alloc& a)
{
return boost::unordered::detail::func::
call_max_size<size_type>(a);
return boost::unordered::detail::call_max_size<size_type>(a);
}
// Allocator propagation on construction
static Alloc select_on_container_copy_construction(Alloc const& rhs)
{
return boost::unordered::detail::func::
return boost::unordered::detail::
call_select_on_container_copy_construction(rhs);
}
@@ -766,7 +758,7 @@ namespace boost { namespace unordered { namespace detail {
#endif
namespace boost { namespace unordered { namespace detail { namespace func {
namespace boost { namespace unordered { namespace detail {
////////////////////////////////////////////////////////////////////////////
// call_construct
@@ -800,7 +792,7 @@ namespace boost { namespace unordered { namespace detail { namespace func {
template <typename Alloc, typename T>
inline void destroy_value_impl(Alloc&, T* x) {
boost::unordered::detail::func::destroy(x);
boost::unordered::detail::destroy(x);
}
@@ -810,7 +802,7 @@ namespace boost { namespace unordered { namespace detail { namespace func {
template <typename Alloc, typename T>
inline void destroy_value_impl(Alloc&, T* x) {
boost::unordered::detail::func::destroy(x);
boost::unordered::detail::destroy(x);
}
#endif
@@ -826,7 +818,7 @@ namespace boost { namespace unordered { namespace detail { namespace func {
template<typename Alloc, typename T> \
void construct_from_tuple(Alloc& alloc, T* ptr, namespace_ tuple<>) \
{ \
boost::unordered::detail::func::call_construct(alloc, ptr); \
boost::unordered::detail::call_construct(alloc, ptr); \
} \
\
BOOST_PP_REPEAT_FROM_TO(1, n, \
@@ -838,7 +830,7 @@ namespace boost { namespace unordered { namespace detail { namespace func {
void construct_from_tuple(Alloc& alloc, T* ptr, \
namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
{ \
boost::unordered::detail::func::call_construct(alloc, ptr, \
boost::unordered::detail::call_construct(alloc, ptr, \
BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \
); \
}
@@ -953,7 +945,7 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
inline void construct_value_impl(Alloc& alloc, T* address,
BOOST_FWD_REF(Args)... args)
{
boost::unordered::detail::func::call_construct(alloc,
boost::unordered::detail::call_construct(alloc,
address, boost::forward<Args>(args)...);
}
@@ -968,9 +960,9 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
construct_value_impl(Alloc& alloc, std::pair<A, B>* address,
BOOST_FWD_REF(A0), BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
{
boost::unordered::detail::func::construct_from_tuple(alloc,
boost::unordered::detail::construct_from_tuple(alloc,
boost::addressof(address->first), boost::forward<A1>(a1));
boost::unordered::detail::func::construct_from_tuple(alloc,
boost::unordered::detail::construct_from_tuple(alloc,
boost::addressof(address->second), boost::forward<A2>(a2));
}
@@ -1040,15 +1032,19 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
boost::unordered::detail::emplace_args3<A0, A1, A2> const& args,
typename enable_if<use_piecewise<A0>, void*>::type = 0)
{
boost::unordered::detail::func::construct_from_tuple(alloc,
boost::unordered::detail::construct_from_tuple(alloc,
boost::addressof(address->first), args.a1);
boost::unordered::detail::func::construct_from_tuple(alloc,
boost::unordered::detail::construct_from_tuple(alloc,
boost::addressof(address->second), args.a2);
}
#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
}}}}
}}}
////////////////////////////////////////////////////////////////////////////////
//
// Some helper functions for allocating & constructing
namespace boost { namespace unordered { namespace detail {
+32 -115
View File
@@ -15,8 +15,6 @@
#include <boost/unordered/detail/allocate.hpp>
#include <boost/type_traits/aligned_storage.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <boost/type_traits/is_nothrow_move_constructible.hpp>
#include <boost/type_traits/is_nothrow_move_assignable.hpp>
#include <boost/swap.hpp>
#include <boost/assert.hpp>
#include <boost/limits.hpp>
@@ -32,10 +30,6 @@ namespace boost { namespace unordered { namespace detail {
}}}
// The 'iterator_detail' namespace was a misguided attempt at avoiding ADL
// in the detail namespace. It didn't work because the template parameters
// were in detail. I'm not changing it at the moment to be safe. I might
// do in the future if I change the iterator types.
namespace boost { namespace unordered { namespace iterator_detail {
////////////////////////////////////////////////////////////////////////////
@@ -77,9 +71,9 @@ namespace boost { namespace unordered { namespace iterator_detail {
typedef typename Node::value_type value_type;
l_iterator() BOOST_NOEXCEPT : ptr_() {}
l_iterator() : ptr_() {}
l_iterator(iterator x, std::size_t b, std::size_t c) BOOST_NOEXCEPT
l_iterator(iterator x, std::size_t b, std::size_t c)
: ptr_(x.node_), bucket_(b), bucket_count_(c) {}
value_type& operator*() const {
@@ -104,11 +98,11 @@ namespace boost { namespace unordered { namespace iterator_detail {
return tmp;
}
bool operator==(l_iterator x) const BOOST_NOEXCEPT {
bool operator==(l_iterator x) const {
return ptr_ == x.ptr_;
}
bool operator!=(l_iterator x) const BOOST_NOEXCEPT {
bool operator!=(l_iterator x) const {
return ptr_ != x.ptr_;
}
};
@@ -136,13 +130,13 @@ namespace boost { namespace unordered { namespace iterator_detail {
typedef typename Node::value_type value_type;
cl_iterator() BOOST_NOEXCEPT : ptr_() {}
cl_iterator() : ptr_() {}
cl_iterator(iterator x, std::size_t b, std::size_t c) BOOST_NOEXCEPT :
cl_iterator(iterator x, std::size_t b, std::size_t c) :
ptr_(x.node_), bucket_(b), bucket_count_(c) {}
cl_iterator(boost::unordered::iterator_detail::l_iterator<
Node, Policy> const& x) BOOST_NOEXCEPT :
Node, Policy> const& x) :
ptr_(x.ptr_), bucket_(x.bucket_), bucket_count_(x.bucket_count_)
{}
@@ -168,15 +162,11 @@ namespace boost { namespace unordered { namespace iterator_detail {
return tmp;
}
friend bool operator==(cl_iterator const& x, cl_iterator const& y)
BOOST_NOEXCEPT
{
friend bool operator==(cl_iterator const& x, cl_iterator const& y) {
return x.ptr_ == y.ptr_;
}
friend bool operator!=(cl_iterator const& x, cl_iterator const& y)
BOOST_NOEXCEPT
{
friend bool operator!=(cl_iterator const& x, cl_iterator const& y) {
return x.ptr_ != y.ptr_;
}
};
@@ -212,9 +202,9 @@ namespace boost { namespace unordered { namespace iterator_detail {
typedef typename Node::value_type value_type;
iterator() BOOST_NOEXCEPT : node_() {}
iterator() : node_() {}
explicit iterator(typename Node::link_pointer x) BOOST_NOEXCEPT :
explicit iterator(typename Node::link_pointer x) :
node_(static_cast<node_pointer>(x)) {}
value_type& operator*() const {
@@ -236,11 +226,11 @@ namespace boost { namespace unordered { namespace iterator_detail {
return tmp;
}
bool operator==(iterator const& x) const BOOST_NOEXCEPT {
bool operator==(iterator const& x) const {
return node_ == x.node_;
}
bool operator!=(iterator const& x) const BOOST_NOEXCEPT {
bool operator!=(iterator const& x) const {
return node_ != x.node_;
}
};
@@ -274,12 +264,12 @@ namespace boost { namespace unordered { namespace iterator_detail {
typedef typename Node::value_type value_type;
c_iterator() BOOST_NOEXCEPT : node_() {}
c_iterator() : node_() {}
explicit c_iterator(typename Node::link_pointer x) BOOST_NOEXCEPT :
explicit c_iterator(typename Node::link_pointer x) :
node_(static_cast<node_pointer>(x)) {}
c_iterator(iterator const& x) BOOST_NOEXCEPT : node_(x.node_) {}
c_iterator(iterator const& x) : node_(x.node_) {}
value_type const& operator*() const {
return node_->value();
@@ -300,15 +290,11 @@ namespace boost { namespace unordered { namespace iterator_detail {
return tmp;
}
friend bool operator==(c_iterator const& x, c_iterator const& y)
BOOST_NOEXCEPT
{
friend bool operator==(c_iterator const& x, c_iterator const& y) {
return x.node_ == y.node_;
}
friend bool operator!=(c_iterator const& x, c_iterator const& y)
BOOST_NOEXCEPT
{
friend bool operator!=(c_iterator const& x, c_iterator const& y) {
return x.node_ != y.node_;
}
};
@@ -357,7 +343,7 @@ namespace boost { namespace unordered { namespace detail {
void construct_with_value(BOOST_UNORDERED_EMPLACE_ARGS)
{
construct();
boost::unordered::detail::func::construct_value_impl(
boost::unordered::detail::construct_value_impl(
alloc_, node_->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
value_constructed_ = true;
}
@@ -366,7 +352,7 @@ namespace boost { namespace unordered { namespace detail {
void construct_with_value2(BOOST_FWD_REF(A0) a0)
{
construct();
boost::unordered::detail::func::construct_value_impl(
boost::unordered::detail::construct_value_impl(
alloc_, node_->value_ptr(),
BOOST_UNORDERED_EMPLACE_ARGS1(boost::forward<A0>(a0)));
value_constructed_ = true;
@@ -396,7 +382,7 @@ namespace boost { namespace unordered { namespace detail {
{
if (node_) {
if (value_constructed_) {
boost::unordered::detail::func::destroy_value_impl(alloc_,
boost::unordered::detail::destroy_value_impl(alloc_,
node_->value_ptr());
}
@@ -428,7 +414,7 @@ namespace boost { namespace unordered { namespace detail {
if (value_constructed_)
{
boost::unordered::detail::func::destroy_value_impl(alloc_,
boost::unordered::detail::destroy_value_impl(alloc_,
node_->value_ptr());
value_constructed_ = false;
}
@@ -545,7 +531,7 @@ namespace boost { namespace unordered { namespace detail {
node_pointer p = nodes_;
nodes_ = static_cast<node_pointer>(p->next_);
boost::unordered::detail::func::destroy_value_impl(this->alloc_,
boost::unordered::detail::destroy_value_impl(this->alloc_,
p->value_ptr());
node_allocator_traits::destroy(this->alloc_, boost::addressof(*p));
node_allocator_traits::deallocate(this->alloc_, p, 1);
@@ -684,23 +670,12 @@ namespace boost { namespace unordered { namespace detail {
// atomically assigns the new function objects in a strongly
// exception safe manner.
template <class H, class P, bool NoThrowMoveAssign>
class set_hash_functions;
template <class H, class P> class set_hash_functions;
template <class H, class P>
class functions
{
public:
static const bool nothrow_move_assignable =
boost::is_nothrow_move_assignable<H>::value &&
boost::is_nothrow_move_assignable<P>::value;
static const bool nothrow_move_constructible =
boost::is_nothrow_move_constructible<H>::value &&
boost::is_nothrow_move_constructible<P>::value;
private:
friend class boost::unordered::detail::set_hash_functions<H, P,
nothrow_move_assignable>;
friend class boost::unordered::detail::set_hash_functions<H, P>;
functions& operator=(functions const&);
typedef compressed<H, P> function_pair;
@@ -717,40 +692,23 @@ namespace boost { namespace unordered { namespace detail {
static_cast<void const*>(&funcs_[current_]));
}
function_pair& current() {
return *static_cast<function_pair*>(
static_cast<void*>(&funcs_[current_]));
}
void construct(bool which, H const& hf, P const& eq)
{
new((void*) &funcs_[which]) function_pair(hf, eq);
}
void construct(bool which, function_pair const& f,
boost::unordered::detail::false_type =
boost::unordered::detail::false_type())
void construct(bool which, function_pair const& f)
{
new((void*) &funcs_[which]) function_pair(f);
}
void construct(bool which, function_pair& f,
boost::unordered::detail::true_type)
{
new((void*) &funcs_[which]) function_pair(f,
boost::unordered::detail::move_tag());
}
void destroy(bool which)
{
boost::unordered::detail::func::destroy((function_pair*)(&funcs_[which]));
boost::unordered::detail::destroy((function_pair*)(&funcs_[which]));
}
public:
typedef boost::unordered::detail::set_hash_functions<H, P,
nothrow_move_assignable> set_hash_functions;
functions(H const& hf, P const& eq)
: current_(false)
{
@@ -763,14 +721,6 @@ namespace boost { namespace unordered { namespace detail {
construct(current_, bf.current());
}
functions(functions& bf, boost::unordered::detail::move_tag)
: current_(false)
{
construct(current_, bf.current(),
boost::unordered::detail::integral_constant<bool,
nothrow_move_constructible>());
}
~functions() {
this->destroy(current_);
}
@@ -783,28 +733,26 @@ namespace boost { namespace unordered { namespace detail {
return current().second();
}
};
template <class H, class P>
class set_hash_functions<H, P, false>
class set_hash_functions
{
set_hash_functions(set_hash_functions const&);
set_hash_functions& operator=(set_hash_functions const&);
typedef functions<H, P> functions_type;
functions_type& functions_;
functions<H,P>& functions_;
bool tmp_functions_;
public:
set_hash_functions(functions_type& f, H const& h, P const& p)
set_hash_functions(functions<H,P>& f, H const& h, P const& p)
: functions_(f),
tmp_functions_(!f.current_)
{
f.construct(tmp_functions_, h, p);
}
set_hash_functions(functions_type& f, functions_type const& other)
set_hash_functions(functions<H,P>& f, functions<H,P> const& other)
: functions_(f),
tmp_functions_(!f.current_)
{
@@ -823,37 +771,6 @@ namespace boost { namespace unordered { namespace detail {
}
};
template <class H, class P>
class set_hash_functions<H, P, true>
{
set_hash_functions(set_hash_functions const&);
set_hash_functions& operator=(set_hash_functions const&);
typedef functions<H, P> functions_type;
functions_type& functions_;
H hash_;
P pred_;
public:
set_hash_functions(functions_type& f, H const& h, P const& p) :
functions_(f),
hash_(h),
pred_(p) {}
set_hash_functions(functions_type& f, functions_type const& other) :
functions_(f),
hash_(other.hash_function()),
pred_(other.key_eq()) {}
void commit()
{
functions_.current().first() = boost::move(hash_);
functions_.current().second() = boost::move(pred_);
}
};
////////////////////////////////////////////////////////////////////////////
// rvalue parameters when type can't be a BOOST_RV_REF(T) parameter
// e.g. for int
+17 -17
View File
@@ -56,19 +56,19 @@ namespace detail {
return no_key();
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class... Args>
static no_key extract(Args const&...)
{
return no_key();
}
#else
template <class Arg>
static no_key extract(Arg const&)
{
return no_key();
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class Arg1, class Arg2, class... Args>
static no_key extract(Arg1 const&, Arg2 const&, Args const&...)
{
return no_key();
}
#else
template <class Arg1, class Arg2>
static no_key extract(Arg1 const&, Arg2 const&)
{
@@ -107,6 +107,14 @@ namespace detail {
return k;
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class... Args>
static no_key extract(Args const&...)
{
return no_key();
}
#else
static no_key extract()
{
return no_key();
@@ -118,16 +126,8 @@ namespace detail {
return no_key();
}
template <class Arg1, class Arg2>
static no_key extract(Arg1 const&, Arg2 const&)
{
return no_key();
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class Arg1, class Arg2, class Arg3, class... Args>
static no_key extract(Arg1 const&, Arg2 const&, Arg3 const&,
Args const&...)
template <class Arg, class Arg1>
static no_key extract(Arg const&, Arg1 const&)
{
return no_key();
}
+16 -13
View File
@@ -159,7 +159,6 @@ namespace boost { namespace unordered { namespace detail {
typedef boost::unordered::detail::functions<
typename Types::hasher,
typename Types::key_equal> functions;
typedef typename functions::set_hash_functions set_hash_functions;
typedef typename Types::allocator allocator;
typedef typename boost::unordered::detail::
@@ -364,7 +363,7 @@ namespace boost { namespace unordered { namespace detail {
{}
table(table& x, boost::unordered::detail::move_tag m) :
functions(x, m),
functions(x),
allocators_(x.allocators_, m),
bucket_count_(x.bucket_count_),
size_(x.size_),
@@ -378,8 +377,8 @@ namespace boost { namespace unordered { namespace detail {
}
table(table& x, node_allocator const& a,
boost::unordered::detail::move_tag m) :
functions(x, m),
boost::unordered::detail::move_tag) :
functions(x),
allocators_(a, a),
bucket_count_(x.bucket_count_),
size_(0),
@@ -456,8 +455,6 @@ namespace boost { namespace unordered { namespace detail {
void swap_allocators(table& other, false_type)
{
boost::unordered::detail::func::ignore_unused_variable_warning(other);
// According to 23.2.1.8, if propagate_on_container_swap is
// false the behaviour is undefined unless the allocators
// are equal.
@@ -472,8 +469,10 @@ namespace boost { namespace unordered { namespace detail {
// Only swaps the allocators if propagate_on_container_swap
void swap(table& x)
{
set_hash_functions op1(*this, x);
set_hash_functions op2(x, *this);
boost::unordered::detail::set_hash_functions<hasher, key_equal>
op1(*this, x);
boost::unordered::detail::set_hash_functions<hasher, key_equal>
op2(x, *this);
// I think swap can throw if Propagate::value,
// since the allocators' swap can throw. Not sure though.
@@ -516,7 +515,7 @@ namespace boost { namespace unordered { namespace detail {
node_pointer n = static_cast<node_pointer>(prev->next_);
prev->next_ = n->next_;
boost::unordered::detail::func::destroy_value_impl(node_alloc(),
boost::unordered::detail::destroy_value_impl(node_alloc(),
n->value_ptr());
node_allocator_traits::destroy(node_alloc(),
boost::addressof(*n));
@@ -638,7 +637,8 @@ namespace boost { namespace unordered { namespace detail {
void assign(table const& x, false_type)
{
// Strong exception safety.
set_hash_functions new_func_this(*this, x);
boost::unordered::detail::set_hash_functions<hasher, key_equal>
new_func_this(*this, x);
new_func_this.commit();
mlf_ = x.mlf_;
recalculate_max_load();
@@ -666,7 +666,8 @@ namespace boost { namespace unordered { namespace detail {
assign(x, false_type());
}
else {
set_hash_functions new_func_this(*this, x);
boost::unordered::detail::set_hash_functions<hasher, key_equal>
new_func_this(*this, x);
// Delete everything with current allocators before assigning
// the new ones.
@@ -713,7 +714,8 @@ namespace boost { namespace unordered { namespace detail {
move_assign_no_alloc(x);
}
else {
set_hash_functions new_func_this(*this, x);
boost::unordered::detail::set_hash_functions<hasher, key_equal>
new_func_this(*this, x);
new_func_this.commit();
mlf_ = x.mlf_;
recalculate_max_load();
@@ -738,7 +740,8 @@ namespace boost { namespace unordered { namespace detail {
void move_assign_no_alloc(table& x)
{
set_hash_functions new_func_this(*this, x);
boost::unordered::detail::set_hash_functions<hasher, key_equal>
new_func_this(*this, x);
// No throw from here.
mlf_ = x.mlf_;
max_load_ = x.max_load_;
@@ -334,6 +334,8 @@ namespace boost { namespace unordered { namespace detail {
value_type& operator[](key_type const& k)
{
typedef typename value_type::second_type mapped_type;
std::size_t key_hash = this->hash(k);
iterator pos = this->find_node(key_hash, k);
-5
View File
@@ -28,11 +28,6 @@ namespace boost { namespace unordered { namespace detail {
struct move_tag {};
struct empty_emplace {};
namespace func {
template <class T>
inline void ignore_unused_variable_warning(T const&) {}
}
////////////////////////////////////////////////////////////////////////////
// iterator SFINAE
+40 -44
View File
@@ -117,13 +117,11 @@ namespace unordered
#if defined(BOOST_UNORDERED_USE_MOVE)
unordered_map(BOOST_RV_REF(unordered_map) other)
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
#elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_map(unordered_map&& other)
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
@@ -144,7 +142,7 @@ namespace unordered
// Destructor
~unordered_map() BOOST_NOEXCEPT;
~unordered_map();
// Assign
@@ -180,53 +178,53 @@ namespace unordered
unordered_map& operator=(std::initializer_list<value_type>);
#endif
allocator_type get_allocator() const BOOST_NOEXCEPT
allocator_type get_allocator() const
{
return table_.node_alloc();
}
// size and capacity
bool empty() const BOOST_NOEXCEPT
bool empty() const
{
return table_.size_ == 0;
}
size_type size() const BOOST_NOEXCEPT
size_type size() const
{
return table_.size_;
}
size_type max_size() const BOOST_NOEXCEPT;
size_type max_size() const;
// iterators
iterator begin() BOOST_NOEXCEPT
iterator begin()
{
return table_.begin();
}
const_iterator begin() const BOOST_NOEXCEPT
const_iterator begin() const
{
return table_.begin();
}
iterator end() BOOST_NOEXCEPT
iterator end()
{
return iterator();
}
const_iterator end() const BOOST_NOEXCEPT
const_iterator end() const
{
return const_iterator();
}
const_iterator cbegin() const BOOST_NOEXCEPT
const_iterator cbegin() const
{
return table_.begin();
}
const_iterator cend() const BOOST_NOEXCEPT
const_iterator cend() const
{
return const_iterator();
}
@@ -451,12 +449,12 @@ namespace unordered
// bucket interface
size_type bucket_count() const BOOST_NOEXCEPT
size_type bucket_count() const
{
return table_.bucket_count_;
}
size_type max_bucket_count() const BOOST_NOEXCEPT
size_type max_bucket_count() const
{
return table_.max_bucket_count();
}
@@ -503,13 +501,13 @@ namespace unordered
// hash policy
float max_load_factor() const BOOST_NOEXCEPT
float max_load_factor() const
{
return table_.mlf_;
}
float load_factor() const BOOST_NOEXCEPT;
void max_load_factor(float) BOOST_NOEXCEPT;
float load_factor() const;
void max_load_factor(float);
void rehash(size_type);
void reserve(size_type);
@@ -600,13 +598,11 @@ namespace unordered
#if defined(BOOST_UNORDERED_USE_MOVE)
unordered_multimap(BOOST_RV_REF(unordered_multimap) other)
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
#elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_multimap(unordered_multimap&& other)
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
@@ -627,7 +623,7 @@ namespace unordered
// Destructor
~unordered_multimap() BOOST_NOEXCEPT;
~unordered_multimap();
// Assign
@@ -664,53 +660,53 @@ namespace unordered
unordered_multimap& operator=(std::initializer_list<value_type>);
#endif
allocator_type get_allocator() const BOOST_NOEXCEPT
allocator_type get_allocator() const
{
return table_.node_alloc();
}
// size and capacity
bool empty() const BOOST_NOEXCEPT
bool empty() const
{
return table_.size_ == 0;
}
size_type size() const BOOST_NOEXCEPT
size_type size() const
{
return table_.size_;
}
size_type max_size() const BOOST_NOEXCEPT;
size_type max_size() const;
// iterators
iterator begin() BOOST_NOEXCEPT
iterator begin()
{
return table_.begin();
}
const_iterator begin() const BOOST_NOEXCEPT
const_iterator begin() const
{
return table_.begin();
}
iterator end() BOOST_NOEXCEPT
iterator end()
{
return iterator();
}
const_iterator end() const BOOST_NOEXCEPT
const_iterator end() const
{
return const_iterator();
}
const_iterator cbegin() const BOOST_NOEXCEPT
const_iterator cbegin() const
{
return table_.begin();
}
const_iterator cend() const BOOST_NOEXCEPT
const_iterator cend() const
{
return const_iterator();
}
@@ -931,12 +927,12 @@ namespace unordered
// bucket interface
size_type bucket_count() const BOOST_NOEXCEPT
size_type bucket_count() const
{
return table_.bucket_count_;
}
size_type max_bucket_count() const BOOST_NOEXCEPT
size_type max_bucket_count() const
{
return table_.max_bucket_count();
}
@@ -983,13 +979,13 @@ namespace unordered
// hash policy
float max_load_factor() const BOOST_NOEXCEPT
float max_load_factor() const
{
return table_.mlf_;
}
float load_factor() const BOOST_NOEXCEPT;
void max_load_factor(float) BOOST_NOEXCEPT;
float load_factor() const;
void max_load_factor(float);
void rehash(size_type);
void reserve(size_type);
@@ -1061,7 +1057,7 @@ namespace unordered
}
template <class K, class T, class H, class P, class A>
unordered_map<K,T,H,P,A>::~unordered_map() BOOST_NOEXCEPT {}
unordered_map<K,T,H,P,A>::~unordered_map() {}
template <class K, class T, class H, class P, class A>
unordered_map<K,T,H,P,A>::unordered_map(
@@ -1109,7 +1105,7 @@ namespace unordered
// size and capacity
template <class K, class T, class H, class P, class A>
std::size_t unordered_map<K,T,H,P,A>::max_size() const BOOST_NOEXCEPT
std::size_t unordered_map<K,T,H,P,A>::max_size() const
{
return table_.max_size();
}
@@ -1278,13 +1274,13 @@ namespace unordered
// hash policy
template <class K, class T, class H, class P, class A>
float unordered_map<K,T,H,P,A>::load_factor() const BOOST_NOEXCEPT
float unordered_map<K,T,H,P,A>::load_factor() const
{
return table_.load_factor();
}
template <class K, class T, class H, class P, class A>
void unordered_map<K,T,H,P,A>::max_load_factor(float m) BOOST_NOEXCEPT
void unordered_map<K,T,H,P,A>::max_load_factor(float m)
{
table_.max_load_factor(m);
}
@@ -1394,7 +1390,7 @@ namespace unordered
}
template <class K, class T, class H, class P, class A>
unordered_multimap<K,T,H,P,A>::~unordered_multimap() BOOST_NOEXCEPT {}
unordered_multimap<K,T,H,P,A>::~unordered_multimap() {}
template <class K, class T, class H, class P, class A>
unordered_multimap<K,T,H,P,A>::unordered_multimap(
@@ -1442,7 +1438,7 @@ namespace unordered
// size and capacity
template <class K, class T, class H, class P, class A>
std::size_t unordered_multimap<K,T,H,P,A>::max_size() const BOOST_NOEXCEPT
std::size_t unordered_multimap<K,T,H,P,A>::max_size() const
{
return table_.max_size();
}
@@ -1590,13 +1586,13 @@ namespace unordered
// hash policy
template <class K, class T, class H, class P, class A>
float unordered_multimap<K,T,H,P,A>::load_factor() const BOOST_NOEXCEPT
float unordered_multimap<K,T,H,P,A>::load_factor() const
{
return table_.load_factor();
}
template <class K, class T, class H, class P, class A>
void unordered_multimap<K,T,H,P,A>::max_load_factor(float m) BOOST_NOEXCEPT
void unordered_multimap<K,T,H,P,A>::max_load_factor(float m)
{
table_.max_load_factor(m);
}
+40 -44
View File
@@ -115,13 +115,11 @@ namespace unordered
#if defined(BOOST_UNORDERED_USE_MOVE)
unordered_set(BOOST_RV_REF(unordered_set) other)
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
#elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_set(unordered_set&& other)
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
@@ -142,7 +140,7 @@ namespace unordered
// Destructor
~unordered_set() BOOST_NOEXCEPT;
~unordered_set();
// Assign
@@ -178,53 +176,53 @@ namespace unordered
unordered_set& operator=(std::initializer_list<value_type>);
#endif
allocator_type get_allocator() const BOOST_NOEXCEPT
allocator_type get_allocator() const
{
return table_.node_alloc();
}
// size and capacity
bool empty() const BOOST_NOEXCEPT
bool empty() const
{
return table_.size_ == 0;
}
size_type size() const BOOST_NOEXCEPT
size_type size() const
{
return table_.size_;
}
size_type max_size() const BOOST_NOEXCEPT;
size_type max_size() const;
// iterators
iterator begin() BOOST_NOEXCEPT
iterator begin()
{
return table_.begin();
}
const_iterator begin() const BOOST_NOEXCEPT
const_iterator begin() const
{
return table_.begin();
}
iterator end() BOOST_NOEXCEPT
iterator end()
{
return iterator();
}
const_iterator end() const BOOST_NOEXCEPT
const_iterator end() const
{
return const_iterator();
}
const_iterator cbegin() const BOOST_NOEXCEPT
const_iterator cbegin() const
{
return table_.begin();
}
const_iterator cend() const BOOST_NOEXCEPT
const_iterator cend() const
{
return const_iterator();
}
@@ -436,12 +434,12 @@ namespace unordered
// bucket interface
size_type bucket_count() const BOOST_NOEXCEPT
size_type bucket_count() const
{
return table_.bucket_count_;
}
size_type max_bucket_count() const BOOST_NOEXCEPT
size_type max_bucket_count() const
{
return table_.max_bucket_count();
}
@@ -488,13 +486,13 @@ namespace unordered
// hash policy
float max_load_factor() const BOOST_NOEXCEPT
float max_load_factor() const
{
return table_.mlf_;
}
float load_factor() const BOOST_NOEXCEPT;
void max_load_factor(float) BOOST_NOEXCEPT;
float load_factor() const;
void max_load_factor(float);
void rehash(size_type);
void reserve(size_type);
@@ -584,13 +582,11 @@ namespace unordered
#if defined(BOOST_UNORDERED_USE_MOVE)
unordered_multiset(BOOST_RV_REF(unordered_multiset) other)
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
#elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
unordered_multiset(unordered_multiset&& other)
BOOST_NOEXCEPT_IF(table::nothrow_move_constructible)
: table_(other.table_, boost::unordered::detail::move_tag())
{
}
@@ -611,7 +607,7 @@ namespace unordered
// Destructor
~unordered_multiset() BOOST_NOEXCEPT;
~unordered_multiset();
// Assign
@@ -648,53 +644,53 @@ namespace unordered
unordered_multiset& operator=(std::initializer_list<value_type>);
#endif
allocator_type get_allocator() const BOOST_NOEXCEPT
allocator_type get_allocator() const
{
return table_.node_alloc();
}
// size and capacity
bool empty() const BOOST_NOEXCEPT
bool empty() const
{
return table_.size_ == 0;
}
size_type size() const BOOST_NOEXCEPT
size_type size() const
{
return table_.size_;
}
size_type max_size() const BOOST_NOEXCEPT;
size_type max_size() const;
// iterators
iterator begin() BOOST_NOEXCEPT
iterator begin()
{
return iterator(table_.begin());
}
const_iterator begin() const BOOST_NOEXCEPT
const_iterator begin() const
{
return const_iterator(table_.begin());
}
iterator end() BOOST_NOEXCEPT
iterator end()
{
return iterator();
}
const_iterator end() const BOOST_NOEXCEPT
const_iterator end() const
{
return const_iterator();
}
const_iterator cbegin() const BOOST_NOEXCEPT
const_iterator cbegin() const
{
return const_iterator(table_.begin());
}
const_iterator cend() const BOOST_NOEXCEPT
const_iterator cend() const
{
return const_iterator();
}
@@ -906,12 +902,12 @@ namespace unordered
// bucket interface
size_type bucket_count() const BOOST_NOEXCEPT
size_type bucket_count() const
{
return table_.bucket_count_;
}
size_type max_bucket_count() const BOOST_NOEXCEPT
size_type max_bucket_count() const
{
return table_.max_bucket_count();
}
@@ -958,13 +954,13 @@ namespace unordered
// hash policy
float max_load_factor() const BOOST_NOEXCEPT
float max_load_factor() const
{
return table_.mlf_;
}
float load_factor() const BOOST_NOEXCEPT;
void max_load_factor(float) BOOST_NOEXCEPT;
float load_factor() const;
void max_load_factor(float);
void rehash(size_type);
void reserve(size_type);
@@ -1036,7 +1032,7 @@ namespace unordered
}
template <class T, class H, class P, class A>
unordered_set<T,H,P,A>::~unordered_set() BOOST_NOEXCEPT {}
unordered_set<T,H,P,A>::~unordered_set() {}
template <class T, class H, class P, class A>
unordered_set<T,H,P,A>::unordered_set(
@@ -1084,7 +1080,7 @@ namespace unordered
// size and capacity
template <class T, class H, class P, class A>
std::size_t unordered_set<T,H,P,A>::max_size() const BOOST_NOEXCEPT
std::size_t unordered_set<T,H,P,A>::max_size() const
{
return table_.max_size();
}
@@ -1204,13 +1200,13 @@ namespace unordered
// hash policy
template <class T, class H, class P, class A>
float unordered_set<T,H,P,A>::load_factor() const BOOST_NOEXCEPT
float unordered_set<T,H,P,A>::load_factor() const
{
return table_.load_factor();
}
template <class T, class H, class P, class A>
void unordered_set<T,H,P,A>::max_load_factor(float m) BOOST_NOEXCEPT
void unordered_set<T,H,P,A>::max_load_factor(float m)
{
table_.max_load_factor(m);
}
@@ -1320,7 +1316,7 @@ namespace unordered
}
template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>::~unordered_multiset() BOOST_NOEXCEPT {}
unordered_multiset<T,H,P,A>::~unordered_multiset() {}
template <class T, class H, class P, class A>
unordered_multiset<T,H,P,A>::unordered_multiset(
@@ -1368,7 +1364,7 @@ namespace unordered
// size and capacity
template <class T, class H, class P, class A>
std::size_t unordered_multiset<T,H,P,A>::max_size() const BOOST_NOEXCEPT
std::size_t unordered_multiset<T,H,P,A>::max_size() const
{
return table_.max_size();
}
@@ -1488,13 +1484,13 @@ namespace unordered
// hash policy
template <class T, class H, class P, class A>
float unordered_multiset<T,H,P,A>::load_factor() const BOOST_NOEXCEPT
float unordered_multiset<T,H,P,A>::load_factor() const
{
return table_.load_factor();
}
template <class T, class H, class P, class A>
void unordered_multiset<T,H,P,A>::max_load_factor(float m) BOOST_NOEXCEPT
void unordered_multiset<T,H,P,A>::max_load_factor(float m)
{
table_.max_load_factor(m);
}
-1
View File
@@ -25,7 +25,6 @@ test-suite unordered
[ run minimal_allocator.cpp ]
[ run compile_set.cpp ]
[ run compile_map.cpp ]
[ run noexcept_tests.cpp ]
[ run link_test_1.cpp link_test_2.cpp ]
[ run incomplete_test.cpp ]
[ run simple_tests.cpp ]
-125
View File
@@ -1,125 +0,0 @@
// Copyright 2013 Daniel James.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#include "../helpers/prefix.hpp"
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include "../helpers/postfix.hpp"
#include "../helpers/test.hpp"
namespace noexcept_tests
{
// Test the noexcept is set correctly for the move constructor.
struct hash_possible_exception : boost::hash<int>
{
hash_possible_exception(hash_possible_exception const&) {}
};
struct equal_to_possible_exception : std::equal_to<int>
{
equal_to_possible_exception(equal_to_possible_exception const&) {}
};
UNORDERED_AUTO_TEST(test_noexcept)
{
#if !defined(BOOST_NO_CXX11_NOEXCEPT)
BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_set<int> >::value));
BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_multiset<int> >::value));
BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_map<int, int> >::value));
BOOST_TEST((boost::is_nothrow_move_constructible<
boost::unordered_multimap<int, int> >::value));
#endif
BOOST_TEST((!boost::is_nothrow_move_constructible<
boost::unordered_set<int, hash_possible_exception>
>::value));
BOOST_TEST((!boost::is_nothrow_move_constructible<
boost::unordered_multiset<int, boost::hash<int>,
equal_to_possible_exception>
>::value));
}
// Test that the move constructor does actually move without throwing
// an exception when it claims to.
struct test_exception {};
bool throwing_test_exception = false;
void test_throw(char const* name) {
if (throwing_test_exception) {
std::cerr << "Throw exception in: " << name << std::endl;
throw test_exception();
}
}
class hash_nothrow_move : boost::hash<int>
{
BOOST_COPYABLE_AND_MOVABLE(hash_nothrow_move)
typedef boost::hash<int> base;
public:
hash_nothrow_move(BOOST_RV_REF(hash_nothrow_move))
BOOST_NOEXCEPT {}
hash_nothrow_move() { test_throw("Constructor"); }
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
{ test_throw("Operator"); return static_cast<base const&>(*this)(x); }
};
class equal_to_nothrow_move : std::equal_to<int>
{
BOOST_COPYABLE_AND_MOVABLE(equal_to_nothrow_move)
typedef std::equal_to<int> base;
public:
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& x)
{ test_throw("Copy"); }
equal_to_nothrow_move& operator=(equal_to_nothrow_move const&)
{ test_throw("Assign"); return *this; }
std::size_t operator()(int x, int y) const
{ test_throw("Operator"); return static_cast<base const&>(*this)(x, y); }
};
UNORDERED_AUTO_TEST(test_no_throw_when_noexcept)
{
typedef boost::unordered_set<int,
hash_nothrow_move, equal_to_nothrow_move> throwing_set;
if (boost::is_nothrow_move_constructible<throwing_set>::value)
{
throwing_test_exception = false;
throwing_set x1;
x1.insert(10);
x1.insert(50);
try {
throwing_test_exception = true;
throwing_set x2 = boost::move(x1);
BOOST_TEST(x2.size() == 2);
BOOST_TEST(*x2.begin() == 10 || *x2.begin() == 50);
} catch(test_exception) {
BOOST_TEST(false);
}
throwing_test_exception = false;
}
}
}
RUN_TESTS()