Commit a2e0054e by Jonathan Wakely Committed by Jonathan Wakely

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
parent f320e6a0
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> 2016-10-20 Ville Voutilainen <ville.voutilainen@gmail.com>
Do the operator= SFINAE in the return type for optional, Do the operator= SFINAE in the return type for optional,
......
...@@ -302,7 +302,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -302,7 +302,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ __r.release(); } { __r.release(); }
template<typename _Tp, _Lock_policy _Lp> template<typename _Tp, _Lock_policy _Lp>
template<typename _Tp1> template<typename _Tp1, typename>
inline inline
__shared_ptr<_Tp, _Lp>::__shared_ptr(std::auto_ptr<_Tp1>&& __r) __shared_ptr<_Tp, _Lp>::__shared_ptr(std::auto_ptr<_Tp1>&& __r)
: _M_ptr(__r.get()), _M_refcount() : _M_ptr(__r.get()), _M_refcount()
...@@ -315,7 +315,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -315,7 +315,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
} }
template<typename _Tp> template<typename _Tp>
template<typename _Tp1> template<typename _Tp1, typename>
inline inline
shared_ptr<_Tp>::shared_ptr(std::auto_ptr<_Tp1>&& __r) shared_ptr<_Tp>::shared_ptr(std::auto_ptr<_Tp1>&& __r)
: __shared_ptr<_Tp>(std::move(__r)) { } : __shared_ptr<_Tp>(std::move(__r)) { }
......
...@@ -92,16 +92,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -92,16 +92,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp> template<typename _Tp>
class shared_ptr : public __shared_ptr<_Tp> class shared_ptr : public __shared_ptr<_Tp>
{ {
template<typename _Ptr> template<typename... _Args>
using _Convertible = typename using _Constructible = typename enable_if<
enable_if<is_convertible<_Ptr, _Tp*>::value>::type; is_constructible<__shared_ptr<_Tp>, _Args...>::value
>::type;
template<typename _Ptr> template<typename _Arg>
using _Assignable = typename using _Assignable = typename enable_if<
enable_if<is_convertible<_Ptr, _Tp*>::value, shared_ptr&>::type; is_assignable<__shared_ptr<_Tp>&, _Arg>::value, shared_ptr&
>::type;
public: public:
using element_type = typename __shared_ptr<_Tp>::element_type;
#if __cplusplus > 201402L #if __cplusplus > 201402L
# define __cpp_lib_shared_ptr_weak_type 201606 # define __cpp_lib_shared_ptr_weak_type 201606
using weak_type = weak_ptr<_Tp>; using weak_type = weak_ptr<_Tp>;
...@@ -110,8 +114,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -110,8 +114,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @brief Construct an empty %shared_ptr. * @brief Construct an empty %shared_ptr.
* @post use_count()==0 && get()==0 * @post use_count()==0 && get()==0
*/ */
constexpr shared_ptr() noexcept constexpr shared_ptr() noexcept : __shared_ptr<_Tp>() { }
: __shared_ptr<_Tp>() { }
shared_ptr(const shared_ptr&) noexcept = default; shared_ptr(const shared_ptr&) noexcept = default;
...@@ -121,9 +124,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -121,9 +124,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @post use_count() == 1 && get() == __p * @post use_count() == 1 && get() == __p
* @throw std::bad_alloc, in which case @c delete @a __p is called. * @throw std::bad_alloc, in which case @c delete @a __p is called.
*/ */
template<typename _Tp1> template<typename _Yp, typename = _Constructible<_Yp*>>
explicit shared_ptr(_Tp1* __p) explicit
: __shared_ptr<_Tp>(__p) { } shared_ptr(_Yp* __p) : __shared_ptr<_Tp>(__p) { }
/** /**
* @brief Construct a %shared_ptr that owns the pointer @a __p * @brief Construct a %shared_ptr that owns the pointer @a __p
...@@ -138,8 +141,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -138,8 +141,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* *
* __shared_ptr will release __p by calling __d(__p) * __shared_ptr will release __p by calling __d(__p)
*/ */
template<typename _Tp1, typename _Deleter> template<typename _Yp, typename _Deleter,
shared_ptr(_Tp1* __p, _Deleter __d) typename = _Constructible<_Yp*, _Deleter>>
shared_ptr(_Yp* __p, _Deleter __d)
: __shared_ptr<_Tp>(__p, __d) { } : __shared_ptr<_Tp>(__p, __d) { }
/** /**
...@@ -174,8 +178,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -174,8 +178,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* *
* __shared_ptr will release __p by calling __d(__p) * __shared_ptr will release __p by calling __d(__p)
*/ */
template<typename _Tp1, typename _Deleter, typename _Alloc> template<typename _Yp, typename _Deleter, typename _Alloc,
shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a) typename = _Constructible<_Yp*, _Deleter, _Alloc>>
shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a)
: __shared_ptr<_Tp>(__p, __d, std::move(__a)) { } : __shared_ptr<_Tp>(__p, __d, std::move(__a)) { }
/** /**
...@@ -215,8 +220,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -215,8 +220,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* assert(pii.use_count() == 2); * assert(pii.use_count() == 2);
* @endcode * @endcode
*/ */
template<typename _Tp1> template<typename _Yp>
shared_ptr(const shared_ptr<_Tp1>& __r, _Tp* __p) noexcept shared_ptr(const shared_ptr<_Yp>& __r, element_type* __p) noexcept
: __shared_ptr<_Tp>(__r, __p) { } : __shared_ptr<_Tp>(__r, __p) { }
/** /**
...@@ -226,8 +231,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -226,8 +231,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @param __r A %shared_ptr. * @param __r A %shared_ptr.
* @post get() == __r.get() && use_count() == __r.use_count() * @post get() == __r.get() && use_count() == __r.use_count()
*/ */
template<typename _Tp1, typename = _Convertible<_Tp1*>> template<typename _Yp,
shared_ptr(const shared_ptr<_Tp1>& __r) noexcept typename = _Constructible<const shared_ptr<_Yp>&>>
shared_ptr(const shared_ptr<_Yp>& __r) noexcept
: __shared_ptr<_Tp>(__r) { } : __shared_ptr<_Tp>(__r) { }
/** /**
...@@ -243,8 +249,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -243,8 +249,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @param __r A %shared_ptr rvalue. * @param __r A %shared_ptr rvalue.
* @post *this contains the old value of @a __r, @a __r is empty. * @post *this contains the old value of @a __r, @a __r is empty.
*/ */
template<typename _Tp1, typename = _Convertible<_Tp1*>> template<typename _Yp, typename = _Constructible<shared_ptr<_Yp>>>
shared_ptr(shared_ptr<_Tp1>&& __r) noexcept shared_ptr(shared_ptr<_Yp>&& __r) noexcept
: __shared_ptr<_Tp>(std::move(__r)) { } : __shared_ptr<_Tp>(std::move(__r)) { }
/** /**
...@@ -255,20 +261,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -255,20 +261,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @throw bad_weak_ptr when __r.expired(), * @throw bad_weak_ptr when __r.expired(),
* in which case the constructor has no effect. * in which case the constructor has no effect.
*/ */
template<typename _Tp1> template<typename _Yp, typename = _Constructible<const weak_ptr<_Yp>&>>
explicit shared_ptr(const weak_ptr<_Tp1>& __r) explicit shared_ptr(const weak_ptr<_Yp>& __r)
: __shared_ptr<_Tp>(__r) { } : __shared_ptr<_Tp>(__r) { }
#if _GLIBCXX_USE_DEPRECATED #if _GLIBCXX_USE_DEPRECATED
template<typename _Tp1> template<typename _Yp, typename = _Constructible<auto_ptr<_Yp>>>
shared_ptr(std::auto_ptr<_Tp1>&& __r); shared_ptr(auto_ptr<_Yp>&& __r);
#endif #endif
// _GLIBCXX_RESOLVE_LIB_DEFECTS // _GLIBCXX_RESOLVE_LIB_DEFECTS
// 2399. shared_ptr's constructor from unique_ptr should be constrained // 2399. shared_ptr's constructor from unique_ptr should be constrained
template<typename _Tp1, typename _Del, typename template<typename _Yp, typename _Del,
= _Convertible<typename unique_ptr<_Tp1, _Del>::pointer>> typename = _Constructible<unique_ptr<_Yp, _Del>>>
shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r) shared_ptr(unique_ptr<_Yp, _Del>&& __r)
: __shared_ptr<_Tp>(std::move(__r)) { } : __shared_ptr<_Tp>(std::move(__r)) { }
/** /**
...@@ -279,18 +285,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -279,18 +285,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
shared_ptr& operator=(const shared_ptr&) noexcept = default; shared_ptr& operator=(const shared_ptr&) noexcept = default;
template<typename _Tp1> template<typename _Yp>
_Assignable<_Tp1*> _Assignable<const shared_ptr<_Yp>&>
operator=(const shared_ptr<_Tp1>& __r) noexcept operator=(const shared_ptr<_Yp>& __r) noexcept
{ {
this->__shared_ptr<_Tp>::operator=(__r); this->__shared_ptr<_Tp>::operator=(__r);
return *this; return *this;
} }
#if _GLIBCXX_USE_DEPRECATED #if _GLIBCXX_USE_DEPRECATED
template<typename _Tp1> template<typename _Yp>
shared_ptr& _Assignable<auto_ptr<_Yp>>
operator=(std::auto_ptr<_Tp1>&& __r) operator=(auto_ptr<_Yp>&& __r)
{ {
this->__shared_ptr<_Tp>::operator=(std::move(__r)); this->__shared_ptr<_Tp>::operator=(std::move(__r));
return *this; return *this;
...@@ -304,17 +310,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -304,17 +310,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return *this; return *this;
} }
template<class _Tp1> template<class _Yp>
_Assignable<_Tp1*> _Assignable<shared_ptr<_Yp>>
operator=(shared_ptr<_Tp1>&& __r) noexcept operator=(shared_ptr<_Yp>&& __r) noexcept
{ {
this->__shared_ptr<_Tp>::operator=(std::move(__r)); this->__shared_ptr<_Tp>::operator=(std::move(__r));
return *this; return *this;
} }
template<typename _Tp1, typename _Del> template<typename _Yp, typename _Del>
_Assignable<typename unique_ptr<_Tp1, _Del>::pointer> _Assignable<unique_ptr<_Yp, _Del>>
operator=(std::unique_ptr<_Tp1, _Del>&& __r) operator=(unique_ptr<_Yp, _Del>&& __r)
{ {
this->__shared_ptr<_Tp>::operator=(std::move(__r)); this->__shared_ptr<_Tp>::operator=(std::move(__r));
return *this; return *this;
...@@ -328,8 +334,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -328,8 +334,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: __shared_ptr<_Tp>(__tag, __a, std::forward<_Args>(__args)...) : __shared_ptr<_Tp>(__tag, __a, std::forward<_Args>(__args)...)
{ } { }
template<typename _Tp1, typename _Alloc, typename... _Args> template<typename _Yp, typename _Alloc, typename... _Args>
friend shared_ptr<_Tp1> friend shared_ptr<_Yp>
allocate_shared(const _Alloc& __a, _Args&&... __args); allocate_shared(const _Alloc& __a, _Args&&... __args);
// This constructor is non-standard, it is used by weak_ptr::lock(). // This constructor is non-standard, it is used by weak_ptr::lock().
...@@ -340,10 +346,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -340,10 +346,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}; };
// 20.7.2.2.7 shared_ptr comparisons // 20.7.2.2.7 shared_ptr comparisons
template<typename _Tp1, typename _Tp2> template<typename _Tp, typename _Up>
inline bool inline bool
operator==(const shared_ptr<_Tp1>& __a, operator==(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
const shared_ptr<_Tp2>& __b) noexcept
{ return __a.get() == __b.get(); } { return __a.get() == __b.get(); }
template<typename _Tp> template<typename _Tp>
...@@ -356,10 +361,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -356,10 +361,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator==(nullptr_t, const shared_ptr<_Tp>& __a) noexcept operator==(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
{ return !__a; } { return !__a; }
template<typename _Tp1, typename _Tp2> template<typename _Tp, typename _Up>
inline bool inline bool
operator!=(const shared_ptr<_Tp1>& __a, operator!=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
const shared_ptr<_Tp2>& __b) noexcept
{ return __a.get() != __b.get(); } { return __a.get() != __b.get(); }
template<typename _Tp> template<typename _Tp>
...@@ -372,29 +376,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -372,29 +376,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator!=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept operator!=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
{ return (bool)__a; } { return (bool)__a; }
template<typename _Tp1, typename _Tp2> template<typename _Tp, typename _Up>
inline bool inline bool
operator<(const shared_ptr<_Tp1>& __a, operator<(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
const shared_ptr<_Tp2>& __b) noexcept
{ {
typedef typename std::common_type<_Tp1*, _Tp2*>::type _CT; using _Tp_elt = typename shared_ptr<_Tp>::element_type;
return std::less<_CT>()(__a.get(), __b.get()); 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> template<typename _Tp>
inline bool inline bool
operator<(const shared_ptr<_Tp>& __a, nullptr_t) noexcept 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> template<typename _Tp>
inline bool inline bool
operator<(nullptr_t, const shared_ptr<_Tp>& __a) noexcept 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 inline bool
operator<=(const shared_ptr<_Tp1>& __a, operator<=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
const shared_ptr<_Tp2>& __b) noexcept
{ return !(__b < __a); } { return !(__b < __a); }
template<typename _Tp> template<typename _Tp>
...@@ -407,26 +417,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -407,26 +417,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator<=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept operator<=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
{ return !(__a < nullptr); } { return !(__a < nullptr); }
template<typename _Tp1, typename _Tp2> template<typename _Tp, typename _Up>
inline bool inline bool
operator>(const shared_ptr<_Tp1>& __a, operator>(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
const shared_ptr<_Tp2>& __b) noexcept
{ return (__b < __a); } { return (__b < __a); }
template<typename _Tp> template<typename _Tp>
inline bool inline bool
operator>(const shared_ptr<_Tp>& __a, nullptr_t) noexcept operator>(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
{ return std::less<_Tp*>()(nullptr, __a.get()); } { return nullptr < __a; }
template<typename _Tp> template<typename _Tp>
inline bool inline bool
operator>(nullptr_t, const shared_ptr<_Tp>& __a) noexcept 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 inline bool
operator>=(const shared_ptr<_Tp1>& __a, operator>=(const shared_ptr<_Tp>& __a, const shared_ptr<_Up>& __b) noexcept
const shared_ptr<_Tp2>& __b) noexcept
{ return !(__a < __b); } { return !(__a < __b); }
template<typename _Tp> template<typename _Tp>
...@@ -450,25 +458,41 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -450,25 +458,41 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ __a.swap(__b); } { __a.swap(__b); }
// 20.7.2.2.9 shared_ptr casts. // 20.7.2.2.9 shared_ptr casts.
template<typename _Tp, typename _Tp1> template<typename _Tp, typename _Up>
inline shared_ptr<_Tp> inline shared_ptr<_Tp>
static_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept static_pointer_cast(const shared_ptr<_Up>& __r) noexcept
{ return shared_ptr<_Tp>(__r, static_cast<_Tp*>(__r.get())); } {
using _Sp = shared_ptr<_Tp>;
return _Sp(__r, static_cast<typename _Sp::element_type*>(__r.get()));
}
template<typename _Tp, typename _Tp1> template<typename _Tp, typename _Up>
inline shared_ptr<_Tp> inline shared_ptr<_Tp>
const_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept const_pointer_cast(const shared_ptr<_Up>& __r) noexcept
{ return shared_ptr<_Tp>(__r, const_cast<_Tp*>(__r.get())); } {
using _Sp = shared_ptr<_Tp>;
return _Sp(__r, const_cast<typename _Sp::element_type*>(__r.get()));
}
template<typename _Tp, typename _Tp1> template<typename _Tp, typename _Up>
inline shared_ptr<_Tp> inline shared_ptr<_Tp>
dynamic_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept dynamic_pointer_cast(const shared_ptr<_Up>& __r) noexcept
{ {
if (_Tp* __p = dynamic_cast<_Tp*>(__r.get())) using _Sp = shared_ptr<_Tp>;
return shared_ptr<_Tp>(__r, __p); if (auto* __p = dynamic_cast<typename _Sp::element_type*>(__r.get()))
return shared_ptr<_Tp>(); 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. * @brief A smart pointer with weak semantics.
...@@ -478,43 +502,50 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -478,43 +502,50 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp> template<typename _Tp>
class weak_ptr : public __weak_ptr<_Tp> class weak_ptr : public __weak_ptr<_Tp>
{ {
template<typename _Ptr> template<typename _Arg>
using _Convertible using _Constructible = typename enable_if<
= typename enable_if<is_convertible<_Ptr, _Tp*>::value>::type; 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: public:
constexpr weak_ptr() noexcept = default; constexpr weak_ptr() noexcept = default;
template<typename _Tp1, typename = _Convertible<_Tp1*>> template<typename _Yp,
weak_ptr(const shared_ptr<_Tp1>& __r) noexcept typename = _Constructible<const shared_ptr<_Yp>&>>
weak_ptr(const shared_ptr<_Yp>& __r) noexcept
: __weak_ptr<_Tp>(__r) { } : __weak_ptr<_Tp>(__r) { }
weak_ptr(const weak_ptr&) noexcept = default; weak_ptr(const weak_ptr&) noexcept = default;
template<typename _Tp1, typename = _Convertible<_Tp1*>> template<typename _Yp, typename = _Constructible<const weak_ptr<_Yp>&>>
weak_ptr(const weak_ptr<_Tp1>& __r) noexcept weak_ptr(const weak_ptr<_Yp>& __r) noexcept
: __weak_ptr<_Tp>(__r) { } : __weak_ptr<_Tp>(__r) { }
weak_ptr(weak_ptr&&) noexcept = default; weak_ptr(weak_ptr&&) noexcept = default;
template<typename _Tp1, typename = _Convertible<_Tp1*>> template<typename _Yp, typename = _Constructible<weak_ptr<_Yp>>>
weak_ptr(weak_ptr<_Tp1>&& __r) noexcept weak_ptr(weak_ptr<_Yp>&& __r) noexcept
: __weak_ptr<_Tp>(std::move(__r)) { } : __weak_ptr<_Tp>(std::move(__r)) { }
weak_ptr& weak_ptr&
operator=(const weak_ptr& __r) noexcept = default; operator=(const weak_ptr& __r) noexcept = default;
template<typename _Tp1> template<typename _Yp>
weak_ptr& _Assignable<const weak_ptr<_Yp>&>
operator=(const weak_ptr<_Tp1>& __r) noexcept operator=(const weak_ptr<_Yp>& __r) noexcept
{ {
this->__weak_ptr<_Tp>::operator=(__r); this->__weak_ptr<_Tp>::operator=(__r);
return *this; return *this;
} }
template<typename _Tp1> template<typename _Yp>
weak_ptr& _Assignable<const shared_ptr<_Yp>&>
operator=(const shared_ptr<_Tp1>& __r) noexcept operator=(const shared_ptr<_Yp>& __r) noexcept
{ {
this->__weak_ptr<_Tp>::operator=(__r); this->__weak_ptr<_Tp>::operator=(__r);
return *this; return *this;
...@@ -523,9 +554,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -523,9 +554,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
weak_ptr& weak_ptr&
operator=(weak_ptr&& __r) noexcept = default; operator=(weak_ptr&& __r) noexcept = default;
template<typename _Tp1> template<typename _Yp>
weak_ptr& _Assignable<weak_ptr<_Yp>>
operator=(weak_ptr<_Tp1>&& __r) noexcept operator=(weak_ptr<_Yp>&& __r) noexcept
{ {
this->__weak_ptr<_Tp>::operator=(std::move(__r)); this->__weak_ptr<_Tp>::operator=(std::move(__r));
return *this; return *this;
......
...@@ -847,19 +847,55 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -847,19 +847,55 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_pi = nullptr; _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> template<typename _Tp, _Lock_policy _Lp>
class __shared_ptr class __shared_ptr
{ {
template<typename _Ptr> public:
using _Convertible using element_type = _Tp;
= typename enable_if<is_convertible<_Ptr, _Tp*>::value>::type;
template<typename _Ptr> private:
using _Assignable = typename // Trait to check if shared_ptr<T> can be constructed from Y*.
enable_if<is_convertible<_Ptr, _Tp*>::value, __shared_ptr&>::type; 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: public:
typedef _Tp element_type;
#if __cplusplus > 201402L #if __cplusplus > 201402L
using weak_type = __weak_ptr<_Tp, _Lp>; using weak_type = __weak_ptr<_Tp, _Lp>;
...@@ -869,31 +905,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -869,31 +905,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: _M_ptr(0), _M_refcount() : _M_ptr(0), _M_refcount()
{ } { }
template<typename _Tp1> template<typename _Yp, typename = _SafeConv<_Yp>>
explicit __shared_ptr(_Tp1* __p) explicit
: _M_ptr(__p), _M_refcount(__p) __shared_ptr(_Yp* __p)
: _M_ptr(__p), _M_refcount(__p)
{ {
__glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) static_assert( !is_void<_Yp>::value, "incomplete type" );
static_assert( !is_void<_Tp1>::value, "incomplete type" ); static_assert( sizeof(_Yp) > 0, "incomplete type" );
static_assert( sizeof(_Tp1) > 0, "incomplete type" );
_M_enable_shared_from_this_with(__p); _M_enable_shared_from_this_with(__p);
} }
template<typename _Tp1, typename _Deleter> template<typename _Yp, typename _Deleter, typename = _SafeConv<_Yp>>
__shared_ptr(_Tp1* __p, _Deleter __d) __shared_ptr(_Yp* __p, _Deleter __d)
: _M_ptr(__p), _M_refcount(__p, __d) : _M_ptr(__p), _M_refcount(__p, __d)
{ {
__glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) static_assert(__is_callable<_Deleter(_Yp*)>::value,
// TODO requires _Deleter CopyConstructible and __d(__p) well-formed "deleter expression d(p) is well-formed");
_M_enable_shared_from_this_with(__p); _M_enable_shared_from_this_with(__p);
} }
template<typename _Tp1, typename _Deleter, typename _Alloc> template<typename _Yp, typename _Deleter, typename _Alloc,
__shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a) typename = _SafeConv<_Yp>>
__shared_ptr(_Yp* __p, _Deleter __d, _Alloc __a)
: _M_ptr(__p), _M_refcount(__p, __d, std::move(__a)) : _M_ptr(__p), _M_refcount(__p, __d, std::move(__a))
{ {
__glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) static_assert(__is_callable<_Deleter(_Yp*)>::value,
// TODO requires _Deleter CopyConstructible and __d(__p) well-formed "deleter expression d(p) is well-formed");
_M_enable_shared_from_this_with(__p); _M_enable_shared_from_this_with(__p);
} }
...@@ -907,8 +944,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -907,8 +944,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: _M_ptr(0), _M_refcount(__p, __d, std::move(__a)) : _M_ptr(0), _M_refcount(__p, __d, std::move(__a))
{ } { }
template<typename _Tp1> template<typename _Yp>
__shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r, _Tp* __p) noexcept __shared_ptr(const __shared_ptr<_Yp, _Lp>& __r,
element_type* __p) noexcept
: _M_ptr(__p), _M_refcount(__r._M_refcount) // never throws : _M_ptr(__p), _M_refcount(__r._M_refcount) // never throws
{ } { }
...@@ -916,8 +954,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -916,8 +954,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__shared_ptr& operator=(const __shared_ptr&) noexcept = default; __shared_ptr& operator=(const __shared_ptr&) noexcept = default;
~__shared_ptr() = default; ~__shared_ptr() = default;
template<typename _Tp1, typename = _Convertible<_Tp1*>> template<typename _Yp, typename = _Compatible<_Yp>>
__shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r) noexcept __shared_ptr(const __shared_ptr<_Yp, _Lp>& __r) noexcept
: _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
{ } { }
...@@ -928,32 +966,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -928,32 +966,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__r._M_ptr = 0; __r._M_ptr = 0;
} }
template<typename _Tp1, typename = _Convertible<_Tp1*>> template<typename _Yp, typename = _Compatible<_Yp>>
__shared_ptr(__shared_ptr<_Tp1, _Lp>&& __r) noexcept __shared_ptr(__shared_ptr<_Yp, _Lp>&& __r) noexcept
: _M_ptr(__r._M_ptr), _M_refcount() : _M_ptr(__r._M_ptr), _M_refcount()
{ {
_M_refcount._M_swap(__r._M_refcount); _M_refcount._M_swap(__r._M_refcount);
__r._M_ptr = 0; __r._M_ptr = 0;
} }
template<typename _Tp1> template<typename _Yp, typename = _Compatible<_Yp>>
explicit __shared_ptr(const __weak_ptr<_Tp1, _Lp>& __r) explicit __shared_ptr(const __weak_ptr<_Yp, _Lp>& __r)
: _M_refcount(__r._M_refcount) // may throw : _M_refcount(__r._M_refcount) // may throw
{ {
__glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
// It is now safe to copy __r._M_ptr, as // It is now safe to copy __r._M_ptr, as
// _M_refcount(__r._M_refcount) did not throw. // _M_refcount(__r._M_refcount) did not throw.
_M_ptr = __r._M_ptr; _M_ptr = __r._M_ptr;
} }
// If an exception is thrown this constructor has no effect. // If an exception is thrown this constructor has no effect.
template<typename _Tp1, typename _Del, typename template<typename _Yp, typename _Del,
= _Convertible<typename unique_ptr<_Tp1, _Del>::pointer>> typename = _UniqCompatible<_Yp, _Del>>
__shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r) __shared_ptr(unique_ptr<_Yp, _Del>&& __r)
: _M_ptr(__r.get()), _M_refcount() : _M_ptr(__r.get()), _M_refcount()
{ {
__glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
auto __raw = _S_raw_ptr(__r.get()); auto __raw = _S_raw_ptr(__r.get());
_M_refcount = __shared_count<_Lp>(std::move(__r)); _M_refcount = __shared_count<_Lp>(std::move(__r));
_M_enable_shared_from_this_with(__raw); _M_enable_shared_from_this_with(__raw);
...@@ -961,15 +996,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -961,15 +996,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if _GLIBCXX_USE_DEPRECATED #if _GLIBCXX_USE_DEPRECATED
// Postcondition: use_count() == 1 and __r.get() == 0 // Postcondition: use_count() == 1 and __r.get() == 0
template<typename _Tp1> template<typename _Yp, typename = _Compatible<_Yp>>
__shared_ptr(std::auto_ptr<_Tp1>&& __r); __shared_ptr(auto_ptr<_Yp>&& __r);
#endif #endif
constexpr __shared_ptr(nullptr_t) noexcept : __shared_ptr() { } constexpr __shared_ptr(nullptr_t) noexcept : __shared_ptr() { }
template<typename _Tp1> template<typename _Yp>
_Assignable<_Tp1*> _Assignable<_Yp>
operator=(const __shared_ptr<_Tp1, _Lp>& __r) noexcept operator=(const __shared_ptr<_Yp, _Lp>& __r) noexcept
{ {
_M_ptr = __r._M_ptr; _M_ptr = __r._M_ptr;
_M_refcount = __r._M_refcount; // __shared_count::op= doesn't throw _M_refcount = __r._M_refcount; // __shared_count::op= doesn't throw
...@@ -977,9 +1012,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -977,9 +1012,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
} }
#if _GLIBCXX_USE_DEPRECATED #if _GLIBCXX_USE_DEPRECATED
template<typename _Tp1> template<typename _Yp>
__shared_ptr& _Assignable<_Yp>
operator=(std::auto_ptr<_Tp1>&& __r) operator=(auto_ptr<_Yp>&& __r)
{ {
__shared_ptr(std::move(__r)).swap(*this); __shared_ptr(std::move(__r)).swap(*this);
return *this; return *this;
...@@ -993,17 +1028,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -993,17 +1028,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return *this; return *this;
} }
template<class _Tp1> template<class _Yp>
_Assignable<_Tp1*> _Assignable<_Yp>
operator=(__shared_ptr<_Tp1, _Lp>&& __r) noexcept operator=(__shared_ptr<_Yp, _Lp>&& __r) noexcept
{ {
__shared_ptr(std::move(__r)).swap(*this); __shared_ptr(std::move(__r)).swap(*this);
return *this; return *this;
} }
template<typename _Tp1, typename _Del> template<typename _Yp, typename _Del>
_Assignable<typename unique_ptr<_Tp1, _Del>::pointer> _UniqAssignable<_Yp, _Del>
operator=(std::unique_ptr<_Tp1, _Del>&& __r) operator=(unique_ptr<_Yp, _Del>&& __r)
{ {
__shared_ptr(std::move(__r)).swap(*this); __shared_ptr(std::move(__r)).swap(*this);
return *this; return *this;
...@@ -1013,41 +1048,41 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -1013,41 +1048,41 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
reset() noexcept reset() noexcept
{ __shared_ptr().swap(*this); } { __shared_ptr().swap(*this); }
template<typename _Tp1> template<typename _Yp>
_Convertible<_Tp1*> _SafeConv<_Yp>
reset(_Tp1* __p) // _Tp1 must be complete. reset(_Yp* __p) // _Yp must be complete.
{ {
// Catch self-reset errors. // Catch self-reset errors.
__glibcxx_assert(__p == 0 || __p != _M_ptr); __glibcxx_assert(__p == 0 || __p != _M_ptr);
__shared_ptr(__p).swap(*this); __shared_ptr(__p).swap(*this);
} }
template<typename _Tp1, typename _Deleter> template<typename _Yp, typename _Deleter>
_Convertible<_Tp1*> _SafeConv<_Yp>
reset(_Tp1* __p, _Deleter __d) reset(_Yp* __p, _Deleter __d)
{ __shared_ptr(__p, __d).swap(*this); } { __shared_ptr(__p, __d).swap(*this); }
template<typename _Tp1, typename _Deleter, typename _Alloc> template<typename _Yp, typename _Deleter, typename _Alloc>
_Convertible<_Tp1*> _SafeConv<_Yp>
reset(_Tp1* __p, _Deleter __d, _Alloc __a) reset(_Yp* __p, _Deleter __d, _Alloc __a)
{ __shared_ptr(__p, __d, std::move(__a)).swap(*this); } { __shared_ptr(__p, __d, std::move(__a)).swap(*this); }
// Allow class instantiation when _Tp is [cv-qual] void. // 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 operator*() const noexcept
{ {
__glibcxx_assert(_M_ptr != 0); __glibcxx_assert(_M_ptr != 0);
return *_M_ptr; return *_M_ptr;
} }
_Tp* element_type*
operator->() const noexcept operator->() const noexcept
{ {
_GLIBCXX_DEBUG_PEDASSERT(_M_ptr != 0); _GLIBCXX_DEBUG_PEDASSERT(_M_ptr != 0);
return _M_ptr; return _M_ptr;
} }
_Tp* element_type*
get() const noexcept get() const noexcept
{ return _M_ptr; } { return _M_ptr; }
...@@ -1192,7 +1227,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -1192,7 +1227,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Del, typename _Tp1, _Lock_policy _Lp1> template<typename _Del, typename _Tp1, _Lock_policy _Lp1>
friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&) noexcept; 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. __shared_count<_Lp> _M_refcount; // Reference counter.
}; };
...@@ -1230,24 +1265,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -1230,24 +1265,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator!=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept operator!=(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept
{ return (bool)__a; } { return (bool)__a; }
template<typename _Tp1, typename _Tp2, _Lock_policy _Lp> template<typename _Tp, typename _Up, _Lock_policy _Lp>
inline bool inline bool
operator<(const __shared_ptr<_Tp1, _Lp>& __a, operator<(const __shared_ptr<_Tp, _Lp>& __a,
const __shared_ptr<_Tp2, _Lp>& __b) noexcept const __shared_ptr<_Up, _Lp>& __b) noexcept
{ {
typedef typename std::common_type<_Tp1*, _Tp2*>::type _CT; using _Tp_elt = typename __shared_ptr<_Tp, _Lp>::element_type;
return std::less<_CT>()(__a.get(), __b.get()); 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> template<typename _Tp, _Lock_policy _Lp>
inline bool inline bool
operator<(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept 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> template<typename _Tp, _Lock_policy _Lp>
inline bool inline bool
operator<(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept 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> template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
inline bool inline bool
...@@ -1274,12 +1317,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -1274,12 +1317,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp, _Lock_policy _Lp> template<typename _Tp, _Lock_policy _Lp>
inline bool inline bool
operator>(const __shared_ptr<_Tp, _Lp>& __a, nullptr_t) noexcept 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> template<typename _Tp, _Lock_policy _Lp>
inline bool inline bool
operator>(nullptr_t, const __shared_ptr<_Tp, _Lp>& __a) noexcept 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> template<typename _Tp1, typename _Tp2, _Lock_policy _Lp>
inline bool inline bool
...@@ -1329,7 +1372,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -1329,7 +1372,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp, typename _Tp1, _Lock_policy _Lp> template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
inline __shared_ptr<_Tp, _Lp> inline __shared_ptr<_Tp, _Lp>
static_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept 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: // The seemingly equivalent code:
// shared_ptr<_Tp, _Lp>(const_cast<_Tp*>(__r.get())) // shared_ptr<_Tp, _Lp>(const_cast<_Tp*>(__r.get()))
...@@ -1339,7 +1385,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -1339,7 +1385,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp, typename _Tp1, _Lock_policy _Lp> template<typename _Tp, typename _Tp1, _Lock_policy _Lp>
inline __shared_ptr<_Tp, _Lp> inline __shared_ptr<_Tp, _Lp>
const_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept 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: // The seemingly equivalent code:
// shared_ptr<_Tp, _Lp>(dynamic_cast<_Tp*>(__r.get())) // shared_ptr<_Tp, _Lp>(dynamic_cast<_Tp*>(__r.get()))
...@@ -1350,21 +1399,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -1350,21 +1399,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline __shared_ptr<_Tp, _Lp> inline __shared_ptr<_Tp, _Lp>
dynamic_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept dynamic_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
{ {
if (_Tp* __p = dynamic_cast<_Tp*>(__r.get())) using _Sp = __shared_ptr<_Tp, _Lp>;
return __shared_ptr<_Tp, _Lp>(__r, __p); if (auto* __p = dynamic_cast<typename _Sp::element_type*>(__r.get()))
return __shared_ptr<_Tp, _Lp>(); 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> template<typename _Tp, _Lock_policy _Lp>
class __weak_ptr class __weak_ptr
{ {
template<typename _Ptr> template<typename _Yp, typename _Res = void>
using _Convertible using _Compatible = typename
= typename enable_if<is_convertible<_Ptr, _Tp*>::value>::type; 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: public:
typedef _Tp element_type; using element_type = _Tp;
constexpr __weak_ptr() noexcept constexpr __weak_ptr() noexcept
: _M_ptr(nullptr), _M_refcount() : _M_ptr(nullptr), _M_refcount()
...@@ -1388,13 +1451,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -1388,13 +1451,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// //
// It is not possible to avoid spurious access violations since // It is not possible to avoid spurious access violations since
// in multithreaded programs __r._M_ptr may be invalidated at any point. // in multithreaded programs __r._M_ptr may be invalidated at any point.
template<typename _Tp1, typename = _Convertible<_Tp1*>> template<typename _Yp, typename = _Compatible<_Yp>>
__weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r) noexcept __weak_ptr(const __weak_ptr<_Yp, _Lp>& __r) noexcept
: _M_refcount(__r._M_refcount) : _M_refcount(__r._M_refcount)
{ _M_ptr = __r.lock().get(); } { _M_ptr = __r.lock().get(); }
template<typename _Tp1, typename = _Convertible<_Tp1*>> template<typename _Yp, typename = _Compatible<_Yp>>
__weak_ptr(const __shared_ptr<_Tp1, _Lp>& __r) noexcept __weak_ptr(const __shared_ptr<_Yp, _Lp>& __r) noexcept
: _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
{ } { }
...@@ -1402,26 +1465,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -1402,26 +1465,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: _M_ptr(__r._M_ptr), _M_refcount(std::move(__r._M_refcount)) : _M_ptr(__r._M_ptr), _M_refcount(std::move(__r._M_refcount))
{ __r._M_ptr = nullptr; } { __r._M_ptr = nullptr; }
template<typename _Tp1, typename = _Convertible<_Tp1*>> template<typename _Yp, typename = _Compatible<_Yp>>
__weak_ptr(__weak_ptr<_Tp1, _Lp>&& __r) noexcept __weak_ptr(__weak_ptr<_Yp, _Lp>&& __r) noexcept
: _M_ptr(__r.lock().get()), _M_refcount(std::move(__r._M_refcount)) : _M_ptr(__r.lock().get()), _M_refcount(std::move(__r._M_refcount))
{ __r._M_ptr = nullptr; } { __r._M_ptr = nullptr; }
__weak_ptr& __weak_ptr&
operator=(const __weak_ptr& __r) noexcept = default; operator=(const __weak_ptr& __r) noexcept = default;
template<typename _Tp1> template<typename _Yp>
__weak_ptr& _Assignable<_Yp>
operator=(const __weak_ptr<_Tp1, _Lp>& __r) noexcept operator=(const __weak_ptr<_Yp, _Lp>& __r) noexcept
{ {
_M_ptr = __r.lock().get(); _M_ptr = __r.lock().get();
_M_refcount = __r._M_refcount; _M_refcount = __r._M_refcount;
return *this; return *this;
} }
template<typename _Tp1> template<typename _Yp>
__weak_ptr& _Assignable<_Yp>
operator=(const __shared_ptr<_Tp1, _Lp>& __r) noexcept operator=(const __shared_ptr<_Yp, _Lp>& __r) noexcept
{ {
_M_ptr = __r._M_ptr; _M_ptr = __r._M_ptr;
_M_refcount = __r._M_refcount; _M_refcount = __r._M_refcount;
...@@ -1437,9 +1500,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -1437,9 +1500,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return *this; return *this;
} }
template<typename _Tp1> template<typename _Yp>
__weak_ptr& _Assignable<_Yp>
operator=(__weak_ptr<_Tp1, _Lp>&& __r) noexcept operator=(__weak_ptr<_Yp, _Lp>&& __r) noexcept
{ {
_M_ptr = __r.lock().get(); _M_ptr = __r.lock().get();
_M_refcount = std::move(__r._M_refcount); _M_refcount = std::move(__r._M_refcount);
...@@ -1497,7 +1560,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -1497,7 +1560,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
friend class __enable_shared_from_this<_Tp, _Lp>; friend class __enable_shared_from_this<_Tp, _Lp>;
friend class enable_shared_from_this<_Tp>; 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. __weak_count<_Lp> _M_refcount; // Reference counter.
}; };
......
...@@ -34,7 +34,7 @@ test01() ...@@ -34,7 +34,7 @@ test01()
{ {
std::shared_ptr<A> a; std::shared_ptr<A> a;
std::auto_ptr<B> b; std::auto_ptr<B> b;
a = std::move(b); // { dg-error "here" } a = std::move(b); // { dg-error "no match" }
return 0; return 0;
} }
......
// { 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));
}
...@@ -25,10 +25,28 @@ ...@@ -25,10 +25,28 @@
struct A { }; struct A { };
int destroyed = 0;
struct B : A { ~B() { ++destroyed; } };
// 20.6.6.2.1 shared_ptr constructors [util.smartptr.shared.const] // 20.6.6.2.1 shared_ptr constructors [util.smartptr.shared.const]
// Construction from auto_ptr // 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() test01()
{ {
std::auto_ptr<A> a(new A); std::auto_ptr<A> a(new A);
...@@ -36,13 +54,24 @@ test01() ...@@ -36,13 +54,24 @@ test01()
VERIFY( a.get() == 0 ); VERIFY( a.get() == 0 );
VERIFY( a2.get() != 0 ); VERIFY( a2.get() != 0 );
VERIFY( a2.use_count() == 1 ); 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 int
main() main()
{ {
test01(); test01();
test02();
return 0; return 0;
} }
...@@ -24,10 +24,28 @@ ...@@ -24,10 +24,28 @@
struct A { }; struct A { };
int destroyed = 0;
struct B : A { ~B() { ++destroyed; } };
// 20.7.2.2.1 shared_ptr constructors [util.smartptr.shared.const] // 20.7.2.2.1 shared_ptr constructors [util.smartptr.shared.const]
// Construction from unique_ptr // 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() test01()
{ {
std::unique_ptr<A> up(new A); std::unique_ptr<A> up(new A);
...@@ -35,13 +53,24 @@ test01() ...@@ -35,13 +53,24 @@ test01()
VERIFY( up.get() == 0 ); VERIFY( up.get() == 0 );
VERIFY( sp.get() != 0 ); VERIFY( sp.get() != 0 );
VERIFY( sp.use_count() == 1 ); 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 int
main() main()
{ {
test01(); test01();
test02();
return 0; return 0;
} }
...@@ -26,3 +26,7 @@ void test01() ...@@ -26,3 +26,7 @@ void test01()
std::shared_ptr<void> p((void*)nullptr); // { dg-error "here" } std::shared_ptr<void> p((void*)nullptr); // { dg-error "here" }
// { dg-error "incomplete" "" { target *-*-* } 0 } // { dg-error "incomplete" "" { target *-*-* } 0 }
} }
using std::shared_ptr;
using std::is_constructible;
static_assert(!is_constructible<shared_ptr<void>, const void*>::value, "");
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment