Implement N4258 (Cleaning-up noexcept in the Library rev 3)
authorJonathan Wakely <jwakely@redhat.com>
Fri, 26 Jun 2015 20:10:24 +0000 (21:10 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Fri, 26 Jun 2015 20:10:24 +0000 (21:10 +0100)
* 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

34 files changed:
libstdc++-v3/ChangeLog
libstdc++-v3/doc/xml/manual/intro.xml
libstdc++-v3/include/bits/alloc_traits.h
libstdc++-v3/include/bits/allocator.h
libstdc++-v3/include/bits/forward_list.h
libstdc++-v3/include/bits/hashtable.h
libstdc++-v3/include/bits/stl_deque.h
libstdc++-v3/include/bits/stl_list.h
libstdc++-v3/include/bits/stl_map.h
libstdc++-v3/include/bits/stl_multimap.h
libstdc++-v3/include/bits/stl_multiset.h
libstdc++-v3/include/bits/stl_set.h
libstdc++-v3/include/bits/stl_tree.h
libstdc++-v3/include/bits/stl_vector.h
libstdc++-v3/include/bits/unordered_map.h
libstdc++-v3/include/bits/unordered_set.h
libstdc++-v3/include/ext/alloc_traits.h
libstdc++-v3/include/ext/array_allocator.h
libstdc++-v3/include/std/scoped_allocator
libstdc++-v3/testsuite/20_util/allocator_traits/members/is_always_equal.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/scoped_allocator/propagation.cc
libstdc++-v3/testsuite/23_containers/deque/allocator/move_assign-2.cc
libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/assign_neg.cc
libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_1_neg.cc
libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_2_neg.cc
libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/insert_neg.cc
libstdc++-v3/testsuite/23_containers/list/requirements/dr438/assign_neg.cc
libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc
libstdc++-v3/testsuite/23_containers/list/requirements/dr438/insert_neg.cc
libstdc++-v3/testsuite/23_containers/vector/52591.cc
libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc
libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc
libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc
libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc

index f2cd0353ea684d8d1d968f96d57c3fabc5211df1..9e76cc4d27e7705fd0b7bb87fea2a6881dea4516 100644 (file)
@@ -1,5 +1,89 @@
 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_map.h (map::map()): Likewise.
        * include/bits/stl_multimap.h (multimap::multimap()): Likewise.
index e6039ebf7a69d08c65eaa0604904dfcfe3ec641f..1cc183e2dc3af12b54b23a206d151d88952b659c 100644 (file)
@@ -868,6 +868,12 @@ requirements of the license of GCC.
     <listitem><para>Change the <code>reference</code> type.
     </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>:
        <emphasis><code>unique_ptr</code> for array does not support cv qualification conversion of actual argument</emphasis>
     </term>
index e434261802fcf1b5f5e95616650da1b7a155f69d..bb98c1d4ce8dc741311cafcc8eea560bd386233e 100644 (file)
@@ -89,9 +89,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 #define _GLIBCXX_ALLOC_TR_NESTED_TYPE(_NTYPE, _ALT) \
   private: \
-  template<typename _Tp> \
-    static typename _Tp::_NTYPE _S_##_NTYPE##_helper(_Tp*); \
-  static _ALT _S_##_NTYPE##_helper(...); \
+    template<typename _Tp> \
+      static typename _Tp::_NTYPE _S_##_NTYPE##_helper(_Tp*); \
+    static _ALT _S_##_NTYPE##_helper(...); \
     typedef decltype(_S_##_NTYPE##_helper((_Alloc*)0)) __##_NTYPE; \
   public:
 
@@ -194,6 +194,17 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(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
 
       template<typename _Tp>
index 7f5e659e22f0aa8dd755bb9755d3817518044a95..c7a250384676d449c81ade32c088ae0b9aaf34f3 100644 (file)
@@ -77,6 +77,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       // _GLIBCXX_RESOLVE_LIB_DEFECTS
       // 2103. std::allocator propagate_on_container_move_assignment
       typedef true_type propagate_on_container_move_assignment;
+
+      typedef true_type is_always_equal;
 #endif
     };
 
index 57c2d7bbfbb9cdfe19288bd13dafec81f0f7b03c..db02661d3a0ea8cc103a30407a1fb67b748b4a0a 100644 (file)
@@ -587,8 +587,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
         constexpr bool __move_storage =
           _Node_alloc_traits::_S_propagate_on_move_assign()
           || _Node_alloc_traits::_S_always_equal();
-        _M_move_assign(std::move(__list),
-                       integral_constant<bool, __move_storage>());
+        _M_move_assign(std::move(__list), __bool_constant<__move_storage>());
        return *this;
       }
 
@@ -1410,6 +1409,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     inline void
     swap(forward_list<_Tp, _Alloc>& __lx,
         forward_list<_Tp, _Alloc>& __ly)
+    noexcept(noexcept(__lx.swap(__ly)))
     { __lx.swap(__ly); }
 
 _GLIBCXX_END_NAMESPACE_CONTAINER
index f5f298ea33c2b8f7abbe43a7600662597dfec77c..31d237e7783e3502667a131aaebc22b9144ed043 100644 (file)
@@ -451,13 +451,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       _Hashtable&
       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 =
-          __node_alloc_traits::_S_propagate_on_move_assign()
-          || __node_alloc_traits::_S_always_equal();
-        _M_move_assign(std::move(__ht),
-                       integral_constant<bool, __move_storage>());
+         __node_alloc_traits::_S_propagate_on_move_assign()
+         || __node_alloc_traits::_S_always_equal();
+       _M_move_assign(std::move(__ht), __bool_constant<__move_storage>());
        return *this;
       }
 
