Implement 2801, Default-constructibility of unique_ptr.
authorVille Voutilainen <ville.voutilainen@gmail.com>
Wed, 4 Jan 2017 13:21:02 +0000 (15:21 +0200)
committerVille Voutilainen <ville@gcc.gnu.org>
Wed, 4 Jan 2017 13:21:02 +0000 (15:21 +0200)
* include/bits/unique_ptr.h (__uniq_ptr_impl::_DeleterConstraint): New.
(unique_ptr::_DeleterConstraint): Likewise.
(unique_ptr()): Constrain.
(unique_ptr(pointer)): Likewise.
(unique_ptr(nullptr_t)): Likewise.
(unique_ptr<_Tp[], _Dp>::_DeleterConstraint): New.
(unique_ptr<_Tp[], _Dp>::unique_ptr()): Constrain.
(unique_ptr<_Tp[], _Dp>::unique_ptr(_Up)): Likewise.
(unique_ptr<_Tp[], _Dp>::unique_ptr(nullptr_t)): Likewise.
* testsuite/20_util/unique_ptr/assign/48635_neg.cc: Adjust.
* testsuite/20_util/unique_ptr/cons/cv_qual_neg.cc: Likewise.
* testsuite/20_util/unique_ptr/cons/default.cc: New.
* testsuite/20_util/unique_ptr/cons/ptr_deleter_neg.cc: Adjust.

From-SVN: r244054

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/unique_ptr.h
libstdc++-v3/testsuite/20_util/unique_ptr/assign/48635_neg.cc
libstdc++-v3/testsuite/20_util/unique_ptr/cons/cv_qual_neg.cc
libstdc++-v3/testsuite/20_util/unique_ptr/cons/default.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/unique_ptr/cons/ptr_deleter_neg.cc

index 26483dab21a959e44328744f05b7d4d71dfc609c..d0bd7e63fbd6697348ff98af5b0e1210de332ba5 100644 (file)
@@ -1,3 +1,20 @@
+2017-01-04  Ville Voutilainen  <ville.voutilainen@gmail.com>
+
+       Implement 2801, Default-constructibility of unique_ptr.
+       * include/bits/unique_ptr.h (__uniq_ptr_impl::_DeleterConstraint): New.
+       (unique_ptr::_DeleterConstraint): Likewise.
+       (unique_ptr()): Constrain.
+       (unique_ptr(pointer)): Likewise.
+       (unique_ptr(nullptr_t)): Likewise.
+       (unique_ptr<_Tp[], _Dp>::_DeleterConstraint): New.
+       (unique_ptr<_Tp[], _Dp>::unique_ptr()): Constrain.
+       (unique_ptr<_Tp[], _Dp>::unique_ptr(_Up)): Likewise.
+       (unique_ptr<_Tp[], _Dp>::unique_ptr(nullptr_t)): Likewise.
+       * testsuite/20_util/unique_ptr/assign/48635_neg.cc: Adjust.
+       * testsuite/20_util/unique_ptr/cons/cv_qual_neg.cc: Likewise.
+       * testsuite/20_util/unique_ptr/cons/default.cc: New.
+       * testsuite/20_util/unique_ptr/cons/ptr_deleter_neg.cc: Adjust.
+
 2017-01-04  Pauli Nieminen  <suokkos@gmail.com>
            Jonathan Wakely  <jwakely@redhat.com>
 
index df3cf92e4fe59d1192c3e7db6bdef65bbd355bd5..a31cd67d6e3fba201b82946270d43273138f890e 100644 (file)
@@ -130,6 +130,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        };
 
     public:
+      using _DeleterConstraint = enable_if<
+        __and_<__not_<is_pointer<_Dp>>,
+              is_default_constructible<_Dp>>::value>;
+
       using pointer = typename _Ptr<_Tp, _Dp>::type;
 
       __uniq_ptr_impl() = default;
