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:
parent
f320e6a091
commit
a2e0054e1d
9 changed files with 457 additions and 202 deletions
|
@ -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,
|
||||
|
|
|
@ -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)) { }
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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, "");
|
||||
|
|
Loading…
Add table
Reference in a new issue