Tested on Linux-x64. The issue doesn't have a proposed resolution yet, so we can certainly wait with this, but I have an inkling that this implementation is what the proposed resolution must say. :)
2016-12-20 Ville Voutilainen <ville.voutilai...@gmail.com> Implement 2801, Default-constructibility of unique_ptr. * include/bits/unique_ptr.h (unique_ptr()): Constrain. (unique_ptr(pointer)): Likewise. (unique_ptr(nullptr_t)): Likewise. (unique_ptr<_Tp[], _Dp>::unique_ptr()): Likewise. (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.
diff --git a/libstdc++-v3/include/bits/unique_ptr.h b/libstdc++-v3/include/bits/unique_ptr.h index 56e6ec0..63dff37 100644 --- a/libstdc++-v3/include/bits/unique_ptr.h +++ b/libstdc++-v3/include/bits/unique_ptr.h @@ -175,10 +175,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Constructors. /// Default constructor, creates a unique_ptr that owns nothing. + template <typename _Up = deleter_type, + typename enable_if< + __and_<__not_<is_pointer<_Up>>, + is_default_constructible<_Up>>::value, + bool>::type = false> constexpr unique_ptr() noexcept : _M_t() - { static_assert(!is_pointer<deleter_type>::value, - "constructed with null function pointer deleter"); } + { } /** Takes ownership of a pointer. * @@ -186,11 +190,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * * The deleter will be value-initialized. */ + template <typename _Up = deleter_type, + typename enable_if< + __and_<__not_<is_pointer<_Up>>, + is_default_constructible<_Up>>::value, + bool>::type = false> explicit unique_ptr(pointer __p) noexcept : _M_t(__p) - { static_assert(!is_pointer<deleter_type>::value, - "constructed with null function pointer deleter"); } + { } /** Takes ownership of a pointer. * @@ -218,6 +226,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION "rvalue deleter bound to reference"); } /// Creates a unique_ptr that owns nothing. + template <typename _Up = deleter_type, + typename enable_if< + __and_<__not_<is_pointer<_Up>>, + is_default_constructible<_Up>>::value, + bool>::type = false> constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { } // Move constructors. @@ -432,10 +445,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Constructors. /// Default constructor, creates a unique_ptr that owns nothing. + template <typename _Up = deleter_type, + typename enable_if< + __and_<__not_<is_pointer<_Up>>, + is_default_constructible<_Up>>::value, + bool>::type = false> constexpr unique_ptr() noexcept : _M_t() - { static_assert(!std::is_pointer<deleter_type>::value, - "constructed with null function pointer deleter"); } + { } /** Takes ownership of a pointer. * @@ -445,13 +462,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * The deleter will be value-initialized. */ template<typename _Up, - typename = typename enable_if< + typename _Vp = deleter_type, + typename enable_if< + __and_<__not_<is_pointer<_Vp>>, + is_default_constructible<_Vp>>::value, + bool>::type = false, + 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"); } + { } /** Takes ownership of a pointer. * @@ -491,6 +512,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { } /// Creates a unique_ptr that owns nothing. + template <typename _Up = deleter_type, + typename enable_if< + __and_<__not_<is_pointer<_Up>>, + is_default_constructible<_Up>>::value, + bool>::type = false> constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { } template<typename _Up, typename _Ep, diff --git a/libstdc++-v3/testsuite/20_util/unique_ptr/assign/48635_neg.cc b/libstdc++-v3/testsuite/20_util/unique_ptr/assign/48635_neg.cc index e9655f1..2489b26 100644 --- a/libstdc++-v3/testsuite/20_util/unique_ptr/assign/48635_neg.cc +++ b/libstdc++-v3/testsuite/20_util/unique_ptr/assign/48635_neg.cc @@ -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 *-*-* } 302 } 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 *-*-* } 566 } } diff --git a/libstdc++-v3/testsuite/20_util/unique_ptr/cons/cv_qual_neg.cc b/libstdc++-v3/testsuite/20_util/unique_ptr/cons/cv_qual_neg.cc index 3e6f41b..824f3c3 100644 --- a/libstdc++-v3/testsuite/20_util/unique_ptr/cons/cv_qual_neg.cc +++ b/libstdc++-v3/testsuite/20_util/unique_ptr/cons/cv_qual_neg.cc @@ -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 *-*-* } 470 } } 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 index 0000000..968b2f1 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/unique_ptr/cons/default.cc @@ -0,0 +1,40 @@ +// { dg-do compile { target c++11 } } + +// Copyright (C) 2011-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, ""); + diff --git a/libstdc++-v3/testsuite/20_util/unique_ptr/cons/ptr_deleter_neg.cc b/libstdc++-v3/testsuite/20_util/unique_ptr/cons/ptr_deleter_neg.cc index 1aa8d43..b7d97e6 100644 --- a/libstdc++-v3/testsuite/20_util/unique_ptr/cons/ptr_deleter_neg.cc +++ b/libstdc++-v3/testsuite/20_util/unique_ptr/cons/ptr_deleter_neg.cc @@ -23,26 +23,31 @@ using std::unique_ptr; -// { dg-prune-output "static assertion failed" } +// { dg-error "no type" "" { target *-*-* } 182 } +// { dg-error "no type" "" { target *-*-* } 197 } +// { dg-error "no type" "" { target *-*-* } 233 } +// { dg-error "no type" "" { target *-*-* } 452 } +// { dg-error "no type" "" { target *-*-* } 469 } +// { dg-error "no type" "" { target *-*-* } 519 } 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" } }