@@ -475,7 +476,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       void
       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
       iterator
@@ -1234,7 +1237,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
               _H1, _H2, _Hash, _RehashPolicy, _Traits>::
     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.
       // We define _Hash_code_base::_M_swap because different
index 1b02b119e28d1a2d189fc4aee48e2f03d263a2e3..9b996684ef999c3f63db8aa0ca0a8d106f29972a 100644 (file)
@@ -515,8 +515,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       }
 
       _Deque_base(_Deque_base&& __x)
-      : _Deque_base(std::move(__x),
-                   __gnu_cxx::__allocator_always_compares_equal<_Alloc>{})
+      : _Deque_base(std::move(__x), typename _Alloc_traits::is_always_equal{})
       { }
 
       _Deque_base(_Deque_base&& __x, const allocator_type& __a, size_type __n)
@@ -1059,9 +1058,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       deque&
       operator=(deque&& __x) noexcept(_Alloc_traits::_S_always_equal())
       {
-       constexpr bool __always_equal = _Alloc_traits::_S_always_equal();
-       _M_move_assign1(std::move(__x),
-                       integral_constant<bool, __always_equal>());
+       using __always_equal = typename _Alloc_traits::is_always_equal;
+       _M_move_assign1(std::move(__x), __always_equal{});
        return *this;
       }
 
@@ -2140,13 +2138,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        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
       _M_move_assign1(deque&& __x, /* always equal: */ false_type)
       {
        constexpr bool __move_storage =
          _Alloc_traits::_S_propagate_on_move_assign();
-       _M_move_assign2(std::move(__x),
-                       integral_constant<bool, __move_storage>());
+       _M_move_assign2(std::move(__x), __bool_constant<__move_storage>());
       }
 
       // Destroy all elements and deallocate all memory, then replace
@@ -2271,6 +2271,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   template<typename _Tp, typename _Alloc>
     inline void
     swap(deque<_Tp,_Alloc>& __x, deque<_Tp,_Alloc>& __y)
