move.h (struct __move_if_noexcept_cond): Add.
authorPaolo Carlini <paolo.carlini@oracle.com>
Tue, 7 Jun 2011 16:11:36 +0000 (16:11 +0000)
committerPaolo Carlini <paolo@gcc.gnu.org>
Tue, 7 Jun 2011 16:11:36 +0000 (16:11 +0000)
2011-06-07  Paolo Carlini  <paolo.carlini@oracle.com>

* include/bits/move.h (struct __move_if_noexcept_cond): Add.
(move_if_noexcept): Use the latter.
* include/bits/stl_iterator.h (__make_move_if_noexcept_iterator,
_GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR): Add.
* include/bits/stl_uninitialized.h
(__uninitialized_move_if_noexcept_a): Add.
* include/bits/vector.tcc (vector<>::reserve): Use
_GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR.
(vector<>::_M_insert_aux, _M_fill_insert, _M_default_append,
_M_range_insert): Use __uninitialized_move_if_noexcept_a.
* testsuite/23_containers/vector/modifiers/moveable2.cc: New.
* testsuite/23_containers/vector/capacity/resize/moveable2.cc:
Likewise.
* testsuite/23_containers/vector/capacity/reserve/moveable2.cc:
Likewise.

From-SVN: r174756

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/move.h
libstdc++-v3/include/bits/stl_iterator.h
libstdc++-v3/include/bits/stl_uninitialized.h
libstdc++-v3/include/bits/vector.tcc
libstdc++-v3/testsuite/23_containers/vector/capacity/reserve/moveable2.cc [new file with mode: 0644]
libstdc++-v3/testsuite/23_containers/vector/capacity/resize/moveable2.cc [new file with mode: 0644]
libstdc++-v3/testsuite/23_containers/vector/modifiers/moveable2.cc [new file with mode: 0644]
libstdc++-v3/testsuite/util/testsuite_rvalref.h

index 0e3d55161dbe5001e22e27d8782955359c14827f..2f3707badc6014a3e2e91b78ebc561343a95a178 100644 (file)
@@ -1,3 +1,21 @@
+2011-06-07  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       * include/bits/move.h (struct __move_if_noexcept_cond): Add.
+       (move_if_noexcept): Use the latter.
+       * include/bits/stl_iterator.h (__make_move_if_noexcept_iterator,
+       _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR): Add.
+       * include/bits/stl_uninitialized.h
+       (__uninitialized_move_if_noexcept_a): Add.
+       * include/bits/vector.tcc (vector<>::reserve): Use
+       _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR.
+       (vector<>::_M_insert_aux, _M_fill_insert, _M_default_append,
+       _M_range_insert): Use __uninitialized_move_if_noexcept_a.
+       * testsuite/23_containers/vector/modifiers/moveable2.cc: New.
+       * testsuite/23_containers/vector/capacity/resize/moveable2.cc:
+       Likewise.
+       * testsuite/23_containers/vector/capacity/reserve/moveable2.cc:
+       Likewise.
+
 2011-06-07  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR libstdc++/49293