@@ -152,6 +156,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template <typename _Tp, typename _Dp = default_delete<_Tp>>
     class unique_ptr
     {
+      template <class _Up>
+      using _DeleterConstraint =
+       typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type;
+
       __uniq_ptr_impl<_Tp, _Dp> _M_t;
 
     public:
@@ -175,10 +183,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       // Constructors.
 
       /// Default constructor, creates a unique_ptr that owns nothing.
-      constexpr unique_ptr() noexcept
-      : _M_t()
-      { static_assert(!is_pointer<deleter_type>::value,
-                    "constructed with null function pointer deleter"); }
+      template <typename _Up = _Dp,
+               typename = _DeleterConstraint<_Up>>
+       constexpr unique_ptr() noexcept
+       : _M_t()
+        { }
 
       /** Takes ownership of a pointer.
        *
@@ -186,11 +195,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        *
        * The deleter will be value-initialized.
        */
-      explicit
-      unique_ptr(pointer __p) noexcept
-      : _M_t(__p)
-      { static_assert(!is_pointer<deleter_type>::value,
-                    "constructed with null function pointer deleter"); }
+      template <typename _Up = _Dp,
+               typename = _DeleterConstraint<_Up>>
+       explicit
+       unique_ptr(pointer __p) noexcept
+       : _M_t(__p)
+        { }
 
       /** Takes ownership of a pointer.
        *
@@ -218,7 +228,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                      "rvalue deleter bound to reference"); }
 
       /// Creates a unique_ptr that owns nothing.
-      constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { }
+      template <typename _Up = _Dp,
+               typename = _DeleterConstraint<_Up>>
+       constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { }
 
       // Move constructors.
 
@@ -384,6 +396,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp, typename _Dp>
     class unique_ptr<_Tp[], _Dp>
     {
+      template <typename _Up>
+      using _DeleterConstraint =
+       typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type;
+
       __uniq_ptr_impl<_Tp, _Dp> _M_t;
 
       template<typename _Up>
@@ -432,10 +448,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       // Constructors.
 
       /// Default constructor, creates a unique_ptr that owns nothing.
-      constexpr unique_ptr() noexcept
-      : _M_t()
-      { static_assert(!std::is_pointer<deleter_type>::value,
-                     "constructed with null function pointer deleter"); }
+      template <typename _Up = _Dp,
+               typename = _DeleterConstraint<_Up>>
+       constexpr unique_ptr() noexcept
+       : _M_t()
+        { }
 
       /** Takes ownership of a pointer.
        *
@@ -445,13 +462,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        * The deleter will be value-initialized.
        */
       template<typename _Up,
-               typename = typename enable_if<
+              typename _Vp = _Dp,
+              typename = _DeleterConstraint<_Vp>,
+              typename = typename enable_if<
                  __safe_conversion_raw<_Up>::value, bool>::type>
-      explicit
-      unique_ptr(_Up __p) noexcept
-      : _M_t(__p)
-      { static_assert(!is_pointer<deleter_type>::value,
-                     "constructed with null function pointer deleter"); }
+       explicit
+       unique_ptr(_Up __p) noexcept
+       : _M_t(__p)
+        { }
 
       /** Takes ownership of a pointer.
        *
@@ -491,7 +509,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
 
       /// Creates a unique_ptr that owns nothing.
-      constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { }
+      template <typename _Up = _Dp,
+               typename = _DeleterConstraint<_Up>>
+       constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { }
 
       template<typename _Up, typename _Ep,
               typename = _Require<__safe_conversion_up<_Up, _Ep>>>
index 4f56712655557bad9a61b096142bf106eb05bfe3..9000ad98ad8b4e2abef897fbb9cd8687a2688d0e 100644 (file)
@@ -42,10 +42,10 @@ void f()
   std::unique_ptr<int, D&> ud(nullptr, d);
   ub = std::move(ud); // { dg-error "no match" }
   ub2 = ud; // { dg-error "no match" }
-// { dg-error "no type" "" { target *-*-* } 289 }
+// { dg-error "no type" "" { target *-*-* } 301 }
 
   std::unique_ptr<int[], B&> uba(nullptr, b);
   std::unique_ptr<int[], D&> uda(nullptr, d);
   uba = std::move(uda); // { dg-error "no match" }
-// { dg-error "no type" "" { target *-*-* } 540 }
+// { dg-error "no type" "" { target *-*-* } 560 }
 }
index d6b0e554cf2d1b2dc554c182121d1dc9b0cc382e..8d29c91fd3a45b7eda08d041191b49c447d12e1d 100644 (file)
@@ -39,7 +39,7 @@ test07()
   std::unique_ptr<const A[]> cA3(p); // { dg-error "no matching function" }
   std::unique_ptr<volatile A[]> vA3(p); // { dg-error "no matching function" }
   std::unique_ptr<const volatile A[]> cvA3(p); // { dg-error "no matching function" }
-  // { dg-error "no type" "" { target *-*-* } 448 }
+  // { dg-error "no type" "" { target *-*-* } 467 }
 }
 
 template<typename T>
diff --git a/libstdc++-v3/testsuite/20_util/unique_ptr/cons/default.cc b/libstdc++-v3/testsuite/20_util/unique_ptr/cons/default.cc
new file mode 100644 (file)
index 0000000..ceffdcd
--- /dev/null
@@ -0,0 +1,40 @@
+// { dg-do compile { target c++11 } }
+
+// Copyright (C) 2016 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 <memory>
+#include <type_traits>
+
+static_assert(!std::is_default_constructible<std::unique_ptr<int,
+             std::default_delete<int>&>>::value, "");
+static_assert(!std::is_default_constructible<std::unique_ptr<int,
+             void(*)(int*)>>::value, "");
+static_assert(!std::is_constructible<std::unique_ptr<int,
+             std::default_delete<int>&>, int*>::value, "");
+static_assert(!std::is_constructible<std::unique_ptr<int,
+             void(*)(int*)>, int*>::value, "");
+
+static_assert(!std::is_default_constructible<std::unique_ptr<int[],
+             std::default_delete<int>&>>::value, "");
+static_assert(!std::is_default_constructible<std::unique_ptr<int[],
+             void(*)(int*)>>::value, "");
+static_assert(!std::is_constructible<std::unique_ptr<int[],
+             std::default_delete<int>&>, int*>::value, "");
+static_assert(!std::is_constructible<std::unique_ptr<int[],
+             void(*)(int*)>, int*>::value, "");
+
index bfb01926fff01f3aab773f56b3d9c54117cbd879..b4d2d8edbfeac2f293ea95d689d13bf89ba8f67c 100644 (file)
 
 using std::unique_ptr;
 
-// { dg-prune-output "static assertion failed" }
-
 void
 test01()
 {
-  unique_ptr<long, void(*)(long*)> p1; // { dg-error "here" }
+  unique_ptr<long, void(*)(long*)> p1; // { dg-error "no matching" }
 
-  unique_ptr<short, void(*)(short*)> p2(nullptr); // { dg-error "here" }
+  unique_ptr<short, void(*)(short*)> p2(nullptr); // { dg-error "no matching" }
 
-  unique_ptr<int, void(*)(int*)> p3(new int); // { dg-error "here" }
+  unique_ptr<int, void(*)(int*)> p3(new int); // { dg-error "no matching" }
 }
 
 void
 test02()
 {
-  unique_ptr<long[], void(*)(long*)> p1; // { dg-error "here" }
+  unique_ptr<long[], void(*)(long*)> p1; // { dg-error "no matching" }
 
-  unique_ptr<short[], void(*)(short*)> p2(nullptr); // { dg-error "here" }
+  unique_ptr<short[], void(*)(short*)> p2(nullptr); // { dg-error "no matching" }
 
-  unique_ptr<int[], void(*)(int*)> p3(new int[1]); // { dg-error "here" }
+  unique_ptr<int[], void(*)(int*)> p3(new int[1]); // { dg-error "no matching" }
 }