+#if __cplusplus >= 201103L
+    noexcept(noexcept(__x.swap(__y)))
+#endif
     { __x.swap(__y); }
 
 #undef _GLIBCXX_DEQUE_BUF_SIZE
index 6a729fb992e6f04ff39497b12cbe0c0142c72405..409f1fc0262b22c0e9ec02e0027bb460cfc3712a 100644 (file)
@@ -751,8 +751,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        constexpr bool __move_storage =
           _Node_alloc_traits::_S_propagate_on_move_assign()
           || _Node_alloc_traits::_S_always_equal();
-        _M_move_assign(std::move(__x),
-                       integral_constant<bool, __move_storage>());
+        _M_move_assign(std::move(__x), __bool_constant<__move_storage>());
        return *this;
       }
 
@@ -1920,6 +1919,9 @@ _GLIBCXX_END_NAMESPACE_CXX11
   template<typename _Tp, typename _Alloc>
     inline void
     swap(list<_Tp, _Alloc>& __x, list<_Tp, _Alloc>& __y)
+#if __cplusplus >= 201103L
+    noexcept(noexcept(__x.swap(__y)))
+#endif
     { __x.swap(__y); }
 
 _GLIBCXX_END_NAMESPACE_CONTAINER
index 179e3f2a0bdeb71edbb1bd0dcdd3b5f3367c291b..d6ad16a195016fd5dff8dcc71689d6cad4c73b25 100644 (file)
@@ -795,7 +795,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       void
       swap(map& __x)
 #if __cplusplus >= 201103L
-      noexcept(_Alloc_traits::_S_nothrow_swap())
+      noexcept(_Alloc_traits::_S_nothrow_swap()
+              && __is_nothrow_swappable<_Compare>::value)
 #endif
       { _M_t.swap(__x._M_t); }
 
@@ -1124,6 +1125,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     inline void
     swap(map<_Key, _Tp, _Compare, _Alloc>& __x,
         map<_Key, _Tp, _Compare, _Alloc>& __y)
+#if __cplusplus >= 201103L
+    noexcept(noexcept(__x.swap(__y)))
+#endif
     { __x.swap(__y); }
 
 _GLIBCXX_END_NAMESPACE_CONTAINER
index 10ac0fadea8855664673534d4debf678877509ff..725dea38aaf8997aa81dfff052794d7e5d8b0b28 100644 (file)
@@ -705,7 +705,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       void
       swap(multimap& __x)
 #if __cplusplus >= 201103L
-      noexcept(_Alloc_traits::_S_nothrow_swap())
+      noexcept(_Alloc_traits::_S_nothrow_swap()
+              && __is_nothrow_swappable<_Compare>::value)
 #endif
       { _M_t.swap(__x._M_t); }
 
@@ -1025,6 +1026,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     inline void
     swap(multimap<_Key, _Tp, _Compare, _Alloc>& __x,
          multimap<_Key, _Tp, _Compare, _Alloc>& __y)
+#if __cplusplus >= 201103L
+    noexcept(noexcept(__x.swap(__y)))
+#endif
     { __x.swap(__y); }
 
 _GLIBCXX_END_NAMESPACE_CONTAINER
index 0a476d1b084bf5a49efc8ccd843b27964f97f9b9..578b6793878839430fcc1ef08ae4a4f71c4864c6 100644 (file)
@@ -407,7 +407,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       void
       swap(multiset& __x)
 #if __cplusplus >= 201103L
-      noexcept(_Alloc_traits::_S_nothrow_swap())
+      noexcept(_Alloc_traits::_S_nothrow_swap()
+              && __is_nothrow_swappable<_Compare>::value)
 #endif
       { _M_t.swap(__x._M_t); }
 
@@ -874,6 +875,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     inline void
     swap(multiset<_Key, _Compare, _Alloc>& __x,
         multiset<_Key, _Compare, _Alloc>& __y)
