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 + unordered_multimap::unordered_multimap( + 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_multimap::unordered_multimap( + 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_multimap& unordered_multimap::operator=( std::initializer_list list) @@ -1520,14 +1712,14 @@ namespace unordered typename unordered_multimap::iterator unordered_multimap::find(const key_type& k) { - return table_.find_node(k); + return iterator(table_.find_node(k)); } template typename unordered_multimap::const_iterator unordered_multimap::find(const key_type& k) const { - return table_.find_node(k); + return const_iterator(table_.find_node(k)); } template @@ -1539,7 +1731,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 @@ -1551,7 +1743,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 diff --git a/include/boost/unordered/unordered_set.hpp b/include/boost/unordered/unordered_set.hpp index aa9911bc..77cd87e0 100644 --- a/include/boost/unordered/unordered_set.hpp +++ b/include/boost/unordered/unordered_set.hpp @@ -67,9 +67,9 @@ namespace unordered typedef std::ptrdiff_t difference_type; typedef typename table::cl_iterator const_local_iterator; - typedef typename table::cl_iterator local_iterator; + typedef typename table::l_iterator local_iterator; typedef typename table::c_iterator const_iterator; - typedef typename table::c_iterator iterator; + typedef typename table::iterator iterator; private: @@ -79,12 +79,23 @@ namespace unordered // constructors + unordered_set(); + explicit unordered_set( - 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_set( + size_type, + const allocator_type&); + + explicit unordered_set( + size_type, + const hasher&, + const allocator_type&); + explicit unordered_set(allocator_type const&); template @@ -105,11 +116,25 @@ namespace unordered const key_equal&, const allocator_type&); + template + unordered_set( + InputIt, InputIt, + size_type, + const hasher&, + const allocator_type&); + + template + unordered_set( + InputIt, InputIt, + size_type, + const allocator_type&); + // copy/move constructors unordered_set(unordered_set const&); unordered_set(unordered_set const&, allocator_type const&); + unordered_set(BOOST_RV_REF(unordered_set), allocator_type const&); #if defined(BOOST_UNORDERED_USE_MOVE) unordered_set(BOOST_RV_REF(unordered_set) other) @@ -125,10 +150,6 @@ namespace unordered } #endif -#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - unordered_set(unordered_set&&, allocator_type const&); -#endif - #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) unordered_set( std::initializer_list, @@ -136,6 +157,15 @@ namespace unordered const hasher& = hasher(), const key_equal&l = key_equal(), const allocator_type& = allocator_type()); + unordered_set( + std::initializer_list, + size_type, + const hasher&, + const allocator_type&); + unordered_set( + std::initializer_list, + size_type, + const allocator_type&); #endif // Destructor @@ -199,12 +229,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 @@ -219,7 +249,7 @@ namespace unordered const_iterator cbegin() const BOOST_NOEXCEPT { - return table_.begin(); + return const_iterator(table_.begin()); } const_iterator cend() const BOOST_NOEXCEPT @@ -536,9 +566,9 @@ namespace unordered typedef std::ptrdiff_t difference_type; typedef typename table::cl_iterator const_local_iterator; - typedef typename table::cl_iterator local_iterator; + typedef typename table::l_iterator local_iterator; typedef typename table::c_iterator const_iterator; - typedef typename table::c_iterator iterator; + typedef typename table::iterator iterator; private: @@ -548,12 +578,23 @@ namespace unordered // constructors + unordered_multiset(); + explicit unordered_multiset( - 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_multiset( + size_type, + const allocator_type&); + + explicit unordered_multiset( + size_type, + const hasher&, + const allocator_type&); + explicit unordered_multiset(allocator_type const&); template @@ -574,11 +615,25 @@ namespace unordered const key_equal&, const allocator_type&); + template + unordered_multiset( + InputIt, InputIt, + size_type, + const hasher&, + const allocator_type&); + + template + unordered_multiset( + InputIt, InputIt, + size_type, + const allocator_type&); + // copy/move constructors unordered_multiset(unordered_multiset const&); unordered_multiset(unordered_multiset const&, allocator_type const&); + unordered_multiset(BOOST_RV_REF(unordered_multiset), allocator_type const&); #if defined(BOOST_UNORDERED_USE_MOVE) unordered_multiset(BOOST_RV_REF(unordered_multiset) other) @@ -594,10 +649,6 @@ namespace unordered } #endif -#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - unordered_multiset(unordered_multiset&&, allocator_type const&); -#endif - #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) unordered_multiset( std::initializer_list, @@ -605,6 +656,15 @@ namespace unordered const hasher& = hasher(), const key_equal&l = key_equal(), const allocator_type& = allocator_type()); + unordered_multiset( + std::initializer_list, + size_type, + const hasher&, + const allocator_type&); + unordered_multiset( + std::initializer_list, + size_type, + const allocator_type&); #endif // Destructor @@ -976,6 +1036,13 @@ namespace unordered //////////////////////////////////////////////////////////////////////////////// + template + unordered_set::unordered_set() + : table_(boost::unordered::detail::default_bucket_count, hasher(), + key_equal(), allocator_type()) + { + } + template unordered_set::unordered_set( size_type n, const hasher &hf, const key_equal &eql, @@ -984,6 +1051,20 @@ namespace unordered { } + template + unordered_set::unordered_set( + size_type n, const allocator_type &a) + : table_(n, hasher(), key_equal(), a) + { + } + + template + unordered_set::unordered_set( + size_type n, const hasher &hf, const allocator_type &a) + : table_(n, hf, key_equal(), a) + { + } + template unordered_set::unordered_set(allocator_type const& a) : table_(boost::unordered::detail::default_bucket_count, @@ -1033,6 +1114,31 @@ namespace unordered table_.insert_range(f, l); } + template + template + unordered_set::unordered_set( + 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_set::unordered_set( + 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_set::~unordered_set() BOOST_NOEXCEPT {} @@ -1043,17 +1149,13 @@ namespace unordered { } -#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - template unordered_set::unordered_set( - unordered_set&& other, allocator_type const& a) + BOOST_RV_REF(unordered_set) other, allocator_type const& a) : table_(other.table_, a, boost::unordered::detail::move_tag()) { } -#endif - #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) template @@ -1068,6 +1170,30 @@ namespace unordered table_.insert_range(list.begin(), list.end()); } + template + unordered_set::unordered_set( + 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_set::unordered_set( + 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_set& unordered_set::operator=( std::initializer_list list) @@ -1161,7 +1287,7 @@ namespace unordered typename unordered_set::const_iterator unordered_set::find(const key_type& k) const { - return table_.find_node(k); + return const_iterator(table_.find_node(k)); } template @@ -1173,7 +1299,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 @@ -1260,6 +1386,13 @@ namespace unordered //////////////////////////////////////////////////////////////////////////////// + template + unordered_multiset::unordered_multiset() + : table_(boost::unordered::detail::default_bucket_count, hasher(), + key_equal(), allocator_type()) + { + } + template unordered_multiset::unordered_multiset( size_type n, const hasher &hf, const key_equal &eql, @@ -1268,6 +1401,20 @@ namespace unordered { } + template + unordered_multiset::unordered_multiset( + size_type n, const allocator_type &a) + : table_(n, hasher(), key_equal(), a) + { + } + + template + unordered_multiset::unordered_multiset( + size_type n, const hasher &hf, const allocator_type &a) + : table_(n, hf, key_equal(), a) + { + } + template unordered_multiset::unordered_multiset(allocator_type const& a) : table_(boost::unordered::detail::default_bucket_count, @@ -1317,6 +1464,31 @@ namespace unordered table_.insert_range(f, l); } + template + template + unordered_multiset::unordered_multiset( + 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_multiset::unordered_multiset( + 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_multiset::~unordered_multiset() BOOST_NOEXCEPT {} @@ -1327,17 +1499,13 @@ namespace unordered { } -#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - template unordered_multiset::unordered_multiset( - unordered_multiset&& other, allocator_type const& a) + BOOST_RV_REF(unordered_multiset) other, allocator_type const& a) : table_(other.table_, a, boost::unordered::detail::move_tag()) { } -#endif - #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) template @@ -1352,6 +1520,30 @@ namespace unordered table_.insert_range(list.begin(), list.end()); } + template + unordered_multiset::unordered_multiset( + 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_multiset::unordered_multiset( + 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_multiset& unordered_multiset::operator=( std::initializer_list list) @@ -1445,7 +1637,7 @@ namespace unordered typename unordered_multiset::const_iterator unordered_multiset::find(const key_type& k) const { - return table_.find_node(k); + return const_iterator(table_.find_node(k)); } template @@ -1457,7 +1649,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 diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index f2207f89..7cfa8d71 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -14,6 +14,7 @@ project unordered-test/unordered gcc:"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow" darwin:"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wconversion -Wfloat-equal -Wshadow" clang:"-pedantic -Wstrict-aliasing -fstrict-aliasing -Wextra -Wsign-promo -Wunused-parameter -Wsign-conversion -Wconversion -Wfloat-equal -Wshadow" + msvc:"/wd4494" ; #alias framework : /boost/test//boost_unit_test_framework ; @@ -27,6 +28,9 @@ test-suite unordered [ run unordered/minimal_allocator.cpp ] [ run unordered/compile_set.cpp ] [ run unordered/compile_map.cpp ] + [ run unordered/compile_map.cpp : : + : BOOST_UNORDERED_USE_ALLOCATOR_TRAITS=0 + : compile_map_unordered_allocator ] [ run unordered/noexcept_tests.cpp ] [ run unordered/link_test_1.cpp unordered/link_test_2.cpp ] [ run unordered/incomplete_test.cpp ] diff --git a/test/helpers/exception_test.hpp b/test/helpers/exception_test.hpp index c3aad5d5..d1bc1317 100644 --- a/test/helpers/exception_test.hpp +++ b/test/helpers/exception_test.hpp @@ -179,12 +179,13 @@ namespace test { class test_runner { Test const& test_; + bool exception_in_check_; test_runner(test_runner const&); test_runner& operator=(test_runner const&); public: - test_runner(Test const& t) : test_(t) {} - void operator()() const { + test_runner(Test const& t) : test_(t), exception_in_check_(false) {} + void run() { DISABLE_EXCEPTIONS; test::scope = ""; BOOST_DEDUCED_TYPENAME Test::data_type x(test_.init()); @@ -199,14 +200,24 @@ namespace test { >(&Test::run, test_, x, strong); } catch(...) { - call_ignore_extra_parameters< - Test, - BOOST_DEDUCED_TYPENAME Test::data_type const, - BOOST_DEDUCED_TYPENAME Test::strong_type const - >(&Test::check, test_, constant(x), constant(strong)); + try { + DISABLE_EXCEPTIONS; + call_ignore_extra_parameters< + Test, + BOOST_DEDUCED_TYPENAME Test::data_type const, + BOOST_DEDUCED_TYPENAME Test::strong_type const + >(&Test::check, test_, constant(x), constant(strong)); + } catch(...) { + exception_in_check_ = true; + } throw; } } + void end() { + if (exception_in_check_) { + BOOST_ERROR("Unexcpected exception in test_runner check call."); + } + } }; // Quick exception testing based on lightweight test @@ -236,26 +247,30 @@ namespace test { iteration = 0; bool success = false; + char const* error_msg = 0; do { ++iteration; count = 0; try { - runner(); + runner.run(); success = true; } catch(test_failure) { - BOOST_ERROR("test_failure caught."); + error_msg = "test_failure caught."; break; } catch(test_exception) { continue; } catch(...) { - BOOST_ERROR("Unexpected exception."); + error_msg = "Unexpected exception."; break; } } while(!success); + + if (error_msg) { BOOST_ERROR(error_msg); } + runner.end(); } } } diff --git a/test/objects/cxx11_allocator.hpp b/test/objects/cxx11_allocator.hpp index 11f67808..8ace50c5 100644 --- a/test/objects/cxx11_allocator.hpp +++ b/test/objects/cxx11_allocator.hpp @@ -201,9 +201,11 @@ namespace test public move_allocator_base, Flags { +#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 402000) template struct rebind { typedef cxx11_allocator other; }; +#endif explicit cxx11_allocator(int t = 0) : cxx11_allocator_base(t) @@ -251,9 +253,11 @@ namespace test return tmp; } +#if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 402000) template struct rebind { typedef cxx11_allocator other; }; +#endif explicit cxx11_allocator(int t = 0) : cxx11_allocator_base(t) diff --git a/test/objects/minimal.hpp b/test/objects/minimal.hpp index b876aa20..d8e8a7eb 100644 --- a/test/objects/minimal.hpp +++ b/test/objects/minimal.hpp @@ -447,7 +447,7 @@ namespace minimal { public: typedef T value_type; - template struct rebind { typedef cxx11_allocator other; }; + //template struct rebind { typedef cxx11_allocator other; }; cxx11_allocator() {} template cxx11_allocator(cxx11_allocator const&) {} diff --git a/test/unordered/compile_map.cpp b/test/unordered/compile_map.cpp index ebd944ea..f42da0de 100644 --- a/test/unordered/compile_map.cpp +++ b/test/unordered/compile_map.cpp @@ -24,15 +24,15 @@ template class boost::unordered_map< std::equal_to, test::minimal::allocator > >; template class boost::unordered_multimap< - int, - int, + int const, + int const, boost::hash, std::equal_to, test::minimal::allocator > >; template class boost::unordered_map< - test::minimal::assignable, - test::minimal::default_assignable, + test::minimal::assignable const, + test::minimal::default_assignable const, test::minimal::hash, test::minimal::equal_to, test::minimal::allocator >; diff --git a/test/unordered/compile_set.cpp b/test/unordered/compile_set.cpp index 5c622902..a95ab007 100644 --- a/test/unordered/compile_set.cpp +++ b/test/unordered/compile_set.cpp @@ -23,13 +23,13 @@ template class boost::unordered_set< std::equal_to, test::minimal::allocator >; template class boost::unordered_multiset< - int, + int const, boost::hash, std::equal_to, test::minimal::allocator >; template class boost::unordered_set< - test::minimal::assignable, + test::minimal::assignable const, test::minimal::hash, test::minimal::equal_to, test::minimal::allocator >; diff --git a/test/unordered/compile_tests.hpp b/test/unordered/compile_tests.hpp index 7e475432..12581763 100644 --- a/test/unordered/compile_tests.hpp +++ b/test/unordered/compile_tests.hpp @@ -101,7 +101,18 @@ void container_test(X& r, T const&) static_cast( (std::numeric_limits::max)())); + // Constructors + // I don't test the runtime post-conditions here. + +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + // It isn't specified in the container requirements that the no argument + // constructor is implicit, but it is defined that way in the concrete + // container specification. + X u_implicit = {}; + sink(u_implicit); +#endif + X u; BOOST_TEST(u.size() == 0); BOOST_TEST(X().size() == 0); @@ -112,6 +123,8 @@ void container_test(X& r, T const&) sink(X(a)); X u2(a); X u3 = a; + X u4(rvalue(a_const)); + X u5 = rvalue(a_const); a.swap(b); boost::swap(a, b); @@ -121,12 +134,25 @@ void container_test(X& r, T const&) typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type; test::check_return_type::equals(a_const.get_allocator()); + + allocator_type m = a.get_allocator(); + sink(X(m)); + X c(m); + sink(X(a_const, m)); + X c2(a_const, m); + sink(X(rvalue(a_const), m)); + X c3(rvalue(a_const), m); // Avoid unused variable warnings: sink(u); sink(u2); sink(u3); + sink(u4); + sink(u5); + sink(c); + sink(c2); + sink(c3); } template @@ -247,6 +273,9 @@ void unordered_map_test(X& r, Key const& k, T const& v) r.emplace(k, v); r.emplace(k_lvalue, v_lvalue); r.emplace(rvalue(k), rvalue(v)); + + r.emplace(boost::unordered::piecewise_construct, + boost::make_tuple(k), boost::make_tuple(v)); } template @@ -355,6 +384,7 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq) typedef BOOST_DEDUCED_TYPENAME boost::iterator_reference::type const_local_iterator_reference; + typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type; BOOST_STATIC_ASSERT((boost::is_same::value)); //boost::function_requires >(); @@ -387,8 +417,13 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq) BOOST_STATIC_ASSERT((boost::is_same::value)); + X a; + allocator_type m = a.get_allocator(); + + // Constructors + X(10, hf, eq); - X a(10, hf, eq); + X a1(10, hf, eq); X(10, hf); X a2(10, hf); X(10); @@ -396,6 +431,15 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq) X(); X a4; + X(10, hf, eq, m); + X a1a(10, hf, eq, m); + X(10, hf, m); + X a2a(10, hf, m); + X(10, m); + X a3a(10, m); + (X(m)); + X a4a(m); + test::check_return_type::equals(a.erase(k)); const_iterator q1 = a.cbegin(), q2 = a.cend(); @@ -438,9 +482,14 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq) // Avoid unused variable warnings: sink(a); + sink(a1); sink(a2); sink(a3); sink(a4); + sink(a1a); + sink(a2a); + sink(a3a); + sink(a4a); } template @@ -450,14 +499,17 @@ void unordered_copyable_test(X& x, Key& k, T& t, Hash& hf, Pred& eq) typedef BOOST_DEDUCED_TYPENAME X::iterator iterator; typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator; + typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type; X a; + allocator_type m = a.get_allocator(); BOOST_DEDUCED_TYPENAME X::value_type* i = 0; BOOST_DEDUCED_TYPENAME X::value_type* j = 0; - X(i, j, 10, hf, eq); + // Constructors + X(i, j, 10, hf, eq); X a5(i, j, 10, hf, eq); X(i, j, 10, hf); X a6(i, j, 10, hf); @@ -466,11 +518,38 @@ void unordered_copyable_test(X& x, Key& k, T& t, Hash& hf, Pred& eq) X(i, j); X a8(i, j); + X(i, j, 10, hf, eq, m); + X a5a(i, j, 10, hf, eq, m); + X(i, j, 10, hf, m); + X a6a(i, j, 10, hf, m); + X(i, j, 10, m); + X a7a(i, j, 10, m); + + // Not specified for some reason (maybe ambiguity with another constructor?) + //X(i, j, m); + //X a8a(i, j, m); + //sink(a8a); + +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + std::size_t min_buckets = 10; + X({t}); + X({t}, min_buckets); + X({t}, min_buckets, hf); + X({t}, min_buckets, hf, eq); + //X({t}, m); + X({t}, min_buckets, m); + X({t}, min_buckets, hf, m); + X({t}, min_buckets, hf, eq, m); +#endif + X const b; sink(X(b)); X a9(b); a = b; + sink(X(b, m)); + X a9a(b, m); + const_iterator q = a.cbegin(); test::check_return_type::equals(a.insert(q, t)); @@ -502,6 +581,10 @@ void unordered_copyable_test(X& x, Key& k, T& t, Hash& hf, Pred& eq) sink(a7); sink(a8); sink(a9); + sink(a5a); + sink(a6a); + sink(a7a); + sink(a9a); } template @@ -511,6 +594,7 @@ void unordered_movable_test(X& x, Key& k, T& /* t */, Hash& hf, Pred& eq) typedef BOOST_DEDUCED_TYPENAME X::iterator iterator; typedef BOOST_DEDUCED_TYPENAME X::const_iterator const_iterator; + typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type; #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) X x1(rvalue_default()); @@ -519,9 +603,14 @@ void unordered_movable_test(X& x, Key& k, T& /* t */, Hash& hf, Pred& eq) x2 = boost::move(x1); #endif + X a; + allocator_type m = a.get_allocator(); + test::minimal::constructor_param* i = 0; test::minimal::constructor_param* j = 0; + // Constructors + X(i, j, 10, hf, eq); X a5(i, j, 10, hf, eq); X(i, j, 10, hf); @@ -531,7 +620,17 @@ void unordered_movable_test(X& x, Key& k, T& /* t */, Hash& hf, Pred& eq) X(i, j); X a8(i, j); - X a; + X(i, j, 10, hf, eq, m); + X a5a(i, j, 10, hf, eq, m); + X(i, j, 10, hf, m); + X a6a(i, j, 10, hf, m); + X(i, j, 10, m); + X a7a(i, j, 10, m); + + // Not specified for some reason (maybe ambiguity with another constructor?) + //X(i, j, m); + //X a8a(i, j, m); + //sink(a8a); const_iterator q = a.cbegin(); @@ -565,6 +664,9 @@ void unordered_movable_test(X& x, Key& k, T& /* t */, Hash& hf, Pred& eq) sink(a6); sink(a7); sink(a8); + sink(a5a); + sink(a6a); + sink(a7a); sink(a10); } diff --git a/test/unordered/insert_tests.cpp b/test/unordered/insert_tests.cpp index 3f13ea0f..a3384652 100644 --- a/test/unordered/insert_tests.cpp +++ b/test/unordered/insert_tests.cpp @@ -434,6 +434,7 @@ void move_emplace_tests(X*, test::random_generator generator) template void default_emplace_tests(X*, test::random_generator) { +#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100)) std::cerr<<"emplace() tests.\n"; bool is_unique = test::has_unique_keys::value; @@ -464,6 +465,7 @@ void default_emplace_tests(X*, test::random_generator) BOOST_TEST(x.count(test::get_key(y)) == (is_unique ? 1u : 2u)); BOOST_TEST(*x.equal_range(test::get_key(y)).first == y); +#endif } template