index 6f3b420640d756239927f9f1a5957920b69daac3..d791d69ae4d27e3e6623e078bce7e83318a23e4c 100644 (file)
@@ -82,6 +82,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     move(_Tp&& __t) noexcept
     { return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
 
+
+  template<typename _Tp>
+    struct __move_if_noexcept_cond
+    : public __and_<__not_<is_nothrow_move_constructible<_Tp>>,
+                    is_copy_constructible<_Tp>>::type { };
+
   /**
    *  @brief Move unless it could throw and the type is copyable.
    *  @ingroup utilities
@@ -90,9 +96,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    */
   template<typename _Tp>
     inline typename
-    conditional<__and_<__not_<is_nothrow_move_constructible<_Tp>>,
-                       is_copy_constructible<_Tp>>::value,
-                const _Tp&, _Tp&&>::type
+    conditional<__move_if_noexcept_cond<_Tp>::value, const _Tp&, _Tp&&>::type
     move_if_noexcept(_Tp& __x) noexcept
     { return std::move(__x); }
 
index b23107d3577dd0190ce12af41f7ea7ab6dfec9ad..c2a16893b86786949fbbc360f599b1f9d54a0e23 100644 (file)
@@ -1118,14 +1118,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     make_move_iterator(const _Iterator& __i)
     { return move_iterator<_Iterator>(__i); }
 
+  template<typename _Iterator, typename _ReturnType
+    = typename conditional<__move_if_noexcept_cond
+      <typename iterator_traits<_Iterator>::value_type>::value,
+                _Iterator, move_iterator<_Iterator>>::type>
+    inline _ReturnType
+    __make_move_if_noexcept_iterator(_Iterator __i)
+    { return _ReturnType(__i); }
+
   // @} group iterators
 
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
 
 #define _GLIBCXX_MAKE_MOVE_ITERATOR(_Iter) std::make_move_iterator(_Iter)
+#define _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(_Iter) \
+  std::__make_move_if_noexcept_iterator(_Iter)
 #else
 #define _GLIBCXX_MAKE_MOVE_ITERATOR(_Iter) (_Iter)
+#define _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(_Iter) (_Iter)
 #endif // __GXX_EXPERIMENTAL_CXX0X__
 
 #endif
index f15be3aee3b60798853e6d833e9a271523cf8388..246d5c36d80284498baf754c3719b3572f332e64 100644 (file)
@@ -269,6 +269,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                                         __result, __alloc);
     }
 
+  template<typename _InputIterator, typename _ForwardIterator,
+          typename _Allocator>
+    inline _ForwardIterator
+    __uninitialized_move_if_noexcept_a(_InputIterator __first,
+                                      _InputIterator __last,
+                                      _ForwardIterator __result,
+                                      _Allocator& __alloc)
+    {
+      return std::__uninitialized_copy_a
+       (_GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(__first),
+        _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(__last), __result, __alloc);
+    }
+
   template<typename _ForwardIterator, typename _Tp, typename _Allocator>
     void
     __uninitialized_fill_a(_ForwardIterator __first, _ForwardIterator __last,
index 3aaee392e55fca50d459c0a8da32e53cad03bcf1..5b6a8d791aefa2f794d5ce1865a9d0008e300961 100644 (file)
@@ -72,8 +72,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        {
          const size_type __old_size = size();
          pointer __tmp = _M_allocate_and_copy(__n,
-                _GLIBCXX_MAKE_MOVE_ITERATOR(this->_M_impl._M_start),
-                _GLIBCXX_MAKE_MOVE_ITERATOR(this->_M_impl._M_finish));
+           _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(this->_M_impl._M_start),
+           _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(this->_M_impl._M_finish));
          std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
                        _M_get_Tp_allocator());
          _M_deallocate(this->_M_impl._M_start,
@@ -337,17 +337,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 #endif
              __new_finish = 0;
 
-             __new_finish =
-               std::__uninitialized_move_a(this->_M_impl._M_start,
-                                           __position.base(), __new_start,
-                                           _M_get_Tp_allocator());
+             __new_finish
+               = std::__uninitialized_move_if_noexcept_a
+               (this->_M_impl._M_start, __position.base(),
+                __new_start, _M_get_Tp_allocator());
+
              ++__new_finish;
 
-             __new_finish =
-               std::__uninitialized_move_a(__position.base(),
-                                           this->_M_impl._M_finish,
-                                           __new_finish,
-                                           _M_get_Tp_allocator());
+             __new_finish
+               = std::__uninitialized_move_if_noexcept_a
+               (__position.base(), this->_M_impl._M_finish,
+                __new_finish, _M_get_Tp_allocator());
            }
           __catch(...)
            {
@@ -423,18 +423,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
                                                _M_get_Tp_allocator());
                  __new_finish = 0;
 
