// Multiset implementation -*- C++ -*-
-// Copyright (C) 2001-2015 Free Software Foundation, Inc.
+// Copyright (C) 2001-2017 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
{
_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
+ template<typename _Key, typename _Compare, typename _Alloc>
+ class set;
+
/**
* @brief A standard container made up of elements, which can be retrieved
* in logarithmic time.
typedef typename _Rep_type::size_type size_type;
typedef typename _Rep_type::difference_type difference_type;
+#if __cplusplus > 201402L
+ using node_type = typename _Rep_type::node_type;
+#endif
+
// allocation/deallocation
/**
* @brief Default constructor creates no elements.
*/
- multiset()
-#if __cplusplus >= 201103L
- noexcept(is_nothrow_default_constructible<allocator_type>::value)
+#if __cplusplus < 201103L
+ multiset() : _M_t() { }
+#else
+ multiset() = default;
#endif
- : _M_t() { }
/**
* @brief Creates a %multiset with no elements.
/**
* @brief %Multiset copy constructor.
- * @param __x A %multiset of identical element and allocator types.
*
- * The newly-created %multiset uses a copy of the allocation object used
- * by @a __x.
+ * Whether the allocator is copied depends on the allocator traits.
*/
+#if __cplusplus < 201103L
multiset(const multiset& __x)
: _M_t(__x._M_t) { }
+#else
+ multiset(const multiset&) = default;
-#if __cplusplus >= 201103L
/**
* @brief %Multiset move constructor.
- * @param __x A %multiset of identical element and allocator types.
*
- * The newly-created %multiset contains the exact contents of @a __x.
- * The contents of @a __x are a valid, but unspecified %multiset.
+ * The newly-created %multiset contains the exact contents of the
+ * moved instance. The moved instance is a valid, but unspecified
+ * %multiset.
*/
- multiset(multiset&& __x)
- noexcept(is_nothrow_copy_constructible<_Compare>::value)
- : _M_t(std::move(__x._M_t)) { }
+ multiset(multiset&&) = default;
/**
* @brief Builds a %multiset from an initializer_list.
const allocator_type& __a)
: _M_t(_Compare(), _Key_alloc_type(__a))
{ _M_t._M_insert_equal(__first, __last); }
+
+ /**
+ * The dtor only erases the elements, and note that if the elements
+ * themselves are pointers, the pointed-to memory is not touched in any
+ * way. Managing the pointer is the user's responsibility.
+ */
+ ~multiset() = default;
#endif
/**
* @brief %Multiset assignment operator.
- * @param __x A %multiset of identical element and allocator types.
*
- * All the elements of @a __x are copied, but unlike the copy
- * constructor, the allocator object is not copied.
+ * Whether the allocator is copied depends on the allocator traits.
*/
+#if __cplusplus < 201103L
multiset&
operator=(const multiset& __x)
{
_M_t = __x._M_t;
return *this;
}
+#else
+ multiset&
+ operator=(const multiset&) = default;
-#if __cplusplus >= 201103L
/// Move assignment operator.
multiset&
operator=(multiset&&) = default;
*
* Note that the assignment completely changes the %multiset and
* that the resulting %multiset's size is the same as the number
- * of elements assigned. Old data may be lost.
+ * of elements assigned.
*/
multiset&
operator=(initializer_list<value_type> __l)
* be quite fast.)
* Note that the global std::swap() function is specialized such that
* std::swap(s1,s2) will feed to this function.
+ *
+ * Whether the allocators are swapped depends on the allocator traits.
*/
void
swap(multiset& __x)
-#if __cplusplus >= 201103L
- noexcept(_Alloc_traits::_S_nothrow_swap())
-#endif
+ _GLIBCXX_NOEXCEPT_IF(__is_nothrow_swappable<_Compare>::value)
{ _M_t.swap(__x._M_t); }
// insert/erase
{ this->insert(__l.begin(), __l.end()); }
#endif
+#if __cplusplus > 201402L
+ /// Extract a node.
+ node_type
+ extract(const_iterator __pos)
+ {
+ __glibcxx_assert(__pos != end());
+ return _M_t.extract(__pos);
+ }
+
+ /// Extract a node.
+ node_type
+ extract(const key_type& __x)
+ { return _M_t.extract(__x); }
+
+ /// Re-insert an extracted node.
+ iterator
+ insert(node_type&& __nh)
+ { return _M_t._M_reinsert_node_equal(std::move(__nh)); }
+
+ /// Re-insert an extracted node.
+ iterator
+ insert(const_iterator __hint, node_type&& __nh)
+ { return _M_t._M_reinsert_node_hint_equal(__hint, std::move(__nh)); }
+
+ template<typename, typename>
+ friend class _Rb_tree_merge_helper;
+
+ template<typename _Compare1>
+ void
+ merge(multiset<_Key, _Compare1, _Alloc>& __source)
+ {
+ using _Merge_helper = _Rb_tree_merge_helper<multiset, _Compare1>;
+ _M_t._M_merge_equal(_Merge_helper::_S_get_tree(__source));
+ }
+
+ template<typename _Compare1>
+ void
+ merge(multiset<_Key, _Compare1, _Alloc>&& __source)
+ { merge(__source); }
+
+ template<typename _Compare1>
+ void
+ merge(set<_Key, _Compare1, _Alloc>& __source)
+ {
+ using _Merge_helper = _Rb_tree_merge_helper<multiset, _Compare1>;
+ _M_t._M_merge_equal(_Merge_helper::_S_get_tree(__source));
+ }
+
+ template<typename _Compare1>
+ void
+ merge(set<_Key, _Compare1, _Alloc>&& __source)
+ { merge(__source); }
+#endif // C++17
+
#if __cplusplus >= 201103L
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// DR 130. Associative erase should return an iterator.
#if __cplusplus > 201103L
template<typename _Kt>
auto
- find(const _Kt& __x) -> decltype(_M_t._M_find_tr(__x))
- { return _M_t._M_find_tr(__x); }
+ find(const _Kt& __x)
+ -> decltype(iterator{_M_t._M_find_tr(__x)})
+ { return iterator{_M_t._M_find_tr(__x)}; }
template<typename _Kt>
auto
- find(const _Kt& __x) const -> decltype(_M_t._M_find_tr(__x))
- { return _M_t._M_find_tr(__x); }
+ find(const _Kt& __x) const
+ -> decltype(const_iterator{_M_t._M_find_tr(__x)})
+ { return const_iterator{_M_t._M_find_tr(__x)}; }
#endif
//@}
inline void
swap(multiset<_Key, _Compare, _Alloc>& __x,
multiset<_Key, _Compare, _Alloc>& __y)
+ _GLIBCXX_NOEXCEPT_IF(noexcept(__x.swap(__y)))
{ __x.swap(__y); }
_GLIBCXX_END_NAMESPACE_CONTAINER
+
+#if __cplusplus > 201402L
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+ // Allow std::multiset access to internals of compatible sets.
+ template<typename _Val, typename _Cmp1, typename _Alloc, typename _Cmp2>
+ struct
+ _Rb_tree_merge_helper<_GLIBCXX_STD_C::multiset<_Val, _Cmp1, _Alloc>,
+ _Cmp2>
+ {
+ private:
+ friend class _GLIBCXX_STD_C::multiset<_Val, _Cmp1, _Alloc>;
+
+ static auto&
+ _S_get_tree(_GLIBCXX_STD_C::set<_Val, _Cmp2, _Alloc>& __set)
+ { return __set._M_t; }
+
+ static auto&
+ _S_get_tree(_GLIBCXX_STD_C::multiset<_Val, _Cmp2, _Alloc>& __set)
+ { return __set._M_t; }
+ };
+_GLIBCXX_END_NAMESPACE_VERSION
+#endif // C++17
+
} // namespace std
#endif /* _STL_MULTISET_H */