@@ -185,25 +185,22 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
/**
* @brief %Map copy constructor.
- * @param __x A %map of identical element and allocator types.
*
- * The newly-created %map uses a copy of the allocator object used
- * by @a __x (unless the allocator traits dictate a different object).
+ * Whether the allocator is copied depends on the allocator traits.
*/
+#if __cplusplus < 201103L
map(const map& __x)
: _M_t(__x._M_t) { }
+#else
+ map(const map&) = default;
-#if __cplusplus >= 201103L
/**
* @brief %Map move constructor.
- * @param __x A %map of identical element and allocator types.
*
- * The newly-created %map contains the exact contents of @a __x.
- * The contents of @a __x are a valid, but unspecified %map.
+ * The newly-created %map contains the exact contents of the moved
+ * instance. The moved instance is a valid, but unspecified, %map.
*/
- map(map&& __x)
- noexcept(is_nothrow_copy_constructible<_Compare>::value)
- : _M_t(std::move(__x._M_t)) { }
+ map(map&&) = default;
/**
* @brief Builds a %map from an initializer_list.
@@ -284,31 +281,31 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
: _M_t(__comp, _Pair_alloc_type(__a))
{ _M_t._M_insert_unique(__first, __last); }
- // FIXME There is no dtor declared, but we should have something
- // generated by Doxygen. I don't know what tags to add to this
- // paragraph to make that happen:
+#if __cplusplus >= 201103L
/**
* 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.
*/
+ ~map() = default;
+#endif
/**
* @brief %Map assignment operator.
- * @param __x A %map of identical element and allocator types.
- *
- * All the elements of @a __x are copied.
*
* Whether the allocator is copied depends on the allocator traits.
*/
+#if __cplusplus < 201103L
map&
operator=(const map& __x)
{
_M_t = __x._M_t;
return *this;
}
+#else
+ map&
+ operator=(const map&) = default;
-#if __cplusplus >= 201103L
/// Move assignment operator.
map&
operator=(map&&) = default;
@@ -182,25 +182,23 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
/**
* @brief %Multimap copy constructor.
- * @param __x A %multimap of identical element and allocator types.
*
- * The newly-created %multimap uses a copy of the allocator object used
- * by @a __x (unless the allocator traits dictate a different object).
+ * Whether the allocator is copied depends on the allocator traits.
*/
+#if __cplusplus < 201103L
multimap(const multimap& __x)
: _M_t(__x._M_t) { }
+#else
+ multimap(const multimap&) = default;
-#if __cplusplus >= 201103L
/**
* @brief %Multimap move constructor.
- * @param __x A %multimap of identical element and allocator types.
*
- * The newly-created %multimap contains the exact contents of @a __x.
- * The contents of @a __x are a valid, but unspecified %multimap.
+ * The newly-created %multimap contains the exact contents of the
+ * moved instance. The moved instance is a valid, but unspecified
+ * %multimap.
*/
- multimap(multimap&& __x)
- noexcept(is_nothrow_copy_constructible<_Compare>::value)
- : _M_t(std::move(__x._M_t)) { }
+ multimap(multimap&&) = default;
/**
* @brief Builds a %multimap from an initializer_list.
@@ -278,31 +276,31 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
: _M_t(__comp, _Pair_alloc_type(__a))
{ _M_t._M_insert_equal(__first, __last); }
- // FIXME There is no dtor declared, but we should have something generated
- // by Doxygen. I don't know what tags to add to this paragraph to make
- // that happen:
+#if __cplusplus >= 201103L
/**
* 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.
*/
+ ~multimap() = default;
+#endif
/**
* @brief %Multimap assignment operator.
- * @param __x A %multimap of identical element and allocator types.
- *
- * All the elements of @a __x are copied.
*
* Whether the allocator is copied depends on the allocator traits.
*/
+#if __cplusplus < 201103L
multimap&
operator=(const multimap& __x)
{
_M_t = __x._M_t;
return *this;
}
+#else
+ multimap&
+ operator=(const multimap&) = default;
-#if __cplusplus >= 201103L
/// Move assignment operator.
multimap&
operator=(multimap&&) = default;
@@ -194,25 +194,23 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
/**
* @brief %Multiset copy constructor.
- * @param __x A %multiset of identical element and allocator types.
*
- * The newly-created %multiset uses a copy of the allocator object used
- * by @a __x (unless the allocator traits dictate a different object).
+ * 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.
@@ -256,24 +254,31 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
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.
*
* 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;
@@ -199,25 +199,22 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
/**
* @brief %Set copy constructor.
- * @param __x A %set of identical element and allocator types.
*
- * The newly-created %set uses a copy of the allocator object used
- * by @a __x (unless the allocator traits dictate a different object).
+ * Whether the allocator is copied depends on the allocator traits.
*/
+#if __cplusplus < 201103L
set(const set& __x)
: _M_t(__x._M_t) { }
+#else
+ set(const set&) = default;
-#if __cplusplus >= 201103L
/**
* @brief %Set move constructor
- * @param __x A %set of identical element and allocator types.
*
- * The newly-created %set contains the exact contents of @a x.
- * The contents of @a x are a valid, but unspecified %set.
+ * The newly-created %set contains the exact contents of the moved
+ * instance. The moved instance is a valid, but unspecified, %set.
*/
- set(set&& __x)
- noexcept(is_nothrow_copy_constructible<_Compare>::value)
- : _M_t(std::move(__x._M_t)) { }
+ set(set&&) = default;
/**
* @brief Builds a %set from an initializer_list.
@@ -261,24 +258,31 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
const allocator_type& __a)
: _M_t(_Compare(), _Key_alloc_type(__a))
{ _M_t._M_insert_unique(__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.
+ */
+ ~set() = default;
#endif
/**
* @brief %Set assignment operator.
- * @param __x A %set of identical element and allocator types.
- *
- * All the elements of @a __x are copied.
*
* Whether the allocator is copied depends on the allocator traits.
*/
+#if __cplusplus < 201103L
set&
operator=(const set& __x)
{
_M_t = __x._M_t;
return *this;
}
+#else
+ set&
+ operator=(const set&) = default;
-#if __cplusplus >= 201103L
/// Move assignment operator.
set&
operator=(set&&) = default;
@@ -137,6 +137,81 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
};
+ // Helper type offering value initialization guaranty on the compare functor.
+ template<typename _Key_compare>
+ struct _Rb_tree_key_compare
+ {
+ _Key_compare _M_key_compare;
+
+ _Rb_tree_key_compare()
+ _GLIBCXX_NOEXCEPT_IF(
+ is_nothrow_default_constructible<_Key_compare>::value)
+ : _M_key_compare()
+ { }
+
+ _Rb_tree_key_compare(const _Key_compare& __comp)
+ : _M_key_compare(__comp)
+ { }
+
+#if __cplusplus >= 201103L
+ _Rb_tree_key_compare(_Rb_tree_key_compare&& __x)
+ noexcept(is_nothrow_copy_constructible<_Key_compare>::value)
+ : _M_key_compare(__x._M_key_compare)
+ { }
+#endif
+ };
+
+ // Helper type to manage default initialization of node count and header.
+ struct _Rb_tree_header
+ {
+ _Rb_tree_node_base _M_header;
+ size_t _M_node_count; // Keeps track of size of tree.
+
+ _Rb_tree_header() _GLIBCXX_NOEXCEPT
+ : _M_node_count(0)
+ { _M_initialize(); }
+
+#if __cplusplus >= 201103L
+ _Rb_tree_header(_Rb_tree_header&& __x) noexcept
+ : _M_node_count(0)
+ {
+ if (__x._M_header._M_parent != nullptr)
+ _M_move_data(__x);
+ else
+ _M_initialize();
+ }
+
+ void
+ _M_move_data(_Rb_tree_header& __x)
+ {
+ _M_header._M_parent = __x._M_header._M_parent;
+ _M_header._M_left = __x._M_header._M_left;
+ _M_header._M_right = __x._M_header._M_right;
+ _M_header._M_parent->_M_parent = &_M_header;
+ _M_node_count = __x._M_node_count;
+
+ __x._M_reset();
+ }
+#endif
+
+ void
+ _M_reset()
+ {
+ _M_initialize();
+ _M_node_count = 0;
+ }
+
+ private:
+ void
+ _M_initialize()
+ {
+ _M_header._M_color = _S_red;
+ _M_header._M_parent = 0;
+ _M_header._M_left = &_M_header;
+ _M_header._M_right = &_M_header;
+ }
+ };
+
template<typename _Val>
struct _Rb_tree_node : public _Rb_tree_node_base
{
@@ -599,50 +674,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Unused _Is_pod_comparator is kept as it is part of mangled name.
template<typename _Key_compare,
bool /* _Is_pod_comparator */ = __is_pod(_Key_compare)>
- struct _Rb_tree_impl : public _Node_allocator
+ struct _Rb_tree_impl
+ : public _Node_allocator
+ , public _Rb_tree_key_compare<_Key_compare>
+ , public _Rb_tree_header
{
- _Key_compare _M_key_compare;
- _Rb_tree_node_base _M_header;
- size_type _M_node_count; // Keeps track of size of tree.
+ typedef _Rb_tree_key_compare<_Key_compare> _Base_key_compare;
+#if __cplusplus < 201103L
_Rb_tree_impl()
- _GLIBCXX_NOEXCEPT_IF(
- is_nothrow_default_constructible<_Node_allocator>::value
- && is_nothrow_default_constructible<_Key_compare>::value)
- : _Node_allocator(), _M_key_compare(), _M_header(),
- _M_node_count(0)
- { _M_initialize(); }
+ { }
+#else
+ _Rb_tree_impl() = default;
+#endif
- _Rb_tree_impl(const _Key_compare& __comp, const _Node_allocator& __a)
- : _Node_allocator(__a), _M_key_compare(__comp), _M_header(),
- _M_node_count(0)
- { _M_initialize(); }
+ _Rb_tree_impl(const _Rb_tree_impl& __x)
+ : _Node_allocator(_Alloc_traits::_S_select_on_copy(__x))
+ , _Base_key_compare(__x._M_key_compare)
+ { }
#if __cplusplus >= 201103L
+ _Rb_tree_impl(_Rb_tree_impl&&) = default;
_Rb_tree_impl(const _Key_compare& __comp, _Node_allocator&& __a)
- : _Node_allocator(std::move(__a)), _M_key_compare(__comp),
- _M_header(), _M_node_count(0)
- { _M_initialize(); }
+ : _Node_allocator(std::move(__a)), _Base_key_compare(__comp)
+ { }
#endif
-
- void
- _M_reset()
- {
- this->_M_header._M_parent = 0;
- this->_M_header._M_left = &this->_M_header;
- this->_M_header._M_right = &this->_M_header;
- this->_M_node_count = 0;
- }
-
- private:
- void
- _M_initialize()
- {
- this->_M_header._M_color = _S_red;
- this->_M_header._M_parent = 0;
- this->_M_header._M_left = &this->_M_header;
- this->_M_header._M_right = &this->_M_header;
- }
};
_Rb_tree_impl<_Compare> _M_impl;
@@ -845,8 +901,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: _M_impl(__comp, _Node_allocator(__a)) { }
_Rb_tree(const _Rb_tree& __x)
- : _M_impl(__x._M_impl._M_key_compare,
- _Alloc_traits::_S_select_on_copy(__x._M_get_Node_allocator()))
+ : _M_impl(__x._M_impl)
{
if (__x._M_root() != 0)
{
@@ -874,13 +929,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
}
- _Rb_tree(_Rb_tree&& __x)
- : _M_impl(__x._M_impl._M_key_compare,
- std::move(__x._M_get_Node_allocator()))
- {
- if (__x._M_root() != 0)
- _M_move_data(__x, std::true_type());
- }
+ _Rb_tree(_Rb_tree&&) = default;
_Rb_tree(_Rb_tree&& __x, const allocator_type& __a)
: _Rb_tree(std::move(__x), _Node_allocator(__a))
@@ -1534,19 +1583,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void
_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
_M_move_data(_Rb_tree& __x, std::true_type)
- {
- _M_root() = __x._M_root();
- _M_leftmost() = __x._M_leftmost();
- _M_rightmost() = __x._M_rightmost();
- _M_root()->_M_parent = _M_end();
-
- __x._M_root() = 0;
- __x._M_leftmost() = __x._M_end();
- __x._M_rightmost() = __x._M_end();
-
- this->_M_impl._M_node_count = __x._M_impl._M_node_count;
- __x._M_impl._M_node_count = 0;
- }
+ { _M_impl._M_move_data(__x._M_impl); }
template<typename _Key, typename _Val, typename _KeyOfValue,
typename _Compare, typename _Alloc>