+#if __cplusplus >= 201103L
+    noexcept(noexcept(__x.swap(__y)))
+#endif
     { __x.swap(__y); }
 
 _GLIBCXX_END_NAMESPACE_CONTAINER
index 2e5c89f22c20c7eb0e390e93c6b68a97fdca684f..21c7db971cdb2614630e8bd7d1142ff135700879 100644 (file)
@@ -411,7 +411,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       void
       swap(set& __x)
 #if __cplusplus >= 201103L
-      noexcept(_Alloc_traits::_S_nothrow_swap())
+      noexcept(_Alloc_traits::_S_nothrow_swap()
+              && __is_nothrow_swappable<_Compare>::value)
 #endif
       { _M_t.swap(__x._M_t); }
 
@@ -890,6 +891,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   template<typename _Key, typename _Compare, typename _Alloc>
     inline void
     swap(set<_Key, _Compare, _Alloc>& __x, set<_Key, _Compare, _Alloc>& __y)
+#if __cplusplus >= 201103L
+    noexcept(noexcept(__x.swap(__y)))
+#endif
     { __x.swap(__y); }
 
 _GLIBCXX_END_NAMESPACE_CONTAINER
index 0ba15ab2b4b4e83641f244b60264362799b5080f..58c6b43fac0a37979e5cb4d1e2e6fa06342d1039 100644 (file)
@@ -1241,7 +1241,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 #if __cplusplus >= 201103L
       _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>
        void
@@ -1325,7 +1327,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __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)
        _M_move_data(__x, __eq());
     }
@@ -1378,7 +1380,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>&
     _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
     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;
       if (_Alloc_traits::_S_propagate_on_move_assign()
index b00f7704f818353dcf4c55985880c70688bd9496..1f3269b1c0a59b7e0ff44ddb3fa4b06c13f6676a 100644 (file)
@@ -450,8 +450,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
         constexpr bool __move_storage =
           _Alloc_traits::_S_propagate_on_move_assign()
           || _Alloc_traits::_S_always_equal();
-        _M_move_assign(std::move(__x),
-                       integral_constant<bool, __move_storage>());
+        _M_move_assign(std::move(__x), __bool_constant<__move_storage>());
        return *this;
       }
 
@@ -1557,6 +1556,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   template<typename _Tp, typename _Alloc>
     inline void
     swap(vector<_Tp, _Alloc>& __x, vector<_Tp, _Alloc>& __y)
+#if __cplusplus >= 201103L
+    noexcept(noexcept(__x.swap(__y)))
+#endif
     { __x.swap(__y); }
 
 _GLIBCXX_END_NAMESPACE_CONTAINER
index 3c434abb6aa88f059a324b20434b296be8646e23..d44efb5f1c3bfc41a0c882c249e9eeb50d627e28 100644 (file)
@@ -1517,12 +1517,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     inline void
     swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
         unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
+    noexcept(noexcept(__x.swap(__y)))
     { __x.swap(__y); }
 
   template<class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
     inline void
     swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
         unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
+    noexcept(noexcept(__x.swap(__y)))
     { __x.swap(__y); }
 
   template<class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
index 664d97ef27a4e2773e2d123cc01b0252753b74db..b9b94ca68034d603d4632c2b13753ea4ed989704 100644 (file)
@@ -1396,12 +1396,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
     inline void
     swap(unordered_set<_Value, _Hash, _Pred, _Alloc>& __x,
         unordered_set<_Value, _Hash, _Pred, _Alloc>& __y)
+    noexcept(noexcept(__x.swap(__y)))
     { __x.swap(__y); }
 
   template<class _Value, class _Hash, class _Pred, class _Alloc>
     inline void
     swap(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
         unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y)
+    noexcept(noexcept(__x.swap(__y)))
     { __x.swap(__y); }
 
   template<class _Value, class _Hash, class _Pred, class _Alloc>
