diff --git a/doc/changes.qbk b/doc/changes.qbk
index 03fe1987..0353e292 100644
--- a/doc/changes.qbk
+++ b/doc/changes.qbk
@@ -293,5 +293,8 @@ C++11 support has resulted in some breaking changes:
objects wouldn't match the container elements, so elements might be in the
wrong bucket and equivalent elements would be incorrectly handled.
* Various reference documentation improvements.
+* Better allocator support ([ticket 12459]).
+* Make the no argument constructors implicit.
+* Implement missing allocator aware constructors.
[endsect]
diff --git a/doc/ref.php b/doc/ref.php
index d2fb2b42..3847ede3 100644
--- a/doc/ref.php
+++ b/doc/ref.php
@@ -189,10 +189,22 @@ EOL;
A const_local_iterator object can be used to iterate through a single bucket.
+
+
+ size() == 0
+
+
+ Constructs an empty container using hasher() as the hash function, key_equal() as the key equality predicate, allocator_type() as the allocator and a maximum load factor of 1.0.
+
+
+ If the defaults are used, hasher
, key_equal
and
+ allocator_type
need to be DefaultConstructible
.
+
+
+
size_type
- implementation-defined
hasher const&
@@ -246,7 +258,12 @@ EOL;
allocator_type()
- Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0 and inserts the elements from [f, l) into it.
+ Constructs an empty container with at least n
buckets,
+ using hf
as the hash function,
+ eq
as the key equality predicate,
+ a
as the allocator and a maximum load factor of 1.0
+ and inserts the elements from [f, l) into it.
+
If the defaults are used, hasher
, key_equal
and
@@ -310,6 +327,168 @@ EOL;
Constructs an container, copying x
's contained elements, hash function, predicate, maximum load factor, but using allocator a
.
+
+
+ &&
+
+
+ Allocator const&
+
+
+ Construct a container moving x
's contained elements, and having the hash function, predicate and maximum load factor, but using allocate a
.
+
+
+ This is implemented using Boost.Move.
+
+
+
+ value_type
is move insertable.
+
+
+
+
+
+ initializer_list<value_type>
+
+
+ size_type
+ implementation-defined
+
+
+ hasher const&
+ hasher()
+
+
+ key_equal const&
+ key_equal()
+
+
+ allocator_type const&
+ allocator_type()
+
+
+ Constructs an empty container with at least n
buckets,
+ using hf
as the hash function,
+ eq
as the key equality predicate,
+ a
as the allocator and a maximum load factor of 1.0
+ and inserts the elements from il
into it.
+
+
+
+ If the defaults are used, hasher
, key_equal
and
+ allocator_type
need to be DefaultConstructible
.
+
+
+
+
+
+ size_type
+
+
+ allocator_type const&
+
+
+ size() == 0
+
+
+ Constructs an empty container with at least n
buckets,
+ using hf
as the hash function,
+ the default hash function and key equality predicate,
+ a
as the allocator and a maximum load factor of 1.0.
+
+
+ hasher
and key_equal
need to be DefaultConstructible
.
+
+
+
+
+
+ size_type
+
+
+ hasher const&
+
+
+ allocator_type const&
+
+
+ size() == 0
+
+
+ Constructs an empty container with at least n
buckets,
+ using hf
as the hash function,
+ the default key equality predicate,
+ a
as the allocator and a maximum load factor of 1.0.
+
+
+ key_equal
needs to be DefaultConstructible
.
+
+
+
+
+
+
+
+
+
+ InputIterator
+
+
+ InputIterator
+
+
+ size_type
+
+
+ allocator_type const&
+
+
+ Constructs an empty container with at least n
buckets,
+ using a
as the allocator, with the
+ default hash function and key equality predicate
+ and a maximum load factor of 1.0
+ and inserts the elements from [f, l) into it.
+
+
+
+ hasher
, key_equal
need to be DefaultConstructible
.
+
+
+
+
+
+
+
+
+
+ InputIterator
+
+
+ InputIterator
+
+
+ size_type
+
+
+ hasher const&
+
+
+ allocator_type const&
+
+
+ Constructs an empty container with at least n
buckets,
+ using hf
as the hash function,
+ a
as the allocator, with the
+ default key equality predicate
+ and a maximum load factor of 1.0
+ and inserts the elements from [f, l) into it.
+
+
+
+ key_equal
needs to be DefaultConstructible
.
+
+
+
The destructor is applied to every element, and all memory is deallocated
diff --git a/doc/ref.xml b/doc/ref.xml
index d03e8dd3..dc22aace 100644
--- a/doc/ref.xml
+++ b/doc/ref.xml
@@ -130,10 +130,22 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
A const_local_iterator object can be used to iterate through a single bucket.
+
+
+ size() == 0
+
+
+ Constructs an empty container using hasher() as the hash function, key_equal() as the key equality predicate, allocator_type() as the allocator and a maximum load factor of 1.0.
+
+
+ If the defaults are used, hasher
, key_equal
and
+ allocator_type
need to be DefaultConstructible
.
+
+
+
size_type
- implementation-defined
hasher const&
@@ -187,7 +199,12 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
allocator_type()
- Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0 and inserts the elements from [f, l) into it.
+ Constructs an empty container with at least n
buckets,
+ using hf
as the hash function,
+ eq
as the key equality predicate,
+ a
as the allocator and a maximum load factor of 1.0
+ and inserts the elements from [f, l) into it.
+
If the defaults are used, hasher
, key_equal
and
@@ -251,6 +268,168 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Constructs an container, copying x
's contained elements, hash function, predicate, maximum load factor, but using allocator a
.
+
+
+ unordered_set &&
+
+
+ Allocator const&
+
+
+ Construct a container moving x
's contained elements, and having the hash function, predicate and maximum load factor, but using allocate a
.
+
+
+ This is implemented using Boost.Move.
+
+
+
+ value_type
is move insertable.
+
+
+
+
+
+ initializer_list<value_type>
+
+
+ size_type
+ implementation-defined
+
+
+ hasher const&
+ hasher()
+
+
+ key_equal const&
+ key_equal()
+
+
+ allocator_type const&
+ allocator_type()
+
+
+ Constructs an empty container with at least n
buckets,
+ using hf
as the hash function,
+ eq
as the key equality predicate,
+ a
as the allocator and a maximum load factor of 1.0
+ and inserts the elements from il
into it.
+
+
+
+ If the defaults are used, hasher
, key_equal
and
+ allocator_type
need to be DefaultConstructible
.
+
+
+
+
+
+ size_type
+
+
+ allocator_type const&
+
+
+ size() == 0
+
+
+ Constructs an empty container with at least n
buckets,
+ using hf
as the hash function,
+ the default hash function and key equality predicate,
+ a
as the allocator and a maximum load factor of 1.0.
+
+
+ hasher
and key_equal
need to be DefaultConstructible
.
+
+
+
+
+
+ size_type
+
+
+ hasher const&
+
+
+ allocator_type const&
+
+
+ size() == 0
+
+
+ Constructs an empty container with at least n
buckets,
+ using hf
as the hash function,
+ the default key equality predicate,
+ a
as the allocator and a maximum load factor of 1.0.
+
+
+ key_equal
needs to be DefaultConstructible
.
+
+
+
+
+
+
+
+
+
+ InputIterator
+
+
+ InputIterator
+
+
+ size_type
+
+
+ allocator_type const&
+
+
+ Constructs an empty container with at least n
buckets,
+ using a
as the allocator, with the
+ default hash function and key equality predicate
+ and a maximum load factor of 1.0
+ and inserts the elements from [f, l) into it.
+
+
+
+ hasher
, key_equal
need to be DefaultConstructible
.
+
+
+
+
+
+
+
+
+
+ InputIterator
+
+
+ InputIterator
+
+
+ size_type
+
+
+ hasher const&
+
+
+ allocator_type const&
+
+
+ Constructs an empty container with at least n
buckets,
+ using hf
as the hash function,
+ a
as the allocator, with the
+ default key equality predicate
+ and a maximum load factor of 1.0
+ and inserts the elements from [f, l) into it.
+
+
+
+ key_equal
needs to be DefaultConstructible
.
+
+
+
The destructor is applied to every element, and all memory is deallocated
@@ -1204,10 +1383,22 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
A const_local_iterator object can be used to iterate through a single bucket.
+
+
+ size() == 0
+
+
+ Constructs an empty container using hasher() as the hash function, key_equal() as the key equality predicate, allocator_type() as the allocator and a maximum load factor of 1.0.
+
+
+ If the defaults are used, hasher
, key_equal
and
+ allocator_type
need to be DefaultConstructible
.
+
+
+
size_type
- implementation-defined
hasher const&
@@ -1261,7 +1452,12 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
allocator_type()
- Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0 and inserts the elements from [f, l) into it.
+ Constructs an empty container with at least n
buckets,
+ using hf
as the hash function,
+ eq
as the key equality predicate,
+ a
as the allocator and a maximum load factor of 1.0
+ and inserts the elements from [f, l) into it.
+
If the defaults are used, hasher
, key_equal
and
@@ -1325,6 +1521,168 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Constructs an container, copying x
's contained elements, hash function, predicate, maximum load factor, but using allocator a
.
+
+
+ unordered_multiset &&
+
+
+ Allocator const&
+
+
+ Construct a container moving x
's contained elements, and having the hash function, predicate and maximum load factor, but using allocate a
.
+
+
+ This is implemented using Boost.Move.
+
+
+
+ value_type
is move insertable.
+
+
+
+
+
+ initializer_list<value_type>
+
+
+ size_type
+ implementation-defined
+
+
+ hasher const&
+ hasher()
+
+
+ key_equal const&
+ key_equal()
+
+
+ allocator_type const&
+ allocator_type()
+
+
+ Constructs an empty container with at least n
buckets,
+ using hf
as the hash function,
+ eq
as the key equality predicate,
+ a
as the allocator and a maximum load factor of 1.0
+ and inserts the elements from il
into it.
+
+
+
+ If the defaults are used, hasher
, key_equal
and
+ allocator_type
need to be DefaultConstructible
.
+
+
+
+
+
+ size_type
+
+
+ allocator_type const&
+
+
+ size() == 0
+
+
+ Constructs an empty container with at least n
buckets,
+ using hf
as the hash function,
+ the default hash function and key equality predicate,
+ a
as the allocator and a maximum load factor of 1.0.
+
+
+ hasher
and key_equal
need to be DefaultConstructible
.
+
+
+
+
+
+ size_type
+
+
+ hasher const&
+
+
+ allocator_type const&
+
+
+ size() == 0
+
+
+ Constructs an empty container with at least n
buckets,
+ using hf
as the hash function,
+ the default key equality predicate,
+ a
as the allocator and a maximum load factor of 1.0.
+
+
+ key_equal
needs to be DefaultConstructible
.
+
+
+
+
+
+
+
+
+
+ InputIterator
+
+
+ InputIterator
+
+
+ size_type
+
+
+ allocator_type const&
+
+
+ Constructs an empty container with at least n
buckets,
+ using a
as the allocator, with the
+ default hash function and key equality predicate
+ and a maximum load factor of 1.0
+ and inserts the elements from [f, l) into it.
+
+
+
+ hasher
, key_equal
need to be DefaultConstructible
.
+
+
+
+
+
+
+
+
+
+ InputIterator
+
+
+ InputIterator
+
+
+ size_type
+
+
+ hasher const&
+
+
+ allocator_type const&
+
+
+ Constructs an empty container with at least n
buckets,
+ using hf
as the hash function,
+ a
as the allocator, with the
+ default key equality predicate
+ and a maximum load factor of 1.0
+ and inserts the elements from [f, l) into it.
+
+
+
+ key_equal
needs to be DefaultConstructible
.
+
+
+
The destructor is applied to every element, and all memory is deallocated
@@ -2287,6 +2645,19 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
A const_local_iterator object can be used to iterate through a single bucket.
+
+
+ size() == 0
+
+
+ Constructs an empty container using hasher() as the hash function, key_equal() as the key equality predicate, allocator_type() as the allocator and a maximum load factor of 1.0.
+
+
+ If the defaults are used, hasher
, key_equal
and
+ allocator_type
need to be DefaultConstructible
.
+
+
+
size_type
@@ -2344,7 +2715,12 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
allocator_type()
- Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0 and inserts the elements from [f, l) into it.
+ Constructs an empty container with at least n
buckets,
+ using hf
as the hash function,
+ eq
as the key equality predicate,
+ a
as the allocator and a maximum load factor of 1.0
+ and inserts the elements from [f, l) into it.
+
If the defaults are used, hasher
, key_equal
and
@@ -2408,6 +2784,167 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Constructs an container, copying x
's contained elements, hash function, predicate, maximum load factor, but using allocator a
.
+
+
+ unordered_map &&
+
+
+ Allocator const&
+
+
+ Construct a container moving x
's contained elements, and having the hash function, predicate and maximum load factor, but using allocate a
.
+
+
+ This is implemented using Boost.Move.
+
+
+
+ value_type
is move insertable.
+
+
+
+
+
+ initializer_list<value_type>
+
+
+ size_type
+
+
+ hasher const&
+ hasher()
+
+
+ key_equal const&
+ key_equal()
+
+
+ allocator_type const&
+ allocator_type()
+
+
+ Constructs an empty container with at least n
buckets,
+ using hf
as the hash function,
+ eq
as the key equality predicate,
+ a
as the allocator and a maximum load factor of 1.0
+ and inserts the elements from il
into it.
+
+
+
+ If the defaults are used, hasher
, key_equal
and
+ allocator_type
need to be DefaultConstructible
.
+
+
+
+
+
+ size_type
+
+
+ allocator_type const&
+
+
+ size() == 0
+
+
+ Constructs an empty container with at least n
buckets,
+ using hf
as the hash function,
+ the default hash function and key equality predicate,
+ a
as the allocator and a maximum load factor of 1.0.
+
+
+ hasher
and key_equal
need to be DefaultConstructible
.
+
+
+
+
+
+ size_type
+
+
+ hasher const&
+
+
+ allocator_type const&
+
+
+ size() == 0
+
+
+ Constructs an empty container with at least n
buckets,
+ using hf
as the hash function,
+ the default key equality predicate,
+ a
as the allocator and a maximum load factor of 1.0.
+
+
+ key_equal
needs to be DefaultConstructible
.
+
+
+
+
+
+
+
+
+
+ InputIterator
+
+
+ InputIterator
+
+
+ size_type
+
+
+ allocator_type const&
+
+
+ Constructs an empty container with at least n
buckets,
+ using a
as the allocator, with the
+ default hash function and key equality predicate
+ and a maximum load factor of 1.0
+ and inserts the elements from [f, l) into it.
+
+
+
+ hasher
, key_equal
need to be DefaultConstructible
.
+
+
+
+
+
+
+
+
+
+ InputIterator
+
+
+ InputIterator
+
+
+ size_type
+
+
+ hasher const&
+
+
+ allocator_type const&
+
+
+ Constructs an empty container with at least n
buckets,
+ using hf
as the hash function,
+ a
as the allocator, with the
+ default key equality predicate
+ and a maximum load factor of 1.0
+ and inserts the elements from [f, l) into it.
+
+
+
+ key_equal
needs to be DefaultConstructible
.
+
+
+
The destructor is applied to every element, and all memory is deallocated
@@ -3408,10 +3945,22 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
A const_local_iterator object can be used to iterate through a single bucket.
+
+
+ size() == 0
+
+
+ Constructs an empty container using hasher() as the hash function, key_equal() as the key equality predicate, allocator_type() as the allocator and a maximum load factor of 1.0.
+
+
+ If the defaults are used, hasher
, key_equal
and
+ allocator_type
need to be DefaultConstructible
.
+
+
+
size_type
- implementation-defined
hasher const&
@@ -3465,7 +4014,12 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
allocator_type()
- Constructs an empty container with at least n buckets, using hf as the hash function, eq as the key equality predicate, a as the allocator and a maximum load factor of 1.0 and inserts the elements from [f, l) into it.
+ Constructs an empty container with at least n
buckets,
+ using hf
as the hash function,
+ eq
as the key equality predicate,
+ a
as the allocator and a maximum load factor of 1.0
+ and inserts the elements from [f, l) into it.
+
If the defaults are used, hasher
, key_equal
and
@@ -3529,6 +4083,168 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Constructs an container, copying x
's contained elements, hash function, predicate, maximum load factor, but using allocator a
.
+
+
+ unordered_multimap &&
+
+
+ Allocator const&
+
+
+ Construct a container moving x
's contained elements, and having the hash function, predicate and maximum load factor, but using allocate a
.
+
+
+ This is implemented using Boost.Move.
+
+
+
+ value_type
is move insertable.
+
+
+
+
+
+ initializer_list<value_type>
+
+
+ size_type
+ implementation-defined
+
+
+ hasher const&
+ hasher()
+
+
+ key_equal const&
+ key_equal()
+
+
+ allocator_type const&
+ allocator_type()
+
+
+ Constructs an empty container with at least n
buckets,
+ using hf
as the hash function,
+ eq
as the key equality predicate,
+ a
as the allocator and a maximum load factor of 1.0
+ and inserts the elements from il
into it.
+
+
+
+ If the defaults are used, hasher
, key_equal
and
+ allocator_type
need to be DefaultConstructible
.
+
+
+
+
+
+ size_type
+
+
+ allocator_type const&
+
+
+ size() == 0
+
+
+ Constructs an empty container with at least n
buckets,
+ using hf
as the hash function,
+ the default hash function and key equality predicate,
+ a
as the allocator and a maximum load factor of 1.0.
+
+
+ hasher
and key_equal
need to be DefaultConstructible
.
+
+
+
+
+
+ size_type
+
+
+ hasher const&
+
+
+ allocator_type const&
+
+
+ size() == 0
+
+
+ Constructs an empty container with at least n
buckets,
+ using hf
as the hash function,
+ the default key equality predicate,
+ a
as the allocator and a maximum load factor of 1.0.
+
+
+ key_equal
needs to be DefaultConstructible
.
+
+
+
+
+
+
+
+
+
+ InputIterator
+
+
+ InputIterator
+
+
+ size_type
+
+
+ allocator_type const&
+
+
+ Constructs an empty container with at least n
buckets,
+ using a
as the allocator, with the
+ default hash function and key equality predicate
+ and a maximum load factor of 1.0
+ and inserts the elements from [f, l) into it.
+
+
+
+ hasher
, key_equal
need to be DefaultConstructible
.
+
+
+
+
+
+
+
+
+
+ InputIterator
+
+
+ InputIterator
+
+
+ size_type
+
+
+ hasher const&
+
+
+ allocator_type const&
+
+
+ Constructs an empty container with at least n
buckets,
+ using hf
as the hash function,
+ a
as the allocator, with the
+ default key equality predicate
+ and a maximum load factor of 1.0
+ and inserts the elements from [f, l) into it.
+
+
+
+ key_equal
needs to be DefaultConstructible
.
+
+
+
The destructor is applied to every element, and all memory is deallocated
diff --git a/include/boost/unordered/detail/allocate.hpp b/include/boost/unordered/detail/allocate.hpp
index 319c9cd5..2d9cf4b6 100644
--- a/include/boost/unordered/detail/allocate.hpp
+++ b/include/boost/unordered/detail/allocate.hpp
@@ -88,6 +88,16 @@ namespace boost { namespace unordered { namespace detail {
convert_from_anything(T const&);
};
+ namespace func {
+ // This is a bit nasty, when constructing the individual members
+ // of a std::pair, need to cast away 'const'. For modern compilers,
+ // should be able to use std::piecewise_construct instead.
+ template T* const_cast_pointer(T* x) { return x; }
+ template T* const_cast_pointer(T const* x) {
+ return const_cast(x);
+ }
+ }
+
////////////////////////////////////////////////////////////////////////////
// emplace_args
//
@@ -237,9 +247,8 @@ BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_EARGS,
// 2 = boost::container::allocator_traits
#if !defined(BOOST_UNORDERED_USE_ALLOCATOR_TRAITS)
-# if defined(__GXX_EXPERIMENTAL_CXX0X__) && \
- (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))
-# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 0
+# if !defined(BOOST_NO_CXX11_ALLOCATOR)
+# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 1
# elif defined(BOOST_MSVC)
# if BOOST_MSVC < 1400
// Use container's allocator_traits for older versions of Visual
@@ -316,7 +325,7 @@ namespace boost { namespace unordered { namespace detail {
#if !defined(BOOST_NO_SFINAE_EXPR)
- template struct expr_test;
+ template struct expr_test;
template struct expr_test : T {};
# define BOOST_UNORDERED_CHECK_EXPRESSION(count, result, expression) \
@@ -412,11 +421,69 @@ namespace boost { namespace unordered { namespace detail {
namespace boost { namespace unordered { namespace detail {
- // TODO: Does this match std::allocator_traits::rebind_alloc?
+ template
+ struct rebind_alloc;
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ template class Alloc,
+ typename U, typename T, typename... Args>
+ struct rebind_alloc, T>
+ {
+ typedef Alloc type;
+ };
+
+#else
+
+ template <
+ template class Alloc,
+ typename U, typename T>
+ struct rebind_alloc, T>
+ {
+ typedef Alloc type;
+ };
+
+ template <
+ template class Alloc,
+ typename U, typename T,
+ typename A0>
+ struct rebind_alloc, T>
+ {
+ typedef Alloc type;
+ };
+
+ template <
+ template class Alloc,
+ typename U, typename T,
+ typename A0, typename A1>
+ struct rebind_alloc, T>
+ {
+ typedef Alloc type;
+ };
+
+#endif
+
template
struct rebind_wrap
{
- typedef typename Alloc::BOOST_NESTED_TEMPLATE rebind::other type;
+ template
+ static choice1::type test(choice1,
+ typename X::BOOST_NESTED_TEMPLATE rebind::other* = 0);
+ template
+ static choice2::type test(choice2, void* = 0);
+
+ enum { value = (1 == sizeof(test(choose()))) };
+
+ struct fallback {
+ template
+ struct rebind {
+ typedef typename rebind_alloc::type other;
+ };
+ };
+
+ typedef typename boost::detail::if_true::
+ BOOST_NESTED_TEMPLATE then
+ ::type::BOOST_NESTED_TEMPLATE rebind::other type;
};
# if defined(BOOST_MSVC) && BOOST_MSVC <= 1400
@@ -606,7 +673,14 @@ namespace boost { namespace unordered { namespace detail {
typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, size_type, std::size_t)
size_type;
- // TODO: rebind_alloc and rebind_traits
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+ template
+ using rebind_alloc = typename rebind_wrap::type;
+
+ template
+ using rebind_traits =
+ boost::unordered::detail::allocator_traits >;
+#endif
static pointer allocate(Alloc& a, size_type n)
{ return a.allocate(n); }
@@ -639,7 +713,7 @@ namespace boost { namespace unordered { namespace detail {
::value>::type
construct(Alloc&, T* p, BOOST_FWD_REF(Args)... x)
{
- new ((void*) p) T(boost::forward(x)...);
+ new (static_cast(p)) T(boost::forward(x)...);
}
template
@@ -673,7 +747,7 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::has_construct::value>::type
construct(Alloc&, T* p, T const& x)
{
- new ((void*) p) T(x);
+ new (static_cast(p)) T(x);
}
template
@@ -715,7 +789,7 @@ namespace boost { namespace unordered { namespace detail {
boost::is_same::value,
void*>::type = 0)
{
- new ((void*) p) T(x);
+ new (static_cast(p)) T(x);
}
template
@@ -843,7 +917,7 @@ namespace boost { namespace unordered { namespace detail { namespace func {
}
template
- inline void destroy_value_impl(Alloc& alloc, T* x) {
+ inline void call_destroy(Alloc& alloc, T* x) {
boost::unordered::detail::allocator_traits::destroy(alloc, x);
}
@@ -858,7 +932,7 @@ namespace boost { namespace unordered { namespace detail { namespace func {
}
template
- inline void destroy_value_impl(Alloc&, T* x) {
+ inline void call_destroy(Alloc&, T* x) {
boost::unordered::detail::func::destroy(x);
}
@@ -880,7 +954,7 @@ namespace boost { namespace unordered { namespace detail { namespace func {
}
template
- inline void destroy_value_impl(Alloc&, T* x) {
+ inline void call_destroy(Alloc&, T* x) {
boost::unordered::detail::func::destroy(x);
}
@@ -1021,7 +1095,7 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
// For the standard pair constructor.
template
- inline void construct_value_impl(Alloc& alloc, T* address,
+ inline void construct_from_args(Alloc& alloc, T* address,
BOOST_FWD_REF(Args)... args)
{
boost::unordered::detail::func::call_construct(alloc,
@@ -1036,32 +1110,36 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
template
inline typename enable_if, void>::type
- construct_value_impl(Alloc& alloc, std::pair* address,
+ construct_from_args(Alloc& alloc, std::pair* address,
BOOST_FWD_REF(A0), BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
{
boost::unordered::detail::func::construct_from_tuple(alloc,
- boost::addressof(address->first), boost::forward(a1));
+ boost::unordered::detail::func::const_cast_pointer(
+ boost::addressof(address->first)),
+ boost::forward(a1));
boost::unordered::detail::func::construct_from_tuple(alloc,
- boost::addressof(address->second), boost::forward(a2));
+ boost::unordered::detail::func::const_cast_pointer(
+ boost::addressof(address->second)),
+ boost::forward(a2));
}
#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
-////////////////////////////////////////////////////////////////////////////////
-// Construct from emplace_args
+ ////////////////////////////////////////////////////////////////////////////
+ // Construct from emplace_args
// Explicitly write out first three overloads for the sake of sane
// error messages.
template
- inline void construct_value_impl(Alloc&, T* address,
+ inline void construct_from_args(Alloc&, T* address,
emplace_args1 const& args)
{
new((void*) address) T(boost::forward(args.a0));
}
template
- inline void construct_value_impl(Alloc&, T* address,
+ inline void construct_from_args(Alloc&, T* address,
emplace_args2 const& args)
{
new((void*) address) T(
@@ -1071,7 +1149,7 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
}
template
- inline void construct_value_impl(Alloc&, T* address,
+ inline void construct_from_args(Alloc&, T* address,
emplace_args3 const& args)
{
new((void*) address) T(
@@ -1088,7 +1166,7 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
typename Alloc, typename T, \
BOOST_PP_ENUM_PARAMS_Z(z, num_params, typename A) \
> \
- inline void construct_value_impl(Alloc&, T* address, \
+ inline void construct_from_args(Alloc&, T* address, \
boost::unordered::detail::BOOST_PP_CAT(emplace_args,num_params) < \
BOOST_PP_ENUM_PARAMS_Z(z, num_params, A) \
> const& args) \
@@ -1107,14 +1185,18 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
template
- inline void construct_value_impl(Alloc& alloc, std::pair* address,
+ inline void construct_from_args(Alloc& alloc, std::pair* address,
boost::unordered::detail::emplace_args3 const& args,
typename enable_if, void*>::type = 0)
{
boost::unordered::detail::func::construct_from_tuple(alloc,
- boost::addressof(address->first), args.a1);
+ boost::unordered::detail::func::const_cast_pointer(
+ boost::addressof(address->first)),
+ args.a1);
boost::unordered::detail::func::construct_from_tuple(alloc,
- boost::addressof(address->second), args.a2);
+ boost::unordered::detail::func::const_cast_pointer(
+ boost::addressof(address->second)),
+ args.a2);
}
#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
@@ -1165,7 +1247,7 @@ namespace boost { namespace unordered { namespace detail {
BOOST_ASSERT(!node_);
node_ = p;
node_constructed_ = true;
- boost::unordered::detail::func::destroy_value_impl(alloc_,
+ boost::unordered::detail::func::call_destroy(alloc_,
node_->value_ptr());
}
@@ -1231,7 +1313,7 @@ namespace boost { namespace unordered { namespace detail {
node_tmp::~node_tmp()
{
if (node_) {
- boost::unordered::detail::func::destroy_value_impl(alloc_,
+ boost::unordered::detail::func::call_destroy(alloc_,
node_->value_ptr());
boost::unordered::detail::func::destroy(
boost::addressof(*node_));
@@ -1242,23 +1324,23 @@ namespace boost { namespace unordered { namespace detail {
namespace boost { namespace unordered { namespace detail { namespace func {
- // Some nicer construct_value functions, might try to
+ // Some nicer construct_node functions, might try to
// improve implementation later.
template
inline typename boost::unordered::detail::allocator_traits::pointer
- construct_value_generic(Alloc& alloc, BOOST_UNORDERED_EMPLACE_ARGS)
+ construct_node_from_args(Alloc& alloc, BOOST_UNORDERED_EMPLACE_ARGS)
{
node_constructor a(alloc);
a.create_node();
- construct_value_impl(alloc, a.node_->value_ptr(),
+ construct_from_args(alloc, a.node_->value_ptr(),
BOOST_UNORDERED_EMPLACE_FORWARD);
return a.release();
}
template
inline typename boost::unordered::detail::allocator_traits::pointer
- construct_value(Alloc& alloc, BOOST_FWD_REF(U) x)
+ construct_node(Alloc& alloc, BOOST_FWD_REF(U) x)
{
node_constructor a(alloc);
a.create_node();
@@ -1271,29 +1353,33 @@ namespace boost { namespace unordered { namespace detail { namespace func {
// constructor for std::piece_construct with std::tuple.
template
inline typename boost::unordered::detail::allocator_traits::pointer
- construct_pair(Alloc& alloc, BOOST_FWD_REF(Key) k)
+ construct_node_pair(Alloc& alloc, BOOST_FWD_REF(Key) k)
{
node_constructor a(alloc);
a.create_node();
- boost::unordered::detail::func::call_construct(
- alloc, boost::addressof(a.node_->value_ptr()->first),
+ boost::unordered::detail::func::call_construct(alloc,
+ boost::unordered::detail::func::const_cast_pointer(
+ boost::addressof(a.node_->value_ptr()->first)),
boost::forward(k));
- boost::unordered::detail::func::call_construct(
- alloc, boost::addressof(a.node_->value_ptr()->second));
+ boost::unordered::detail::func::call_construct(alloc,
+ boost::unordered::detail::func::const_cast_pointer(
+ boost::addressof(a.node_->value_ptr()->second)));
return a.release();
}
template
inline typename boost::unordered::detail::allocator_traits::pointer
- construct_pair(Alloc& alloc, BOOST_FWD_REF(Key) k, BOOST_FWD_REF(Mapped) m)
+ construct_node_pair(Alloc& alloc, BOOST_FWD_REF(Key) k, BOOST_FWD_REF(Mapped) m)
{
node_constructor a(alloc);
a.create_node();
- boost::unordered::detail::func::call_construct(
- alloc, boost::addressof(a.node_->value_ptr()->first),
+ boost::unordered::detail::func::call_construct(alloc,
+ boost::unordered::detail::func::const_cast_pointer(
+ boost::addressof(a.node_->value_ptr()->first)),
boost::forward(k));
- boost::unordered::detail::func::call_construct(
- alloc, boost::addressof(a.node_->value_ptr()->second),
+ boost::unordered::detail::func::call_construct(alloc,
+ boost::unordered::detail::func::const_cast_pointer(
+ boost::addressof(a.node_->value_ptr()->second)),
boost::forward(m));
return a.release();
}
diff --git a/include/boost/unordered/detail/buckets.hpp b/include/boost/unordered/detail/buckets.hpp
index 31e1ee59..bd9a5cbb 100644
--- a/include/boost/unordered/detail/buckets.hpp
+++ b/include/boost/unordered/detail/buckets.hpp
@@ -61,7 +61,6 @@ namespace boost { namespace unordered { namespace iterator_detail {
private:
#endif
typedef typename Node::node_pointer node_pointer;
- typedef boost::unordered::iterator_detail::iterator n_iterator;
node_pointer ptr_;
std::size_t bucket_;
std::size_t bucket_count_;
@@ -72,8 +71,8 @@ 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
- : ptr_(x.node_), bucket_(b), bucket_count_(c) {}
+ l_iterator(node_pointer n, std::size_t b, std::size_t c) BOOST_NOEXCEPT
+ : ptr_(n), bucket_(b), bucket_count_(c) {}
value_type& operator*() const {
return ptr_->value();
@@ -120,7 +119,6 @@ namespace boost { namespace unordered { namespace iterator_detail {
private:
typedef typename Node::node_pointer node_pointer;
- typedef boost::unordered::iterator_detail::iterator n_iterator;
node_pointer ptr_;
std::size_t bucket_;
std::size_t bucket_count_;
@@ -131,8 +129,8 @@ 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 :
- ptr_(x.node_), bucket_(b), bucket_count_(c) {}
+ cl_iterator(node_pointer n, std::size_t b, std::size_t c) BOOST_NOEXCEPT :
+ ptr_(n), bucket_(b), bucket_count_(c) {}
cl_iterator(boost::unordered::iterator_detail::l_iterator<
Node, Policy> const& x) BOOST_NOEXCEPT :
@@ -186,10 +184,6 @@ namespace boost { namespace unordered { namespace iterator_detail {
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template
friend struct boost::unordered::iterator_detail::c_iterator;
- template
- friend struct boost::unordered::iterator_detail::l_iterator;
- template
- friend struct boost::unordered::iterator_detail::cl_iterator;
template
friend struct boost::unordered::detail::table;
template
@@ -359,21 +353,6 @@ namespace boost { namespace unordered { namespace detail {
template
inline node_pointer copy_of(T const& v) {
- if (nodes_) {
- node_tmp a(pop_node(), constructor_.alloc_);
- a.node_->value() = v;
- return a.release();
- }
- else {
- constructor_.create_node();
- boost::unordered::detail::func::call_construct(
- constructor_.alloc_, constructor_.node_->value_ptr(), v);
- return constructor_.release();
- }
- }
-
- template
- inline node_pointer copy_of(std::pair const& v) {
if (nodes_) {
constructor_.reclaim(pop_node());
}
@@ -387,22 +366,6 @@ namespace boost { namespace unordered { namespace detail {
template
inline node_pointer move_copy_of(T& v) {
- if (nodes_) {
- node_tmp a(pop_node(), constructor_.alloc_);
- a.node_->value() = boost::move(v);
- return a.release();
- }
- else {
- constructor_.create_node();
- boost::unordered::detail::func::call_construct(
- constructor_.alloc_, constructor_.node_->value_ptr(),
- boost::move(v));
- return constructor_.release();
- }
- }
-
- template
- inline node_pointer move_copy_of(std::pair& v) {
if (nodes_) {
constructor_.reclaim(pop_node());
}
@@ -428,7 +391,7 @@ namespace boost { namespace unordered { namespace detail {
node_pointer p = nodes_;
nodes_ = static_cast(p->next_);
- boost::unordered::detail::func::destroy_value_impl(constructor_.alloc_,
+ boost::unordered::detail::func::call_destroy(constructor_.alloc_,
p->value_ptr());
boost::unordered::detail::func::destroy(boost::addressof(*p));
node_allocator_traits::deallocate(constructor_.alloc_, p, 1);
diff --git a/include/boost/unordered/detail/equivalent.hpp b/include/boost/unordered/detail/equivalent.hpp
index 5835884a..618d3af9 100644
--- a/include/boost/unordered/detail/equivalent.hpp
+++ b/include/boost/unordered/detail/equivalent.hpp
@@ -110,9 +110,11 @@ namespace boost { namespace unordered { namespace detail {
template
struct pick_grouped_node
{
+ typedef typename boost::remove_const::type nonconst;
+
typedef boost::unordered::detail::allocator_traits<
typename boost::unordered::detail::rebind_wrap >::type
+ boost::unordered::detail::grouped_ptr_node >::type
> tentative_node_traits;
typedef boost::unordered::detail::allocator_traits<
@@ -120,7 +122,7 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::ptr_bucket >::type
> tentative_bucket_traits;
- typedef pick_grouped_node2 pick;
@@ -186,48 +188,58 @@ namespace boost { namespace unordered { namespace detail {
this->move_init(x);
}
+ // Node functions.
+
+ static inline node_pointer next_node(link_pointer n) {
+ return static_cast(n->next_);
+ }
+
+ static inline node_pointer next_group(node_pointer n) {
+ return static_cast(n->group_prev_->next_);
+ }
+
// Accessors
template
- iterator find_node_impl(
+ node_pointer find_node_impl(
std::size_t key_hash,
Key const& k,
Pred const& eq) const
{
std::size_t bucket_index = this->hash_to_bucket(key_hash);
- iterator n = this->begin(bucket_index);
+ node_pointer n = this->begin(bucket_index);
for (;;)
{
- if (!n.node_) return n;
+ if (!n) return n;
- std::size_t node_hash = n.node_->hash_;
+ std::size_t node_hash = n->hash_;
if (key_hash == node_hash)
{
- if (eq(k, this->get_key(*n)))
+ if (eq(k, this->get_key(n->value())))
return n;
}
else
{
if (this->hash_to_bucket(node_hash) != bucket_index)
- return iterator();
+ return node_pointer();
}
- n = iterator(n.node_->group_prev_->next_);
+ n = next_group(n);
}
}
std::size_t count(key_type const& k) const
{
- iterator n = this->find_node(k);
- if (!n.node_) return 0;
+ node_pointer n = this->find_node(k);
+ if (!n) return 0;
std::size_t x = 0;
- node_pointer it = n.node_;
+ node_pointer it = n;
do {
it = it->group_prev_;
++x;
- } while(it != n.node_);
+ } while(it != n);
return x;
}
@@ -235,9 +247,8 @@ namespace boost { namespace unordered { namespace detail {
std::pair
equal_range(key_type const& k) const
{
- iterator n = this->find_node(k);
- return std::make_pair(
- n, n.node_ ? iterator(n.node_->group_prev_->next_) : n);
+ node_pointer n = this->find_node(k);
+ return std::make_pair(iterator(n), iterator(n ? next_group(n) : n));
}
// Equality
@@ -246,12 +257,12 @@ namespace boost { namespace unordered { namespace detail {
{
if(this->size_ != other.size_) return false;
- for(iterator n1 = this->begin(); n1.node_;)
+ for(node_pointer n1 = this->begin(); n1;)
{
- iterator n2 = other.find_matching_node(n1);
- if (!n2.node_) return false;
- iterator end1(n1.node_->group_prev_->next_);
- iterator end2(n2.node_->group_prev_->next_);
+ node_pointer n2 = other.find_node(other.get_key(n1->value()));
+ if (!n2) return false;
+ node_pointer end1 = next_group(n1);
+ node_pointer end2 = next_group(n2);
if (!group_equals(n1, end1, n2, end2)) return false;
n1 = end1;
}
@@ -259,24 +270,24 @@ namespace boost { namespace unordered { namespace detail {
return true;
}
- static bool group_equals(iterator n1, iterator end1,
- iterator n2, iterator end2)
+ static bool group_equals(node_pointer n1, node_pointer end1,
+ node_pointer n2, node_pointer end2)
{
for(;;)
{
- if (*n1 != *n2) break;
+ if (n1->value() != n2->value()) break;
- ++n1;
- ++n2;
+ n1 = next_node(n1);
+ n2 = next_node(n2);
if (n1 == end1) return n2 == end2;
if (n2 == end2) return false;
}
- for(iterator n1a = n1, n2a = n2;;)
+ for(node_pointer n1a = n1, n2a = n2;;)
{
- ++n1a;
- ++n2a;
+ n1a = next_node(n1a);
+ n2a = next_node(n2a);
if (n1a == end1)
{
@@ -287,35 +298,34 @@ namespace boost { namespace unordered { namespace detail {
if (n2a == end2) return false;
}
- iterator start = n1;
- for(;n1 != end1; ++n1)
+ node_pointer start = n1;
+ for(;n1 != end1; n1 = next_node(n1))
{
- value_type const& v = *n1;
- if (find(start, n1, v)) continue;
- std::size_t matches = count_equal(n2, end2, v);
- if (!matches) return false;
- iterator next = n1;
- ++next;
- if (matches != 1 + count_equal(next, end1, v)) return false;
+ value_type const& v = n1->value();
+ if (!find(start, n1, v)) {
+ std::size_t matches = count_equal(n2, end2, v);
+ if (!matches) return false;
+ if (matches != 1 + count_equal(next_node(n1), end1, v)) return false;
+ }
}
return true;
}
- static bool find(iterator n, iterator end, value_type const& v)
+ static bool find(node_pointer n, node_pointer end, value_type const& v)
{
- for(;n != end; ++n)
- if (*n == v)
+ for(;n != end; n = next_node(n))
+ if (n->value() == v)
return true;
return false;
}
- static std::size_t count_equal(iterator n, iterator end,
+ static std::size_t count_equal(node_pointer n, node_pointer end,
value_type const& v)
{
std::size_t count = 0;
- for(;n != end; ++n)
- if (*n == v) ++count;
+ for(;n != end; n = next_node(n))
+ if (n->value() == v) ++count;
return count;
}
@@ -334,17 +344,17 @@ namespace boost { namespace unordered { namespace detail {
pos->group_prev_ = n;
}
- inline iterator add_node(
+ inline node_pointer add_node(
node_pointer n,
std::size_t key_hash,
- iterator pos)
+ node_pointer pos)
{
n->hash_ = key_hash;
- if (pos.node_) {
- this->add_to_node_group(n, pos.node_);
+ if (pos) {
+ this->add_to_node_group(n, pos);
if (n->next_) {
std::size_t next_bucket = this->hash_to_bucket(
- static_cast(n->next_)->hash_);
+ next_node(n)->hash_);
if (next_bucket != this->hash_to_bucket(key_hash)) {
this->get_bucket(next_bucket)->next_ = n;
}
@@ -360,7 +370,7 @@ namespace boost { namespace unordered { namespace detail {
if (start_node->next_) {
this->get_bucket(this->hash_to_bucket(
- static_cast(start_node->next_)->hash_
+ next_node(start_node)->hash_
))->next_ = n;
}
@@ -375,10 +385,10 @@ namespace boost { namespace unordered { namespace detail {
}
}
++this->size_;
- return iterator(n);
+ return n;
}
- inline iterator add_using_hint(
+ inline node_pointer add_using_hint(
node_pointer n,
node_pointer hint)
{
@@ -386,13 +396,13 @@ namespace boost { namespace unordered { namespace detail {
this->add_to_node_group(n, hint);
if (n->next_ != hint && n->next_) {
std::size_t next_bucket = this->hash_to_bucket(
- static_cast(n->next_)->hash_);
+ next_node(n)->hash_);
if (next_bucket != this->hash_to_bucket(n->hash_)) {
this->get_bucket(next_bucket)->next_ = n;
}
}
++this->size_;
- return iterator(n);
+ return n;
}
@@ -432,7 +442,7 @@ namespace boost { namespace unordered { namespace detail {
iterator emplace(BOOST_UNORDERED_EMPLACE_ARGS)
{
return iterator(emplace_impl(
- boost::unordered::detail::func::construct_value_generic(
+ boost::unordered::detail::func::construct_node_from_args(
this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD)));
}
@@ -440,7 +450,7 @@ namespace boost { namespace unordered { namespace detail {
iterator emplace_hint(c_iterator hint, BOOST_UNORDERED_EMPLACE_ARGS)
{
return iterator(emplace_hint_impl(hint,
- boost::unordered::detail::func::construct_value_generic(
+ boost::unordered::detail::func::construct_node_from_args(
this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD)));
}
@@ -449,9 +459,9 @@ namespace boost { namespace unordered { namespace detail {
node_tmp a(n, this->node_alloc());
key_type const& k = this->get_key(a.node_->value());
std::size_t key_hash = this->hash(k);
- iterator position = this->find_node(key_hash, k);
+ node_pointer position = this->find_node(key_hash, k);
this->reserve_for_insert(this->size_ + 1);
- return this->add_node(a.release(), key_hash, position);
+ return iterator(this->add_node(a.release(), key_hash, position));
}
iterator emplace_hint_impl(c_iterator hint, node_pointer n)
@@ -460,13 +470,13 @@ namespace boost { namespace unordered { namespace detail {
key_type const& k = this->get_key(a.node_->value());
if (hint.node_ && this->key_eq()(k, this->get_key(*hint))) {
this->reserve_for_insert(this->size_ + 1);
- return this->add_using_hint(a.release(), hint.node_);
+ return iterator(this->add_using_hint(a.release(), hint.node_));
}
else {
std::size_t key_hash = this->hash(k);
- iterator position = this->find_node(key_hash, k);
+ node_pointer position = this->find_node(key_hash, k);
this->reserve_for_insert(this->size_ + 1);
- return this->add_node(a.release(), key_hash, position);
+ return iterator(this->add_node(a.release(), key_hash, position));
}
}
@@ -475,7 +485,7 @@ namespace boost { namespace unordered { namespace detail {
node_tmp a(n, this->node_alloc());
key_type const& k = this->get_key(a.node_->value());
std::size_t key_hash = this->hash(k);
- iterator position = this->find_node(key_hash, k);
+ node_pointer position = this->find_node(key_hash, k);
this->add_node(a.release(), key_hash, position);
}
@@ -493,7 +503,7 @@ namespace boost { namespace unordered { namespace detail {
std::size_t distance = static_cast(std::distance(i, j));
if(distance == 1) {
emplace_impl(
- boost::unordered::detail::func::construct_value(
+ boost::unordered::detail::func::construct_node(
this->node_alloc(), *i));
}
else {
@@ -502,7 +512,7 @@ namespace boost { namespace unordered { namespace detail {
for (; i != j; ++i) {
emplace_impl_no_rehash(
- boost::unordered::detail::func::construct_value(
+ boost::unordered::detail::func::construct_node(
this->node_alloc(), *i));
}
}
@@ -514,7 +524,7 @@ namespace boost { namespace unordered { namespace detail {
{
for (; i != j; ++i) {
emplace_impl(
- boost::unordered::detail::func::construct_value(
+ boost::unordered::detail::func::construct_node(
this->node_alloc(), *i));
}
}
@@ -533,21 +543,21 @@ namespace boost { namespace unordered { namespace detail {
link_pointer prev = this->get_previous_start(bucket_index);
if (!prev) return 0;
+ node_pointer first_node;
+
for (;;)
{
if (!prev->next_) return 0;
- std::size_t node_hash =
- static_cast(prev->next_)->hash_;
+ first_node = next_node(prev);
+ std::size_t node_hash = first_node->hash_;
if (this->hash_to_bucket(node_hash) != bucket_index)
return 0;
if (node_hash == key_hash &&
- this->key_eq()(k, this->get_key(
- static_cast(prev->next_)->value())))
+ this->key_eq()(k, this->get_key(first_node->value())))
break;
- prev = static_cast(prev->next_)->group_prev_;
+ prev = first_node->group_prev_;
}
- node_pointer first_node = static_cast(prev->next_);
link_pointer end = first_node->group_prev_->next_;
std::size_t deleted_count = this->delete_nodes(prev, end);
@@ -558,10 +568,9 @@ namespace boost { namespace unordered { namespace detail {
iterator erase(c_iterator r)
{
BOOST_ASSERT(r.node_);
- iterator next(r.node_);
- ++next;
- erase_nodes(r.node_, next.node_);
- return next;
+ node_pointer next = next_node(r.node_);
+ erase_nodes(r.node_, next);
+ return iterator(next);
}
iterator erase_range(c_iterator r1, c_iterator r2)
@@ -586,13 +595,12 @@ namespace boost { namespace unordered { namespace detail {
if (!prev) {
prev = this->get_previous_start(bucket_index);
while (prev->next_ != i)
- prev = static_cast(prev->next_)->group_prev_;
+ prev = next_node(prev)->group_prev_;
}
// Delete the nodes.
do {
- link_pointer group_end =
- static_cast(prev->next_)->group_prev_->next_;
+ link_pointer group_end = next_group(next_node(prev));
this->delete_nodes(prev, group_end);
bucket_index = this->fix_bucket(bucket_index, prev);
} while(prev->next_ != j);
@@ -632,17 +640,17 @@ namespace boost { namespace unordered { namespace detail {
void copy_buckets(table const& src) {
this->create_buckets(this->bucket_count_);
- for (iterator n = src.begin(); n.node_;) {
- std::size_t key_hash = n.node_->hash_;
- iterator group_end(n.node_->group_prev_->next_);
- iterator pos = this->add_node(
- boost::unordered::detail::func::construct_value(
- this->node_alloc(), *n), key_hash, iterator());
- for (++n; n != group_end; ++n)
+ for (node_pointer n = src.begin(); n;) {
+ std::size_t key_hash = n->hash_;
+ node_pointer group_end(next_group(n));
+ node_pointer pos = this->add_node(
+ boost::unordered::detail::func::construct_node(
+ this->node_alloc(), n->value()), key_hash, node_pointer());
+ for (n = next_node(n); n != group_end; n = next_node(n))
{
this->add_node(
- boost::unordered::detail::func::construct_value(
- this->node_alloc(), *n), key_hash, pos);
+ boost::unordered::detail::func::construct_node(
+ this->node_alloc(), n->value()), key_hash, pos);
}
}
}
@@ -650,43 +658,43 @@ namespace boost { namespace unordered { namespace detail {
void move_buckets(table const& src) {
this->create_buckets(this->bucket_count_);
- for (iterator n = src.begin(); n.node_;) {
- std::size_t key_hash = n.node_->hash_;
- iterator group_end(n.node_->group_prev_->next_);
- iterator pos = this->add_node(
- boost::unordered::detail::func::construct_value(
- this->node_alloc(), boost::move(*n)), key_hash, iterator());
- for (++n; n != group_end; ++n)
+ for (node_pointer n = src.begin(); n;) {
+ std::size_t key_hash = n->hash_;
+ node_pointer group_end(next_group(n));
+ node_pointer pos = this->add_node(
+ boost::unordered::detail::func::construct_node(
+ this->node_alloc(), boost::move(n->value())), key_hash, node_pointer());
+ for (n = next_node(n); n != group_end; n = next_node(n))
{
this->add_node(
- boost::unordered::detail::func::construct_value(
- this->node_alloc(), boost::move(*n)), key_hash, pos);
+ boost::unordered::detail::func::construct_node(
+ this->node_alloc(), boost::move(n->value())), key_hash, pos);
}
}
}
void assign_buckets(table const& src) {
node_holder holder(*this);
- for (iterator n = src.begin(); n.node_;) {
- std::size_t key_hash = n.node_->hash_;
- iterator group_end(n.node_->group_prev_->next_);
- iterator pos = this->add_node(holder.copy_of(*n), key_hash, iterator());
- for (++n; n != group_end; ++n)
+ for (node_pointer n = src.begin(); n;) {
+ std::size_t key_hash = n->hash_;
+ node_pointer group_end(next_group(n));
+ node_pointer pos = this->add_node(holder.copy_of(n->value()), key_hash, node_pointer());
+ for (n = next_node(n); n != group_end; n = next_node(n))
{
- this->add_node(holder.copy_of(*n), key_hash, pos);
+ this->add_node(holder.copy_of(n->value()), key_hash, pos);
}
}
}
void move_assign_buckets(table& src) {
node_holder holder(*this);
- for (iterator n = src.begin(); n.node_;) {
- std::size_t key_hash = n.node_->hash_;
- iterator group_end(n.node_->group_prev_->next_);
- iterator pos = this->add_node(holder.move_copy_of(*n), key_hash, iterator());
- for (++n; n != group_end; ++n)
+ for (node_pointer n = src.begin(); n;) {
+ std::size_t key_hash = n->hash_;
+ node_pointer group_end(next_group(n));
+ node_pointer pos = this->add_node(holder.move_copy_of(n->value()), key_hash, node_pointer());
+ for (n = next_node(n); n != group_end; n = next_node(n))
{
- this->add_node(holder.move_copy_of(*n), key_hash, pos);
+ this->add_node(holder.move_copy_of(n->value()), key_hash, pos);
}
}
}
@@ -699,8 +707,7 @@ namespace boost { namespace unordered { namespace detail {
this->create_buckets(num_buckets);
link_pointer prev = this->get_previous_start();
while (prev->next_)
- prev = place_in_bucket(*this, prev,
- static_cast(prev->next_)->group_prev_);
+ prev = place_in_bucket(*this, prev, next_node(prev)->group_prev_);
}
// Iterate through the nodes placing them in the correct buckets.
diff --git a/include/boost/unordered/detail/map.hpp b/include/boost/unordered/detail/map.hpp
index 22f8e633..14253ef4 100644
--- a/include/boost/unordered/detail/map.hpp
+++ b/include/boost/unordered/detail/map.hpp
@@ -31,6 +31,15 @@ namespace boost { namespace unordered { namespace detail {
extractor;
typedef typename boost::unordered::detail::pick_policy::type policy;
+
+ typedef boost::unordered::iterator_detail::
+ iterator iterator;
+ typedef boost::unordered::iterator_detail::
+ c_iterator c_iterator;
+ typedef boost::unordered::iterator_detail::
+ l_iterator l_iterator;
+ typedef boost::unordered::iterator_detail::
+ cl_iterator cl_iterator;
};
template
@@ -56,6 +65,15 @@ namespace boost { namespace unordered { namespace detail {
extractor;
typedef typename boost::unordered::detail::pick_policy::type policy;
+
+ typedef boost::unordered::iterator_detail::
+ iterator iterator;
+ typedef boost::unordered::iterator_detail::
+ c_iterator c_iterator;
+ typedef boost::unordered::iterator_detail::
+ l_iterator l_iterator;
+ typedef boost::unordered::iterator_detail::
+ cl_iterator cl_iterator;
};
}}}
diff --git a/include/boost/unordered/detail/set.hpp b/include/boost/unordered/detail/set.hpp
index 3ed9dde0..ccbc4c99 100644
--- a/include/boost/unordered/detail/set.hpp
+++ b/include/boost/unordered/detail/set.hpp
@@ -29,6 +29,15 @@ namespace boost { namespace unordered { namespace detail {
typedef boost::unordered::detail::set_extractor extractor;
typedef typename boost::unordered::detail::pick_policy::type policy;
+
+ typedef boost::unordered::iterator_detail::
+ c_iterator iterator;
+ typedef boost::unordered::iterator_detail::
+ c_iterator c_iterator;
+ typedef boost::unordered::iterator_detail::
+ cl_iterator l_iterator;
+ typedef boost::unordered::iterator_detail::
+ cl_iterator cl_iterator;
};
template
@@ -53,5 +62,14 @@ namespace boost { namespace unordered { namespace detail {
typedef boost::unordered::detail::set_extractor extractor;
typedef typename boost::unordered::detail::pick_policy::type policy;
+
+ typedef boost::unordered::iterator_detail::
+ c_iterator iterator;
+ typedef boost::unordered::iterator_detail::
+ c_iterator c_iterator;
+ typedef boost::unordered::iterator_detail::
+ cl_iterator l_iterator;
+ typedef boost::unordered::iterator_detail::
+ cl_iterator cl_iterator;
};
}}}
diff --git a/include/boost/unordered/detail/table.hpp b/include/boost/unordered/detail/table.hpp
index 6ae1d73e..9657c763 100644
--- a/include/boost/unordered/detail/table.hpp
+++ b/include/boost/unordered/detail/table.hpp
@@ -84,6 +84,10 @@ namespace boost { namespace unordered { namespace detail {
typedef typename Types::table table_impl;
typedef typename Types::link_pointer link_pointer;
typedef typename Types::policy policy;
+ typedef typename Types::iterator iterator;
+ typedef typename Types::c_iterator c_iterator;
+ typedef typename Types::l_iterator l_iterator;
+ typedef typename Types::cl_iterator cl_iterator;
typedef boost::unordered::detail::functions<
typename Types::hasher,
@@ -110,15 +114,6 @@ namespace boost { namespace unordered { namespace detail {
typedef boost::unordered::detail::node_tmp
node_tmp;
- typedef boost::unordered::iterator_detail::
- iterator iterator;
- typedef boost::unordered::iterator_detail::
- c_iterator c_iterator;
- typedef boost::unordered::iterator_detail::
- l_iterator l_iterator;
- typedef boost::unordered::iterator_detail::
- cl_iterator cl_iterator;
-
////////////////////////////////////////////////////////////////////////
// Members
@@ -130,6 +125,13 @@ namespace boost { namespace unordered { namespace detail {
std::size_t max_load_;
bucket_pointer buckets_;
+ ////////////////////////////////////////////////////////////////////////
+ // Node functions
+
+ static inline node_pointer next_node(link_pointer n) {
+ return static_cast(n->next_);
+ }
+
////////////////////////////////////////////////////////////////////////
// Data access
@@ -176,16 +178,16 @@ namespace boost { namespace unordered { namespace detail {
return get_bucket(bucket_index)->next_;
}
- iterator begin() const
+ node_pointer begin() const
{
- return size_ ? iterator(get_previous_start()->next_) : iterator();
+ return size_ ? next_node(get_previous_start()) : node_pointer();
}
- iterator begin(std::size_t bucket_index) const
+ node_pointer begin(std::size_t bucket_index) const
{
- if (!size_) return iterator();
+ if (!size_) return node_pointer();
link_pointer prev = get_previous_start(bucket_index);
- return prev ? iterator(prev->next_) : iterator();
+ return prev ? next_node(prev) : node_pointer();
}
std::size_t hash_to_bucket(std::size_t hash_value) const
@@ -202,14 +204,14 @@ namespace boost { namespace unordered { namespace detail {
std::size_t bucket_size(std::size_t index) const
{
- iterator it = begin(index);
- if (!it.node_) return 0;
+ node_pointer n = begin(index);
+ if (!n) return 0;
std::size_t count = 0;
- while(it.node_ && hash_to_bucket(it.node_->hash_) == index)
+ while(n && hash_to_bucket(n->hash_) == index)
{
++count;
- ++it;
+ n = next_node(n);
}
return count;
@@ -462,7 +464,7 @@ namespace boost { namespace unordered { namespace detail {
node_pointer n = static_cast(prev->next_);
prev->next_ = n->next_;
- boost::unordered::detail::func::destroy_value_impl(node_alloc(),
+ boost::unordered::detail::func::call_destroy(node_alloc(),
n->value_ptr());
boost::unordered::detail::func::destroy(boost::addressof(*n));
node_allocator_traits::deallocate(node_alloc(), n, 1);
@@ -698,7 +700,7 @@ namespace boost { namespace unordered { namespace detail {
// Find Node
template
- iterator generic_find_node(
+ node_pointer generic_find_node(
Key const& k,
Hash const& hf,
Pred const& eq) const
@@ -707,7 +709,7 @@ namespace boost { namespace unordered { namespace detail {
find_node_impl(policy::apply_hash(hf, k), k, eq);
}
- iterator find_node(
+ node_pointer find_node(
std::size_t key_hash,
key_type const& k) const
{
@@ -715,23 +717,12 @@ namespace boost { namespace unordered { namespace detail {
find_node_impl(key_hash, k, this->key_eq());
}
- iterator find_node(key_type const& k) const
+ node_pointer find_node(key_type const& k) const
{
return static_cast(this)->
find_node_impl(hash(k), k, this->key_eq());
}
- iterator find_matching_node(iterator n) const
- {
- // TODO: Does this apply to C++11?
- //
- // For some stupid reason, I decided to support equality comparison
- // when different hash functions are used. So I can't use the hash
- // value from the node here.
-
- return find_node(get_key(*n));
- }
-
// Reserve and rehash
void reserve_for_insert(std::size_t);
diff --git a/include/boost/unordered/detail/unique.hpp b/include/boost/unordered/detail/unique.hpp
index db397980..e77b4c14 100644
--- a/include/boost/unordered/detail/unique.hpp
+++ b/include/boost/unordered/detail/unique.hpp
@@ -106,9 +106,11 @@ namespace boost { namespace unordered { namespace detail {
template
struct pick_node
{
+ typedef typename boost::remove_const::type nonconst;
+
typedef boost::unordered::detail::allocator_traits<
typename boost::unordered::detail::rebind_wrap >::type
+ boost::unordered::detail::ptr_node >::type
> tentative_node_traits;
typedef boost::unordered::detail::allocator_traits<
@@ -116,7 +118,7 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::ptr_bucket >::type
> tentative_bucket_traits;
- typedef pick_node2 pick;
@@ -184,47 +186,53 @@ namespace boost { namespace unordered { namespace detail {
this->move_init(x);
}
+ // Node functions.
+
+ static inline node_pointer next_node(link_pointer n) {
+ return static_cast(n->next_);
+ }
+
// Accessors
template
- iterator find_node_impl(
+ node_pointer find_node_impl(
std::size_t key_hash,
Key const& k,
Pred const& eq) const
{
std::size_t bucket_index = this->hash_to_bucket(key_hash);
- iterator n = this->begin(bucket_index);
+ node_pointer n = this->begin(bucket_index);
for (;;)
{
- if (!n.node_) return n;
+ if (!n) return n;
- std::size_t node_hash = n.node_->hash_;
+ std::size_t node_hash = n->hash_;
if (key_hash == node_hash)
{
- if (eq(k, this->get_key(*n)))
+ if (eq(k, this->get_key(n->value())))
return n;
}
else
{
if (this->hash_to_bucket(node_hash) != bucket_index)
- return iterator();
+ return node_pointer();
}
- ++n;
+ n = next_node(n);
}
}
std::size_t count(key_type const& k) const
{
- return this->find_node(k).node_ ? 1 : 0;
+ return this->find_node(k) ? 1 : 0;
}
value_type& at(key_type const& k) const
{
if (this->size_) {
- iterator it = this->find_node(k);
- if (it.node_) return *it;
+ node_pointer n = this->find_node(k);
+ if (n) return n->value();
}
boost::throw_exception(
@@ -234,10 +242,8 @@ namespace boost { namespace unordered { namespace detail {
std::pair
equal_range(key_type const& k) const
{
- iterator n = this->find_node(k);
- iterator n2 = n;
- if (n2.node_) ++n2;
- return std::make_pair(n, n2);
+ node_pointer n = this->find_node(k);
+ return std::make_pair(iterator(n), iterator(n ? next_node(n) : n));
}
// equals
@@ -246,11 +252,11 @@ namespace boost { namespace unordered { namespace detail {
{
if(this->size_ != other.size_) return false;
- for(iterator n1 = this->begin(); n1.node_; ++n1)
+ for(node_pointer n1 = this->begin(); n1; n1 = next_node(n1))
{
- iterator n2 = other.find_matching_node(n1);
+ node_pointer n2 = other.find_node(other.get_key(n1->value()));
- if (!n2.node_ || *n1 != *n2)
+ if (!n2 || n1->value() != n2->value())
return false;
}
@@ -259,7 +265,7 @@ namespace boost { namespace unordered { namespace detail {
// Emplace/Insert
- inline iterator add_node(
+ inline node_pointer add_node(
node_pointer n,
std::size_t key_hash)
{
@@ -273,7 +279,7 @@ namespace boost { namespace unordered { namespace detail {
if (start_node->next_) {
this->get_bucket(this->hash_to_bucket(
- static_cast(start_node->next_)->hash_)
+ next_node(start_node)->hash_)
)->next_ = n;
}
@@ -288,10 +294,10 @@ namespace boost { namespace unordered { namespace detail {
}
++this->size_;
- return iterator(n);
+ return n;
}
- inline iterator resize_and_add_node(node_pointer n, std::size_t key_hash)
+ inline node_pointer resize_and_add_node(node_pointer n, std::size_t key_hash)
{
node_tmp b(n, this->node_alloc());
this->reserve_for_insert(this->size_ + 1);
@@ -301,11 +307,15 @@ namespace boost { namespace unordered { namespace detail {
value_type& operator[](key_type const& k)
{
std::size_t key_hash = this->hash(k);
- iterator pos = this->find_node(key_hash, k);
- if (pos.node_) return *pos;
- return *this->resize_and_add_node(
- boost::unordered::detail::func::construct_pair(this->node_alloc(), k),
- key_hash);
+ node_pointer pos = this->find_node(key_hash, k);
+ if (pos) {
+ return pos->value();
+ }
+ else {
+ return this->resize_and_add_node(
+ boost::unordered::detail::func::construct_node_pair(this->node_alloc(), k),
+ key_hash)->value();
+ }
}
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
@@ -314,7 +324,7 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::please_ignore_this_overload> const&)
{
BOOST_ASSERT(false);
- return emplace_return(this->begin(), false);
+ return emplace_return(iterator(), false);
}
iterator emplace_hint(c_iterator,
@@ -322,21 +332,21 @@ namespace boost { namespace unordered { namespace detail {
boost::unordered::detail::please_ignore_this_overload> const&)
{
BOOST_ASSERT(false);
- return this->begin();
+ return iterator();
}
# else
emplace_return emplace(
boost::unordered::detail::please_ignore_this_overload const&)
{
BOOST_ASSERT(false);
- return emplace_return(this->begin(), false);
+ return emplace_return(iterator(), false);
}
iterator emplace_hint(c_iterator,
boost::unordered::detail::please_ignore_this_overload const&)
{
BOOST_ASSERT(false);
- return this->begin();
+ return iterator();
}
# endif
#endif
@@ -403,16 +413,16 @@ namespace boost { namespace unordered { namespace detail {
BOOST_UNORDERED_EMPLACE_ARGS)
{
std::size_t key_hash = this->hash(k);
- iterator pos = this->find_node(key_hash, k);
- if (pos.node_) {
- return emplace_return(pos, false);
+ node_pointer pos = this->find_node(key_hash, k);
+ if (pos) {
+ return emplace_return(iterator(pos), false);
}
else {
return emplace_return(
- this->resize_and_add_node(
- boost::unordered::detail::func::construct_value_generic(
+ iterator(this->resize_and_add_node(
+ boost::unordered::detail::func::construct_node_from_args(
this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD),
- key_hash),
+ key_hash)),
true);
}
}
@@ -422,7 +432,7 @@ namespace boost { namespace unordered { namespace detail {
BOOST_UNORDERED_EMPLACE_ARGS)
{
node_tmp b(
- boost::unordered::detail::func::construct_value_generic(
+ boost::unordered::detail::func::construct_node_from_args(
this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD),
this->node_alloc());
key_type const& k = this->get_key(b.node_->value());
@@ -430,12 +440,12 @@ namespace boost { namespace unordered { namespace detail {
return iterator(hint.node_);
}
std::size_t key_hash = this->hash(k);
- iterator pos = this->find_node(key_hash, k);
- if (pos.node_) {
- return pos;
+ node_pointer pos = this->find_node(key_hash, k);
+ if (pos) {
+ return iterator(pos);
}
else {
- return this->resize_and_add_node(b.release(), key_hash);
+ return iterator(this->resize_and_add_node(b.release(), key_hash));
}
}
@@ -443,18 +453,18 @@ namespace boost { namespace unordered { namespace detail {
emplace_return emplace_impl(no_key, BOOST_UNORDERED_EMPLACE_ARGS)
{
node_tmp b(
- boost::unordered::detail::func::construct_value_generic(
+ boost::unordered::detail::func::construct_node_from_args(
this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD),
this->node_alloc());
key_type const& k = this->get_key(b.node_->value());
std::size_t key_hash = this->hash(k);
- iterator pos = this->find_node(key_hash, k);
- if (pos.node_) {
- return emplace_return(pos, false);
+ node_pointer pos = this->find_node(key_hash, k);
+ if (pos) {
+ return emplace_return(iterator(pos), false);
}
else {
return emplace_return(
- this->resize_and_add_node(b.release(), key_hash),
+ iterator(this->resize_and_add_node(b.release(), key_hash)),
true);
}
}
@@ -495,11 +505,11 @@ namespace boost { namespace unordered { namespace detail {
{
// No side effects in this initial code
std::size_t key_hash = this->hash(k);
- iterator pos = this->find_node(key_hash, k);
+ node_pointer pos = this->find_node(key_hash, k);
- if (!pos.node_) {
+ if (!pos) {
node_tmp b(
- boost::unordered::detail::func::construct_value(this->node_alloc(), *i),
+ boost::unordered::detail::func::construct_node(this->node_alloc(), *i),
this->node_alloc());
if(this->size_ + 1 > this->max_load_)
this->reserve_for_insert(this->size_ +
@@ -521,9 +531,9 @@ namespace boost { namespace unordered { namespace detail {
key_type const& k = this->get_key(b.node_->value());
std::size_t key_hash = this->hash(k);
- iterator pos = this->find_node(key_hash, k);
+ node_pointer pos = this->find_node(key_hash, k);
- if (pos.node_) {
+ if (pos) {
a.reclaim(b.release());
}
else {
@@ -552,18 +562,17 @@ namespace boost { namespace unordered { namespace detail {
for (;;)
{
if (!prev->next_) return 0;
- std::size_t node_hash =
- static_cast(prev->next_)->hash_;
+ std::size_t node_hash = next_node(prev)->hash_;
if (this->hash_to_bucket(node_hash) != bucket_index)
return 0;
if (node_hash == key_hash &&
this->key_eq()(k, this->get_key(
- static_cast(prev->next_)->value())))
+ next_node(prev)->value())))
break;
prev = prev->next_;
}
- link_pointer end = static_cast(prev->next_)->next_;
+ link_pointer end = next_node(prev)->next_;
std::size_t deleted_count = this->delete_nodes(prev, end);
this->fix_bucket(bucket_index, prev);
@@ -573,10 +582,9 @@ namespace boost { namespace unordered { namespace detail {
iterator erase(c_iterator r)
{
BOOST_ASSERT(r.node_);
- iterator next(r.node_);
- ++next;
- erase_nodes(r.node_, next.node_);
- return next;
+ node_pointer next = next_node(r.node_);
+ erase_nodes(r.node_, next);
+ return iterator(next);
}
iterator erase_range(c_iterator r1, c_iterator r2)
@@ -607,36 +615,36 @@ namespace boost { namespace unordered { namespace detail {
void copy_buckets(table const& src) {
this->create_buckets(this->bucket_count_);
- for(iterator n = src.begin(); n.node_; ++n) {
+ for(node_pointer n = src.begin(); n; n = next_node(n)) {
this->add_node(
- boost::unordered::detail::func::construct_value(
- this->node_alloc(), *n), n.node_->hash_);
+ boost::unordered::detail::func::construct_node(
+ this->node_alloc(), n->value()), n->hash_);
}
}
void move_buckets(table const& src) {
this->create_buckets(this->bucket_count_);
- for(iterator n = src.begin(); n.node_; ++n) {
+ for(node_pointer n = src.begin(); n; n = next_node(n)) {
this->add_node(
- boost::unordered::detail::func::construct_value(
- this->node_alloc(), boost::move(*n)), n.node_->hash_);
+ boost::unordered::detail::func::construct_node(
+ this->node_alloc(), boost::move(n->value())), n->hash_);
}
}
void assign_buckets(table const& src)
{
node_holder holder(*this);
- for(iterator n = src.begin(); n.node_; ++n) {
- this->add_node(holder.copy_of(*n), n.node_->hash_);
+ for(node_pointer n = src.begin(); n; n = next_node(n)) {
+ this->add_node(holder.copy_of(n->value()), n->hash_);
}
}
void move_assign_buckets(table& src)
{
node_holder holder(*this);
- for(iterator n = src.begin(); n.node_; ++n) {
- this->add_node(holder.move_copy_of(*n), n.node_->hash_);
+ for(node_pointer n = src.begin(); n; n = next_node(n)) {
+ this->add_node(holder.move_copy_of(n->value()), n->hash_);
}
}
@@ -655,7 +663,7 @@ namespace boost { namespace unordered { namespace detail {
// pre: prev->next_ is not null.
static link_pointer place_in_bucket(table& dst, link_pointer prev)
{
- node_pointer n = static_cast(prev->next_);
+ node_pointer n = next_node(prev);
bucket_pointer b = dst.get_bucket(dst.hash_to_bucket(n->hash_));
if (!b->next_) {
diff --git a/include/boost/unordered/unordered_map.hpp b/include/boost/unordered/unordered_map.hpp
index fc6fbe0e..101b1c1c 100644
--- a/include/boost/unordered/unordered_map.hpp
+++ b/include/boost/unordered/unordered_map.hpp
@@ -82,12 +82,23 @@ namespace unordered
// constructors
+ unordered_map();
+
explicit unordered_map(
- size_type = boost::unordered::detail::default_bucket_count,
+ size_type,
const hasher& = hasher(),
const key_equal& = key_equal(),
const allocator_type& = allocator_type());
+ explicit unordered_map(
+ size_type,
+ const allocator_type&);
+
+ explicit unordered_map(
+ size_type,
+ const hasher&,
+ const allocator_type&);
+
explicit unordered_map(allocator_type const&);
template
@@ -108,11 +119,25 @@ namespace unordered
const key_equal&,
const allocator_type&);
+ template
+ unordered_map(
+ InputIt, InputIt,
+ size_type,
+ const hasher&,
+ const allocator_type&);
+
+ template
+ unordered_map(
+ InputIt, InputIt,
+ size_type,
+ const allocator_type&);
+
// copy/move constructors
unordered_map(unordered_map const&);
unordered_map(unordered_map const&, allocator_type const&);
+ unordered_map(BOOST_RV_REF(unordered_map), allocator_type const&);
#if defined(BOOST_UNORDERED_USE_MOVE)
unordered_map(BOOST_RV_REF(unordered_map) other)
@@ -128,10 +153,6 @@ namespace unordered
}
#endif
-#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
- unordered_map(unordered_map&&, allocator_type const&);
-#endif
-
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_map(
std::initializer_list,
@@ -139,6 +160,15 @@ namespace unordered
const hasher& = hasher(),
const key_equal&l = key_equal(),
const allocator_type& = allocator_type());
+ unordered_map(
+ std::initializer_list,
+ size_type,
+ const hasher&,
+ const allocator_type&);
+ unordered_map(
+ std::initializer_list,
+ size_type,
+ const allocator_type&);
#endif
// Destructor
@@ -202,12 +232,12 @@ namespace unordered
iterator begin() BOOST_NOEXCEPT
{
- return table_.begin();
+ return iterator(table_.begin());
}
const_iterator begin() const BOOST_NOEXCEPT
{
- return table_.begin();
+ return const_iterator(table_.begin());
}
iterator end() BOOST_NOEXCEPT
@@ -222,7 +252,7 @@ namespace unordered
const_iterator cbegin() const BOOST_NOEXCEPT
{
- return table_.begin();
+ return const_iterator(table_.begin());
}
const_iterator cend() const BOOST_NOEXCEPT
@@ -565,12 +595,23 @@ namespace unordered
// constructors
+ unordered_multimap();
+
explicit unordered_multimap(
- size_type = boost::unordered::detail::default_bucket_count,
+ size_type,
const hasher& = hasher(),
const key_equal& = key_equal(),
const allocator_type& = allocator_type());
+ explicit unordered_multimap(
+ size_type,
+ const allocator_type&);
+
+ explicit unordered_multimap(
+ size_type,
+ const hasher&,
+ const allocator_type&);
+
explicit unordered_multimap(allocator_type const&);
template
@@ -591,11 +632,25 @@ namespace unordered
const key_equal&,
const allocator_type&);
+ template
+ unordered_multimap(
+ InputIt, InputIt,
+ size_type,
+ const hasher&,
+ const allocator_type&);
+
+ template
+ unordered_multimap(
+ InputIt, InputIt,
+ size_type,
+ const allocator_type&);
+
// copy/move constructors
unordered_multimap(unordered_multimap const&);
unordered_multimap(unordered_multimap const&, allocator_type const&);
+ unordered_multimap(BOOST_RV_REF(unordered_multimap), allocator_type const&);
#if defined(BOOST_UNORDERED_USE_MOVE)
unordered_multimap(BOOST_RV_REF(unordered_multimap) other)
@@ -611,10 +666,6 @@ namespace unordered
}
#endif
-#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
- unordered_multimap(unordered_multimap&&, allocator_type const&);
-#endif
-
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
unordered_multimap(
std::initializer_list,
@@ -622,6 +673,15 @@ namespace unordered
const hasher& = hasher(),
const key_equal&l = key_equal(),
const allocator_type& = allocator_type());
+ unordered_multimap(
+ std::initializer_list,
+ size_type,
+ const hasher&,
+ const allocator_type&);
+ unordered_multimap(
+ std::initializer_list,
+ size_type,
+ const allocator_type&);
#endif
// Destructor
@@ -686,12 +746,12 @@ namespace unordered
iterator begin() BOOST_NOEXCEPT
{
- return table_.begin();
+ return iterator(table_.begin());
}
const_iterator begin() const BOOST_NOEXCEPT
{
- return table_.begin();
+ return const_iterator(table_.begin());
}
iterator end() BOOST_NOEXCEPT
@@ -706,7 +766,7 @@ namespace unordered
const_iterator cbegin() const BOOST_NOEXCEPT
{
- return table_.begin();
+ return const_iterator(table_.begin());
}
const_iterator cend() const BOOST_NOEXCEPT
@@ -1002,6 +1062,13 @@ namespace unordered
////////////////////////////////////////////////////////////////////////////////
+ template
+ unordered_map::unordered_map()
+ : table_(boost::unordered::detail::default_bucket_count, hasher(),
+ key_equal(), allocator_type())
+ {
+ }
+
template
unordered_map::unordered_map(
size_type n, const hasher &hf, const key_equal &eql,
@@ -1010,6 +1077,20 @@ namespace unordered
{
}
+ template
+ unordered_map::unordered_map(
+ size_type n, const allocator_type &a)
+ : table_(n, hasher(), key_equal(), a)
+ {
+ }
+
+ template
+ unordered_map::unordered_map(
+ size_type n, const hasher &hf, const allocator_type &a)
+ : table_(n, hf, key_equal(), a)
+ {
+ }
+
template
unordered_map::unordered_map(allocator_type const& a)
: table_(boost::unordered::detail::default_bucket_count,
@@ -1059,6 +1140,31 @@ namespace unordered
table_.insert_range(f, l);
}
+ template
+ template
+ unordered_map::unordered_map(
+ InputIt f, InputIt l,
+ size_type n,
+ const hasher &hf,
+ const allocator_type &a)
+ : table_(boost::unordered::detail::initial_size(f, l, n),
+ hf, key_equal(), a)
+ {
+ table_.insert_range(f, l);
+ }
+
+ template
+ template
+ unordered_map::unordered_map(
+ InputIt f, InputIt l,
+ size_type n,
+ const allocator_type &a)
+ : table_(boost::unordered::detail::initial_size(f, l, n),
+ hasher(), key_equal(), a)
+ {
+ table_.insert_range(f, l);
+ }
+
template
unordered_map::~unordered_map() BOOST_NOEXCEPT {}
@@ -1069,17 +1175,13 @@ namespace unordered
{
}
-#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
-
template
unordered_map::unordered_map(
- unordered_map&& other, allocator_type const& a)
+ BOOST_RV_REF(unordered_map) other, allocator_type const& a)
: table_(other.table_, a, boost::unordered::detail::move_tag())
{
}
-#endif
-
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template
@@ -1094,6 +1196,30 @@ namespace unordered
table_.insert_range(list.begin(), list.end());
}
+ template
+ unordered_map::unordered_map(
+ std::initializer_list list, size_type n,
+ const hasher &hf, const allocator_type &a)
+ : table_(
+ boost::unordered::detail::initial_size(
+ list.begin(), list.end(), n),
+ hf, key_equal(), a)
+ {
+ table_.insert_range(list.begin(), list.end());
+ }
+
+ template
+ unordered_map::unordered_map(
+ std::initializer_list list, size_type n,
+ const allocator_type &a)
+ : table_(
+ boost::unordered::detail::initial_size(
+ list.begin(), list.end(), n),
+ hasher(), key_equal(), a)
+ {
+ table_.insert_range(list.begin(), list.end());
+ }
+
template
unordered_map& unordered_map::operator=(
std::initializer_list list)
@@ -1208,14 +1334,14 @@ namespace unordered
typename unordered_map::iterator
unordered_map::find(const key_type& k)
{
- return table_.find_node(k);
+ return iterator(table_.find_node(k));
}
template
typename unordered_map::const_iterator
unordered_map::find(const key_type& k) const
{
- return table_.find_node(k);
+ return const_iterator(table_.find_node(k));
}
template
@@ -1227,7 +1353,7 @@ namespace unordered
CompatibleHash const& hash,
CompatiblePredicate const& eq)
{
- return table_.generic_find_node(k, hash, eq);
+ return iterator(table_.generic_find_node(k, hash, eq));
}
template
@@ -1239,7 +1365,7 @@ namespace unordered
CompatibleHash const& hash,
CompatiblePredicate const& eq) const
{
- return table_.generic_find_node(k, hash, eq);
+ return const_iterator(table_.generic_find_node(k, hash, eq));
}
template
@@ -1335,6 +1461,13 @@ namespace unordered
////////////////////////////////////////////////////////////////////////////////
+ template
+ unordered_multimap::unordered_multimap()
+ : table_(boost::unordered::detail::default_bucket_count, hasher(),
+ key_equal(), allocator_type())
+ {
+ }
+
template
unordered_multimap::unordered_multimap(
size_type n, const hasher &hf, const key_equal &eql,
@@ -1343,6 +1476,20 @@ namespace unordered
{
}
+ template
+ unordered_multimap::unordered_multimap(
+ size_type n, const allocator_type &a)
+ : table_(n, hasher(), key_equal(), a)
+ {
+ }
+
+ template
+ unordered_multimap::unordered_multimap(
+ size_type n, const hasher &hf, const allocator_type &a)
+ : table_(n, hf, key_equal(), a)
+ {
+ }
+
template
unordered_multimap::unordered_multimap(allocator_type const& a)
: table_(boost::unordered::detail::default_bucket_count,
@@ -1392,6 +1539,31 @@ namespace unordered
table_.insert_range(f, l);
}
+ template
+ template
+ unordered_multimap::unordered_multimap(
+ InputIt f, InputIt l,
+ size_type n,
+ const hasher &hf,
+ const allocator_type &a)
+ : table_(boost::unordered::detail::initial_size(f, l, n),
+ hf, key_equal(), a)
+ {
+ table_.insert_range(f, l);
+ }
+
+ template
+ template
+ unordered_multimap::unordered_multimap(
+ InputIt f, InputIt l,
+ size_type n,
+ const allocator_type &a)
+ : table_(boost::unordered::detail::initial_size(f, l, n),
+ hasher(), key_equal(), a)
+ {
+ table_.insert_range(f, l);
+ }
+
template
unordered_multimap::~unordered_multimap() BOOST_NOEXCEPT {}
@@ -1402,17 +1574,13 @@ namespace unordered
{
}
-#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
-
template
unordered_multimap::unordered_multimap(
- unordered_multimap&& other, allocator_type const& a)
+ BOOST_RV_REF(unordered_multimap) other, allocator_type const& a)
: table_(other.table_, a, boost::unordered::detail::move_tag())
{
}
-#endif
-
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
template
@@ -1427,6 +1595,30 @@ namespace unordered
table_.insert_range(list.begin(), list.end());
}
+ template