Commit a2b5fdcb by Jonathan Wakely Committed by Jonathan Wakely

Implement N4258 (Cleaning-up noexcept in the Library rev 3)

	* doc/xml/manual/intro.xml: Document LWG 2108 status.
	* include/bits/alloc_traits.h (allocator_traits::is_always_equal):
	Define.
	* include/bits/allocator.h (allocator::is_always_equal): Likewise.
	* include/bits/forward_list.h
	(forward_list::operator=(forward_list&&)): Use __bool_constant.
	(forward_list::swap(forward_list&)): Add noexcept.
	* include/bits/hashtable.h (_Hashtable::operator=(_Hashtable&&)):
	Likewise.
	(_Hashtable::swap(_Hashtable&)): Likewise.
	* include/bits/stl_deque.h (_Deque_base::_Deque_base(_Deque_base&&)):
	Use _Alloc_traits::is_always_equal.
	(deque::operator=(deque&&)): Likewise.
	(deque::_M_move_assign1(deque&&, false_type)): Add comment and use
	__bool_constant.
	(swap(deque&, deque&)): Add noexcept.
	* include/bits/stl_list.h (list::operator=(list&&)): Use
	__bool_constant.
	(swap(list&, list&)): Add noexcept.
	* include/bits/stl_map.h (map::swap(map&)): Include _Compare in
	noexcept.
	(swap(map&, map&)): Add noexcept.
	* include/bits/stl_multimap.h (multimap::swap(multimap&)): Include
	_Compare in noexcept.
	(swap(multimap&, multimap&)): Add noexcept.
	* include/bits/stl_multiset.h (multiset::swap(multiset&)): Include
	_Compare in noexcept.
	(swap(multiset&, multiset&)): Add noexcept.
	* include/bits/stl_set.h (set::swap(set&)): Include _Compare in
	noexcept.
	(swap(set&, set&)): Add noexcept.
	* include/bits/stl_tree.h (_Rb_tree::operator=(_Rb_tree&&)): Include
	_Compare in noexcept.
	(_Rb_tree::_Rb_tree(_Rb_tree&&, _Node_alloc_type&&)): Use
	is_always_equal.
	* include/bits/stl_vector.h (vector::operator=(vector&&)): Use
	__bool_constant.
	(swap(vector&, vector&)): Add noexcept.
	* include/bits/unordered_map.h (swap(unordered_map&, unordered_map&),
	swap(unordered_multimap& unordered_multimap&)): Add noexcept.
	* include/bits/unordered_set.h (swap(unordered_set&, unordered_set&),
	swap(unordered_multiset& unordered_multiset&)): Add noexcept.
	* include/ext/alloc_traits.h (__allocator_always_compares_equal):
	Remove.
	(__alloc_traits::_S_always_equal()): Use is_always_equal instead of
	__allocator_always_compares_equal.
	* include/ext/array_allocator.h (array_allocator::is_always_equal):
	Define.
	* include/std/scoped_allocator (__any_of, __propagate_on_copy,
	__propagate_on_move, __propagate_on_swap): Remove.
	(scoped_allocator_adaptor::propagate_on_container_copy_assignment,
	scoped_allocator_adaptor::propagate_on_container_move_assignment,
	scoped_allocator_adaptor::propagate_on_container_swap): Define with
	__and_ instead of __any_of.
	(scoped_allocator_adaptor::is_always_equal): Define.
	* testsuite/20_util/allocator_traits/members/is_always_equal.cc: New.
	* testsuite/20_util/scoped_allocator/propagation.cc: Make traits
	derive from true_type or false_type.
	* testsuite/23_containers/deque/allocator/move_assign-2.cc: Add
	is_always_equal member and remove the trait specialization.
	* testsuite/23_containers/vector/52591.cc: Likewise.
	* testsuite/23_containers/deque/requirements/dr438/assign_neg.cc:
	Adjust dg-error line number.
	* testsuite/23_containers/deque/requirements/dr438/
	constructor_1_neg.cc: Likewise.
	* testsuite/23_containers/deque/requirements/dr438/
	constructor_2_neg.cc: Likewise.
	* testsuite/23_containers/deque/requirements/dr438/insert_neg.cc:
	Likewise.
	* testsuite/23_containers/list/requirements/dr438/assign_neg.cc:
	Likewise.
	* testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc:
	Likewise.
	* testsuite/23_containers/list/requirements/dr438/insert_neg.cc:
	Likewise.
	* testsuite/23_containers/vector/requirements/dr438/assign_neg.cc:
	Likewise.
	* testsuite/23_containers/vector/requirements/dr438/
	constructor_1_neg.cc: Likewise.
	* testsuite/23_containers/vector/requirements/dr438/
	constructor_2_neg.cc: Likewise.
	* testsuite/23_containers/vector/requirements/dr438/insert_neg.cc:
	Likewise.