-                 __new_finish =
-                   std::__uninitialized_move_a(this->_M_impl._M_start,
-                                               __position.base(),
-                                               __new_start,
-                                               _M_get_Tp_allocator());
+                 __new_finish
+                   = std::__uninitialized_move_if_noexcept_a
+                   (this->_M_impl._M_start, __position.base(),
+                    __new_start, _M_get_Tp_allocator());
+
                  __new_finish += __n;
 
-                 __new_finish =
-                   std::__uninitialized_move_a(__position.base(),
-                                               this->_M_impl._M_finish,
-                                               __new_finish,
-                                               _M_get_Tp_allocator());
+                 __new_finish
+                   = std::__uninitialized_move_if_noexcept_a
+                   (__position.base(), this->_M_impl._M_finish,
+                    __new_finish, _M_get_Tp_allocator());
                }
              __catch(...)
                {
@@ -484,11 +483,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
              pointer __new_finish(__new_start);
              __try
                {
-                 __new_finish =
-                   std::__uninitialized_move_a(this->_M_impl._M_start,
-                                               this->_M_impl._M_finish,
-                                               __new_start,
-                                               _M_get_Tp_allocator());
+                 __new_finish
+                   = std::__uninitialized_move_if_noexcept_a
+                   (this->_M_impl._M_start, this->_M_impl._M_finish,
+                    __new_start, _M_get_Tp_allocator());
                  std::__uninitialized_default_n_a(__new_finish, __n,
                                                   _M_get_Tp_allocator());
                  __new_finish += __n;
@@ -577,20 +575,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
                pointer __new_finish(__new_start);
                __try
                  {
-                   __new_finish =
-                     std::__uninitialized_move_a(this->_M_impl._M_start,
-                                                 __position.base(),
-                                                 __new_start,
-                                                 _M_get_Tp_allocator());
-                   __new_finish =
-                     std::__uninitialized_copy_a(__first, __last,
-                                                 __new_finish,
-                                                 _M_get_Tp_allocator());
-                   __new_finish =
-                     std::__uninitialized_move_a(__position.base(),
-                                                 this->_M_impl._M_finish,
-                                                 __new_finish,
-                                                 _M_get_Tp_allocator());
+                   __new_finish
+                     = std::__uninitialized_move_if_noexcept_a
+                     (this->_M_impl._M_start, __position.base(),
+                      __new_start, _M_get_Tp_allocator());
+                   __new_finish
+                     = std::__uninitialized_copy_a(__first, __last,
+                                                   __new_finish,
+                                                   _M_get_Tp_allocator());
+                   __new_finish
+                     = std::__uninitialized_move_if_noexcept_a
+                     (__position.base(), this->_M_impl._M_finish,
+                      __new_finish, _M_get_Tp_allocator());
                  }
                __catch(...)
                  {
diff --git a/libstdc++-v3/testsuite/23_containers/vector/capacity/reserve/moveable2.cc b/libstdc++-v3/testsuite/23_containers/vector/capacity/reserve/moveable2.cc
new file mode 100644 (file)
index 0000000..3a6c313
--- /dev/null
@@ -0,0 +1,45 @@
+// { dg-options "-std=gnu++0x" }
+
+// 2011-06-07  Paolo Carlini  <paolo.carlini@oracle.com>
+
+// Copyright (C) 2011 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/>.
+
+#include <vector>
+#include <testsuite_hooks.h>
+#include <testsuite_rvalref.h>
+
+void
+test01()
+{
+  bool test __attribute__((unused)) = true;
+  using namespace __gnu_test;
+
+  std::vector<throwing_move_constructor> v(5);
+
+  v.reserve(50);
+  VERIFY( v.capacity() >= 50 );
+
+  v.reserve(500);
+  VERIFY( v.capacity() >= 500 );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/vector/capacity/resize/moveable2.cc b/libstdc++-v3/testsuite/23_containers/vector/capacity/resize/moveable2.cc
new file mode 100644 (file)
index 0000000..5bdb981
--- /dev/null
@@ -0,0 +1,57 @@
+// { dg-options "-std=gnu++0x" }
+
+// 2011-06-07  Paolo Carlini  <paolo.carlini@oracle.com>
+
+// Copyright (C) 2011 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/>.
+
+#include <vector>
+#include <testsuite_hooks.h>
+#include <testsuite_rvalref.h>
+
+void
+test01()
+{
+  bool test __attribute__((unused)) = true;
+  using namespace __gnu_test;
+
+  std::vector<throwing_move_constructor> v(5);
+
+  v.resize(50);
+  VERIFY( v.size() == 50 );
+
+  v.reserve(200);
+  VERIFY( v.capacity() >= 200 );
+
+  v.resize(100);
+  VERIFY( v.size() == 100 );
+
+  v.resize(500, throwing_move_constructor());
+  VERIFY( v.size() == 500 );
+
+  v.reserve(2000);
+  VERIFY( v.capacity() >= 2000 );
+
+  v.resize(1000, throwing_move_constructor());
+  VERIFY( v.size() == 1000 );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/vector/modifiers/moveable2.cc b/libstdc++-v3/testsuite/23_containers/vector/modifiers/moveable2.cc
new file mode 100644 (file)
index 0000000..000db2c
--- /dev/null
@@ -0,0 +1,77 @@
+// { dg-options "-std=gnu++0x" }
+
+// 2011-06-07  Paolo Carlini  <paolo.carlini@oracle.com>
+
+// Copyright (C) 2011 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/>.
+
+#include <vector>
+#include <testsuite_hooks.h>
+#include <testsuite_rvalref.h>
+
+void
+test01()
+{
+  bool test __attribute__((unused)) = true;
+  using namespace __gnu_test;
+
+  std::vector<throwing_move_constructor> v1;
+
+  throwing_move_constructor tmc;
+
+  v1.push_back(tmc);
+  VERIFY( v1.size() == 1 );
+
+  v1.push_back(tmc);
+  VERIFY( v1.size() == 2 );
+
+  v1.insert(v1.end(), tmc);
+  VERIFY( v1.size() == 3 );
+
+  v1.insert(v1.end(), 100, tmc);
+  VERIFY( v1.size() == 103 );
+
+  v1.insert(v1.end(), 10, tmc);
+  VERIFY( v1.size() == 113 );
+
+  v1.insert(v1.end(), 1, tmc);
+  VERIFY( v1.size() == 114 );
+
+  std::vector<throwing_move_constructor> v2;
+
+  throwing_move_constructor tmca[]
+    = { throwing_move_constructor(), throwing_move_constructor(),
+       throwing_move_constructor(), throwing_move_constructor() };
+
+  v2.insert(v2.end(), tmca, tmca + 1);
+  VERIFY( v2.size() == 1 );
+
+  v2.insert(v2.end(), tmca, tmca + 4);
+  VERIFY( v2.size() == 5 );
+
+  v2.insert(v2.end(), tmca, tmca + 2);
+  VERIFY( v2.size() == 7 );
+
+  v2.insert(v2.end(), tmca, tmca + 1);
+  VERIFY( v2.size() == 8 );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
index 8e37bbdb0978a8d91159e77acb988e5b0a93f832..31599157bd459d37c9fc4333a837fbfa04d2a6f7 100644 (file)
@@ -117,7 +117,7 @@ namespace __gnu_test
       ++copycount;
     }
 
-    copycounter(copycounter&& in)
+    copycounter(copycounter&& in) noexcept
     {
       bool test __attribute__((unused)) = true;
       VERIFY( in.valid == true );
@@ -156,7 +156,7 @@ namespace __gnu_test
       return *this;
     }
     
-    ~copycounter()
+    ~copycounter() noexcept
     { valid = false; }
   };
 
@@ -246,6 +246,16 @@ namespace __gnu_test
     return lh.val < rh.val;
   }
 
+  struct throwing_move_constructor
+  {
+    throwing_move_constructor() = default;
+
+    throwing_move_constructor(throwing_move_constructor&&)
+    { throw 1; }
+
+    throwing_move_constructor(const throwing_move_constructor&) = default;
+  };
+
 } // namespace __gnu_test
 
 namespace std