diff --git a/include/boost/unordered/detail/implementation.hpp b/include/boost/unordered/detail/implementation.hpp index 3b4c3a47..c08adf29 100644 --- a/include/boost/unordered/detail/implementation.hpp +++ b/include/boost/unordered/detail/implementation.hpp @@ -168,17 +168,16 @@ namespace detail { template struct table; template struct bucket; struct ptr_bucket; + template struct table_unique; template struct table_equiv; template struct unique_node; template struct ptr_node; -template struct table_unique; +template struct node_algo; template struct grouped_node; template struct grouped_ptr_node; -template struct table_equiv; -template struct node_algo; template struct grouped_node_algo; static const float minimum_max_load_factor = 1e-3f; diff --git a/include/boost/unordered/unordered_map.hpp b/include/boost/unordered/unordered_map.hpp index 75e8a02a..a991950c 100644 --- a/include/boost/unordered/unordered_map.hpp +++ b/include/boost/unordered/unordered_map.hpp @@ -85,59 +85,53 @@ template class unordered_map 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 unordered_map(InputIt, InputIt); - template - unordered_map(InputIt, InputIt, size_type, const hasher& = hasher(), - const key_equal& = key_equal()); - - template - unordered_map(InputIt, InputIt, size_type, const hasher&, 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(InputIt, InputIt, + size_type = boost::unordered::detail::default_bucket_count, + const hasher& = hasher(), const key_equal& = key_equal(), + const allocator_type& = allocator_type()); 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) +#if defined(BOOST_UNORDERED_USE_MOVE) || \ + !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) unordered_map(BOOST_RV_REF(unordered_map) other) BOOST_NOEXCEPT_IF(table::nothrow_move_constructible) : table_(other.table_, boost::unordered::detail::move_tag()) { } -#elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - unordered_map(unordered_map&& other) - BOOST_NOEXCEPT_IF(table::nothrow_move_constructible) - : table_(other.table_, boost::unordered::detail::move_tag()) - { - } #endif + explicit unordered_map(allocator_type const&); + + unordered_map(unordered_map const&, allocator_type const&); + + unordered_map(BOOST_RV_REF(unordered_map), allocator_type const&); + #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) unordered_map(std::initializer_list, size_type = boost::unordered::detail::default_bucket_count, 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&); +#endif + + explicit unordered_map(size_type, const allocator_type&); + + explicit unordered_map(size_type, const hasher&, const allocator_type&); + + template + unordered_map(InputIt, InputIt, size_type, const allocator_type&); + + template + unordered_map( + InputIt, InputIt, size_type, const hasher&, const allocator_type&); + +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) unordered_map( std::initializer_list, size_type, const allocator_type&); + + unordered_map(std::initializer_list, size_type, const hasher&, + const allocator_type&); #endif // Destructor @@ -154,6 +148,10 @@ template class unordered_map } unordered_map& operator=(BOOST_RV_REF(unordered_map) x) + // C++17 support: BOOST_NOEXCEPT_IF( + // value_allocator_traits::is_always_equal::value && + // is_nothrow_move_assignable_v && + // is_nothrow_move_assignable_v

) { table_.move_assign(x.table_); return *this; @@ -167,6 +165,10 @@ template class unordered_map #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) unordered_map& operator=(unordered_map&& x) + // C++17 support: BOOST_NOEXCEPT_IF( + // value_allocator_traits::is_always_equal::value && + // is_nothrow_move_assignable_v && + // is_nothrow_move_assignable_v

) { table_.move_assign(x.table_); return *this; @@ -183,14 +185,6 @@ template class unordered_map return table_.node_alloc(); } - // size and capacity - - bool empty() const BOOST_NOEXCEPT { return table_.size_ == 0; } - - size_type size() const BOOST_NOEXCEPT { return table_.size_; } - - size_type max_size() const BOOST_NOEXCEPT; - // iterators iterator begin() BOOST_NOEXCEPT { return iterator(table_.begin()); } @@ -211,64 +205,24 @@ template class unordered_map const_iterator cend() const BOOST_NOEXCEPT { return const_iterator(); } - // extract + // size and capacity - node_type extract(const_iterator position) - { - return node_type( - table_.extract_by_iterator(position), table_.node_alloc()); - } + bool empty() const BOOST_NOEXCEPT { return table_.size_ == 0; } - node_type extract(const key_type& k) - { - return node_type(table_.extract_by_key(k), table_.node_alloc()); - } + size_type size() const BOOST_NOEXCEPT { return table_.size_; } + + size_type max_size() const BOOST_NOEXCEPT; // emplace #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template std::pair emplace(BOOST_FWD_REF(Args)... args) { return table_.emplace(boost::forward(args)...); } - template - iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args) - { - return table_.emplace_hint(hint, boost::forward(args)...); - } - - template - std::pair try_emplace( - key_type const& k, BOOST_FWD_REF(Args)... args) - { - return table_.try_emplace_impl(k, boost::forward(args)...); - } - - template - iterator try_emplace( - const_iterator hint, key_type const& k, BOOST_FWD_REF(Args)... args) - { - return table_.try_emplace_hint_impl( - hint, k, boost::forward(args)...); - } - - template - std::pair try_emplace( - BOOST_RV_REF(key_type) k, BOOST_FWD_REF(Args)... args) - { - return table_.try_emplace_impl( - boost::move(k), boost::forward(args)...); - } - - template - iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k, - BOOST_FWD_REF(Args)... args) - { - return table_.try_emplace_hint_impl( - hint, boost::move(k), boost::forward(args)...); - } #else #if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100)) @@ -285,28 +239,8 @@ template class unordered_map return this->emplace(boost::move(v)); } - iterator emplace_hint(const_iterator hint, - boost::unordered::detail::empty_emplace = - boost::unordered::detail::empty_emplace(), - value_type v = value_type()) - { - return this->emplace_hint(hint, boost::move(v)); - } - #endif - template - std::pair try_emplace(BOOST_FWD_REF(Key) k) - { - return table_.try_emplace_impl(boost::forward(k)); - } - - template - iterator try_emplace(const_iterator hint, BOOST_FWD_REF(Key) k) - { - return table_.try_emplace_hint_impl(hint, boost::forward(k)); - } - template std::pair emplace(BOOST_FWD_REF(A0) a0) { @@ -314,50 +248,6 @@ template class unordered_map boost::forward(a0))); } - template - iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0) - { - return table_.emplace_hint( - hint, boost::unordered::detail::create_emplace_args( - boost::forward(a0))); - } - - template - std::pair try_emplace( - key_type const& k, BOOST_FWD_REF(A0) a0) - { - return table_.try_emplace_impl( - k, boost::unordered::detail::create_emplace_args( - boost::forward(a0))); - } - - template - iterator try_emplace( - const_iterator hint, key_type const& k, BOOST_FWD_REF(A0) a0) - { - return table_.try_emplace_hint_impl( - hint, k, boost::unordered::detail::create_emplace_args( - boost::forward(a0))); - } - - template - std::pair try_emplace( - BOOST_RV_REF(key_type) k, BOOST_FWD_REF(A0) a0) - { - return table_.try_emplace_impl( - boost::move(k), boost::unordered::detail::create_emplace_args( - boost::forward(a0))); - } - - template - iterator try_emplace( - const_iterator hint, BOOST_RV_REF(key_type) k, BOOST_FWD_REF(A0) a0) - { - return table_.try_emplace_hint_impl( - hint, boost::move(k), boost::unordered::detail::create_emplace_args( - boost::forward(a0))); - } - template std::pair emplace( BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) @@ -366,53 +256,6 @@ template class unordered_map boost::forward(a0), boost::forward(a1))); } - template - iterator emplace_hint( - const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) - { - return table_.emplace_hint( - hint, boost::unordered::detail::create_emplace_args( - boost::forward(a0), boost::forward(a1))); - } - - template - std::pair try_emplace( - key_type const& k, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) - { - return table_.try_emplace_impl( - k, boost::unordered::detail::create_emplace_args( - boost::forward(a0), boost::forward(a1))); - } - - template - iterator try_emplace(const_iterator hint, key_type const& k, - BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) - { - return table_.try_emplace_hint_impl( - hint, k, boost::unordered::detail::create_emplace_args( - boost::forward(a0), boost::forward(a1))); - } - - template - std::pair try_emplace( - BOOST_RV_REF(key_type) k, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) - { - return table_.try_emplace_impl( - boost::move(k), - boost::unordered::detail::create_emplace_args( - boost::forward(a0), boost::forward(a1))); - } - - template - iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k, - BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) - { - return table_.try_emplace_hint_impl( - hint, boost::move(k), - boost::unordered::detail::create_emplace_args( - boost::forward(a0), boost::forward(a1))); - } - template std::pair emplace( BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) @@ -422,6 +265,47 @@ template class unordered_map boost::forward(a2))); } +#endif + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + + template + iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args) + { + return table_.emplace_hint(hint, boost::forward(args)...); + } + +#else + +#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100)) + + iterator emplace_hint(const_iterator hint, + boost::unordered::detail::empty_emplace = + boost::unordered::detail::empty_emplace(), + value_type v = value_type()) + { + return this->emplace_hint(hint, boost::move(v)); + } + +#endif + + template + iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0) + { + return table_.emplace_hint( + hint, boost::unordered::detail::create_emplace_args( + boost::forward(a0))); + } + + template + iterator emplace_hint( + const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) + { + return table_.emplace_hint( + hint, boost::unordered::detail::create_emplace_args( + boost::forward(a0), boost::forward(a1))); + } + template iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) @@ -432,48 +316,9 @@ template class unordered_map boost::forward(a2))); } - template - std::pair try_emplace(key_type const& k, - BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) - { - return table_.try_emplace_impl( - k, boost::unordered::detail::create_emplace_args( - boost::forward(a0), boost::forward(a1), - boost::forward(a2))); - } +#endif - template - iterator try_emplace(const_iterator hint, key_type const& k, - BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) - { - return table_ - .try_emplace_impl_( - hint, k, boost::unordered::detail::create_emplace_args( - boost::forward(a0), boost::forward(a1), - boost::forward(a2))) - .first; - } - - template - std::pair try_emplace(BOOST_RV_REF(key_type) k, - BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) - { - return table_.try_emplace_impl( - boost::move(k), boost::unordered::detail::create_emplace_args( - boost::forward(a0), boost::forward(a1), - boost::forward(a2))); - } - - template - iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k, - BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) - { - return table_.try_emplace_hint_impl( - hint, boost::move(k), - boost::unordered::detail::create_emplace_args( - boost::forward(a0), boost::forward(a1), - boost::forward(a2))); - } +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) #define BOOST_UNORDERED_EMPLACE(z, n, _) \ template \ @@ -491,42 +336,6 @@ template class unordered_map return table_.emplace_hint( \ hint, boost::unordered::detail::create_emplace_args( \ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))); \ - } \ - \ - template \ - std::pair try_emplace( \ - key_type const& k, BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \ - { \ - return table_.try_emplace_impl( \ - k, boost::unordered::detail::create_emplace_args( \ - BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))); \ - } \ - \ - template \ - iterator try_emplace(const_iterator hint, key_type const& k, \ - BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \ - { \ - return table_.try_emplace_hint_impl(hint, k, \ - boost::unordered::detail::create_emplace_args(BOOST_PP_ENUM_##z( \ - n, BOOST_UNORDERED_CALL_FORWARD, a))); \ - } \ - \ - template \ - std::pair try_emplace(BOOST_RV_REF(key_type) k, \ - BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \ - { \ - return table_.try_emplace_impl(boost::move(k), \ - boost::unordered::detail::create_emplace_args(BOOST_PP_ENUM_##z( \ - n, BOOST_UNORDERED_CALL_FORWARD, a))); \ - } \ - \ - template \ - iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k, \ - BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \ - { \ - return table_.try_emplace_hint_impl(hint, boost::move(k), \ - boost::unordered::detail::create_emplace_args(BOOST_PP_ENUM_##z( \ - n, BOOST_UNORDERED_CALL_FORWARD, a))); \ } BOOST_PP_REPEAT_FROM_TO( @@ -574,43 +383,25 @@ template class unordered_map return this->emplace_hint(hint, boost::forward(obj)); } - template - std::pair insert_or_assign( - key_type const& k, BOOST_FWD_REF(M) obj) - { - return table_.insert_or_assign_impl(k, boost::forward(obj)); - } - - template - iterator insert_or_assign( - const_iterator, key_type const& k, BOOST_FWD_REF(M) obj) - { - return table_.insert_or_assign_impl(k, boost::forward(obj)).first; - } - - template - std::pair insert_or_assign( - BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj) - { - return table_.insert_or_assign_impl( - boost::move(k), boost::forward(obj)); - } - - template - iterator insert_or_assign( - const_iterator, BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj) - { - return table_ - .insert_or_assign_impl(boost::move(k), boost::forward(obj)) - .first; - } - template void insert(InputIt, InputIt); #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) void insert(std::initializer_list); #endif + // extract + + node_type extract(const_iterator position) + { + return node_type( + table_.extract_by_iterator(position), table_.node_alloc()); + } + + node_type extract(const key_type& k) + { + return node_type(table_.extract_by_key(k), table_.node_alloc()); + } + insert_return_type insert(BOOST_RV_REF(node_type) np) { insert_return_type result; @@ -632,6 +423,247 @@ template class unordered_map public: #endif +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + + template + std::pair try_emplace( + key_type const& k, BOOST_FWD_REF(Args)... args) + { + return table_.try_emplace_impl(k, boost::forward(args)...); + } + + template + iterator try_emplace( + const_iterator hint, key_type const& k, BOOST_FWD_REF(Args)... args) + { + return table_.try_emplace_hint_impl( + hint, k, boost::forward(args)...); + } + + template + std::pair try_emplace( + BOOST_RV_REF(key_type) k, BOOST_FWD_REF(Args)... args) + { + return table_.try_emplace_impl( + boost::move(k), boost::forward(args)...); + } + + template + iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k, + BOOST_FWD_REF(Args)... args) + { + return table_.try_emplace_hint_impl( + hint, boost::move(k), boost::forward(args)...); + } + +#else + + template + std::pair try_emplace(BOOST_FWD_REF(Key) k) + { + return table_.try_emplace_impl(boost::forward(k)); + } + + template + iterator try_emplace(const_iterator hint, BOOST_FWD_REF(Key) k) + { + return table_.try_emplace_hint_impl(hint, boost::forward(k)); + } + + template + std::pair try_emplace( + key_type const& k, BOOST_FWD_REF(A0) a0) + { + return table_.try_emplace_impl( + k, boost::unordered::detail::create_emplace_args( + boost::forward(a0))); + } + + template + iterator try_emplace( + const_iterator hint, key_type const& k, BOOST_FWD_REF(A0) a0) + { + return table_.try_emplace_hint_impl( + hint, k, boost::unordered::detail::create_emplace_args( + boost::forward(a0))); + } + + template + std::pair try_emplace( + BOOST_RV_REF(key_type) k, BOOST_FWD_REF(A0) a0) + { + return table_.try_emplace_impl( + boost::move(k), boost::unordered::detail::create_emplace_args( + boost::forward(a0))); + } + + template + iterator try_emplace( + const_iterator hint, BOOST_RV_REF(key_type) k, BOOST_FWD_REF(A0) a0) + { + return table_.try_emplace_hint_impl( + hint, boost::move(k), boost::unordered::detail::create_emplace_args( + boost::forward(a0))); + } + + template + std::pair try_emplace( + key_type const& k, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) + { + return table_.try_emplace_impl( + k, boost::unordered::detail::create_emplace_args( + boost::forward(a0), boost::forward(a1))); + } + + template + iterator try_emplace(const_iterator hint, key_type const& k, + BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) + { + return table_.try_emplace_hint_impl( + hint, k, boost::unordered::detail::create_emplace_args( + boost::forward(a0), boost::forward(a1))); + } + + template + std::pair try_emplace( + BOOST_RV_REF(key_type) k, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) + { + return table_.try_emplace_impl( + boost::move(k), + boost::unordered::detail::create_emplace_args( + boost::forward(a0), boost::forward(a1))); + } + + template + iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k, + BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) + { + return table_.try_emplace_hint_impl( + hint, boost::move(k), + boost::unordered::detail::create_emplace_args( + boost::forward(a0), boost::forward(a1))); + } + + template + std::pair try_emplace(key_type const& k, + BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) + { + return table_.try_emplace_impl( + k, boost::unordered::detail::create_emplace_args( + boost::forward(a0), boost::forward(a1), + boost::forward(a2))); + } + + template + iterator try_emplace(const_iterator hint, key_type const& k, + BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) + { + return table_ + .try_emplace_impl_( + hint, k, boost::unordered::detail::create_emplace_args( + boost::forward(a0), boost::forward(a1), + boost::forward(a2))) + .first; + } + + template + std::pair try_emplace(BOOST_RV_REF(key_type) k, + BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) + { + return table_.try_emplace_impl( + boost::move(k), boost::unordered::detail::create_emplace_args( + boost::forward(a0), boost::forward(a1), + boost::forward(a2))); + } + + template + iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k, + BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) + { + return table_.try_emplace_hint_impl( + hint, boost::move(k), + boost::unordered::detail::create_emplace_args( + boost::forward(a0), boost::forward(a1), + boost::forward(a2))); + } + +#define BOOST_UNORDERED_TRY_EMPLACE(z, n, _) \ + \ + template \ + std::pair try_emplace( \ + key_type const& k, BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \ + { \ + return table_.try_emplace_impl( \ + k, boost::unordered::detail::create_emplace_args( \ + BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))); \ + } \ + \ + template \ + iterator try_emplace(const_iterator hint, key_type const& k, \ + BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \ + { \ + return table_.try_emplace_hint_impl(hint, k, \ + boost::unordered::detail::create_emplace_args(BOOST_PP_ENUM_##z( \ + n, BOOST_UNORDERED_CALL_FORWARD, a))); \ + } \ + \ + template \ + std::pair try_emplace(BOOST_RV_REF(key_type) k, \ + BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \ + { \ + return table_.try_emplace_impl(boost::move(k), \ + boost::unordered::detail::create_emplace_args(BOOST_PP_ENUM_##z( \ + n, BOOST_UNORDERED_CALL_FORWARD, a))); \ + } \ + \ + template \ + iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k, \ + BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \ + { \ + return table_.try_emplace_hint_impl(hint, boost::move(k), \ + boost::unordered::detail::create_emplace_args(BOOST_PP_ENUM_##z( \ + n, BOOST_UNORDERED_CALL_FORWARD, a))); \ + } + + BOOST_PP_REPEAT_FROM_TO( + 4, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_TRY_EMPLACE, _) + +#undef BOOST_UNORDERED_TRY_EMPLACE + +#endif + + template + std::pair insert_or_assign( + key_type const& k, BOOST_FWD_REF(M) obj) + { + return table_.insert_or_assign_impl(k, boost::forward(obj)); + } + + template + std::pair insert_or_assign( + BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj) + { + return table_.insert_or_assign_impl( + boost::move(k), boost::forward(obj)); + } + + template + iterator insert_or_assign( + const_iterator, key_type const& k, BOOST_FWD_REF(M) obj) + { + return table_.insert_or_assign_impl(k, boost::forward(obj)).first; + } + + template + iterator insert_or_assign( + const_iterator, BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj) + { + return table_ + .insert_or_assign_impl(boost::move(k), boost::forward(obj)) + .first; + } + + iterator erase(iterator); iterator erase(const_iterator); size_type erase(const key_type&); iterator erase(const_iterator, const_iterator); @@ -640,8 +672,12 @@ template class unordered_map BOOST_UNORDERED_DEPRECATED("Use erase instead") void erase_return_void(const_iterator it) { erase(it); } - void clear(); void swap(unordered_map&); + // C++17 support: BOOST_NOEXCEPT_IF( + // value_allocator_traits::is_always_equal::value && + // is_nothrow_move_assignable_v && + // is_nothrow_move_assignable_v

) + void clear() BOOST_NOEXCEPT; template void merge(boost::unordered_map& source); @@ -666,10 +702,6 @@ template class unordered_map hasher hash_function() const; key_equal key_eq() const; - mapped_type& operator[](const key_type&); - mapped_type& at(const key_type&); - mapped_type const& at(const key_type&) const; - // lookup iterator find(const key_type&); @@ -691,6 +723,11 @@ template class unordered_map std::pair equal_range( const key_type&) const; + mapped_type& operator[](const key_type&); + mapped_type& operator[](BOOST_RV_REF(key_type)); + mapped_type& at(const key_type&); + mapped_type const& at(const key_type&) const; + // bucket interface size_type bucket_count() const BOOST_NOEXCEPT @@ -800,60 +837,54 @@ template class unordered_multimap 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 unordered_multimap(InputIt, InputIt); - template - unordered_multimap(InputIt, InputIt, size_type, const hasher& = hasher(), - const key_equal& = key_equal()); - - template - unordered_multimap(InputIt, InputIt, size_type, const hasher&, - 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(InputIt, InputIt, + size_type = boost::unordered::detail::default_bucket_count, + const hasher& = hasher(), const key_equal& = key_equal(), + const allocator_type& = allocator_type()); 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) +#if defined(BOOST_UNORDERED_USE_MOVE) || \ + !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) unordered_multimap(BOOST_RV_REF(unordered_multimap) other) BOOST_NOEXCEPT_IF(table::nothrow_move_constructible) : table_(other.table_, boost::unordered::detail::move_tag()) { } -#elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - unordered_multimap(unordered_multimap&& other) - BOOST_NOEXCEPT_IF(table::nothrow_move_constructible) - : table_(other.table_, boost::unordered::detail::move_tag()) - { - } #endif + explicit unordered_multimap(allocator_type const&); + + unordered_multimap(unordered_multimap const&, allocator_type const&); + + unordered_multimap(BOOST_RV_REF(unordered_multimap), allocator_type const&); + #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) unordered_multimap(std::initializer_list, size_type = boost::unordered::detail::default_bucket_count, 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&); +#endif + + explicit unordered_multimap(size_type, const allocator_type&); + + explicit unordered_multimap( + size_type, const hasher&, const allocator_type&); + + template + unordered_multimap(InputIt, InputIt, size_type, const allocator_type&); + + template + unordered_multimap( + InputIt, InputIt, size_type, const hasher&, const allocator_type&); + +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) unordered_multimap( std::initializer_list, size_type, const allocator_type&); + + unordered_multimap(std::initializer_list, size_type, + const hasher&, const allocator_type&); #endif // Destructor @@ -870,6 +901,10 @@ template class unordered_multimap } unordered_multimap& operator=(BOOST_RV_REF(unordered_multimap) x) + // C++17 support: BOOST_NOEXCEPT_IF( + // value_allocator_traits::is_always_equal::value && + // is_nothrow_move_assignable_v && + // is_nothrow_move_assignable_v

) { table_.move_assign(x.table_); return *this; @@ -883,6 +918,10 @@ template class unordered_multimap #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) unordered_multimap& operator=(unordered_multimap&& x) + // C++17 support: BOOST_NOEXCEPT_IF( + // value_allocator_traits::is_always_equal::value && + // is_nothrow_move_assignable_v && + // is_nothrow_move_assignable_v

) { table_.move_assign(x.table_); return *this; @@ -899,14 +938,6 @@ template class unordered_multimap return table_.node_alloc(); } - // size and capacity - - bool empty() const BOOST_NOEXCEPT { return table_.size_ == 0; } - - size_type size() const BOOST_NOEXCEPT { return table_.size_; } - - size_type max_size() const BOOST_NOEXCEPT; - // iterators iterator begin() BOOST_NOEXCEPT { return iterator(table_.begin()); } @@ -927,32 +958,23 @@ template class unordered_multimap const_iterator cend() const BOOST_NOEXCEPT { return const_iterator(); } - // extract + // size and capacity - node_type extract(const_iterator position) - { - return node_type( - table_.extract_by_iterator(position), table_.node_alloc()); - } + bool empty() const BOOST_NOEXCEPT { return table_.size_ == 0; } - node_type extract(const key_type& k) - { - return node_type(table_.extract_by_key(k), table_.node_alloc()); - } + size_type size() const BOOST_NOEXCEPT { return table_.size_; } + + size_type max_size() const BOOST_NOEXCEPT; // emplace #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template iterator emplace(BOOST_FWD_REF(Args)... args) { return table_.emplace(boost::forward(args)...); } - template - iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args) - { - return table_.emplace_hint(hint, boost::forward(args)...); - } #else #if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100)) @@ -968,14 +990,6 @@ template class unordered_multimap return this->emplace(boost::move(v)); } - iterator emplace_hint(const_iterator hint, - boost::unordered::detail::empty_emplace = - boost::unordered::detail::empty_emplace(), - value_type v = value_type()) - { - return this->emplace_hint(hint, boost::move(v)); - } - #endif template iterator emplace(BOOST_FWD_REF(A0) a0) @@ -984,14 +998,6 @@ template class unordered_multimap boost::forward(a0))); } - template - iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0) - { - return table_.emplace_hint( - hint, boost::unordered::detail::create_emplace_args( - boost::forward(a0))); - } - template iterator emplace(BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) { @@ -999,15 +1005,6 @@ template class unordered_multimap boost::forward(a0), boost::forward(a1))); } - template - iterator emplace_hint( - const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) - { - return table_.emplace_hint( - hint, boost::unordered::detail::create_emplace_args( - boost::forward(a0), boost::forward(a1))); - } - template iterator emplace( BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) @@ -1017,6 +1014,46 @@ template class unordered_multimap boost::forward(a2))); } +#endif + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + + template + iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args) + { + return table_.emplace_hint(hint, boost::forward(args)...); + } + +#else + +#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100)) + + iterator emplace_hint(const_iterator hint, + boost::unordered::detail::empty_emplace = + boost::unordered::detail::empty_emplace(), + value_type v = value_type()) + { + return this->emplace_hint(hint, boost::move(v)); + } + +#endif + + template + iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0) + { + return table_.emplace_hint( + hint, boost::unordered::detail::create_emplace_args( + boost::forward(a0))); + } + template + iterator emplace_hint( + const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) + { + return table_.emplace_hint( + hint, boost::unordered::detail::create_emplace_args( + boost::forward(a0), boost::forward(a1))); + } + template iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) @@ -1027,6 +1064,10 @@ template class unordered_multimap boost::forward(a2))); } +#endif + +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + #define BOOST_UNORDERED_EMPLACE(z, n, _) \ template \ iterator emplace(BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \ @@ -1092,6 +1133,19 @@ template class unordered_multimap void insert(std::initializer_list); #endif + // extract + + node_type extract(const_iterator position) + { + return node_type( + table_.extract_by_iterator(position), table_.node_alloc()); + } + + node_type extract(const key_type& k) + { + return node_type(table_.extract_by_key(k), table_.node_alloc()); + } + iterator insert(BOOST_RV_REF(node_type) np) { return table_.move_insert_node_type(np); @@ -1111,6 +1165,7 @@ template class unordered_multimap public: #endif + iterator erase(iterator); iterator erase(const_iterator); size_type erase(const key_type&); iterator erase(const_iterator, const_iterator); @@ -1119,8 +1174,12 @@ template class unordered_multimap BOOST_UNORDERED_DEPRECATED("Use erase instead") void erase_return_void(const_iterator it) { erase(it); } - void clear(); void swap(unordered_multimap&); + // C++17 support: BOOST_NOEXCEPT_IF( + // value_allocator_traits::is_always_equal::value && + // is_nothrow_move_assignable_v && + // is_nothrow_move_assignable_v

) + void clear() BOOST_NOEXCEPT; template void merge(boost::unordered_multimap& source); @@ -1243,16 +1302,17 @@ unordered_map::unordered_map(size_type n, const hasher& hf, } template -unordered_map::unordered_map( - size_type n, const allocator_type& a) - : table_(n, hasher(), key_equal(), a) +template +unordered_map::unordered_map(InputIt f, InputIt l, size_type n, + const hasher& hf, const key_equal& eql, const allocator_type& a) + : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a) { + table_.insert_range(f, l); } template -unordered_map::unordered_map( - size_type n, const hasher& hf, const allocator_type& a) - : table_(n, hf, key_equal(), a) +unordered_map::unordered_map(unordered_map const& other) + : table_(other.table_) { } @@ -1270,65 +1330,6 @@ unordered_map::unordered_map( { } -template -template -unordered_map::unordered_map(InputIt f, InputIt l) - : table_(boost::unordered::detail::initial_size(f, l), hasher(), - key_equal(), allocator_type()) -{ - table_.insert_range(f, l); -} - -template -template -unordered_map::unordered_map( - InputIt f, InputIt l, size_type n, const hasher& hf, const key_equal& eql) - : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, - allocator_type()) -{ - table_.insert_range(f, l); -} - -template -template -unordered_map::unordered_map(InputIt f, InputIt l, size_type n, - const hasher& hf, const key_equal& eql, const allocator_type& a) - : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a) -{ - 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 -{ -} - -template -unordered_map::unordered_map(unordered_map const& other) - : table_(other.table_) -{ -} - template unordered_map::unordered_map( BOOST_RV_REF(unordered_map) other, allocator_type const& a) @@ -1349,17 +1350,44 @@ unordered_map::unordered_map( table_.insert_range(list.begin(), list.end()); } +#endif + 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) + size_type n, const allocator_type& a) + : table_(n, hasher(), key_equal(), a) { - table_.insert_range(list.begin(), list.end()); } +template +unordered_map::unordered_map( + size_type n, const hasher& hf, const allocator_type& a) + : table_(n, hf, key_equal(), a) +{ +} + +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 +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); +} + +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + template unordered_map::unordered_map( std::initializer_list list, size_type n, @@ -1371,6 +1399,26 @@ unordered_map::unordered_map( 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()); +} + +#endif + +template +unordered_map::~unordered_map() BOOST_NOEXCEPT +{ +} + +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + template unordered_map& unordered_map::operator=( std::initializer_list list) @@ -1408,6 +1456,13 @@ void unordered_map::insert( } #endif +template +typename unordered_map::iterator +unordered_map::erase(iterator position) +{ + return table_.erase(position); +} + template typename unordered_map::iterator unordered_map::erase(const_iterator position) @@ -1430,15 +1485,19 @@ unordered_map::erase(const_iterator first, const_iterator last) } template -void unordered_map::clear() +void unordered_map::swap(unordered_map& other) +// C++17 support: BOOST_NOEXCEPT_IF( +// value_allocator_traits::is_always_equal::value && +// is_nothrow_move_assignable_v && +// is_nothrow_move_assignable_v

) { - table_.clear(); + table_.swap(other.table_); } template -void unordered_map::swap(unordered_map& other) +void unordered_map::clear() BOOST_NOEXCEPT { - table_.swap(other.table_); + table_.clear(); } template @@ -1495,27 +1554,6 @@ unordered_map::key_eq() const return table_.key_eq(); } -template -typename unordered_map::mapped_type& - unordered_map::operator[](const key_type& k) -{ - return table_.try_emplace_impl(k).first->second; -} - -template -typename unordered_map::mapped_type& -unordered_map::at(const key_type& k) -{ - return table_.at(k).second; -} - -template -typename unordered_map::mapped_type const& -unordered_map::at(const key_type& k) const -{ - return table_.at(k).second; -} - // lookup template @@ -1573,6 +1611,34 @@ unordered_map::equal_range(const key_type& k) const return table_.equal_range(k); } +template +typename unordered_map::mapped_type& + unordered_map::operator[](const key_type& k) +{ + return table_.try_emplace_impl(k).first->second; +} + +template +typename unordered_map::mapped_type& + unordered_map::operator[](BOOST_RV_REF(key_type) k) +{ + return table_.try_emplace_impl(boost::move(k)).first->second; +} + +template +typename unordered_map::mapped_type& +unordered_map::at(const key_type& k) +{ + return table_.at(k).second; +} + +template +typename unordered_map::mapped_type const& +unordered_map::at(const key_type& k) const +{ + return table_.at(k).second; +} + template typename unordered_map::size_type unordered_map::bucket_size(size_type n) const @@ -1663,16 +1729,19 @@ unordered_multimap::unordered_multimap(size_type n, } template -unordered_multimap::unordered_multimap( - size_type n, const allocator_type& a) - : table_(n, hasher(), key_equal(), a) +template +unordered_multimap::unordered_multimap(InputIt f, InputIt l, + size_type n, const hasher& hf, const key_equal& eql, + const allocator_type& a) + : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a) { + table_.insert_range(f, l); } template unordered_multimap::unordered_multimap( - size_type n, const hasher& hf, const allocator_type& a) - : table_(n, hf, key_equal(), a) + unordered_multimap const& other) + : table_(other.table_) { } @@ -1690,67 +1759,6 @@ unordered_multimap::unordered_multimap( { } -template -template -unordered_multimap::unordered_multimap(InputIt f, InputIt l) - : table_(boost::unordered::detail::initial_size(f, l), hasher(), - key_equal(), allocator_type()) -{ - table_.insert_range(f, l); -} - -template -template -unordered_multimap::unordered_multimap( - InputIt f, InputIt l, size_type n, const hasher& hf, const key_equal& eql) - : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, - allocator_type()) -{ - table_.insert_range(f, l); -} - -template -template -unordered_multimap::unordered_multimap(InputIt f, InputIt l, - size_type n, const hasher& hf, const key_equal& eql, - const allocator_type& a) - : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a) -{ - 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 -{ -} - -template -unordered_multimap::unordered_multimap( - unordered_multimap const& other) - : table_(other.table_) -{ -} - template unordered_multimap::unordered_multimap( BOOST_RV_REF(unordered_multimap) other, allocator_type const& a) @@ -1771,17 +1779,44 @@ unordered_multimap::unordered_multimap( table_.insert_range(list.begin(), list.end()); } +#endif + 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) + size_type n, const allocator_type& a) + : table_(n, hasher(), key_equal(), a) { - table_.insert_range(list.begin(), list.end()); } +template +unordered_multimap::unordered_multimap( + size_type n, const hasher& hf, const allocator_type& a) + : table_(n, hf, key_equal(), a) +{ +} + +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 +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); +} + +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + template unordered_multimap::unordered_multimap( std::initializer_list list, size_type n, @@ -1793,6 +1828,26 @@ unordered_multimap::unordered_multimap( 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()); +} + +#endif + +template +unordered_multimap::~unordered_multimap() BOOST_NOEXCEPT +{ +} + +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + template unordered_multimap& unordered_multimap::operator=( std::initializer_list list) @@ -1830,6 +1885,13 @@ void unordered_multimap::insert( } #endif +template +typename unordered_multimap::iterator +unordered_multimap::erase(iterator position) +{ + return table_.erase(position); +} + template typename unordered_multimap::iterator unordered_multimap::erase(const_iterator position) @@ -1853,15 +1915,19 @@ unordered_multimap::erase( } template -void unordered_multimap::clear() +void unordered_multimap::swap(unordered_multimap& other) +// C++17 support: BOOST_NOEXCEPT_IF( +// value_allocator_traits::is_always_equal::value && +// is_nothrow_move_assignable_v && +// is_nothrow_move_assignable_v

) { - table_.clear(); + table_.swap(other.table_); } template -void unordered_multimap::swap(unordered_multimap& other) +void unordered_multimap::clear() BOOST_NOEXCEPT { - table_.swap(other.table_); + table_.clear(); } // observers diff --git a/include/boost/unordered/unordered_set.hpp b/include/boost/unordered/unordered_set.hpp index afb25916..747f00f5 100644 --- a/include/boost/unordered/unordered_set.hpp +++ b/include/boost/unordered/unordered_set.hpp @@ -83,59 +83,53 @@ template class unordered_set 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 unordered_set(InputIt, InputIt); - template - unordered_set(InputIt, InputIt, size_type, const hasher& = hasher(), - const key_equal& = key_equal()); - - template - unordered_set(InputIt, InputIt, size_type, const hasher&, 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(InputIt, InputIt, + size_type = boost::unordered::detail::default_bucket_count, + const hasher& = hasher(), const key_equal& = key_equal(), + const allocator_type& = allocator_type()); 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) +#if defined(BOOST_UNORDERED_USE_MOVE) || \ + !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) unordered_set(BOOST_RV_REF(unordered_set) other) BOOST_NOEXCEPT_IF(table::nothrow_move_constructible) : table_(other.table_, boost::unordered::detail::move_tag()) { } -#elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - unordered_set(unordered_set&& other) - BOOST_NOEXCEPT_IF(table::nothrow_move_constructible) - : table_(other.table_, boost::unordered::detail::move_tag()) - { - } #endif + explicit unordered_set(allocator_type const&); + + unordered_set(unordered_set const&, allocator_type const&); + + unordered_set(BOOST_RV_REF(unordered_set), allocator_type const&); + #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) unordered_set(std::initializer_list, size_type = boost::unordered::detail::default_bucket_count, 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&); +#endif + + explicit unordered_set(size_type, const allocator_type&); + + explicit unordered_set(size_type, const hasher&, const allocator_type&); + + template + unordered_set(InputIt, InputIt, size_type, const allocator_type&); + + template + unordered_set( + InputIt, InputIt, size_type, const hasher&, const allocator_type&); + +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) unordered_set( std::initializer_list, size_type, const allocator_type&); + + unordered_set(std::initializer_list, size_type, const hasher&, + const allocator_type&); #endif // Destructor @@ -152,6 +146,10 @@ template class unordered_set } unordered_set& operator=(BOOST_RV_REF(unordered_set) x) + // C++17 support: BOOST_NOEXCEPT_IF( + // value_allocator_traits::is_always_equal::value && + // is_nothrow_move_assignable_v && + // is_nothrow_move_assignable_v

) { table_.move_assign(x.table_); return *this; @@ -165,6 +163,10 @@ template class unordered_set #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) unordered_set& operator=(unordered_set&& x) + // C++17 support: BOOST_NOEXCEPT_IF( + // value_allocator_traits::is_always_equal::value && + // is_nothrow_move_assignable_v && + // is_nothrow_move_assignable_v

) { table_.move_assign(x.table_); return *this; @@ -181,14 +183,6 @@ template class unordered_set return table_.node_alloc(); } - // size and capacity - - bool empty() const BOOST_NOEXCEPT { return table_.size_ == 0; } - - size_type size() const BOOST_NOEXCEPT { return table_.size_; } - - size_type max_size() const BOOST_NOEXCEPT; - // iterators iterator begin() BOOST_NOEXCEPT { return iterator(table_.begin()); } @@ -209,33 +203,24 @@ template class unordered_set const_iterator cend() const BOOST_NOEXCEPT { return const_iterator(); } - // extract + // size and capacity - node_type extract(const_iterator position) - { - return node_type( - table_.extract_by_iterator(position), table_.node_alloc()); - } + bool empty() const BOOST_NOEXCEPT { return table_.size_ == 0; } - node_type extract(const key_type& k) - { - return node_type(table_.extract_by_key(k), table_.node_alloc()); - } + size_type size() const BOOST_NOEXCEPT { return table_.size_; } + + size_type max_size() const BOOST_NOEXCEPT; // emplace #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template std::pair emplace(BOOST_FWD_REF(Args)... args) { return table_.emplace(boost::forward(args)...); } - template - iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args) - { - return table_.emplace_hint(hint, boost::forward(args)...); - } #else #if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100)) @@ -252,6 +237,46 @@ template class unordered_set return this->emplace(boost::move(v)); } +#endif + + template + std::pair emplace(BOOST_FWD_REF(A0) a0) + { + return table_.emplace(boost::unordered::detail::create_emplace_args( + boost::forward(a0))); + } + + template + std::pair emplace( + BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) + { + return table_.emplace(boost::unordered::detail::create_emplace_args( + boost::forward(a0), boost::forward(a1))); + } + + template + std::pair emplace( + BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) + { + return table_.emplace(boost::unordered::detail::create_emplace_args( + boost::forward(a0), boost::forward(a1), + boost::forward(a2))); + } + +#endif + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + + template + iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args) + { + return table_.emplace_hint(hint, boost::forward(args)...); + } + +#else + +#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100)) + iterator emplace_hint(const_iterator hint, boost::unordered::detail::empty_emplace = boost::unordered::detail::empty_emplace(), @@ -262,13 +287,6 @@ template class unordered_set #endif - template - std::pair emplace(BOOST_FWD_REF(A0) a0) - { - return table_.emplace(boost::unordered::detail::create_emplace_args( - boost::forward(a0))); - } - template iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0) { @@ -277,14 +295,6 @@ template class unordered_set boost::forward(a0))); } - template - std::pair emplace( - BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) - { - return table_.emplace(boost::unordered::detail::create_emplace_args( - boost::forward(a0), boost::forward(a1))); - } - template iterator emplace_hint( const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) @@ -294,15 +304,6 @@ template class unordered_set boost::forward(a0), boost::forward(a1))); } - template - std::pair emplace( - BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) - { - return table_.emplace(boost::unordered::detail::create_emplace_args( - boost::forward(a0), boost::forward(a1), - boost::forward(a2))); - } - template iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) @@ -313,6 +314,10 @@ template class unordered_set boost::forward(a2))); } +#endif + +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + #define BOOST_UNORDERED_EMPLACE(z, n, _) \ template \ std::pair emplace( \ @@ -364,6 +369,19 @@ template class unordered_set void insert(std::initializer_list); #endif + // extract + + node_type extract(const_iterator position) + { + return node_type( + table_.extract_by_iterator(position), table_.node_alloc()); + } + + node_type extract(const key_type& k) + { + return node_type(table_.extract_by_key(k), table_.node_alloc()); + } + insert_return_type insert(BOOST_RV_REF(node_type) np) { insert_return_type result; @@ -393,8 +411,12 @@ template class unordered_set BOOST_UNORDERED_DEPRECATED("Use erase instead") void erase_return_void(const_iterator it) { erase(it); } - void clear(); void swap(unordered_set&); + // C++17 support: BOOST_NOEXCEPT_IF( + // value_allocator_traits::is_always_equal::value && + // is_nothrow_move_assignable_v && + // is_nothrow_move_assignable_v

) + void clear() BOOST_NOEXCEPT; template void merge(boost::unordered_set& source); @@ -541,60 +563,54 @@ template class unordered_multiset 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 unordered_multiset(InputIt, InputIt); - template - unordered_multiset(InputIt, InputIt, size_type, const hasher& = hasher(), - const key_equal& = key_equal()); - - template - unordered_multiset(InputIt, InputIt, size_type, const hasher&, - 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(InputIt, InputIt, + size_type = boost::unordered::detail::default_bucket_count, + const hasher& = hasher(), const key_equal& = key_equal(), + const allocator_type& = allocator_type()); 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) +#if defined(BOOST_UNORDERED_USE_MOVE) || \ + !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) unordered_multiset(BOOST_RV_REF(unordered_multiset) other) BOOST_NOEXCEPT_IF(table::nothrow_move_constructible) : table_(other.table_, boost::unordered::detail::move_tag()) { } -#elif !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - unordered_multiset(unordered_multiset&& other) - BOOST_NOEXCEPT_IF(table::nothrow_move_constructible) - : table_(other.table_, boost::unordered::detail::move_tag()) - { - } #endif + explicit unordered_multiset(allocator_type const&); + + unordered_multiset(unordered_multiset const&, allocator_type const&); + + unordered_multiset(BOOST_RV_REF(unordered_multiset), allocator_type const&); + #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) unordered_multiset(std::initializer_list, size_type = boost::unordered::detail::default_bucket_count, 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&); +#endif + + explicit unordered_multiset(size_type, const allocator_type&); + + explicit unordered_multiset( + size_type, const hasher&, const allocator_type&); + + template + unordered_multiset(InputIt, InputIt, size_type, const allocator_type&); + + template + unordered_multiset( + InputIt, InputIt, size_type, const hasher&, const allocator_type&); + +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) unordered_multiset( std::initializer_list, size_type, const allocator_type&); + + unordered_multiset(std::initializer_list, size_type, + const hasher&, const allocator_type&); #endif // Destructor @@ -611,6 +627,10 @@ template class unordered_multiset } unordered_multiset& operator=(BOOST_RV_REF(unordered_multiset) x) + // C++17 support: BOOST_NOEXCEPT_IF( + // value_allocator_traits::is_always_equal::value && + // is_nothrow_move_assignable_v && + // is_nothrow_move_assignable_v

) { table_.move_assign(x.table_); return *this; @@ -624,6 +644,10 @@ template class unordered_multiset #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) unordered_multiset& operator=(unordered_multiset&& x) + // C++17 support: BOOST_NOEXCEPT_IF( + // value_allocator_traits::is_always_equal::value && + // is_nothrow_move_assignable_v && + // is_nothrow_move_assignable_v

) { table_.move_assign(x.table_); return *this; @@ -640,14 +664,6 @@ template class unordered_multiset return table_.node_alloc(); } - // size and capacity - - bool empty() const BOOST_NOEXCEPT { return table_.size_ == 0; } - - size_type size() const BOOST_NOEXCEPT { return table_.size_; } - - size_type max_size() const BOOST_NOEXCEPT; - // iterators iterator begin() BOOST_NOEXCEPT { return iterator(table_.begin()); } @@ -668,18 +684,13 @@ template class unordered_multiset const_iterator cend() const BOOST_NOEXCEPT { return const_iterator(); } - // extract + // size and capacity - node_type extract(const_iterator position) - { - return node_type( - table_.extract_by_iterator(position), table_.node_alloc()); - } + bool empty() const BOOST_NOEXCEPT { return table_.size_ == 0; } - node_type extract(const key_type& k) - { - return node_type(table_.extract_by_key(k), table_.node_alloc()); - } + size_type size() const BOOST_NOEXCEPT { return table_.size_; } + + size_type max_size() const BOOST_NOEXCEPT; // emplace @@ -689,11 +700,6 @@ template class unordered_multiset return table_.emplace(boost::forward(args)...); } - template - iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args) - { - return table_.emplace_hint(hint, boost::forward(args)...); - } #else #if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100)) @@ -709,6 +715,44 @@ template class unordered_multiset return this->emplace(boost::move(v)); } +#endif + + template iterator emplace(BOOST_FWD_REF(A0) a0) + { + return table_.emplace(boost::unordered::detail::create_emplace_args( + boost::forward(a0))); + } + + template + iterator emplace(BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) + { + return table_.emplace(boost::unordered::detail::create_emplace_args( + boost::forward(a0), boost::forward(a1))); + } + + template + iterator emplace( + BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) + { + return table_.emplace(boost::unordered::detail::create_emplace_args( + boost::forward(a0), boost::forward(a1), + boost::forward(a2))); + } + +#endif + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + + template + iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args) + { + return table_.emplace_hint(hint, boost::forward(args)...); + } + +#else + +#if !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x5100)) + iterator emplace_hint(const_iterator hint, boost::unordered::detail::empty_emplace = boost::unordered::detail::empty_emplace(), @@ -719,12 +763,6 @@ template class unordered_multiset #endif - template iterator emplace(BOOST_FWD_REF(A0) a0) - { - return table_.emplace(boost::unordered::detail::create_emplace_args( - boost::forward(a0))); - } - template iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0) { @@ -733,13 +771,6 @@ template class unordered_multiset boost::forward(a0))); } - template - iterator emplace(BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) - { - return table_.emplace(boost::unordered::detail::create_emplace_args( - boost::forward(a0), boost::forward(a1))); - } - template iterator emplace_hint( const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) @@ -749,15 +780,6 @@ template class unordered_multiset boost::forward(a0), boost::forward(a1))); } - template - iterator emplace( - BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) - { - return table_.emplace(boost::unordered::detail::create_emplace_args( - boost::forward(a0), boost::forward(a1), - boost::forward(a2))); - } - template iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) @@ -768,6 +790,10 @@ template class unordered_multiset boost::forward(a2))); } +#endif + +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + #define BOOST_UNORDERED_EMPLACE(z, n, _) \ template \ iterator emplace(BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \ @@ -815,6 +841,19 @@ template class unordered_multiset void insert(std::initializer_list); #endif + // extract + + node_type extract(const_iterator position) + { + return node_type( + table_.extract_by_iterator(position), table_.node_alloc()); + } + + node_type extract(const key_type& k) + { + return node_type(table_.extract_by_key(k), table_.node_alloc()); + } + iterator insert(BOOST_RV_REF(node_type) np) { return table_.move_insert_node_type(np); @@ -842,8 +881,12 @@ template class unordered_multiset BOOST_UNORDERED_DEPRECATED("Use erase instead") void erase_return_void(const_iterator it) { erase(it); } - void clear(); void swap(unordered_multiset&); + // C++17 support: BOOST_NOEXCEPT_IF( + // value_allocator_traits::is_always_equal::value && + // is_nothrow_move_assignable_v && + // is_nothrow_move_assignable_v

) + void clear() BOOST_NOEXCEPT; template void merge(boost::unordered_multiset& source); @@ -943,7 +986,6 @@ template class unordered_multiset }; // class template unordered_multiset //////////////////////////////////////////////////////////////////////////////// - template unordered_set::unordered_set() : table_(boost::unordered::detail::default_bucket_count, hasher(), @@ -959,15 +1001,17 @@ unordered_set::unordered_set(size_type n, const hasher& hf, } template -unordered_set::unordered_set(size_type n, const allocator_type& a) - : table_(n, hasher(), key_equal(), a) +template +unordered_set::unordered_set(InputIt f, InputIt l, size_type n, + const hasher& hf, const key_equal& eql, const allocator_type& a) + : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a) { + table_.insert_range(f, l); } template -unordered_set::unordered_set( - size_type n, const hasher& hf, const allocator_type& a) - : table_(n, hf, key_equal(), a) +unordered_set::unordered_set(unordered_set const& other) + : table_(other.table_) { } @@ -985,65 +1029,6 @@ unordered_set::unordered_set( { } -template -template -unordered_set::unordered_set(InputIt f, InputIt l) - : table_(boost::unordered::detail::initial_size(f, l), hasher(), - key_equal(), allocator_type()) -{ - table_.insert_range(f, l); -} - -template -template -unordered_set::unordered_set( - InputIt f, InputIt l, size_type n, const hasher& hf, const key_equal& eql) - : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, - allocator_type()) -{ - table_.insert_range(f, l); -} - -template -template -unordered_set::unordered_set(InputIt f, InputIt l, size_type n, - const hasher& hf, const key_equal& eql, const allocator_type& a) - : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a) -{ - 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 -{ -} - -template -unordered_set::unordered_set(unordered_set const& other) - : table_(other.table_) -{ -} - template unordered_set::unordered_set( BOOST_RV_REF(unordered_set) other, allocator_type const& a) @@ -1064,16 +1049,43 @@ unordered_set::unordered_set(std::initializer_list list, table_.insert_range(list.begin(), list.end()); } +#endif + 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) +unordered_set::unordered_set(size_type n, const allocator_type& a) + : table_(n, hasher(), key_equal(), a) { - table_.insert_range(list.begin(), list.end()); } +template +unordered_set::unordered_set( + size_type n, const hasher& hf, const allocator_type& a) + : table_(n, hf, key_equal(), a) +{ +} + +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 +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); +} + +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + template unordered_set::unordered_set(std::initializer_list list, size_type n, const allocator_type& a) @@ -1084,6 +1096,25 @@ unordered_set::unordered_set(std::initializer_list list, 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()); +} + +#endif + +template +unordered_set::~unordered_set() BOOST_NOEXCEPT +{ +} + +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + template unordered_set& unordered_set::operator=( std::initializer_list list) @@ -1142,15 +1173,25 @@ typename unordered_set::iterator unordered_set::erase( } template -void unordered_set::clear() +void unordered_set::swap(unordered_set& other) +// C++17 support: BOOST_NOEXCEPT_IF( +// value_allocator_traits::is_always_equal::value && +// is_nothrow_move_assignable_v && +// is_nothrow_move_assignable_v

) +{ + table_.swap(other.table_); +} + +template +void unordered_set::clear() BOOST_NOEXCEPT { table_.clear(); } template -void unordered_set::swap(unordered_set& other) +void unordered_multiset::clear() BOOST_NOEXCEPT { - table_.swap(other.table_); + table_.clear(); } // observers @@ -1329,16 +1370,19 @@ unordered_multiset::unordered_multiset(size_type n, } template -unordered_multiset::unordered_multiset( - size_type n, const allocator_type& a) - : table_(n, hasher(), key_equal(), a) +template +unordered_multiset::unordered_multiset(InputIt f, InputIt l, + size_type n, const hasher& hf, const key_equal& eql, + const allocator_type& a) + : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a) { + table_.insert_range(f, l); } template unordered_multiset::unordered_multiset( - size_type n, const hasher& hf, const allocator_type& a) - : table_(n, hf, key_equal(), a) + unordered_multiset const& other) + : table_(other.table_) { } @@ -1356,67 +1400,6 @@ unordered_multiset::unordered_multiset( { } -template -template -unordered_multiset::unordered_multiset(InputIt f, InputIt l) - : table_(boost::unordered::detail::initial_size(f, l), hasher(), - key_equal(), allocator_type()) -{ - table_.insert_range(f, l); -} - -template -template -unordered_multiset::unordered_multiset( - InputIt f, InputIt l, size_type n, const hasher& hf, const key_equal& eql) - : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, - allocator_type()) -{ - table_.insert_range(f, l); -} - -template -template -unordered_multiset::unordered_multiset(InputIt f, InputIt l, - size_type n, const hasher& hf, const key_equal& eql, - const allocator_type& a) - : table_(boost::unordered::detail::initial_size(f, l, n), hf, eql, a) -{ - 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 -{ -} - -template -unordered_multiset::unordered_multiset( - unordered_multiset const& other) - : table_(other.table_) -{ -} - template unordered_multiset::unordered_multiset( BOOST_RV_REF(unordered_multiset) other, allocator_type const& a) @@ -1437,17 +1420,44 @@ unordered_multiset::unordered_multiset( table_.insert_range(list.begin(), list.end()); } +#endif + 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) + size_type n, const allocator_type& a) + : table_(n, hasher(), key_equal(), a) { - table_.insert_range(list.begin(), list.end()); } +template +unordered_multiset::unordered_multiset( + size_type n, const hasher& hf, const allocator_type& a) + : table_(n, hf, key_equal(), a) +{ +} + +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 +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); +} + +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + template unordered_multiset::unordered_multiset( std::initializer_list list, size_type n, @@ -1459,6 +1469,26 @@ unordered_multiset::unordered_multiset( 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()); +} + +#endif + +template +unordered_multiset::~unordered_multiset() BOOST_NOEXCEPT +{ +} + +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + template unordered_multiset& unordered_multiset::operator=( std::initializer_list list) @@ -1517,14 +1547,12 @@ unordered_multiset::erase(const_iterator first, const_iterator last) return table_.erase_range(first, last); } -template -void unordered_multiset::clear() -{ - table_.clear(); -} - template void unordered_multiset::swap(unordered_multiset& other) +// C++17 support: BOOST_NOEXCEPT_IF( +// value_allocator_traits::is_always_equal::value && +// is_nothrow_move_assignable_v && +// is_nothrow_move_assignable_v

) { table_.swap(other.table_); } diff --git a/test/unordered/compile_map.cpp b/test/unordered/compile_map.cpp index 1b099c70..6293dfb8 100644 --- a/test/unordered/compile_map.cpp +++ b/test/unordered/compile_map.cpp @@ -227,4 +227,36 @@ UNORDERED_AUTO_TEST(test2) unordered_map_member_test(multimap, map_value); } +// Test for ambiguity when using key convertible from iterator +// See LWG2059 + +struct lwg2059_key +{ + int value; + + template lwg2059_key(T v) : value(v) {} +}; + +std::size_t hash_value(lwg2059_key x) +{ + return static_cast(x.value); +} + +bool operator==(lwg2059_key x, lwg2059_key y) { return x.value == y.value; } + +UNORDERED_AUTO_TEST(lwg2059) +{ + { + boost::unordered_map x; + x.emplace(lwg2059_key(10), 5); + x.erase(x.begin()); + } + + { + boost::unordered_multimap x; + x.emplace(lwg2059_key(10), 5); + x.erase(x.begin()); + } +} + RUN_TESTS() diff --git a/test/unordered/compile_set.cpp b/test/unordered/compile_set.cpp index 3ea98703..e0a07737 100644 --- a/test/unordered/compile_set.cpp +++ b/test/unordered/compile_set.cpp @@ -290,4 +290,36 @@ UNORDERED_AUTO_TEST(destructible_tests) unordered_destructible_test(multiset); } +// Test for ambiguity when using key convertible from iterator +// See LWG2059 + +struct lwg2059_key +{ + int value; + + template lwg2059_key(T v) : value(v) {} +}; + +std::size_t hash_value(lwg2059_key x) +{ + return static_cast(x.value); +} + +bool operator==(lwg2059_key x, lwg2059_key y) { return x.value == y.value; } + +UNORDERED_AUTO_TEST(lwg2059) +{ + { + boost::unordered_set x; + x.emplace(lwg2059_key(10)); + x.erase(x.begin()); + } + + { + boost::unordered_multiset x; + x.emplace(lwg2059_key(10)); + x.erase(x.begin()); + } +} + RUN_TESTS() diff --git a/test/unordered/compile_tests.hpp b/test/unordered/compile_tests.hpp index 45ad2111..12759c16 100644 --- a/test/unordered/compile_tests.hpp +++ b/test/unordered/compile_tests.hpp @@ -422,6 +422,7 @@ void unordered_map_functions(X&, Key const& k, T const& v) X a; test::check_return_type::equals_ref(a[k]); + test::check_return_type::equals_ref(a[rvalue(k)]); test::check_return_type::equals_ref(a.at(k)); test::check_return_type >::equals( a.try_emplace(k, v)); @@ -554,6 +555,7 @@ void unordered_test(X& x, Key& k, Hash& hf, Pred& eq) const_iterator q1 = a.cbegin(), q2 = a.cend(); test::check_return_type::equals(a.erase(q1, q2)); + TEST_NOEXCEPT_EXPR(a.clear()); a.clear(); X const b;