index bd0f75945aa834fba7bd42fb745cd0271c27f8be..5da32c5b0ecbbe046401f86df1c3f531322bbc0d 100644 (file)
@@ -42,53 +42,8 @@ namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
 {
 _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
 */
 template<typename _Alloc>
@@ -152,7 +107,7 @@ template<typename _Alloc>
     { return _Base_type::propagate_on_container_swap::value; }
 
     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()
     { return _S_propagate_on_move_assign() || _S_always_equal(); }
index d909ceab9ca6797d5cb7cd5f2403e9d29d1e0b17..779d155d8927906fc1cab6cabc3be03960baee36 100644 (file)
@@ -123,6 +123,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       // _GLIBCXX_RESOLVE_LIB_DEFECTS
       // 2103. std::allocator propagate_on_container_move_assignment
       typedef std::true_type propagate_on_container_move_assignment;
+
+      typedef std::true_type is_always_equal;
 #endif
 
     private:
index d163edd109a9d020dd6105e3921e91ba266df39c..b3b9493cd8850c47c415da1db6eeddb2f87c9e63 100644 (file)
@@ -43,38 +43,11 @@ namespace std _GLIBCXX_VISIBILITY(default)
 {
 _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
    * @{
    */
 
-  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
     __do_outermost(_Alloc& __a, _Alloc*) -> decltype(__a.outer_allocator())
@@ -263,15 +236,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef typename __traits::void_pointer           void_pointer;
       typedef typename __traits::const_void_pointer     const_void_pointer;
 
-      typedef typename conditional<
-        __any_of<__propagate_on_copy, _OuterAlloc, _InnerAllocs...>::value,
-        true_type, false_type>::type propagate_on_container_copy_assignment;
-      typedef typename conditional<
-        __any_of<__propagate_on_move, _OuterAlloc, _InnerAllocs...>::value,
-        true_type, false_type>::type propagate_on_container_move_assignment;
-      typedef typename conditional<
-        __any_of<__propagate_on_swap, _OuterAlloc, _InnerAllocs...>::value,
-        true_type, false_type>::type propagate_on_container_swap;
+      typedef typename __or_<
+       typename __traits::propagate_on_container_copy_assignment,
+       typename allocator_traits<_InnerAllocs>::
+         propagate_on_container_copy_assignment...>::type
+         propagate_on_container_copy_assignment;
+
+      typedef typename __or_<
+       typename __traits::propagate_on_container_move_assignment,
+       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>
         struct rebind
diff --git a/libstdc++-v3/testsuite/20_util/allocator_traits/members/is_always_equal.cc b/libstdc++-v3/testsuite/20_util/allocator_traits/members/is_always_equal.cc
new file mode 100644 (file)
index 0000000..16974d1
--- /dev/null
@@ -0,0 +1,66 @@
+// 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" );
index ee63629b02c06284b65bb6ef14aae015aac36dbe..e1e594602889ee9db28e7b08161a4d160c9ae9cc 100644 (file)
@@ -42,13 +42,13 @@ template<typename T, bool copy, bool move, bool swap>
   struct test_allocator : minimal_allocator<T>
   {
     struct propagate_on_container_copy_assignment
-    { static const bool value = copy; };
+    : std::integral_constant<bool, copy> { };
 
     struct propagate_on_container_move_assignment
-    { static const bool value = move; };
+    : std::integral_constant<bool, move> { };
 
     struct propagate_on_container_swap
-    { static const bool value = swap; };
+    : std::integral_constant<bool, swap> { };
   };
 
 template<typename A>
index b852f6cac7515044f80c8042047c8ad61c022c02..e0a09d231c3a562d2f9235d23da0e58b09422e89 100644 (file)
@@ -61,14 +61,9 @@ struct A2 : std::allocator<T>
   template<typename U> A2(const A2<U>&) { }
 
   using propagate_on_container_move_assignment = std::false_type;
-};
 
-namespace __gnu_cxx
-{
-  template<typename T>
-    struct __allocator_always_compares_equal<A2<T>> : std::true_type
-    { };
-}
+  using is_always_equal = std::true_type;
+};
 
 void test02()
 {
index d9bc2ace552adb8dcc6e78d8b6254f38b2ca624d..09e2fc2041699f9c7947b33a6a1085d7587b5c9e 100644 (file)
@@ -18,7 +18,7 @@
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-prune-output 1881 }
+// { dg-prune-output 1879 }
 
 #include <deque>
 
index b4eb75edde1fd6bdba01ad8ae4662d2f99a549d3..deb75489019f4225b3597c1433fa9ce9827f1607 100644 (file)
@@ -18,7 +18,7 @@
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-prune-output 1814 }
+// { dg-prune-output 1812 }
 
 #include <deque>
 