From-SVN: r225081
parent 22d03525
2015-06-26 Jonathan Wakely <jwakely@redhat.com> 2015-06-26 Jonathan Wakely <jwakely@redhat.com>
* doc/xml/manual/intro.xml: Document LWG 2108 status.
* include/bits/alloc_traits.h (allocator_traits::is_always_equal):
Define.
* include/bits/allocator.h (allocator::is_always_equal): Likewise.
* include/bits/forward_list.h
(forward_list::operator=(forward_list&&)): Use __bool_constant.
(forward_list::swap(forward_list&)): Add noexcept.
* include/bits/hashtable.h (_Hashtable::operator=(_Hashtable&&)):
Likewise.
(_Hashtable::swap(_Hashtable&)): Likewise.
* include/bits/stl_deque.h (_Deque_base::_Deque_base(_Deque_base&&)):
Use _Alloc_traits::is_always_equal.
(deque::operator=(deque&&)): Likewise.
(deque::_M_move_assign1(deque&&, false_type)): Add comment and use
__bool_constant.
(swap(deque&, deque&)): Add noexcept.
* include/bits/stl_list.h (list::operator=(list&&)): Use
__bool_constant.
(swap(list&, list&)): Add noexcept.
* include/bits/stl_map.h (map::swap(map&)): Include _Compare in
noexcept.
(swap(map&, map&)): Add noexcept.
* include/bits/stl_multimap.h (multimap::swap(multimap&)): Include
_Compare in noexcept.
(swap(multimap&, multimap&)): Add noexcept.
* include/bits/stl_multiset.h (multiset::swap(multiset&)): Include
_Compare in noexcept.
(swap(multiset&, multiset&)): Add noexcept.
* include/bits/stl_set.h (set::swap(set&)): Include _Compare in
noexcept.
(swap(set&, set&)): Add noexcept.
* include/bits/stl_tree.h (_Rb_tree::operator=(_Rb_tree&&)): Include
_Compare in noexcept.
(_Rb_tree::_Rb_tree(_Rb_tree&&, _Node_alloc_type&&)): Use
is_always_equal.
* include/bits/stl_vector.h (vector::operator=(vector&&)): Use
__bool_constant.
(swap(vector&, vector&)): Add noexcept.
* include/bits/unordered_map.h (swap(unordered_map&, unordered_map&),
swap(unordered_multimap& unordered_multimap&)): Add noexcept.
* include/bits/unordered_set.h (swap(unordered_set&, unordered_set&),
swap(unordered_multiset& unordered_multiset&)): Add noexcept.
* include/ext/alloc_traits.h (__allocator_always_compares_equal):
Remove.
(__alloc_traits::_S_always_equal()): Use is_always_equal instead of
__allocator_always_compares_equal.
* include/ext/array_allocator.h (array_allocator::is_always_equal):
Define.
* include/std/scoped_allocator (__any_of, __propagate_on_copy,
__propagate_on_move, __propagate_on_swap): Remove.
(scoped_allocator_adaptor::propagate_on_container_copy_assignment,
scoped_allocator_adaptor::propagate_on_container_move_assignment,
scoped_allocator_adaptor::propagate_on_container_swap): Define with
__and_ instead of __any_of.
(scoped_allocator_adaptor::is_always_equal): Define.
* testsuite/20_util/allocator_traits/members/is_always_equal.cc: New.
* testsuite/20_util/scoped_allocator/propagation.cc: Make traits
derive from true_type or false_type.
* testsuite/23_containers/deque/allocator/move_assign-2.cc: Add
is_always_equal member and remove the trait specialization.
* testsuite/23_containers/vector/52591.cc: Likewise.
* testsuite/23_containers/deque/requirements/dr438/assign_neg.cc:
Adjust dg-error line number.
* testsuite/23_containers/deque/requirements/dr438/
constructor_1_neg.cc: Likewise.
* testsuite/23_containers/deque/requirements/dr438/
constructor_2_neg.cc: Likewise.
* testsuite/23_containers/deque/requirements/dr438/insert_neg.cc:
Likewise.
* testsuite/23_containers/list/requirements/dr438/assign_neg.cc:
Likewise.
* testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc:
Likewise.
* testsuite/23_containers/list/requirements/dr438/insert_neg.cc:
Likewise.
* testsuite/23_containers/vector/requirements/dr438/assign_neg.cc:
Likewise.
* testsuite/23_containers/vector/requirements/dr438/
constructor_1_neg.cc: Likewise.
* testsuite/23_containers/vector/requirements/dr438/
constructor_2_neg.cc: Likewise.
* testsuite/23_containers/vector/requirements/dr438/insert_neg.cc:
Likewise.
* include/bits/stl_bvector.h (vector<bool>::vector()): Add noexcept. * include/bits/stl_bvector.h (vector<bool>::vector()): Add noexcept.
* include/bits/stl_map.h (map::map()): Likewise. * include/bits/stl_map.h (map::map()): Likewise.
* include/bits/stl_multimap.h (multimap::multimap()): Likewise. * include/bits/stl_multimap.h (multimap::multimap()): Likewise.
......
...@@ -868,6 +868,12 @@ requirements of the license of GCC. ...@@ -868,6 +868,12 @@ requirements of the license of GCC.
<listitem><para>Change the <code>reference</code> type. <listitem><para>Change the <code>reference</code> type.
</para></listitem></varlistentry> </para></listitem></varlistentry>
<varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="../ext/lwg-defects.html#2108">2108</link>:
<emphasis>No way to identify allocator types that always compare equal</emphasis>
</term>
<listitem><para>Define and use <code>is_always_equal</code> even for C++11.
</para></listitem></varlistentry>
<varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="../ext/lwg-defects.html#2118">2118</link>: <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="../ext/lwg-defects.html#2118">2118</link>:
<emphasis><code>unique_ptr</code> for array does not support cv qualification conversion of actual argument</emphasis> <emphasis><code>unique_ptr</code> for array does not support cv qualification conversion of actual argument</emphasis>
</term> </term>
......
...@@ -194,6 +194,17 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap, ...@@ -194,6 +194,17 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap,
*/ */
typedef __propagate_on_container_swap propagate_on_container_swap; typedef __propagate_on_container_swap propagate_on_container_swap;
_GLIBCXX_ALLOC_TR_NESTED_TYPE(is_always_equal,
typename is_empty<_Alloc>::type)
/**
* @brief Whether all instances of the allocator type compare equal.
*
* @c Alloc::is_always_equal if that type exists,
* otherwise @c is_empty<Alloc>::type
*/
typedef __is_always_equal is_always_equal;
#undef _GLIBCXX_ALLOC_TR_NESTED_TYPE #undef _GLIBCXX_ALLOC_TR_NESTED_TYPE
template<typename _Tp> template<typename _Tp>
......
...@@ -77,6 +77,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -77,6 +77,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// _GLIBCXX_RESOLVE_LIB_DEFECTS // _GLIBCXX_RESOLVE_LIB_DEFECTS
// 2103. std::allocator propagate_on_container_move_assignment // 2103. std::allocator propagate_on_container_move_assignment
typedef true_type propagate_on_container_move_assignment; typedef true_type propagate_on_container_move_assignment;
typedef true_type is_always_equal;
#endif #endif
}; };
......
...@@ -587,8 +587,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -587,8 +587,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
constexpr bool __move_storage = constexpr bool __move_storage =
_Node_alloc_traits::_S_propagate_on_move_assign() _Node_alloc_traits::_S_propagate_on_move_assign()
|| _Node_alloc_traits::_S_always_equal(); || _Node_alloc_traits::_S_always_equal();
_M_move_assign(std::move(__list), _M_move_assign(std::move(__list), __bool_constant<__move_storage>());
integral_constant<bool, __move_storage>());
return *this; return *this;
} }
...@@ -1410,6 +1409,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -1410,6 +1409,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
inline void inline void
swap(forward_list<_Tp, _Alloc>& __lx, swap(forward_list<_Tp, _Alloc>& __lx,
forward_list<_Tp, _Alloc>& __ly) forward_list<_Tp, _Alloc>& __ly)
noexcept(noexcept(__lx.swap(__ly)))
{ __lx.swap(__ly); } { __lx.swap(__ly); }
_GLIBCXX_END_NAMESPACE_CONTAINER _GLIBCXX_END_NAMESPACE_CONTAINER
......
...@@ -451,13 +451,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -451,13 +451,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Hashtable& _Hashtable&
operator=(_Hashtable&& __ht) operator=(_Hashtable&& __ht)
noexcept(__node_alloc_traits::_S_nothrow_move()) noexcept(__node_alloc_traits::_S_nothrow_move()
&& is_nothrow_move_assignable<_H1>::value
&& is_nothrow_move_assignable<_Equal>::value)
{ {
constexpr bool __move_storage = constexpr bool __move_storage =
__node_alloc_traits::_S_propagate_on_move_assign() __node_alloc_traits::_S_propagate_on_move_assign()
|| __node_alloc_traits::_S_always_equal(); || __node_alloc_traits::_S_always_equal();
_M_move_assign(std::move(__ht), _M_move_assign(std::move(__ht), __bool_constant<__move_storage>());
integral_constant<bool, __move_storage>());
return *this; return *this;
} }
...@@ -475,7 +476,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -475,7 +476,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void void
swap(_Hashtable&) swap(_Hashtable&)
noexcept(__node_alloc_traits::_S_nothrow_swap()); noexcept(__node_alloc_traits::_S_nothrow_swap()
&& __is_nothrow_swappable<_H1>::value
&& __is_nothrow_swappable<_Equal>::value);
// Basic container operations // Basic container operations
iterator iterator
...@@ -1234,7 +1237,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -1234,7 +1237,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
_H1, _H2, _Hash, _RehashPolicy, _Traits>:: _H1, _H2, _Hash, _RehashPolicy, _Traits>::
swap(_Hashtable& __x) swap(_Hashtable& __x)
noexcept(__node_alloc_traits::_S_nothrow_swap()) noexcept(__node_alloc_traits::_S_nothrow_swap()
&& __is_nothrow_swappable<_H1>::value
&& __is_nothrow_swappable<_Equal>::value)
{ {
// The only base class with member variables is hash_code_base. // The only base class with member variables is hash_code_base.
// We define _Hash_code_base::_M_swap because different // We define _Hash_code_base::_M_swap because different
......
...@@ -515,8 +515,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -515,8 +515,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
} }
_Deque_base(_Deque_base&& __x) _Deque_base(_Deque_base&& __x)
: _Deque_base(std::move(__x), : _Deque_base(std::move(__x), typename _Alloc_traits::is_always_equal{})
__gnu_cxx::__allocator_always_compares_equal<_Alloc>{})
{ } { }
_Deque_base(_Deque_base&& __x, const allocator_type& __a, size_type __n) _Deque_base(_Deque_base&& __x, const allocator_type& __a, size_type __n)
...@@ -1059,9 +1058,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -1059,9 +1058,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
deque& deque&
operator=(deque&& __x) noexcept(_Alloc_traits::_S_always_equal()) operator=(deque&& __x) noexcept(_Alloc_traits::_S_always_equal())
{ {
constexpr bool __always_equal = _Alloc_traits::_S_always_equal(); using __always_equal = typename _Alloc_traits::is_always_equal;
_M_move_assign1(std::move(__x), _M_move_assign1(std::move(__x), __always_equal{});
integral_constant<bool, __always_equal>());
return *this; return *this;
} }
...@@ -2140,13 +2138,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -2140,13 +2138,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
std::__alloc_on_move(_M_get_Tp_allocator(), __x._M_get_Tp_allocator()); std::__alloc_on_move(_M_get_Tp_allocator(), __x._M_get_Tp_allocator());
} }
// When the allocators are not equal the operation could throw, because
// we might need to allocate a new map for __x after moving from it
// or we might need to allocate new elements for *this.
void void
_M_move_assign1(deque&& __x, /* always equal: */ false_type) _M_move_assign1(deque&& __x, /* always equal: */ false_type)
{ {
constexpr bool __move_storage = constexpr bool __move_storage =
_Alloc_traits::_S_propagate_on_move_assign(); _Alloc_traits::_S_propagate_on_move_assign();
_M_move_assign2(std::move(__x), _M_move_assign2(std::move(__x), __bool_constant<__move_storage>());
integral_constant<bool, __move_storage>());
} }
// Destroy all elements and deallocate all memory, then replace // Destroy all elements and deallocate all memory, then replace
...@@ -2271,6 +2271,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -2271,6 +2271,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _Tp, typename _Alloc> template<typename _Tp, typename _Alloc>
inline void inline void
swap(deque<_Tp,_Alloc>& __x, deque<_Tp,_Alloc>& __y) swap(deque<_Tp,_Alloc>& __x, deque<_Tp,_Alloc>& __y)
#if __cplusplus >= 201103L
noexcept(noexcept(__x.swap(__y)))
#endif
{ __x.swap(__y); } { __x.swap(__y); }
#undef _GLIBCXX_DEQUE_BUF_SIZE #undef _GLIBCXX_DEQUE_BUF_SIZE
......
...@@ -751,8 +751,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 ...@@ -751,8 +751,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
constexpr bool __move_storage = constexpr bool __move_storage =
_Node_alloc_traits::_S_propagate_on_move_assign() _Node_alloc_traits::_S_propagate_on_move_assign()
|| _Node_alloc_traits::_S_always_equal(); || _Node_alloc_traits::_S_always_equal();
_M_move_assign(std::move(__x), _M_move_assign(std::move(__x), __bool_constant<__move_storage>());
integral_constant<bool, __move_storage>());
return *this; return *this;
} }
...@@ -1920,6 +1919,9 @@ _GLIBCXX_END_NAMESPACE_CXX11 ...@@ -1920,6 +1919,9 @@ _GLIBCXX_END_NAMESPACE_CXX11
template<typename _Tp, typename _Alloc> template<typename _Tp, typename _Alloc>
inline void inline void
swap(list<_Tp, _Alloc>& __x, list<_Tp, _Alloc>& __y) swap(list<_Tp, _Alloc>& __x, list<_Tp, _Alloc>& __y)
#if __cplusplus >= 201103L
noexcept(noexcept(__x.swap(__y)))
#endif
{ __x.swap(__y); } { __x.swap(__y); }
_GLIBCXX_END_NAMESPACE_CONTAINER _GLIBCXX_END_NAMESPACE_CONTAINER
......
...@@ -795,7 +795,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -795,7 +795,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
void void
swap(map& __x) swap(map& __x)
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
noexcept(_Alloc_traits::_S_nothrow_swap()) noexcept(_Alloc_traits::_S_nothrow_swap()
&& __is_nothrow_swappable<_Compare>::value)
#endif #endif
{ _M_t.swap(__x._M_t); } { _M_t.swap(__x._M_t); }
...@@ -1124,6 +1125,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -1124,6 +1125,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
inline void inline void
swap(map<_Key, _Tp, _Compare, _Alloc>& __x, swap(map<_Key, _Tp, _Compare, _Alloc>& __x,
map<_Key, _Tp, _Compare, _Alloc>& __y) map<_Key, _Tp, _Compare, _Alloc>& __y)
#if __cplusplus >= 201103L
noexcept(noexcept(__x.swap(__y)))
#endif
{ __x.swap(__y); } { __x.swap(__y); }
_GLIBCXX_END_NAMESPACE_CONTAINER _GLIBCXX_END_NAMESPACE_CONTAINER
......
...@@ -705,7 +705,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -705,7 +705,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
void void
swap(multimap& __x) swap(multimap& __x)
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
noexcept(_Alloc_traits::_S_nothrow_swap()) noexcept(_Alloc_traits::_S_nothrow_swap()
&& __is_nothrow_swappable<_Compare>::value)
#endif #endif
{ _M_t.swap(__x._M_t); } { _M_t.swap(__x._M_t); }
...@@ -1025,6 +1026,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -1025,6 +1026,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
inline void inline void
swap(multimap<_Key, _Tp, _Compare, _Alloc>& __x, swap(multimap<_Key, _Tp, _Compare, _Alloc>& __x,
multimap<_Key, _Tp, _Compare, _Alloc>& __y) multimap<_Key, _Tp, _Compare, _Alloc>& __y)
#if __cplusplus >= 201103L
noexcept(noexcept(__x.swap(__y)))
#endif
{ __x.swap(__y); } { __x.swap(__y); }
_GLIBCXX_END_NAMESPACE_CONTAINER _GLIBCXX_END_NAMESPACE_CONTAINER
......
...@@ -407,7 +407,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -407,7 +407,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
void void
swap(multiset& __x) swap(multiset& __x)
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
noexcept(_Alloc_traits::_S_nothrow_swap()) noexcept(_Alloc_traits::_S_nothrow_swap()
&& __is_nothrow_swappable<_Compare>::value)
#endif #endif
{ _M_t.swap(__x._M_t); } { _M_t.swap(__x._M_t); }
...@@ -874,6 +875,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -874,6 +875,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
inline void inline void
swap(multiset<_Key, _Compare, _Alloc>& __x, swap(multiset<_Key, _Compare, _Alloc>& __x,
multiset<_Key, _Compare, _Alloc>& __y) multiset<_Key, _Compare, _Alloc>& __y)
#if __cplusplus >= 201103L
noexcept(noexcept(__x.swap(__y)))
#endif
{ __x.swap(__y); } { __x.swap(__y); }
_GLIBCXX_END_NAMESPACE_CONTAINER _GLIBCXX_END_NAMESPACE_CONTAINER
......
...@@ -411,7 +411,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -411,7 +411,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
void void
swap(set& __x) swap(set& __x)
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
noexcept(_Alloc_traits::_S_nothrow_swap()) noexcept(_Alloc_traits::_S_nothrow_swap()
&& __is_nothrow_swappable<_Compare>::value)
#endif #endif
{ _M_t.swap(__x._M_t); } { _M_t.swap(__x._M_t); }
...@@ -890,6 +891,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -890,6 +891,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _Key, typename _Compare, typename _Alloc> template<typename _Key, typename _Compare, typename _Alloc>
inline void inline void
swap(set<_Key, _Compare, _Alloc>& __x, set<_Key, _Compare, _Alloc>& __y) swap(set<_Key, _Compare, _Alloc>& __x, set<_Key, _Compare, _Alloc>& __y)
#if __cplusplus >= 201103L
noexcept(noexcept(__x.swap(__y)))
#endif
{ __x.swap(__y); } { __x.swap(__y); }
_GLIBCXX_END_NAMESPACE_CONTAINER _GLIBCXX_END_NAMESPACE_CONTAINER
......
...@@ -1241,7 +1241,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -1241,7 +1241,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
_Rb_tree& _Rb_tree&
operator=(_Rb_tree&&) noexcept(_Alloc_traits::_S_nothrow_move()); operator=(_Rb_tree&&)
noexcept(_Alloc_traits::_S_nothrow_move()
&& is_nothrow_move_assignable<_Compare>::value);
template<typename _Iterator> template<typename _Iterator>
void void
...@@ -1325,7 +1327,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -1325,7 +1327,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a) _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a)
: _M_impl(__x._M_impl._M_key_compare, std::move(__a)) : _M_impl(__x._M_impl._M_key_compare, std::move(__a))
{ {
using __eq = integral_constant<bool, _Alloc_traits::_S_always_equal()>; using __eq = typename _Alloc_traits::is_always_equal;
if (__x._M_root() != nullptr) if (__x._M_root() != nullptr)
_M_move_data(__x, __eq()); _M_move_data(__x, __eq());
} }
...@@ -1378,7 +1380,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -1378,7 +1380,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>&
_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
operator=(_Rb_tree&& __x) operator=(_Rb_tree&& __x)
noexcept(_Alloc_traits::_S_nothrow_move()) noexcept(_Alloc_traits::_S_nothrow_move()
&& is_nothrow_move_assignable<_Compare>::value)
{ {
_M_impl._M_key_compare = __x._M_impl._M_key_compare; _M_impl._M_key_compare = __x._M_impl._M_key_compare;
if (_Alloc_traits::_S_propagate_on_move_assign() if (_Alloc_traits::_S_propagate_on_move_assign()
......
...@@ -450,8 +450,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -450,8 +450,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
constexpr bool __move_storage = constexpr bool __move_storage =
_Alloc_traits::_S_propagate_on_move_assign() _Alloc_traits::_S_propagate_on_move_assign()
|| _Alloc_traits::_S_always_equal(); || _Alloc_traits::_S_always_equal();
_M_move_assign(std::move(__x), _M_move_assign(std::move(__x), __bool_constant<__move_storage>());
integral_constant<bool, __move_storage>());
return *this; return *this;
} }
...@@ -1557,6 +1556,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -1557,6 +1556,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _Tp, typename _Alloc> template<typename _Tp, typename _Alloc>
inline void inline void
swap(vector<_Tp, _Alloc>& __x, vector<_Tp, _Alloc>& __y) swap(vector<_Tp, _Alloc>& __x, vector<_Tp, _Alloc>& __y)
#if __cplusplus >= 201103L
noexcept(noexcept(__x.swap(__y)))
#endif
{ __x.swap(__y); } { __x.swap(__y); }
_GLIBCXX_END_NAMESPACE_CONTAINER _GLIBCXX_END_NAMESPACE_CONTAINER
......
...@@ -1517,12 +1517,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -1517,12 +1517,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
inline void inline void
swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
noexcept(noexcept(__x.swap(__y)))
{ __x.swap(__y); } { __x.swap(__y); }
template<class _Key, class _Tp, class _Hash, class _Pred, class _Alloc> template<class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
inline void inline void
swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
noexcept(noexcept(__x.swap(__y)))
{ __x.swap(__y); } { __x.swap(__y); }
template<class _Key, class _Tp, class _Hash, class _Pred, class _Alloc> template<class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
......
...@@ -1396,12 +1396,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -1396,12 +1396,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
inline void inline void
swap(unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, swap(unordered_set<_Value, _Hash, _Pred, _Alloc>& __x,
unordered_set<_Value, _Hash, _Pred, _Alloc>& __y) unordered_set<_Value, _Hash, _Pred, _Alloc>& __y)
noexcept(noexcept(__x.swap(__y)))
{ __x.swap(__y); } { __x.swap(__y); }
template<class _Value, class _Hash, class _Pred, class _Alloc> template<class _Value, class _Hash, class _Pred, class _Alloc>
inline void inline void
swap(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, swap(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y) unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y)
noexcept(noexcept(__x.swap(__y)))
{ __x.swap(__y); } { __x.swap(__y); }
template<class _Value, class _Hash, class _Pred, class _Alloc> template<class _Value, class _Hash, class _Pred, class _Alloc>
......
...@@ -42,53 +42,8 @@ namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) ...@@ -42,53 +42,8 @@ namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
{ {
_GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if __cplusplus >= 201103L
template<typename _Alloc>
struct __allocator_always_compares_equal : std::false_type { };
template<typename _Tp>
struct __allocator_always_compares_equal<std::allocator<_Tp>>
: std::true_type { };
template<typename, typename> struct array_allocator;
template<typename _Tp, typename _Array>
struct __allocator_always_compares_equal<array_allocator<_Tp, _Array>>
: std::true_type { };
template<typename> struct bitmap_allocator;
template<typename _Tp>
struct __allocator_always_compares_equal<bitmap_allocator<_Tp>>
: std::true_type { };
template<typename> struct malloc_allocator;
template<typename _Tp>
struct __allocator_always_compares_equal<malloc_allocator<_Tp>>
: std::true_type { };
template<typename> struct mt_allocator;
template<typename _Tp>
struct __allocator_always_compares_equal<mt_allocator<_Tp>>
: std::true_type { };
template<typename> struct new_allocator;
template<typename _Tp>
struct __allocator_always_compares_equal<new_allocator<_Tp>>
: std::true_type { };
template<typename> struct pool_allocator;
template<typename _Tp>
struct __allocator_always_compares_equal<pool_allocator<_Tp>>
: std::true_type { };
#endif
/** /**
* @brief Uniform interface to C++98 and C++0x allocators. * @brief Uniform interface to C++98 and C++11 allocators.
* @ingroup allocators * @ingroup allocators
*/ */
template<typename _Alloc> template<typename _Alloc>
...@@ -152,7 +107,7 @@ template<typename _Alloc> ...@@ -152,7 +107,7 @@ template<typename _Alloc>
{ return _Base_type::propagate_on_container_swap::value; } { return _Base_type::propagate_on_container_swap::value; }
static constexpr bool _S_always_equal() static constexpr bool _S_always_equal()
{ return __allocator_always_compares_equal<_Alloc>::value; } { return _Base_type::is_always_equal::value; }
static constexpr bool _S_nothrow_move() static constexpr bool _S_nothrow_move()
{ return _S_propagate_on_move_assign() || _S_always_equal(); } { return _S_propagate_on_move_assign() || _S_always_equal(); }
......
...@@ -123,6 +123,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -123,6 +123,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// _GLIBCXX_RESOLVE_LIB_DEFECTS // _GLIBCXX_RESOLVE_LIB_DEFECTS
// 2103. std::allocator propagate_on_container_move_assignment // 2103. std::allocator propagate_on_container_move_assignment
typedef std::true_type propagate_on_container_move_assignment; typedef std::true_type propagate_on_container_move_assignment;
typedef std::true_type is_always_equal;
#endif #endif
private: private:
......
...@@ -43,39 +43,12 @@ namespace std _GLIBCXX_VISIBILITY(default) ...@@ -43,39 +43,12 @@ namespace std _GLIBCXX_VISIBILITY(default)
{ {
_GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<template<typename> class _Pred, typename... _Allocs>
struct __any_of;
template<template<typename> class _Pred, typename _Alloc, typename... _Allocs>
struct __any_of<_Pred, _Alloc, _Allocs...>
: __or_<_Pred<_Alloc>, __any_of<_Pred, _Allocs...>>
{ };
template<template<typename> class _Pred, typename _Alloc>
struct __any_of<_Pred, _Alloc>
: _Pred<_Alloc>
{ };
/** /**
* @addtogroup allocators * @addtogroup allocators
* @{ * @{
*/ */
template<typename _Alloc> template<typename _Alloc>
struct __propagate_on_copy
: allocator_traits<_Alloc>::propagate_on_container_copy_assignment
{ };
template<typename _Alloc>
struct __propagate_on_move
: allocator_traits<_Alloc>::propagate_on_container_move_assignment
{ };
template<typename _Alloc>
struct __propagate_on_swap
: allocator_traits<_Alloc>::propagate_on_container_swap
{ };
template<typename _Alloc>
inline auto inline auto
__do_outermost(_Alloc& __a, _Alloc*) -> decltype(__a.outer_allocator()) __do_outermost(_Alloc& __a, _Alloc*) -> decltype(__a.outer_allocator())
{ return __a.outer_allocator(); } { return __a.outer_allocator(); }
...@@ -263,15 +236,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -263,15 +236,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef typename __traits::void_pointer void_pointer; typedef typename __traits::void_pointer void_pointer;
typedef typename __traits::const_void_pointer const_void_pointer; typedef typename __traits::const_void_pointer const_void_pointer;
typedef typename conditional< typedef typename __or_<
__any_of<__propagate_on_copy, _OuterAlloc, _InnerAllocs...>::value, typename __traits::propagate_on_container_copy_assignment,
true_type, false_type>::type propagate_on_container_copy_assignment; typename allocator_traits<_InnerAllocs>::
typedef typename conditional< propagate_on_container_copy_assignment...>::type
__any_of<__propagate_on_move, _OuterAlloc, _InnerAllocs...>::value, propagate_on_container_copy_assignment;
true_type, false_type>::type propagate_on_container_move_assignment;
typedef typename conditional< typedef typename __or_<
__any_of<__propagate_on_swap, _OuterAlloc, _InnerAllocs...>::value, typename __traits::propagate_on_container_move_assignment,
true_type, false_type>::type propagate_on_container_swap; typename allocator_traits<_InnerAllocs>::
propagate_on_container_move_assignment...>::type
propagate_on_container_move_assignment;
typedef typename __or_<
typename __traits::propagate_on_container_swap,
typename allocator_traits<_InnerAllocs>::
propagate_on_container_swap...>::type
propagate_on_container_swap;
typedef typename __and_<
typename __traits::is_always_equal,
typename allocator_traits<_InnerAllocs>::is_always_equal...>::type
is_always_equal;
template <class _Tp> template <class _Tp>
struct rebind struct rebind
......
// Copyright (C) 2015 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
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
// { dg-options "-std=gnu++11" }
// { dg-do compile }
#include <type_traits>
#include <memory>
template<typename T, typename Base>
struct Alloc : Base
{
typedef T value_type;
Alloc();
template <typename U>
Alloc(const Alloc<U, Base>&);
T* allocate(std::size_t);
void deallocate(T*, std::size_t);
};
template<bool> struct Empty { };
template<> struct Empty<false> { int x; };
template<bool B>
struct WithType
{ using is_always_equal = std::integral_constant<bool, B>; };
struct EmptyAndTrue : Empty<true>, WithType<true> { };
struct EmptyButFalse : Empty<true>, WithType<false> { };
struct NotEmptyButTrue : Empty<false>, WithType<true> { };
struct NotEmptyAndFalse : Empty<false>, WithType<false> { };
template<typename Base>
constexpr bool test()
{
using traits = std::allocator_traits<Alloc<int, Base>>;
using test_type = typename traits::is_always_equal;
static_assert(std::is_base_of<std::true_type, test_type>::value
|| std::is_base_of<std::false_type, test_type>::value,
"has correct base characteristic");
return test_type::value;
}
static_assert( test<Empty<true>>(), "empty type is always equal" );
static_assert( !test<Empty<false>>(), "non-empty type is not always equal" );
static_assert( test<EmptyAndTrue>(), "nested type is used" );
static_assert( !test<EmptyButFalse>(), "nested type is used" );
static_assert( test<NotEmptyButTrue>(), "nested type is used" );
static_assert( !test<NotEmptyAndFalse>(), "nested type is used" );
...@@ -42,13 +42,13 @@ template<typename T, bool copy, bool move, bool swap> ...@@ -42,13 +42,13 @@ template<typename T, bool copy, bool move, bool swap>
struct test_allocator : minimal_allocator<T> struct test_allocator : minimal_allocator<T>
{ {
struct propagate_on_container_copy_assignment struct propagate_on_container_copy_assignment
{ static const bool value = copy; }; : std::integral_constant<bool, copy> { };
struct propagate_on_container_move_assignment struct propagate_on_container_move_assignment
{ static const bool value = move; }; : std::integral_constant<bool, move> { };
struct propagate_on_container_swap struct propagate_on_container_swap
{ static const bool value = swap; }; : std::integral_constant<bool, swap> { };
}; };
template<typename A> template<typename A>
......
...@@ -61,14 +61,9 @@ struct A2 : std::allocator<T> ...@@ -61,14 +61,9 @@ struct A2 : std::allocator<T>
template<typename U> A2(const A2<U>&) { } template<typename U> A2(const A2<U>&) { }
using propagate_on_container_move_assignment = std::false_type; using propagate_on_container_move_assignment = std::false_type;
};
namespace __gnu_cxx using is_always_equal = std::true_type;
{ };
template<typename T>
struct __allocator_always_compares_equal<A2<T>> : std::true_type
{ };
}
void test02() void test02()
{ {
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>. // <http://www.gnu.org/licenses/>.
// { dg-do compile } // { dg-do compile }
// { dg-prune-output 1881 } // { dg-prune-output 1879 }
#include <deque> #include <deque>
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>. // <http://www.gnu.org/licenses/>.
// { dg-do compile } // { dg-do compile }
// { dg-prune-output 1814 } // { dg-prune-output 1812 }
#include <deque> #include <deque>
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>. // <http://www.gnu.org/licenses/>.
// { dg-do compile } // { dg-do compile }
// { dg-prune-output 1814 } // { dg-prune-output 1812 }
#include <deque> #include <deque>
#include <utility> #include <utility>
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>. // <http://www.gnu.org/licenses/>.
// { dg-do compile } // { dg-do compile }
// { dg-prune-output 1965 } // { dg-prune-output 1963 }
#include <deque> #include <deque>
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>. // <http://www.gnu.org/licenses/>.
// { dg-do compile } // { dg-do compile }
// { dg-prune-output 1741 } // { dg-prune-output 1740 }
#include <list> #include <list>
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>. // <http://www.gnu.org/licenses/>.
// { dg-do compile } // { dg-do compile }
// { dg-prune-output 1693 } // { dg-prune-output 1692 }
#include <list> #include <list>
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>. // <http://www.gnu.org/licenses/>.
// { dg-do compile } // { dg-do compile }
// { dg-prune-output 1693 } // { dg-prune-output 1692 }
#include <list> #include <list>
......
...@@ -60,15 +60,9 @@ struct A2 : std::allocator<T> ...@@ -60,15 +60,9 @@ struct A2 : std::allocator<T>
template<typename U> A2(const A2<U>&) { } template<typename U> A2(const A2<U>&) { }
using propagate_on_container_move_assignment = std::false_type; using propagate_on_container_move_assignment = std::false_type;
using is_always_equal = std::true_type;
}; };
namespace __gnu_cxx
{
template<typename T>
struct __allocator_always_compares_equal<A2<T>> : std::true_type
{ };
}
void test02() void test02()
{ {
using test_type = std::vector<C, A2<C>>; using test_type = std::vector<C, A2<C>>;
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>. // <http://www.gnu.org/licenses/>.
// { dg-do compile } // { dg-do compile }
// { dg-prune-output 1326 } // { dg-prune-output 1325 }
#include <vector> #include <vector>
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>. // <http://www.gnu.org/licenses/>.
// { dg-do compile } // { dg-do compile }
// { dg-prune-output 1252 } // { dg-prune-output 1251 }
#include <vector> #include <vector>
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>. // <http://www.gnu.org/licenses/>.
// { dg-do compile } // { dg-do compile }
// { dg-prune-output 1252 } // { dg-prune-output 1251 }
#include <vector> #include <vector>
#include <utility> #include <utility>
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>. // <http://www.gnu.org/licenses/>.
// { dg-do compile } // { dg-do compile }
// { dg-prune-output 1367 } // { dg-prune-output 1366 }
#include <vector> #include <vector>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment