Prepare shared_ptr for array support

* include/backward/auto_ptr.h (__shared_ptr(auto_ptr&&))
	(shared_ptr(auto_ptr&&)): Adjust template parameter lists.
	* include/bits/shared_ptr.h (__sp_compatible_with)
	(__sp_is_constructible): New helper traits for shared_ptr.
	(shared_ptr::_Convertible): Replace with _Constructible.
	(shared_ptr::_Constructible, shared_ptr::_Assignable): Forward checks
	to base class.
	(shared_ptr::shared_ptr, shared_ptr::operator=): Constrain template
	with _Constructible and _Assignable.
	(shared_ptr::shared_ptr(shared_ptr<_Tp1>, _Tp*)): Use element_type
	instead of _Tp.
	(operator<): Likewise.
	(operator>): Define in terms of operator<.
	(static_pointer_cast, const_pointer_cast, dynamic_pointer_cast): Use
	element_type instead of _Tp.
	(reinterpret_pointer_cast): Define for C++17.
	(weak_ptr::_Convertible): Replace with _Constructible.
	(weak_ptr::_Constructible, weak_ptr::_Assignable): Forward checks
	to base class.
	(weak_ptr::weak_ptr, weak_ptr::operator=): Constrain templates
	with _Constructible and _Assignable.
	* include/bits/shared_ptr_base.h (__shared_ptr::_Convertible): Replace
	with _Compatible.
	(__shared_ptr::_SafeConv): New constraint for incoming raw pointers.
	(__shared_ptr::_Compatible): New constraint for converting from
	other types of shared_ptr and weak_ptr.
	(__shared_ptr::_Assignable): Define in terms of _Compatible.
	(__shared_ptr::_UniqCompatible, __shared_ptr::_UniqAssignable): New
	constraints for converting from unique_ptr.
	(__shared_ptr::__shared_ptr, __shared_ptr::operator=): Constrain
	template with _SaveConf, _Compatible and _Assignable. Remove
	__glibcxx_function_requires concept checks. Add static assertion for
	deleter expression being well-formed.
	(__shared_ptr::__shared_ptr(__shared_ptr<_Tp1>, _Tp*))
	(__shared_ptr::operator*, __shared_ptr::operator->)
	(__shared_ptr::get, __shared_ptr::_M_ptr): Use element_type instead
	of _Tp.
	(operator<): Likewise.
	(operator>): Define in terms of operator<.
	(static_pointer_cast, const_pointer_cast, dynamic_pointer_cast): Use
	element_type instead of _Tp.
	(reinterpret_pointer_cast): Define for C++17.
	(weak_ptr::_Convertible): Replace with _Compatible.
	(weak_ptr::_Compatible, weak_ptr::_Assignable): New constraints for
	conversions from other types of weak_ptr and shared_ptr.
	(__weak_ptr::__weak_ptr, __weak_ptr::operator=): Constrain templates
	with _Constructible and _Assignable.
	(__weak_ptr::_M_ptr): Use element_type instead of _Tp.
	* testsuite/20_util/shared_ptr/assign/auto_ptr_neg.cc: Adjust
	dg-error pattern.
	* testsuite/20_util/shared_ptr/cons/auto_ptr.cc: Test conversions.
	* testsuite/20_util/shared_ptr/cons/unique_ptr.cc: Likewise.
	* testsuite/20_util/shared_ptr/cons/void_neg.cc: Likewise.
	* testsuite/20_util/shared_ptr/casts/reinterpret.cc: New test.

From-SVN: r241373
This commit is contained in:
Jonathan Wakely 2016-10-20 13:07:45 +01:00 committed by Jonathan Wakely
parent f320e6a091
commit a2e0054e1d
9 changed files with 457 additions and 202 deletions

View file

@ -1,3 +1,60 @@
2016-10-20 Jonathan Wakely <jwakely@redhat.com>
* include/backward/auto_ptr.h (__shared_ptr(auto_ptr&&))
(shared_ptr(auto_ptr&&)): Adjust template parameter lists.
* include/bits/shared_ptr.h (__sp_compatible_with)
(__sp_is_constructible): New helper traits for shared_ptr.
(shared_ptr::_Convertible): Replace with _Constructible.
(shared_ptr::_Constructible, shared_ptr::_Assignable): Forward checks
to base class.
(shared_ptr::shared_ptr, shared_ptr::operator=): Constrain template
with _Constructible and _Assignable.
(shared_ptr::shared_ptr(shared_ptr<_Tp1>, _Tp*)): Use element_type
instead of _Tp.
(operator<): Likewise.
(operator>): Define in terms of operator<.
(static_pointer_cast, const_pointer_cast, dynamic_pointer_cast): Use
element_type instead of _Tp.
(reinterpret_pointer_cast): Define for C++17.
(weak_ptr::_Convertible): Replace with _Constructible.
(weak_ptr::_Constructible, weak_ptr::_Assignable): Forward checks
to base class.
(weak_ptr::weak_ptr, weak_ptr::operator=): Constrain templates
with _Constructible and _Assignable.
* include/bits/shared_ptr_base.h (__shared_ptr::_Convertible): Replace
with _Compatible.
(__shared_ptr::_SafeConv): New constraint for incoming raw pointers.
(__shared_ptr::_Compatible): New constraint for converting from
other types of shared_ptr and weak_ptr.
(__shared_ptr::_Assignable): Define in terms of _Compatible.
(__shared_ptr::_UniqCompatible, __shared_ptr::_UniqAssignable): New
constraints for converting from unique_ptr.
(__shared_ptr::__shared_ptr, __shared_ptr::operator=): Constrain
template with _SaveConf, _Compatible and _Assignable. Remove
__glibcxx_function_requires concept checks. Add static assertion for
deleter expression being well-formed.
(__shared_ptr::__shared_ptr(__shared_ptr<_Tp1>, _Tp*))
(__shared_ptr::operator*, __shared_ptr::operator->)
(__shared_ptr::get, __shared_ptr::_M_ptr): Use element_type instead
of _Tp.
(operator<): Likewise.
(operator>): Define in terms of operator<.
(static_pointer_cast, const_pointer_cast, dynamic_pointer_cast): Use
element_type instead of _Tp.
(reinterpret_pointer_cast): Define for C++17.
(weak_ptr::_Convertible): Replace with _Compatible.
(weak_ptr::_Compatible, weak_ptr::_Assignable): New constraints for
conversions from other types of weak_ptr and shared_ptr.
(__weak_ptr::__weak_ptr, __weak_ptr::operator=): Constrain templates
with _Constructible and _Assignable.
(__weak_ptr::_M_ptr): Use element_type instead of _Tp.
* testsuite/20_util/shared_ptr/assign/auto_ptr_neg.cc: Adjust
dg-error pattern.
* testsuite/20_util/shared_ptr/cons/auto_ptr.cc: Test conversions.
* testsuite/20_util/shared_ptr/cons/unique_ptr.cc: Likewise.
* testsuite/20_util/shared_ptr/cons/void_neg.cc: Likewise.
* testsuite/20_util/shared_ptr/casts/reinterpret.cc: New test.
2016-10-20 Ville Voutilainen <ville.voutilainen@gmail.com>
Do the operator= SFINAE in the return type for optional,

View file

@ -302,7 +302,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ __r.release(); }
template<typename _Tp, _Lock_policy _Lp>
template<typename _Tp1>
template<typename _Tp1, typename>
inline
__shared_ptr<_Tp, _Lp>::__shared_ptr(std::auto_ptr<_Tp1>&& __r)
: _M_ptr(__r.get()), _M_refcount()
@ -315,7 +315,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
template<typename _Tp>
template<typename _Tp1>
template<typename _Tp1, typename>
inline
shared_ptr<_Tp>::shared_ptr(std::auto_ptr<_Tp1>&& __r)
: __shared_ptr<_Tp>(std::move(__r)) { }

View file

@ -92,16 +92,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp>
class shared_ptr : public __shared_ptr<_Tp>
{
template<typename _Ptr>
using _Convertible = typename
enable_if<is_convertible<_Ptr, _Tp*>::value>::type;
template<typename... _Args>
using _Constructible = typename enable_if<
is_constructible<__shared_ptr<_Tp>, _Args...>::value
>::type;
template<typename _Ptr>
using _Assignable = typename
enable_if<is_convertible<_Ptr, _Tp*>::value, shared_ptr&>::type;
template<typename _Arg>
using _Assignable = typename enable_if<
is_assignable<__shared_ptr<_Tp>&, _Arg>::value, shared_ptr&
>::type;
public:
using element_type = typename __shared_ptr<_Tp>::element_type;
#if __cplusplus > 201402L
# define __cpp_lib_shared_ptr_weak_type 201606
using weak_type = weak_ptr<_Tp>;
@ -110,8 +114,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @brief Construct an empty %shared_ptr.
* @post use_count()==0 && get()==0
*/
constexpr shared_ptr() noexcept
: __shared_ptr<_Tp>() { }
constexpr shared_ptr() noexcept : __shared_ptr<_Tp>() { }
shared_ptr(const shared_ptr&) noexcept = default;
@ -121,9 +124,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @post use_count() == 1 && get() == __p
* @throw std::bad_alloc, in which case @c delete @a __p is called.
*/
template<typename _Tp1>
explicit shared_ptr(_Tp1* __p)
: __shared_ptr<_Tp>(__p) { }
template<typename _Yp, typename = _Constructible<_Yp*>>
explicit
shared_ptr(_Yp* __p) : __shared_ptr<_Tp>(__p) { }
/**
* @brief Construct a %shared_ptr that owns the pointer @a __p
@ -138,8 +141,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*
* __shared_ptr will release __p by calling __d(__p)
*/
template<typename _Tp1, typename _Deleter>
shared_ptr(_Tp1* __p, _Deleter __d)
template<typename _Yp, typename _Deleter,
typename = _Constructible<_Yp*, _Deleter>>
shared_ptr(_Yp* __p, _Deleter __d)
: __shared_ptr<_Tp>(__p, __d) { }
/**
@ -174,8 +178,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*
* __shared_ptr will release __p by calling __d(__p)
*/
template<typename _Tp1, typename _Deleter, typename _Alloc>
shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)
template<typename _Yp, typename _Deleter, typename _Alloc,
typename = _Constructible<_Yp*, _Deleter, _Alloc>>
shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a)
: __shared_ptr<_Tp>(__p, __d, std::move(__a)) { }
/**
@ -215,8 +220,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* assert(pii.use_count() == 2);
* @endcode
*/
template<typename _Tp1>
shared_ptr(const shared_ptr<_Tp1>& __r, _Tp* __p) noexcept
template<typename _Yp>
shared_ptr(const shared_ptr<_Yp>& __r, element_type* __p) noexcept
: __shared_ptr<_Tp>(__r, __p) { }
/**
@ -226,8 +231,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @param __r A %shared_ptr.
* @post get() == __r.get() && use_count() == __r.use_count()
*/
template<typename _Tp1, typename = _Convertible<_Tp1*>>
shared_ptr(const shared_ptr<_Tp1>& __r) noexcept
template<typename _Yp,
typename = _Constructible<const shared_ptr<_Yp>&>>
shared_ptr(const shared_ptr<_Yp>& __r) noexcept
: __shared_ptr<_Tp>(__r) { }
/**
@ -243,8 +249,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @param __r A %shared_ptr rvalue.
* @post *this contains the old value of @a __r, @a __r is empty.
*/
template<typename _Tp1, typename = _Convertible<_Tp1*>>
shared_ptr(shared_ptr<_Tp1>&& __r) noexcept
template<typename _Yp, typename = _Constructible<shared_ptr<_Yp>>>
shared_ptr(shared_ptr<_Yp>&& __r) noexcept
: __shared_ptr<_Tp>(std::move(__r)) { }
/**
@ -255,20 +261,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @throw bad_weak_ptr when __r.expired(),
* in which case the constructor has no effect.
*/
template<typename _Tp1>
explicit shared_ptr(const weak_ptr<_Tp1>& __r)
template<typename _Yp, typename = _Constructible<const weak_ptr<_Yp>&>>
explicit shared_ptr(const weak_ptr<_Yp>& __r)
: __shared_ptr<_Tp>(__r) { }
#if _GLIBCXX_USE_DEPRECATED
template<typename _Tp1>
shared_ptr(std::auto_ptr<_Tp1>&& __r);
template<typename _Yp, typename = _Constructible<auto_ptr<_Yp>>>
shared_ptr(auto_ptr<_Yp>&& __r);
#endif
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 2399. shared_ptr's constructor from unique_ptr should be constrained
template<typename _Tp1, typename _Del, typename
= _Convertible<typename unique_ptr<_Tp1, _Del>::pointer>>
shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r)
template<typename _Yp, typename _Del,
typename = _Constructible<unique_ptr<_Yp, _Del>>>
shared_ptr(unique_ptr<_Yp, _Del>&& __r)
: __shared_ptr<_Tp>(std::move(__r)) { }
/**
@ -279,18 +285,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
shared_ptr& operator=(const shared_ptr&) noexcept = default;
template<typename _Tp1>
_Assignable<_Tp1*>
operator=(const shared_ptr<_Tp1>& __r) noexcept
template<typename _Yp>
_Assignable<const shared_ptr<_Yp>&>
operator=(const shared_ptr<_Yp>& __r) noexcept
{
this->__shared_ptr<_Tp>::operator=(__r);
return *this;
}
#if _GLIBCXX_USE_DEPRECATED
template<typename _Tp1>
shared_ptr&
operator=(std::auto_ptr<_Tp1>&& __r)
template<typename _Yp>
_Assignable<auto_ptr<_Yp>>
operator=(auto_ptr<_Yp>&& __r)
{
this->__shared_ptr<_Tp>::operator=(std::move(__r));
return *this;
@ -304,17 +310,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return *this;
}
template<class _Tp1>
_Assignable<_Tp1*>
operator=(shared_ptr<_Tp1>&& __r) noexcept
template<class _Yp>
_Assignable<shared_ptr<_Yp>>
operator=(shared_ptr<_Yp>&& __r) noexcept
{
this->__shared_ptr<_Tp>::operator=(std::move(__r));
return *this;
}
template<typename _Tp1, typename _Del>
_Assignable<typename unique_ptr<_Tp1, _Del>::pointer>
operator=(std::unique_ptr<_Tp1, _Del>&& __r)
template<typename _Yp, typename _Del>
_Assignable<unique_ptr<_Yp, _Del>>
operator=(unique_ptr<_Yp, _Del>&& __r)
{
this->__shared_ptr<_Tp>::operator=(std::move(__r));
return *this;
@ -328,8 +334,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: __shared_ptr<_Tp>(__tag, __a, std::forward<_Args>(__args)...)
{ }
template<typename _Tp1, typename _Alloc, typename... _Args>
friend shared_ptr<_Tp1>
template<typename _Yp, typename _Alloc, typename... _Args>
friend shared_ptr<_Yp>
allocate_shared(const _Alloc& __a, _Args&&... __args);
// This constructor is non-standard, it is used by weak_ptr::lock().
@ -340,10 +346,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
// 20.7.2.2.7 shared_ptr comparisons
template<typename _Tp1, typename _Tp2>
template<typename _Tp, typename _Up>
inline bool
operator==(const shared_ptr<_Tp1>& __a,
const shared_ptr<_Tp2>& __b) noexcept
operator==(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
{ return __a.get() == __b.get(); }
template<typename _Tp>
@ -356,10 +361,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator==(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
{ return !__a; }
template<typename _Tp1, typename _Tp2>
template<typename _Tp, typename _Up>
inline bool
operator!=(const shared_ptr<_Tp1>& __a,
const shared_ptr<_Tp2>& __b) noexcept
operator!=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
{ return __a.get() != __b.get(); }
template<typename _Tp>
@ -372,29 +376,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator!=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
{ return (bool)__a; }
template<typename _Tp1, typename _Tp2>
template<typename _Tp, typename _Up>
inline bool
operator<(const shared_ptr<_Tp1>& __a,
const shared_ptr<_Tp2>& __b) noexcept
operator<(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
{
typedef typename std::common_type<_Tp1*, _Tp2*>::type _CT;
return std::less<_CT>()(__a.get(), __b.get());
using _Tp_elt = typename shared_ptr<_Tp>::element_type;
using _Up_elt = typename shared_ptr<_Up>::element_type;
using _Vp = typename common_type<_Tp_elt*, _Up_elt*>::type;
return less<_Vp>()(__a.get(), __b.get());
}
template<typename _Tp>
inline bool
operator<(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
{ return std::less<_Tp*>()(__a.get(), nullptr); }
{
using _Tp_elt = typename shared_ptr<_Tp>::element_type;
return less<_Tp_elt*>()(__a.get(), nullptr);
}
template<typename _Tp>
inline bool
operator<(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
{ return std::less<_Tp*>()(nullptr, __a.get()); }
{
using _Tp_elt = typename shared_ptr<_Tp>::element_type;
return less<_Tp_elt*>()(nullptr, __a.get());
}
template<typename _Tp1, typename _Tp2>
template<typename _Tp, typename _Up>
inline bool
operator<=(const shared_ptr<_Tp1>& __a,
const shared_ptr<_Tp2>& __b) noexcept
operator<=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
{ return !(__b < __a); }
template<typename _Tp>
@ -407,26 +417,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator<=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
{ return !(__a < nullptr); }
template<typename _Tp1, typename _Tp2>
template<typename _Tp, typename _Up>
inline bool
operator>(const shared_ptr<_Tp1>& __a,
const shared_ptr<_Tp2>& __b) noexcept
operator>(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
{ return (__b < __a); }
template<typename _Tp>
inline bool
operator>(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
{ return std::less<_Tp*>()(nullptr, __a.get()); }
{ return nullptr < __a; }
template<typename _Tp>
inline bool
operator>(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
{ return std::less<_Tp*>()(__a.get(), nullptr); }
{ return __a < nullptr; }
template<typename _Tp1, typename _Tp2>
template<typename _Tp, typename _Up>
inline bool
operator>=(const shared_ptr<_Tp1>& __a,
const shared_ptr<_Tp2>& __b) noexcept
operator>=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
{ return !(__a < __b); }
template<typename _Tp>
@ -450,25 +458,41 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ __a.swap(__b); }
// 20.7.2.2.9 shared_ptr casts.
template<typename _Tp, typename _Tp1>
template<typename _Tp, typename _Up>
inline shared_ptr<_Tp>
static_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
{ return shared_ptr<_Tp>(__r, static_cast<_Tp*>(__r.get())); }
template<typename _Tp, typename _Tp1>
inline shared_ptr<_Tp>
const_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
{ return shared_ptr<_Tp>(__r, const_cast<_Tp*>(__r.get())); }
template<typename _Tp, typename _Tp1>
inline shared_ptr<_Tp>
dynamic_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
static_pointer_cast(const shared_ptr<_Up>& __r) noexcept
{
if (_Tp* __p = dynamic_cast<_Tp*>(__r.get()))
return shared_ptr<_Tp>(__r, __p);
return shared_ptr<_Tp>();
using _Sp = shared_ptr<_Tp>;
return _Sp(__r, static_cast<typename _Sp::element_type*>(__r.get()));
}
template<typename _Tp, typename _Up>
inline shared_ptr<_Tp>
const_pointer_cast(const shared_ptr<_Up>& __r) noexcept
{
using _Sp = shared_ptr<_Tp>;
return _Sp(__r, const_cast<typename _Sp::element_type*>(__r.get()));
}
template<typename _Tp, typename _Up>
inline shared_ptr<_Tp>
dynamic_pointer_cast(const shared_ptr<_Up>& __r) noexcept
{
using _Sp = shared_ptr<_Tp>;
if (auto* __p = dynamic_cast<typename _Sp::element_type*>(__r.get()))
return _Sp(__r, __p);
return _Sp();
}
#if __cplusplus > 201402L
template<typename _Tp, typename _Up>
inline shared_ptr<_Tp>
reinterpret_pointer_cast(const shared_ptr<_Up>& __r) noexcept
{
using _Sp = shared_ptr<_Tp>;
return _Sp(__r, reinterpret_cast<typename _Sp::element_type*>(__r.get()));
}
#endif
/**
* @brief A smart pointer with weak semantics.
@ -478,43 +502,50 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp>
class weak_ptr : public __weak_ptr<_Tp>
{
template<typename _Ptr>
using _Convertible
= typename enable_if<is_convertible<_Ptr, _Tp*>::value>::type;
template<typename _Arg>
using _Constructible = typename enable_if<
is_constructible<__weak_ptr<_Tp>, _Arg>::value
>::type;
template<typename _Arg>
using _Assignable = typename enable_if<
is_assignable<__weak_ptr<_Tp>&, _Arg>::value, weak_ptr&
>::type;
public:
constexpr weak_ptr() noexcept = default;
template<typename _Tp1, typename = _Convertible<_Tp1*>>
weak_ptr(const shared_ptr<_Tp1>& __r) noexcept
template<typename _Yp,
typename = _Constructible<const shared_ptr<_Yp>&>>
weak_ptr(const shared_ptr<_Yp>& __r) noexcept
: __weak_ptr<_Tp>(__r) { }
weak_ptr(const weak_ptr&) noexcept = default;
template<typename _Tp1, typename = _Convertible<_Tp1*>>
weak_ptr(const weak_ptr<_Tp1>& __r) noexcept
template<typename _Yp, typename = _Constructible<const weak_ptr<_Yp>&>>
weak_ptr(const weak_ptr<_Yp>& __r) noexcept
: __weak_ptr<_Tp>(__r) { }
weak_ptr(weak_ptr&&) noexcept = default;
template<typename _Tp1, typename = _Convertible<_Tp1*>>
weak_ptr(weak_ptr<_Tp1>&& __r) noexcept
template<typename _Yp, typename = _Constructible<weak_ptr<_Yp>>>
weak_ptr(weak_ptr<_Yp>&& __r) noexcept
: __weak_ptr<_Tp>(std::move(__r)) { }
weak_ptr&
operator=(const weak_ptr& __r) noexcept = default;
template<typename _Tp1>
weak_ptr&
operator=(const weak_ptr<_Tp1>& __r) noexcept
template<typename _Yp>
_Assignable<const weak_ptr<_Yp>&>
operator=(const weak_ptr<_Yp>& __r) noexcept
{
this->__weak_ptr<_Tp>::operator=(__r);
return *this;
}
template<typename _Tp1>
weak_ptr&
operator=(const shared_ptr<_Tp1>& __r) noexcept
template<typename _Yp>
_Assignable<const shared_ptr<_Yp>&>
operator=(const shared_ptr<_Yp>& __r) noexcept
{
this->__weak_ptr<_Tp>::operator=(__r);
return *this;
@ -523,9 +554,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
weak_ptr&
operator=(weak_ptr&& __r) noexcept = default;
template<typename _Tp1>
weak_ptr&
operator=(weak_ptr<_Tp1>&& __r) noexcept
template<typename _Yp>
_Assignable<weak_ptr<_Yp>>
operator=(weak_ptr<_Yp>&& __r) noexcept
{
this->__weak_ptr<_Tp>::operator=(std::move(__r));
return *this;

View file

@ -847,19 +847,55 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_pi = nullptr;
}
// Helper traits for shared_ptr
template<typename _Yp_ptr, typename _Tp_ptr>
struct __sp_compatible_with
: false_type
{ };
template<typename _Yp, typename _Tp>
struct __sp_compatible_with<_Yp*, _Tp*>
: is_convertible<_Yp*, _Tp*>::type
{ };
template<typename _Tp, _Lock_policy _Lp>
class __shared_ptr
{
template<typename _Ptr>
using _Convertible
= typename enable_if<is_convertible<_Ptr, _Tp*>::value>::type;
public:
using element_type = _Tp;
template<typename _Ptr>
using _Assignable = typename
enable_if<is_convertible<_Ptr, _Tp*>::value, __shared_ptr&>::type;
private:
// Trait to check if shared_ptr<T> can be constructed from Y*.
template<typename _Tp1, typename _Yp>
using __sp_is_constructible = is_convertible<_Yp*, _Tp1*>;
// Constraint for taking ownership of a pointer of type _Yp*:
template<typename _Yp>
using _SafeConv
= typename enable_if<__sp_is_constructible<_Tp, _Yp>::value>::type;
// Constraint for construction from shared_ptr and weak_ptr:
template<typename _Yp, typename _Res = void>
using _Compatible = typename
enable_if<__sp_compatible_with<_Yp*, _Tp*>::value, _Res>::type;
// Constraint for assignment from shared_ptr and weak_ptr:
template<typename _Yp>
using _Assignable = _Compatible<_Yp, __shared_ptr&>;
// Constraint for construction from unique_ptr:
template<typename _Yp, typename _Del, typename _Res = void,
typename _Ptr = typename unique_ptr<_Yp, _Del>::pointer>
using _UniqCompatible = typename enable_if<
is_convertible<_Ptr, element_type*>::value
, _Res>::type;
// Constraint for assignment from unique_ptr:
template<typename _Yp, typename _Del>
using _UniqAssignable = _UniqCompatible<_Yp, _Del, __shared_ptr&>;
public:
typedef _Tp element_type;
#if __cplusplus > 201402L
using weak_type = __weak_ptr<_Tp, _Lp>;
@ -869,31 +905,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: _M_ptr(0), _M_refcount()
{ }
template<typename _Tp1>
explicit __shared_ptr(_Tp1* __p)
: _M_ptr(__p), _M_refcount(__p)
template<typename _Yp, typename = _SafeConv<_Yp>>
explicit
__shared_ptr(_Yp* __p)
: _M_ptr(__p), _M_refcount(__p)
{
__glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
static_assert( !is_void<_Tp1>::value, "incomplete type" );
static_assert( sizeof(_Tp1) > 0, "incomplete type" );
static_assert( !is_void<_Yp>::value, "incomplete type" );
static_assert( sizeof(_Yp) > 0, "incomplete type" );
_M_enable_shared_from_this_with(__p);
}
template<typename _Tp1, typename _Deleter>
__shared_ptr(_Tp1* __p, _Deleter __d)
template<typename _Yp, typename _Deleter, typename = _SafeConv<_Yp>>
__shared_ptr(_Yp* __p, _Deleter __d)
: _M_ptr(__p), _M_refcount(__p, __d)
{
__glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
// TODO requires _Deleter CopyConstructible and __d(__p) well-formed
static_assert(__is_callable<_Deleter(_Yp*)>::value,
"deleter expression d(p) is well-formed");
_M_enable_shared_from_this_with(__p);
}
template<typename _Tp1, typename _Deleter, typename _Alloc>
__shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)
template<typename _Yp, typename _Deleter, typename _Alloc,
typename = _SafeConv<_Yp>>
__shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a)
: _M_ptr(__p), _M_refcount(__p, __d, std::move(__a))
{
__glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
// TODO requires _Deleter CopyConstructible and __d(__p) well-formed
static_assert(__is_callable<_Deleter(_Yp*)>::value,
"deleter expression d(p) is well-formed");
_M_enable_shared_from_this_with(__p);
}
@ -907,8 +944,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: _M_ptr(0), _M_refcount(__p, __d, std::move(__a))
{ }
template<typename _Tp1>
__shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r, _Tp* __p) noexcept
template<typename _Yp>
__shared_ptr(const __shared_ptr<_Yp, _Lp>& __r,
element_type* __p) noexcept
: _M_ptr(__p), _M_refcount(__r._M_refcount) // never throws
{ }
@ -916,8 +954,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__shared_ptr& operator=(const __shared_ptr&) noexcept = default;
~__shared_ptr() = default;
template<typename _Tp1, typename = _Convertible<_Tp1*>>
__shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
template<typename _Yp, typename = _Compatible<_Yp>>
__shared_ptr(const __shared_ptr<_Yp, _Lp>& __r) noexcept
: _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
{ }
@ -928,32 +966,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__r._M_ptr = 0;
}
template<typename _Tp1, typename = _Convertible<_Tp1*>>
__shared_ptr(__shared_ptr<_Tp1, _Lp>&& __r) noexcept
template<typename _Yp, typename = _Compatible<_Yp>>
__shared_ptr(__shared_ptr<_Yp, _Lp>&& __r) noexcept
: _M_ptr(__r._M_ptr), _M_refcount()
{
_M_refcount._M_swap(__r._M_refcount);
__r._M_ptr = 0;
}
template<typename _Tp1>
explicit __shared_ptr(const __weak_ptr<_Tp1, _Lp>& __r)
template<typename _Yp, typename = _Compatible<_Yp>>
explicit __shared_ptr(const __weak_ptr<_Yp, _Lp>& __r)
: _M_refcount(__r._M_refcount) // may throw
{
__glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
// It is now safe to copy __r._M_ptr, as
// _M_refcount(__r._M_refcount) did not throw.
_M_ptr = __r._M_ptr;
}
// If an exception is thrown this constructor has no effect.
template<typename _Tp1, typename _Del, typename
= _Convertible<typename unique_ptr<_Tp1, _Del>::pointer>>
__shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r)
template<typename _Yp, typename _Del,
typename = _UniqCompatible<_Yp, _Del>>
__shared_ptr(unique_ptr<_Yp, _Del>&& __r)
: _M_ptr(__r.get()), _M_refcount()
{
__glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
auto __raw = _S_raw_ptr(__r.get());
_M_refcount = __shared_count<_Lp>(std::move(__r));
_M_enable_shared_from_this_with(__raw);
@ -961,15 +996,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if _GLIBCXX_USE_DEPRECATED
// Postcondition: use_count() == 1 and __r.get() == 0
template<typename _Tp1>
__shared_ptr(std::auto_ptr<_Tp1>&& __r);
template<typename _Yp, typename = _Compatible<_Yp>>
__shared_ptr(auto_ptr<_Yp>&& __r);
#endif
constexpr __shared_ptr(nullptr_t) noexcept : __shared_ptr() { }
template<typename _Tp1>
_Assignable<_Tp1*>
operator=(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
template<typename _Yp>
_Assignable<_Yp>
operator=(const __shared_ptr<_Yp, _Lp>& __r) noexcept
{
_M_ptr = __r._M_ptr;
_M_refcount = __r._M_refcount; // __shared_count::op= doesn't throw
@ -977,9 +1012,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
#if _GLIBCXX_USE_DEPRECATED
template<typename _Tp1>
__shared_ptr&
operator=(std::auto_ptr<_Tp1>&& __r)
template<typename _Yp>
_Assignable<_Yp>
operator=(auto_ptr<_Yp>&& __r)
{
__shared_ptr(std::move(__r)).swap(*this);
return *this;
@ -993,17 +1028,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return *this;
}
template<class _Tp1>
_Assignable<_Tp1*>
operator=(__shared_ptr<_Tp1, _Lp>&& __r) noexcept
template<class _Yp>
_Assignable<_Yp>
operator=(__shared_ptr<_Yp, _Lp>&& __r) noexcept
{
__shared_ptr(std::move(__r)).swap(*this);
return *this;
}
template<typename _Tp1, typename _Del>
_Assignable<typename unique_ptr<_Tp1, _Del>::pointer>
operator=(std::unique_ptr<_Tp1, _Del>&& __r)
template<typename _Yp, typename _Del>
_UniqAssignable<_Yp, _Del>
operator=(unique_ptr<_Yp, _Del>&& __r)
{
__shared_ptr(std::move(__r)).swap(*this);
return *this;
@ -1013,41 +1048,41 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
reset() noexcept
{ __shared_ptr().swap(*this); }
template<typename _Tp1>
_Convertible<_Tp1*>
reset(_Tp1* __p) // _Tp1 must be complete.
template<typename _Yp>
_SafeConv<_Yp>
reset(_Yp* __p) // _Yp must be complete.
{
// Catch self-reset errors.
__glibcxx_assert(__p == 0 || __p != _M_ptr);
__shared_ptr(__p).swap(*this);
}
template<typename _Tp1, typename _Deleter>
_Convertible<_Tp1*>
reset(_Tp1* __p, _Deleter __d)
template<typename _Yp, typename _Deleter>
_SafeConv<_Yp>
reset(_Yp* __p, _Deleter __d)
{ __shared_ptr(__p, __d).swap(*this); }
template<typename _Tp1, typename _Deleter, typename _Alloc>
_Convertible<_Tp1*>
reset(_Tp1* __p, _Deleter __d, _Alloc __a)
template<typename _Yp, typename _Deleter, typename _Alloc>
_SafeConv<_Yp>
reset(_Yp* __p, _Deleter __d, _Alloc __a)
{ __shared_ptr(__p, __d, std::move(__a)).swap(*this); }
// Allow class instantiation when _Tp is [cv-qual] void.
typename std::add_lvalue_reference<_Tp>::type
typename std::add_lvalue_reference<element_type>::type
operator*() const noexcept
{
__glibcxx_assert(_M_ptr != 0);
return *_M_ptr;
}
_Tp*
element_type*
operator->() const noexcept
{
_GLIBCXX_DEBUG_PEDASSERT(_M_ptr != 0);
return _M_ptr;
}
_Tp*
element_type*
get() const noexcept
{ return _M_ptr; }
@ -1192,7 +1227,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Del, typename _Tp1, _Lock_policy _Lp1>
friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&) noexcept;
_Tp* _M_ptr; // Contained pointer.
element_type* _M_ptr; // Contained pointer.
__shared_count<_Lp> _M_refcount; // Reference counter.
};
@ -1230,24 +1265,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator!=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
{ return (bool)__a; }
template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
template<typename _Tp, typename _Up, _Lock_policy _Lp>
inline bool
operator<(const __shared_ptr<_Tp1, _Lp>& __a,
const __shared_ptr<_Tp2, _Lp>& __b) noexcept
operator<(const __shared_ptr<_Tp, _Lp>& __a,
const __shared_ptr<_Up, _Lp>& __b) noexcept
{
typedef typename std::common_type<_Tp1*, _Tp2*>::type _CT;
return std::less<_CT>()(__a.get(), __b.get());
using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type;
using _Up_elt = typename __shared_ptr<_Up, _Lp>::element_type;
using _Vp = typename common_type<_Tp_elt*, _Up_elt*>::type;
return less<_Vp>()(__a.get(), __b.get());
}
template<typename _Tp, _Lock_policy _Lp>
inline bool
operator<(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
{ return std::less<_Tp*>()(__a.get(), nullptr); }
{
using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type;
return less<_Tp_elt*>()(__a.get(), nullptr);
}
template<typename _Tp, _Lock_policy _Lp>
inline bool
operator<(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
{ return std::less<_Tp*>()(nullptr, __a.get()); }
{
using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type;
return less<_Tp_elt*>()(nullptr, __a.get());
}
template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
inline bool
@ -1274,12 +1317,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp, _Lock_policy _Lp>
inline bool
operator>(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept
{ return std::less<_Tp*>()(nullptr, __a.get()); }
{ return nullptr < __a; }
template<typename _Tp, _Lock_policy _Lp>
inline bool
operator>(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
{ return std::less<_Tp*>()(__a.get(), nullptr); }
{ return __a < nullptr; }
template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
inline bool
@ -1329,7 +1372,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
inline __shared_ptr<_Tp, _Lp>
static_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
{ return __shared_ptr<_Tp, _Lp>(__r, static_cast<_Tp*>(__r.get())); }
{
using _Sp = __shared_ptr<_Tp, _Lp>;
return _Sp(__r, static_cast<typename _Sp::element_type*>(__r.get()));
}
// The seemingly equivalent code:
// shared_ptr<_Tp, _Lp>(const_cast<_Tp*>(__r.get()))
@ -1339,7 +1385,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
inline __shared_ptr<_Tp, _Lp>
const_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
{ return __shared_ptr<_Tp, _Lp>(__r, const_cast<_Tp*>(__r.get())); }
{
using _Sp = __shared_ptr<_Tp, _Lp>;
return _Sp(__r, const_cast<typename _Sp::element_type*>(__r.get()));
}
// The seemingly equivalent code:
// shared_ptr<_Tp, _Lp>(dynamic_cast<_Tp*>(__r.get()))
@ -1350,21 +1399,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline __shared_ptr<_Tp, _Lp>
dynamic_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
{
if (_Tp* __p = dynamic_cast<_Tp*>(__r.get()))
return __shared_ptr<_Tp, _Lp>(__r, __p);
return __shared_ptr<_Tp, _Lp>();
using _Sp = __shared_ptr<_Tp, _Lp>;
if (auto* __p = dynamic_cast<typename _Sp::element_type*>(__r.get()))
return _Sp(__r, __p);
return _Sp();
}
#if __cplusplus > 201402L
template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
inline __shared_ptr<_Tp, _Lp>
reinterpret_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
{
using _Sp = __shared_ptr<_Tp, _Lp>;
return _Sp(__r, reinterpret_cast<typename _Sp::element_type*>(__r.get()));
}
#endif
template<typename _Tp, _Lock_policy _Lp>
class __weak_ptr
{
template<typename _Ptr>
using _Convertible
= typename enable_if<is_convertible<_Ptr, _Tp*>::value>::type;
template<typename _Yp, typename _Res = void>
using _Compatible = typename
enable_if<__sp_compatible_with<_Yp*, _Tp*>::value, _Res>::type;
// Constraint for assignment from shared_ptr and weak_ptr:
template<typename _Yp>
using _Assignable = _Compatible<_Yp, __weak_ptr&>;
public:
typedef _Tp element_type;
using element_type = _Tp;
constexpr __weak_ptr() noexcept
: _M_ptr(nullptr), _M_refcount()
@ -1388,13 +1451,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
//
// It is not possible to avoid spurious access violations since
// in multithreaded programs __r._M_ptr may be invalidated at any point.
template<typename _Tp1, typename = _Convertible<_Tp1*>>
__weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r) noexcept
template<typename _Yp, typename = _Compatible<_Yp>>
__weak_ptr(const __weak_ptr<_Yp, _Lp>& __r) noexcept
: _M_refcount(__r._M_refcount)
{ _M_ptr = __r.lock().get(); }
template<typename _Tp1, typename = _Convertible<_Tp1*>>
__weak_ptr(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
template<typename _Yp, typename = _Compatible<_Yp>>
__weak_ptr(const __shared_ptr<_Yp, _Lp>& __r) noexcept
: _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
{ }
@ -1402,26 +1465,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: _M_ptr(__r._M_ptr), _M_refcount(std::move(__r._M_refcount))
{ __r._M_ptr = nullptr; }
template<typename _Tp1, typename = _Convertible<_Tp1*>>
__weak_ptr(__weak_ptr<_Tp1, _Lp>&& __r) noexcept
template<typename _Yp, typename = _Compatible<_Yp>>
__weak_ptr(__weak_ptr<_Yp, _Lp>&& __r) noexcept
: _M_ptr(__r.lock().get()), _M_refcount(std::move(__r._M_refcount))
{ __r._M_ptr = nullptr; }
__weak_ptr&
operator=(const __weak_ptr& __r) noexcept = default;
template<typename _Tp1>
__weak_ptr&
operator=(const __weak_ptr<_Tp1, _Lp>& __r) noexcept
template<typename _Yp>
_Assignable<_Yp>
operator=(const __weak_ptr<_Yp, _Lp>& __r) noexcept
{
_M_ptr = __r.lock().get();
_M_refcount = __r._M_refcount;
return *this;
}
template<typename _Tp1>
__weak_ptr&
operator=(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
template<typename _Yp>
_Assignable<_Yp>
operator=(const __shared_ptr<_Yp, _Lp>& __r) noexcept
{
_M_ptr = __r._M_ptr;
_M_refcount = __r._M_refcount;
@ -1437,9 +1500,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return *this;
}
template<typename _Tp1>
__weak_ptr&
operator=(__weak_ptr<_Tp1, _Lp>&& __r) noexcept
template<typename _Yp>
_Assignable<_Yp>
operator=(__weak_ptr<_Yp, _Lp>&& __r) noexcept
{
_M_ptr = __r.lock().get();
_M_refcount = std::move(__r._M_refcount);
@ -1497,7 +1560,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
friend class __enable_shared_from_this<_Tp, _Lp>;
friend class enable_shared_from_this<_Tp>;
_Tp* _M_ptr; // Contained pointer.
element_type* _M_ptr; // Contained pointer.
__weak_count<_Lp> _M_refcount; // Reference counter.
};

View file

@ -34,7 +34,7 @@ test01()
{
std::shared_ptr<A> a;
std::auto_ptr<B> b;
a = std::move(b); // { dg-error "here" }
a = std::move(b); // { dg-error "no match" }
return 0;
}

View file

@ -0,0 +1,42 @@
// { dg-options "-std=gnu++17" }
// { dg-do compile { target c++1z } }
// 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/>.
// 20.11.2.2.9 shared_ptr casts [util.smartptr.shared.cast]
#include <memory>
#include <testsuite_tr1.h>
struct MyP { virtual ~MyP() { }; };
struct MyDP : MyP { };
int main()
{
using __gnu_test::check_ret_type;
using std::shared_ptr;
using std::reinterpret_pointer_cast;
shared_ptr<double> spd;
shared_ptr<const int> spci;
shared_ptr<MyP> spa;
check_ret_type<shared_ptr<void> >(reinterpret_pointer_cast<void>(spd));
check_ret_type<shared_ptr<const short> >(reinterpret_pointer_cast<const short>(spci));
check_ret_type<shared_ptr<MyDP> >(reinterpret_pointer_cast<MyDP>(spa));
}

View file

@ -25,10 +25,28 @@
struct A { };
int destroyed = 0;
struct B : A { ~B() { ++destroyed; } };
// 20.6.6.2.1 shared_ptr constructors [util.smartptr.shared.const]
// Construction from auto_ptr
int
template<typename From, typename To>
constexpr bool constructible()
{
using namespace std;
return is_constructible<shared_ptr<To>, auto_ptr<From>>::value
&& is_constructible<shared_ptr<const To>, auto_ptr<From>>::value
&& is_constructible<shared_ptr<const To>, auto_ptr<const From>>::value;
}
static_assert( constructible< A, A >(), "A -> A compatible" );
static_assert( constructible< B, A >(), "B -> A compatible" );
static_assert( constructible< int, int >(), "int -> int compatible" );
static_assert( !constructible< int, long >(), "int -> long not compatible" );
void
test01()
{
std::auto_ptr<A> a(new A);
@ -36,13 +54,24 @@ test01()
VERIFY( a.get() == 0 );
VERIFY( a2.get() != 0 );
VERIFY( a2.use_count() == 1 );
}
return 0;
void
test02()
{
std::auto_ptr<B> b(new B);
std::shared_ptr<A> a(std::move(b));
VERIFY( b.get() == 0 );
VERIFY( a.get() != 0 );
VERIFY( a.use_count() == 1 );
a.reset();
VERIFY( destroyed == 1 );
}
int
main()
{
test01();
test02();
return 0;
}

View file

@ -24,10 +24,28 @@
struct A { };
int destroyed = 0;
struct B : A { ~B() { ++destroyed; } };
// 20.7.2.2.1 shared_ptr constructors [util.smartptr.shared.const]
// Construction from unique_ptr
int
template<typename From, typename To>
constexpr bool constructible()
{
using namespace std;
return is_constructible<shared_ptr<To>, unique_ptr<From>>::value
&& is_constructible<shared_ptr<const To>, unique_ptr<From>>::value
&& is_constructible<shared_ptr<const To>, unique_ptr<const From>>::value;
}
static_assert( constructible< A, A >(), "A -> A compatible" );
static_assert( constructible< B, A >(), "B -> A compatible" );
static_assert( constructible< int, int >(), "int -> int compatible" );
static_assert( !constructible< int, long >(), "int -> long not compatible" );
void
test01()
{
std::unique_ptr<A> up(new A);
@ -35,13 +53,24 @@ test01()
VERIFY( up.get() == 0 );
VERIFY( sp.get() != 0 );
VERIFY( sp.use_count() == 1 );
}
return 0;
void
test02()
{
std::unique_ptr<B> b(new B);
std::shared_ptr<A> a(std::move(b));
VERIFY( b.get() == 0 );
VERIFY( a.get() != 0 );
VERIFY( a.use_count() == 1 );
a.reset();
VERIFY( destroyed == 1 );
}
int
main()
{
test01();
test02();
return 0;
}

View file

@ -26,3 +26,7 @@ void test01()
std::shared_ptr<void> p((void*)nullptr); // { dg-error "here" }
// { dg-error "incomplete" "" { target *-*-* } 0 }
}
using std::shared_ptr;
using std::is_constructible;
static_assert(!is_constructible<shared_ptr<void>, const void*>::value, "");