* include/bits/shared_ptr.h (_Assignable): New alias template.
(shared_ptr::operator=(const shared_ptr<_Tp1>&))
(shared_ptr::operator=(shared_ptr<_Tp1>&&))
(shared_ptr::operator=(unique_ptr<_Tp1>&&)): Constrain with
_Assignable.
* include/bits/shared_ptr_base.h (_Assignable): New alias template.
(__shared_ptr::operator=(const __shared_ptr<_Tp1>&))
(__shared_ptr::operator=(__shared_ptr<_Tp1>&&))
(__shared_ptr::operator=(unique_ptr<_Tp1>&&)): Constrain with
_Assignable.
(__shared_ptr::reset(_Tp1*), __shared_ptr::reset(_Tp1*, _Deleter))
(__shared_ptr::reset(_Tp1*, _Deleter, _Alloc)): Constrain with
_Convertible.
* testsuite/20_util/shared_ptr/cons/43820_neg.cc: Change dg-error to
match on any line.
* testsuite/20_util/shared_ptr/cons/void_neg.cc: Likewise.
* testsuite/20_util/shared_ptr/assign/sfinae.cc: New test.
* testsuite/20_util/shared_ptr/assign/shared_ptr_neg.cc: Update
expected errors. Remove unnecessary code.
* testsuite/20_util/shared_ptr/modifiers/reset_sfinae.cc: New test.
From-SVN: r239898
2016-08-31 Jonathan Wakely <jwakely@redhat.com>
+ * include/bits/shared_ptr.h (_Assignable): New alias template.
+ (shared_ptr::operator=(const shared_ptr<_Tp1>&))
+ (shared_ptr::operator=(shared_ptr<_Tp1>&&))
+ (shared_ptr::operator=(unique_ptr<_Tp1>&&)): Constrain with
+ _Assignable.
+ * include/bits/shared_ptr_base.h (_Assignable): New alias template.
+ (__shared_ptr::operator=(const __shared_ptr<_Tp1>&))
+ (__shared_ptr::operator=(__shared_ptr<_Tp1>&&))
+ (__shared_ptr::operator=(unique_ptr<_Tp1>&&)): Constrain with
+ _Assignable.
+ (__shared_ptr::reset(_Tp1*), __shared_ptr::reset(_Tp1*, _Deleter))
+ (__shared_ptr::reset(_Tp1*, _Deleter, _Alloc)): Constrain with
+ _Convertible.
+ * testsuite/20_util/shared_ptr/cons/43820_neg.cc: Change dg-error to
+ match on any line.
+ * testsuite/20_util/shared_ptr/cons/void_neg.cc: Likewise.
+ * testsuite/20_util/shared_ptr/assign/sfinae.cc: New test.
+ * testsuite/20_util/shared_ptr/assign/shared_ptr_neg.cc: Update
+ expected errors. Remove unnecessary code.
+ * testsuite/20_util/shared_ptr/modifiers/reset_sfinae.cc: New test.
+
* include/bits/stl_tree.h (_Rb_tree::operator=(_Rb_tree&&)): Move
comparison object.
* testsuite/23_containers/set/move_comparison.cc: New test.
class shared_ptr : public __shared_ptr<_Tp>
{
template<typename _Ptr>
- using _Convertible
- = typename enable_if<is_convertible<_Ptr, _Tp*>::value>::type;
+ using _Convertible = typename
+ enable_if<is_convertible<_Ptr, _Tp*>::value>::type;
+
+ template<typename _Ptr>
+ using _Assignable = typename
+ enable_if<is_convertible<_Ptr, _Tp*>::value, shared_ptr&>::type;
public:
shared_ptr& operator=(const shared_ptr&) noexcept = default;
template<typename _Tp1>
- shared_ptr&
+ _Assignable<_Tp1*>
operator=(const shared_ptr<_Tp1>& __r) noexcept
{
this->__shared_ptr<_Tp>::operator=(__r);
}
template<class _Tp1>
- shared_ptr&
+ _Assignable<_Tp1*>
operator=(shared_ptr<_Tp1>&& __r) noexcept
{
this->__shared_ptr<_Tp>::operator=(std::move(__r));
}
template<typename _Tp1, typename _Del>
- shared_ptr&
+ _Assignable<typename unique_ptr<_Tp1, _Del>::pointer>
operator=(std::unique_ptr<_Tp1, _Del>&& __r)
{
this->__shared_ptr<_Tp>::operator=(std::move(__r));
using _Convertible
= typename enable_if<is_convertible<_Ptr, _Tp*>::value>::type;
+ template<typename _Ptr>
+ using _Assignable = typename
+ enable_if<is_convertible<_Ptr, _Tp*>::value, __shared_ptr&>::type;
+
public:
typedef _Tp element_type;
constexpr __shared_ptr(nullptr_t) noexcept : __shared_ptr() { }
template<typename _Tp1>
- __shared_ptr&
+ _Assignable<_Tp1*>
operator=(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
{
_M_ptr = __r._M_ptr;
}
template<class _Tp1>
- __shared_ptr&
+ _Assignable<_Tp1*>
operator=(__shared_ptr<_Tp1, _Lp>&& __r) noexcept
{
__shared_ptr(std::move(__r)).swap(*this);
}
template<typename _Tp1, typename _Del>
- __shared_ptr&
+ _Assignable<typename unique_ptr<_Tp1, _Del>::pointer>
operator=(std::unique_ptr<_Tp1, _Del>&& __r)
{
__shared_ptr(std::move(__r)).swap(*this);
{ __shared_ptr().swap(*this); }
template<typename _Tp1>
- void
+ _Convertible<_Tp1*>
reset(_Tp1* __p) // _Tp1 must be complete.
{
// Catch self-reset errors.
}
template<typename _Tp1, typename _Deleter>
- void
+ _Convertible<_Tp1*>
reset(_Tp1* __p, _Deleter __d)
{ __shared_ptr(__p, __d).swap(*this); }
template<typename _Tp1, typename _Deleter, typename _Alloc>
- void
+ _Convertible<_Tp1*>
reset(_Tp1* __p, _Deleter __d, _Alloc __a)
{ __shared_ptr(__p, __d, std::move(__a)).swap(*this); }
--- /dev/null
+// 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/>.
+
+// { dg-do compile { target c++11 } }
+
+#include <memory>
+
+template<typename T, typename From>
+constexpr bool can_assign()
+{ return std::is_assignable<std::shared_ptr<T>, From>::value; }
+
+struct Base { };
+struct Derived : Base { };
+
+// Positive cases:
+
+static_assert( can_assign<const void, const std::shared_ptr<void>&>(),
+ "void* convertible to const void*");
+static_assert( can_assign<const void, std::shared_ptr<void>&&>(),
+ "void* convertible to const void*");
+static_assert( can_assign<const int, std::shared_ptr<int>>(),
+ "int* convertible to const int*");
+static_assert( can_assign<Base, std::shared_ptr<Derived>>(),
+ "Derived* convertible to Base*");
+static_assert( can_assign<const Base, std::shared_ptr<Derived>>(),
+ "Derived* convertible to const Base*");
+
+// Negative cases:
+
+static_assert( !can_assign<int, const std::shared_ptr<void>&>(),
+ "void* not convertible to int*");
+static_assert( !can_assign<int, std::shared_ptr<void>&&>(),
+ "void* not convertible to int*");
+
+static_assert( !can_assign<int, const std::shared_ptr<const int>&>(),
+ "const int* not convertible to int*");
+static_assert( !can_assign<int, std::shared_ptr<const int>&&>(),
+ "const int* not convertible to int*");
+
+static_assert( !can_assign<int, const std::shared_ptr<long>&>(),
+ "long* not convertible to int*");
+static_assert( !can_assign<int, std::shared_ptr<long>&&>(),
+ "long* not convertible to int*");
+
+static_assert( !can_assign<int, std::unique_ptr<long>&&>(),
+ "unique_ptr<long>::pointer not convertible to int*");
+
+static_assert( !can_assign<Derived, const std::shared_ptr<Base>&>(),
+ "Base* not convertible to Derived*");
+static_assert( !can_assign<int, std::shared_ptr<long>&&>(),
+ "Base* not convertible to Derived*");
+static_assert( !can_assign<Derived, std::unique_ptr<Base>&&>(),
+ "unique_ptr<Base>::pointer not convertible to Derived*");
+
+struct Deleter {
+ using pointer = void*;
+ void operator()(pointer) const { }
+};
+
+static_assert( !can_assign<Derived, std::unique_ptr<Derived, Deleter>&&>(),
+ "unique_ptr<Derived, Deleter>::pointer not convertible to Derived*");
// 20.6.6.2.3 shared_ptr assignment [util.smartptr.shared.assign]
// Assignment from incompatible shared_ptr<Y>
-int
+void
test01()
{
- bool test __attribute__((unused)) = true;
-
std::shared_ptr<A> a;
std::shared_ptr<B> b;
- a = b; // { dg-error "here" }
-
- return 0;
-}
-
-int
-main()
-{
- test01();
- return 0;
+ a = b; // { dg-error "no match" }
}
-// { dg-error "In instantiation" "" { target *-*-* } 0 }
-// { dg-error "cannot convert" "" { target *-*-* } 0 }
-// { dg-error "required from" "" { target *-*-* } 0 }
{
X* px = 0;
std::shared_ptr<X> p1(px); // { dg-error "here" }
- // { dg-error "incomplete" "" { target *-*-* } 893 }
-
std::shared_ptr<X> p9(ap()); // { dg-error "here" }
- // { dg-error "incomplete" "" { target *-*-* } 307 }
+ // { dg-error "incomplete" "" { target *-*-* } 0 }
}
void test01()
{
std::shared_ptr<void> p((void*)nullptr); // { dg-error "here" }
- // { dg-error "incomplete" "" { target *-*-* } 892 }
+ // { dg-error "incomplete" "" { target *-*-* } 0 }
}
--- /dev/null
+// 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/>.
+
+// { dg-do compile { target c++11 } }
+
+#include <memory>
+
+template<typename T, typename Args, typename = void>
+ struct resettable
+ : std::false_type
+ { };
+
+template<typename... T> struct type_list { };
+
+template<typename T, typename... Args>
+ using reset_result
+ = decltype(std::shared_ptr<T>{}.reset(std::declval<Args>()...));
+
+template<typename T, typename... Args>
+ struct resettable<T, type_list<Args...>, reset_result<T, Args...>>
+ : std::true_type
+ { };
+
+template<typename T, typename... Args>
+constexpr bool can_reset()
+{ return resettable<T, type_list<Args...>>::value; }
+
+template<typename T>
+struct Deleter {
+ void operator()(T*) const;
+};
+
+template<typename T>
+using Alloc = std::allocator<T>;
+
+struct Base { };
+struct Derived : Base { };
+
+// Positive cases:
+
+static_assert( can_reset<const void, void*>(),
+ "void* convertible to const void*");
+static_assert( can_reset<const int, int*>(),
+ "int* convertible to const int*");
+static_assert( can_reset<Base, Derived*>(),
+ "Derived* convertible to Base*");
+static_assert( can_reset<const Base, Derived*>(),
+ "Derived* convertible to const Base*");
+
+// Negative cases:
+
+static_assert( !can_reset<int, void*>(),
+ "void* not convertible to int*");
+static_assert( !can_reset<int, void*, Deleter<int>>(),
+ "void* not convertible to int*");
+static_assert( !can_reset<int, void*, Deleter<int>, Alloc<int>>(),
+ "void* not convertible to int*");
+
+static_assert( !can_reset<int, const int*>(),
+ "const int* not convertible to int*");
+static_assert( !can_reset<int, const int*, Deleter<int>>(),
+ "const int* not convertible to int*");
+static_assert( !can_reset<int, const int*, Deleter<int>, Alloc<int>>(),
+ "const int* not convertible to int*");
+
+static_assert( !can_reset<int, long*>(),
+ "long* not convertible to int*");
+static_assert( !can_reset<int, long*, Deleter<int>>(),
+ "long* not convertible to int*");
+static_assert( !can_reset<int, long*, Deleter<int>, Alloc<int>>(),
+ "long* not convertible to int*");
+
+static_assert( !can_reset<Derived, Base*>(),
+ "Base* not convertible to Derived*");
+static_assert( !can_reset<Derived, Base*, Deleter<int>>(),
+ "Base* not convertible to Derived*");
+static_assert( !can_reset<Derived, Base*, Deleter<int>, Alloc<int>>(),
+ "Base* not convertible to Derived*");