summaryrefslogtreecommitdiff
path: root/boost/unordered/unordered_map.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/unordered/unordered_map.hpp')
-rw-r--r--boost/unordered/unordered_map.hpp302
1 files changed, 199 insertions, 103 deletions
diff --git a/boost/unordered/unordered_map.hpp b/boost/unordered/unordered_map.hpp
index bae3aa2f02..1910219ccb 100644
--- a/boost/unordered/unordered_map.hpp
+++ b/boost/unordered/unordered_map.hpp
@@ -26,10 +26,12 @@
#if defined(BOOST_MSVC)
#pragma warning(push)
+// conditional expression is constant
+#pragma warning(disable : 4127)
#if BOOST_MSVC >= 1400
-#pragma warning(disable : 4396) // the inline specifier cannot be used when a
-// friend declaration refers to a specialization
-// of a function template
+// the inline specifier cannot be used when a friend declaration refers to a
+// specialization of a function template
+#pragma warning(disable : 4396)
#endif
#endif
@@ -151,10 +153,9 @@ namespace boost {
}
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<H> &&
- // is_nothrow_move_assignable_v<P>)
+ BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&&
+ boost::is_nothrow_move_assignable<H>::value&&
+ boost::is_nothrow_move_assignable<P>::value)
{
table_.move_assign(x.table_, boost::unordered::detail::true_type());
return *this;
@@ -168,10 +169,9 @@ namespace boost {
#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<H> &&
- // is_nothrow_move_assignable_v<P>)
+ BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&&
+ boost::is_nothrow_move_assignable<H>::value&&
+ boost::is_nothrow_move_assignable<P>::value)
{
table_.move_assign(x.table_, boost::unordered::detail::true_type());
return *this;
@@ -715,11 +715,10 @@ namespace boost {
BOOST_UNORDERED_DEPRECATED("Use erase instead")
void erase_return_void(const_iterator it) { erase(it); }
- void swap(unordered_map&);
- // C++17 support: BOOST_NOEXCEPT_IF(
- // value_allocator_traits::is_always_equal::value &&
- // is_nothrow_move_assignable_v<H> &&
- // is_nothrow_move_assignable_v<P>)
+ void swap(unordered_map&)
+ BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&&
+ boost::is_nothrow_swappable<H>::value&&
+ boost::is_nothrow_swappable<P>::value);
void clear() BOOST_NOEXCEPT { table_.clear_impl(); }
template <typename H2, typename P2>
@@ -831,6 +830,81 @@ namespace boost {
#endif
}; // class template unordered_map
+#if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
+
+ namespace detail {
+ template <typename T>
+ using iter_key_t =
+ typename std::iterator_traits<T>::value_type::first_type;
+ template <typename T>
+ using iter_val_t =
+ typename std::iterator_traits<T>::value_type::second_type;
+ template <typename T>
+ using iter_to_alloc_t =
+ typename std::pair<iter_key_t<T> const, iter_val_t<T> >;
+ }
+
+ template <class InputIterator,
+ class Hash =
+ boost::hash<boost::unordered::detail::iter_key_t<InputIterator> >,
+ class Pred =
+ std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
+ class Allocator = std::allocator<
+ boost::unordered::detail::iter_to_alloc_t<InputIterator> > >
+ unordered_map(InputIterator, InputIterator,
+ std::size_t = boost::unordered::detail::default_bucket_count,
+ Hash = Hash(), Pred = Pred(), Allocator = Allocator())
+ ->unordered_map<boost::unordered::detail::iter_key_t<InputIterator>,
+ boost::unordered::detail::iter_val_t<InputIterator>, Hash, Pred,
+ Allocator>;
+
+ template <class Key, class T, class Hash = boost::hash<Key>,
+ class Pred = std::equal_to<Key>,
+ class Allocator = std::allocator<std::pair<const Key, T> > >
+ unordered_map(std::initializer_list<std::pair<const Key, T> >,
+ std::size_t = boost::unordered::detail::default_bucket_count,
+ Hash = Hash(), Pred = Pred(), Allocator = Allocator())
+ ->unordered_map<Key, T, Hash, Pred, Allocator>;
+
+ template <class InputIterator, class Allocator>
+ unordered_map(InputIterator, InputIterator, std::size_t, Allocator)
+ ->unordered_map<boost::unordered::detail::iter_key_t<InputIterator>,
+ boost::unordered::detail::iter_val_t<InputIterator>,
+ boost::hash<boost::unordered::detail::iter_key_t<InputIterator> >,
+ std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
+ Allocator>;
+
+ template <class InputIterator, class Allocator>
+ unordered_map(InputIterator, InputIterator, Allocator)
+ ->unordered_map<boost::unordered::detail::iter_key_t<InputIterator>,
+ boost::unordered::detail::iter_val_t<InputIterator>,
+ boost::hash<boost::unordered::detail::iter_key_t<InputIterator> >,
+ std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
+ Allocator>;
+
+ template <class InputIterator, class Hash, class Allocator>
+ unordered_map(InputIterator, InputIterator, std::size_t, Hash, Allocator)
+ ->unordered_map<boost::unordered::detail::iter_key_t<InputIterator>,
+ boost::unordered::detail::iter_val_t<InputIterator>, Hash,
+ std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
+ Allocator>;
+
+ template <class Key, class T, typename Allocator>
+ unordered_map(
+ std::initializer_list<std::pair<const Key, T> >, std::size_t, Allocator)
+ ->unordered_map<Key, T, boost::hash<Key>, std::equal_to<Key>, Allocator>;
+
+ template <class Key, class T, typename Allocator>
+ unordered_map(std::initializer_list<std::pair<const Key, T> >, Allocator)
+ ->unordered_map<Key, T, boost::hash<Key>, std::equal_to<Key>, Allocator>;
+
+ template <class Key, class T, class Hash, class Allocator>
+ unordered_map(std::initializer_list<std::pair<const Key, T> >, std::size_t,
+ Hash, Allocator)
+ ->unordered_map<Key, T, Hash, std::equal_to<Key>, Allocator>;
+
+#endif
+
template <class K, class T, class H, class P, class A>
class unordered_multimap
{
@@ -949,10 +1023,9 @@ namespace boost {
}
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<H> &&
- // is_nothrow_move_assignable_v<P>)
+ BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&&
+ boost::is_nothrow_move_assignable<H>::value&&
+ boost::is_nothrow_move_assignable<P>::value)
{
table_.move_assign(x.table_, boost::unordered::detail::false_type());
return *this;
@@ -966,10 +1039,9 @@ namespace boost {
#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<H> &&
- // is_nothrow_move_assignable_v<P>)
+ BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&&
+ boost::is_nothrow_move_assignable<H>::value&&
+ boost::is_nothrow_move_assignable<P>::value)
{
table_.move_assign(x.table_, boost::unordered::detail::false_type());
return *this;
@@ -1252,11 +1324,10 @@ namespace boost {
BOOST_UNORDERED_DEPRECATED("Use erase instead")
void erase_return_void(const_iterator it) { erase(it); }
- void swap(unordered_multimap&);
- // C++17 support: BOOST_NOEXCEPT_IF(
- // value_allocator_traits::is_always_equal::value &&
- // is_nothrow_move_assignable_v<H> &&
- // is_nothrow_move_assignable_v<P>)
+ void swap(unordered_multimap&)
+ BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&&
+ boost::is_nothrow_swappable<H>::value&&
+ boost::is_nothrow_swappable<P>::value);
void clear() BOOST_NOEXCEPT { table_.clear_impl(); }
template <typename H2, typename P2>
@@ -1363,6 +1434,73 @@ namespace boost {
#endif
}; // class template unordered_multimap
+#if BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
+
+ template <class InputIterator,
+ class Hash =
+ boost::hash<boost::unordered::detail::iter_key_t<InputIterator> >,
+ class Pred =
+ std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
+ class Allocator = std::allocator<
+ boost::unordered::detail::iter_to_alloc_t<InputIterator> > >
+ unordered_multimap(InputIterator, InputIterator,
+ std::size_t = boost::unordered::detail::default_bucket_count,
+ Hash = Hash(), Pred = Pred(), Allocator = Allocator())
+ ->unordered_multimap<boost::unordered::detail::iter_key_t<InputIterator>,
+ boost::unordered::detail::iter_val_t<InputIterator>, Hash, Pred,
+ Allocator>;
+
+ template <class Key, class T, class Hash = boost::hash<Key>,
+ class Pred = std::equal_to<Key>,
+ class Allocator = std::allocator<std::pair<const Key, T> > >
+ unordered_multimap(std::initializer_list<std::pair<const Key, T> >,
+ std::size_t = boost::unordered::detail::default_bucket_count,
+ Hash = Hash(), Pred = Pred(), Allocator = Allocator())
+ ->unordered_multimap<Key, T, Hash, Pred, Allocator>;
+
+ template <class InputIterator, class Allocator>
+ unordered_multimap(InputIterator, InputIterator, std::size_t, Allocator)
+ ->unordered_multimap<boost::unordered::detail::iter_key_t<InputIterator>,
+ boost::unordered::detail::iter_val_t<InputIterator>,
+ boost::hash<boost::unordered::detail::iter_key_t<InputIterator> >,
+ std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
+ Allocator>;
+
+ template <class InputIterator, class Allocator>
+ unordered_multimap(InputIterator, InputIterator, Allocator)
+ ->unordered_multimap<boost::unordered::detail::iter_key_t<InputIterator>,
+ boost::unordered::detail::iter_val_t<InputIterator>,
+ boost::hash<boost::unordered::detail::iter_key_t<InputIterator> >,
+ std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
+ Allocator>;
+
+ template <class InputIterator, class Hash, class Allocator>
+ unordered_multimap(
+ InputIterator, InputIterator, std::size_t, Hash, Allocator)
+ ->unordered_multimap<boost::unordered::detail::iter_key_t<InputIterator>,
+ boost::unordered::detail::iter_val_t<InputIterator>, Hash,
+ std::equal_to<boost::unordered::detail::iter_key_t<InputIterator> >,
+ Allocator>;
+
+ template <class Key, class T, typename Allocator>
+ unordered_multimap(
+ std::initializer_list<std::pair<const Key, T> >, std::size_t, Allocator)
+ ->unordered_multimap<Key, T, boost::hash<Key>, std::equal_to<Key>,
+ Allocator>;
+
+ template <class Key, class T, typename Allocator>
+ unordered_multimap(
+ std::initializer_list<std::pair<const Key, T> >, Allocator)
+ ->unordered_multimap<Key, T, boost::hash<Key>, std::equal_to<Key>,
+ Allocator>;
+
+ template <class Key, class T, class Hash, class Allocator>
+ unordered_multimap(std::initializer_list<std::pair<const Key, T> >,
+ std::size_t, Hash, Allocator)
+ ->unordered_multimap<Key, T, Hash, std::equal_to<Key>, Allocator>;
+
+#endif
+
////////////////////////////////////////////////////////////////////////////
template <class K, class T, class H, class P, class A>
@@ -1598,10 +1736,9 @@ namespace boost {
template <class K, class T, class H, class P, class A>
void unordered_map<K, T, H, P, A>::swap(unordered_map& other)
- // C++17 support: BOOST_NOEXCEPT_IF(
- // value_allocator_traits::is_always_equal::value &&
- // is_nothrow_move_assignable_v<H> &&
- // is_nothrow_move_assignable_v<P>)
+ BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&&
+ boost::is_nothrow_swappable<H>::value&&
+ boost::is_nothrow_swappable<P>::value)
{
table_.swap(other.table_);
}
@@ -2075,10 +2212,9 @@ namespace boost {
template <class K, class T, class H, class P, class A>
void unordered_multimap<K, T, H, P, A>::swap(unordered_multimap& other)
- // C++17 support: BOOST_NOEXCEPT_IF(
- // value_allocator_traits::is_always_equal::value &&
- // is_nothrow_move_assignable_v<H> &&
- // is_nothrow_move_assignable_v<P>)
+ BOOST_NOEXCEPT_IF(value_allocator_traits::is_always_equal::value&&
+ boost::is_nothrow_swappable<H>::value&&
+ boost::is_nothrow_swappable<P>::value)
{
table_.swap(other.table_);
}
@@ -2314,72 +2450,51 @@ namespace boost {
private:
node_pointer ptr_;
- bool has_alloc_;
- boost::unordered::detail::value_base<value_allocator> alloc_;
+ boost::unordered::detail::optional<value_allocator> alloc_;
node_handle_map(node_pointer ptr, allocator_type const& a)
- : ptr_(ptr), has_alloc_(false)
+ : ptr_(ptr), alloc_(a)
{
- if (ptr_) {
- new ((void*)&alloc_) value_allocator(a);
- has_alloc_ = true;
- }
}
public:
- BOOST_CONSTEXPR node_handle_map() BOOST_NOEXCEPT : ptr_(),
- has_alloc_(false)
- {
- }
+ BOOST_CONSTEXPR node_handle_map() BOOST_NOEXCEPT : ptr_(), alloc_() {}
~node_handle_map()
{
- if (has_alloc_ && ptr_) {
- node_allocator node_alloc(alloc_.value());
+ if (ptr_) {
+ node_allocator node_alloc(*alloc_);
boost::unordered::detail::node_tmp<node_allocator> tmp(
ptr_, node_alloc);
}
- if (has_alloc_) {
- alloc_.value_ptr()->~value_allocator();
- }
}
node_handle_map(BOOST_RV_REF(node_handle_map) n) BOOST_NOEXCEPT
: ptr_(n.ptr_),
- has_alloc_(false)
- {
- if (n.has_alloc_) {
- new ((void*)&alloc_) value_allocator(boost::move(n.alloc_.value()));
- has_alloc_ = true;
- n.ptr_ = node_pointer();
- n.alloc_.value_ptr()->~value_allocator();
- n.has_alloc_ = false;
- }
+ alloc_(boost::move(n.alloc_))
+ {
+ n.ptr_ = node_pointer();
}
node_handle_map& operator=(BOOST_RV_REF(node_handle_map) n)
{
- BOOST_ASSERT(!has_alloc_ ||
+ BOOST_ASSERT(!alloc_.has_value() ||
value_allocator_traits::
propagate_on_container_move_assignment::value ||
- (n.has_alloc_ && alloc_.value() == n.alloc_.value()));
+ (n.alloc_.has_value() && alloc_ == n.alloc_));
if (ptr_) {
- node_allocator node_alloc(alloc_.value());
+ node_allocator node_alloc(*alloc_);
boost::unordered::detail::node_tmp<node_allocator> tmp(
ptr_, node_alloc);
ptr_ = node_pointer();
}
- if (has_alloc_) {
- alloc_.value_ptr()->~value_allocator();
- has_alloc_ = false;
- }
-
- if (!has_alloc_ && n.has_alloc_) {
- move_allocator(n);
+ if (!alloc_.has_value() ||
+ value_allocator_traits::propagate_on_container_move_assignment::
+ value) {
+ alloc_ = boost::move(n.alloc_);
}
-
ptr_ = n.ptr_;
n.ptr_ = node_pointer();
@@ -2393,7 +2508,7 @@ namespace boost {
mapped_type& mapped() const { return ptr_->value().second; }
- allocator_type get_allocator() const { return alloc_.value(); }
+ allocator_type get_allocator() const { return *alloc_; }
BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
@@ -2402,38 +2517,19 @@ namespace boost {
bool empty() const BOOST_NOEXCEPT { return ptr_ ? 0 : 1; }
void swap(node_handle_map& n) BOOST_NOEXCEPT_IF(
- value_allocator_traits::propagate_on_container_swap::value
- /* || value_allocator_traits::is_always_equal::value */)
- {
- if (!has_alloc_) {
- if (n.has_alloc_) {
- move_allocator(n);
- }
- } else if (!n.has_alloc_) {
- n.move_allocator(*this);
- } else {
- swap_impl(
- n, boost::unordered::detail::integral_constant<bool,
- value_allocator_traits::propagate_on_container_swap::value>());
+ value_allocator_traits::propagate_on_container_swap::value ||
+ value_allocator_traits::is_always_equal::value)
+ {
+ BOOST_ASSERT(
+ !alloc_.has_value() || !n.alloc_.has_value() ||
+ value_allocator_traits::propagate_on_container_swap::value ||
+ alloc_ == n.alloc_);
+ if (value_allocator_traits::propagate_on_container_swap::value ||
+ !alloc_.has_value() || !n.alloc_.has_value()) {
+ boost::swap(alloc_, n.alloc_);
}
boost::swap(ptr_, n.ptr_);
}
-
- private:
- void move_allocator(node_handle_map& n)
- {
- new ((void*)&alloc_) value_allocator(boost::move(n.alloc_.value()));
- n.alloc_.value_ptr()->~value_allocator();
- has_alloc_ = true;
- n.has_alloc_ = false;
- }
-
- void swap_impl(node_handle_map&, boost::unordered::detail::false_type) {}
-
- void swap_impl(node_handle_map& n, boost::unordered::detail::true_type)
- {
- boost::swap(alloc_, n.alloc_);
- }
};
template <class N, class K, class T, class A>