index 90ce50a1fee507b2dcef2b47042705cd62bb63bf..f02cd27ad1f8e11dd6aef63234b8565b6f53267a 100644 (file)
@@ -18,7 +18,7 @@
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-prune-output 1814 }
+// { dg-prune-output 1812 }
 
 #include <deque>
 #include <utility>
index 5ff969580a978d90113019bb586fba014d53293f..5fffef7aff87662606f153187f2b4f71f683df72 100644 (file)
@@ -18,7 +18,7 @@
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-prune-output 1965 }
+// { dg-prune-output 1963 }
 
 #include <deque>
 
index 84c74734806d22257e710243d068e9f5c86a2341..c6eab0beb25f646dc3eb85a4fbfae509500eb657 100644 (file)
@@ -18,7 +18,7 @@
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-prune-output 1741 }
+// { dg-prune-output 1740 }
 
 #include <list>
 
index 947029c043ff30b2d8c1fe367fb49e79315cc542..833f731b146ad49ae160f7f38fcb9ec260b4cef9 100644 (file)
@@ -18,7 +18,7 @@
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-prune-output 1693 }
+// { dg-prune-output 1692 }
 
 #include <list>
 
index 54e89328ce0cb0c1b4f3bcfcb64974b30bbdb13f..09d1d470ed3540772d3846316c250f4d4f834382 100644 (file)
@@ -18,7 +18,7 @@
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-prune-output 1693 }
+// { dg-prune-output 1692 }
 
 #include <list>
 
index c32f0622d7ed23a7d845ba6c17c490f74d88fe94..291fb29798bcbf46a84528991a2cdb64bd5d365a 100644 (file)
@@ -60,15 +60,9 @@ struct A2 : std::allocator<T>
   template<typename U> A2(const A2<U>&) { }
 
   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()
 {
   using test_type = std::vector<C, A2<C>>;
index ce8f525c2e670fa0c414983edc821724d7a3717c..8d87c34f919685df76c147c32f7c848c6d3a2d6a 100644 (file)
@@ -18,7 +18,7 @@
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-prune-output 1326 }
+// { dg-prune-output 1325 }
 
 #include <vector>
 
index 4f0d365d2476e47e72c3148dabfbe5cc09d5ddf1..2c453d1e626d4784a2a3352e9f67ba5f7f859124 100644 (file)
@@ -18,7 +18,7 @@
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-prune-output 1252 }
+// { dg-prune-output 1251 }
 
 #include <vector>
 
index 34ffaecfc0b0c239e09ed67e0f1fe43e6c506545..d0c8d447ee3230086b9806408be193b9b38e9ca8 100644 (file)
@@ -18,7 +18,7 @@
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-prune-output 1252 }
+// { dg-prune-output 1251 }
 
 #include <vector>
 #include <utility>
index 6f611bf4cb1c27d417c74cf5ffde13df90305b38..f176a6f0152a2a9af1cbdf5bb590ce57422a3828 100644 (file)
@@ -18,7 +18,7 @@
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-prune-output 1367 }
+// { dg-prune-output 1366 }
 
 #include <vector>