mirror of git://gcc.gnu.org/git/gcc.git
Fix std::experimental::shared_ptr SFINAE constraints
* include/experimental/bits/shared_ptr.h (__shared_ptr<__libfund_v1<_Tp, false>, _Lp>::_Compatible): Just use is_convertible for non-array specialization. (__shared_ptr<__libfund_v1<_Tp, false>, _Lp>::_UniqCompatible): New constraint for conversions from unique_ptr. (__shared_ptr<__libfund_v1<_Tp, false>, _Lp>::__shared_ptr): Constrain. (__shared_ptr<__libfund_v1<_Tp, false>, _Lp>::reset): Likewise. (__sp_compatible_v): New variable template for trait. (__sp_is_constructible): New trait to check shared_ptr constraints. (__sp_is_constructible_v): New variable template for trait. (__shared_ptr<__libfund_v1<_Tp, true>, _Lp>::_SafeConv): New constraint for construction/reset, using __sp_is_constructible_v. (__shared_ptr<__libfund_v1<_Tp, true>, _Lp>::_UniqCompatible): New constraint for conversions from unique_ptr. (__shared_ptr<__libfund_v1<_Tp, true>, _Lp>::__shared_ptr): Constrain. (__shared_ptr<__libfund_v1<_Tp, true>, _Lp>::reset): Likewise. (shared_ptr::_SafeConv): Constraint for checking constructors. (shared_ptr(Tp1*), shared_ptr(_Tp1, _Deleter)) (shared_ptr(_Tp1, _Deleter, _Alloc)): Constrain with _SafeConv. (shared_ptr(const weak_ptr<_Tp1>&)): Constrain with _Compatible. (shared_ptr(auto_ptr<_Tp1>&&)): Fix, remove TODO. * testsuite/experimental/memory/shared_ptr/cons/pointer_ctor.cc: Remove tests using invalid conversions. * testsuite/experimental/memory/shared_ptr/cons/pointer_ctor_neg.cc: New test. * testsuite/experimental/memory/shared_ptr/cons/torture.cc: New test. * testsuite/experimental/memory/shared_ptr/modifiers/reset.cc: Remove tests using invalid conversions. * testsuite/experimental/memory/shared_ptr/modifiers/reset_neg.cc: New test. * testsuite/experimental/memory/shared_ptr/observers/use_count.cc: Remove tests using invalid conversions. From-SVN: r241331
This commit is contained in:
parent
e182393e31
commit
84870b6bb2
|
|
@ -1,5 +1,38 @@
|
||||||
2016-10-19 Jonathan Wakely <jwakely@redhat.com>
|
2016-10-19 Jonathan Wakely <jwakely@redhat.com>
|
||||||
|
|
||||||
|
* include/experimental/bits/shared_ptr.h
|
||||||
|
(__shared_ptr<__libfund_v1<_Tp, false>, _Lp>::_Compatible): Just use
|
||||||
|
is_convertible for non-array specialization.
|
||||||
|
(__shared_ptr<__libfund_v1<_Tp, false>, _Lp>::_UniqCompatible): New
|
||||||
|
constraint for conversions from unique_ptr.
|
||||||
|
(__shared_ptr<__libfund_v1<_Tp, false>, _Lp>::__shared_ptr): Constrain.
|
||||||
|
(__shared_ptr<__libfund_v1<_Tp, false>, _Lp>::reset): Likewise.
|
||||||
|
(__sp_compatible_v): New variable template for trait.
|
||||||
|
(__sp_is_constructible): New trait to check shared_ptr constraints.
|
||||||
|
(__sp_is_constructible_v): New variable template for trait.
|
||||||
|
(__shared_ptr<__libfund_v1<_Tp, true>, _Lp>::_SafeConv): New
|
||||||
|
constraint for construction/reset, using __sp_is_constructible_v.
|
||||||
|
(__shared_ptr<__libfund_v1<_Tp, true>, _Lp>::_UniqCompatible): New
|
||||||
|
constraint for conversions from unique_ptr.
|
||||||
|
(__shared_ptr<__libfund_v1<_Tp, true>, _Lp>::__shared_ptr): Constrain.
|
||||||
|
(__shared_ptr<__libfund_v1<_Tp, true>, _Lp>::reset): Likewise.
|
||||||
|
(shared_ptr::_SafeConv): Constraint for checking constructors.
|
||||||
|
(shared_ptr(Tp1*), shared_ptr(_Tp1, _Deleter))
|
||||||
|
(shared_ptr(_Tp1, _Deleter, _Alloc)): Constrain with _SafeConv.
|
||||||
|
(shared_ptr(const weak_ptr<_Tp1>&)): Constrain with _Compatible.
|
||||||
|
(shared_ptr(auto_ptr<_Tp1>&&)): Fix, remove TODO.
|
||||||
|
* testsuite/experimental/memory/shared_ptr/cons/pointer_ctor.cc:
|
||||||
|
Remove tests using invalid conversions.
|
||||||
|
* testsuite/experimental/memory/shared_ptr/cons/pointer_ctor_neg.cc:
|
||||||
|
New test.
|
||||||
|
* testsuite/experimental/memory/shared_ptr/cons/torture.cc: New test.
|
||||||
|
* testsuite/experimental/memory/shared_ptr/modifiers/reset.cc: Remove
|
||||||
|
tests using invalid conversions.
|
||||||
|
* testsuite/experimental/memory/shared_ptr/modifiers/reset_neg.cc: New
|
||||||
|
test.
|
||||||
|
* testsuite/experimental/memory/shared_ptr/observers/use_count.cc:
|
||||||
|
Remove tests using invalid conversions.
|
||||||
|
|
||||||
PR libstdc++/77990
|
PR libstdc++/77990
|
||||||
* include/bits/unique_ptr.h (__uniq_ptr_impl): New type to
|
* include/bits/unique_ptr.h (__uniq_ptr_impl): New type to
|
||||||
encapsulate implementation details.
|
encapsulate implementation details.
|
||||||
|
|
|
||||||
|
|
@ -69,53 +69,48 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
template <typename _Tp, bool = is_array<_Tp>::value>
|
template <typename _Tp, bool = is_array<_Tp>::value>
|
||||||
struct __libfund_v1 { using type = _Tp; };
|
struct __libfund_v1 { using type = _Tp; };
|
||||||
|
|
||||||
// helper for _Compatible
|
|
||||||
template<typename _From_type, typename _To_type>
|
|
||||||
struct __sp_compatible
|
|
||||||
: is_convertible<_From_type*, _To_type*>::type
|
|
||||||
{ };
|
|
||||||
|
|
||||||
template<size_t _Nm, typename _Tp>
|
|
||||||
struct __sp_compatible<_Tp[_Nm], _Tp[]>
|
|
||||||
: true_type
|
|
||||||
{ };
|
|
||||||
|
|
||||||
template<size_t _Nm, typename _Tp>
|
|
||||||
struct __sp_compatible<_Tp[_Nm], const _Tp[]>
|
|
||||||
: true_type
|
|
||||||
{ };
|
|
||||||
|
|
||||||
// Partial specialization for base class of experimental::shared_ptr<T>
|
// Partial specialization for base class of experimental::shared_ptr<T>
|
||||||
// (i.e. the non-array form of experimental::shared_ptr)
|
// (i.e. the non-array form of experimental::shared_ptr)
|
||||||
template<typename _Tp, _Lock_policy _Lp>
|
template<typename _Tp, _Lock_policy _Lp>
|
||||||
class __shared_ptr<__libfund_v1<_Tp, false>, _Lp>
|
class __shared_ptr<__libfund_v1<_Tp, false>, _Lp>
|
||||||
: private __shared_ptr<_Tp, _Lp>
|
: private __shared_ptr<_Tp, _Lp>
|
||||||
{
|
{
|
||||||
template<typename _Tp1, typename _Res = void>
|
// For non-arrays, Y* is compatible with T* if Y* is convertible to T*.
|
||||||
|
template<typename _Yp, typename _Res = void>
|
||||||
using _Compatible
|
using _Compatible
|
||||||
= enable_if_t<__sp_compatible<_Tp1, _Tp>::value, _Res>;
|
= enable_if_t<experimental::is_convertible_v<_Yp*, _Tp*>, _Res>;
|
||||||
|
|
||||||
|
template<typename _Yp, typename _Del,
|
||||||
|
typename _Ptr = typename unique_ptr<_Yp, _Del>::pointer,
|
||||||
|
typename _Res = void>
|
||||||
|
using _UniqCompatible = enable_if_t<
|
||||||
|
experimental::is_convertible_v<_Yp*, _Tp*>
|
||||||
|
&& experimental::is_convertible_v<_Ptr, _Tp*>,
|
||||||
|
_Res>;
|
||||||
|
|
||||||
using _Base_type = __shared_ptr<_Tp>;
|
using _Base_type = __shared_ptr<_Tp>;
|
||||||
|
|
||||||
_Base_type& _M_get_base() { return *this;}
|
_Base_type& _M_get_base() { return *this; }
|
||||||
const _Base_type& _M_get_base() const { return *this;}
|
const _Base_type& _M_get_base() const { return *this; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using element_type = _Tp;
|
using element_type = _Tp;
|
||||||
|
|
||||||
constexpr __shared_ptr() noexcept = default;
|
constexpr __shared_ptr() noexcept = default;
|
||||||
|
|
||||||
template<typename _Tp1>
|
template<typename _Tp1, typename = _Compatible<_Tp1>>
|
||||||
explicit __shared_ptr(_Tp1* __p)
|
explicit
|
||||||
|
__shared_ptr(_Tp1* __p)
|
||||||
: _Base_type(__p)
|
: _Base_type(__p)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
template<typename _Tp1, typename _Deleter>
|
template<typename _Tp1, typename _Deleter, typename = _Compatible<_Tp1>>
|
||||||
__shared_ptr(_Tp1* __p, _Deleter __d)
|
__shared_ptr(_Tp1* __p, _Deleter __d)
|
||||||
: _Base_type(__p, __d)
|
: _Base_type(__p, __d)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
template<typename _Tp1, typename _Deleter, typename _Alloc>
|
template<typename _Tp1, typename _Deleter, typename _Alloc,
|
||||||
|
typename = _Compatible<_Tp1>>
|
||||||
__shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)
|
__shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)
|
||||||
: _Base_type(__p, __d, __a)
|
: _Base_type(__p, __d, __a)
|
||||||
{ }
|
{ }
|
||||||
|
|
@ -152,21 +147,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
: _Base_type(std::move((__r._M_get_base())))
|
: _Base_type(std::move((__r._M_get_base())))
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
template<typename _Tp1>
|
template<typename _Tp1, typename = _Compatible<_Tp1>>
|
||||||
explicit __shared_ptr(const __weak_ptr<__libfund_v1<_Tp1>, _Lp>& __r)
|
explicit
|
||||||
|
__shared_ptr(const __weak_ptr<__libfund_v1<_Tp1>, _Lp>& __r)
|
||||||
: _Base_type(__r._M_get_base())
|
: _Base_type(__r._M_get_base())
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
template<typename _Tp1, typename _Del, typename
|
template<typename _Tp1, typename _Del,
|
||||||
= _Compatible<remove_pointer_t<
|
typename = _UniqCompatible<_Tp1, _Del>>
|
||||||
typename unique_ptr<_Tp1, _Del>::pointer>>>
|
__shared_ptr(unique_ptr<_Tp1, _Del>&& __r)
|
||||||
__shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r)
|
: _Base_type(std::move(__r))
|
||||||
: _Base_type(std::move(__r))
|
{ }
|
||||||
{ }
|
|
||||||
|
|
||||||
#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 _Tp1, typename = _Compatible<_Tp1>>
|
||||||
__shared_ptr(std::auto_ptr<_Tp1>&& __r)
|
__shared_ptr(std::auto_ptr<_Tp1>&& __r)
|
||||||
: _Base_type(std::move(__r))
|
: _Base_type(std::move(__r))
|
||||||
{ }
|
{ }
|
||||||
|
|
@ -180,7 +175,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
{ __shared_ptr(nullptr).swap(*this); }
|
{ __shared_ptr(nullptr).swap(*this); }
|
||||||
|
|
||||||
template<typename _Tp1>
|
template<typename _Tp1>
|
||||||
void
|
_Compatible<_Tp1>
|
||||||
reset(_Tp1* __p)
|
reset(_Tp1* __p)
|
||||||
{
|
{
|
||||||
_GLIBCXX_DEBUG_ASSERT(__p == 0 || __p != get());
|
_GLIBCXX_DEBUG_ASSERT(__p == 0 || __p != get());
|
||||||
|
|
@ -188,12 +183,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename _Tp1, typename _Deleter>
|
template<typename _Tp1, typename _Deleter>
|
||||||
void
|
_Compatible<_Tp1>
|
||||||
reset(_Tp1* __p, _Deleter __d)
|
reset(_Tp1* __p, _Deleter __d)
|
||||||
{ __shared_ptr(__p, __d).swap(*this); }
|
{ __shared_ptr(__p, __d).swap(*this); }
|
||||||
|
|
||||||
template<typename _Tp1, typename _Deleter, typename _Alloc>
|
template<typename _Tp1, typename _Deleter, typename _Alloc>
|
||||||
void
|
_Compatible<_Tp1>
|
||||||
reset(_Tp1* __p, _Deleter __d, _Alloc __a)
|
reset(_Tp1* __p, _Deleter __d, _Alloc __a)
|
||||||
{ __shared_ptr(__p, __d, std::move(__a)).swap(*this); }
|
{ __shared_ptr(__p, __d, std::move(__a)).swap(*this); }
|
||||||
|
|
||||||
|
|
@ -216,9 +211,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename _Tp1>
|
template<typename _Tp1, typename _Del>
|
||||||
_Compatible<_Tp1, __shared_ptr&>
|
_UniqCompatible<_Tp1, _Del, __shared_ptr&>
|
||||||
operator=(std::unique_ptr<_Tp1>&& __r)
|
operator=(unique_ptr<_Tp1, _Del>&& __r)
|
||||||
{
|
{
|
||||||
_Base_type::operator=(std::move(__r));
|
_Base_type::operator=(std::move(__r));
|
||||||
return *this;
|
return *this;
|
||||||
|
|
@ -282,6 +277,77 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&) noexcept;
|
friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&) noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Helper traits for shared_ptr of array:
|
||||||
|
|
||||||
|
// Trait that tests if Y* is compatible with T*, for shared_ptr purposes.
|
||||||
|
template<typename _Yp, typename _Tp>
|
||||||
|
struct __sp_compatible
|
||||||
|
: is_convertible<_Yp*, _Tp*>::type
|
||||||
|
{ };
|
||||||
|
|
||||||
|
template<size_t _Nm, typename _Tp>
|
||||||
|
struct __sp_compatible<_Tp[_Nm], _Tp[]>
|
||||||
|
: true_type
|
||||||
|
{ };
|
||||||
|
|
||||||
|
template<size_t _Nm, typename _Tp>
|
||||||
|
struct __sp_compatible<_Tp[_Nm], const _Tp[]>
|
||||||
|
: true_type
|
||||||
|
{ };
|
||||||
|
|
||||||
|
template<typename _Yp, typename _Tp>
|
||||||
|
constexpr bool __sp_compatible_v
|
||||||
|
= __sp_compatible<_Yp, _Tp>::value;
|
||||||
|
|
||||||
|
// Test conversion from Y(*)[N] to U(*)[N] without forming invalid type Y[N].
|
||||||
|
template<typename _Up, size_t _Nm, typename _Yp, typename = void>
|
||||||
|
struct __sp_is_constructible_arrN
|
||||||
|
: false_type
|
||||||
|
{ };
|
||||||
|
|
||||||
|
template<typename _Up, size_t _Nm, typename _Yp>
|
||||||
|
struct __sp_is_constructible_arrN<_Up, _Nm, _Yp, __void_t<_Yp[_Nm]>>
|
||||||
|
: is_convertible<_Yp(*)[_Nm], _Up(*)[_Nm]>::type
|
||||||
|
{ };
|
||||||
|
|
||||||
|
// Test conversion from Y(*)[] to U(*)[] without forming invalid type Y[].
|
||||||
|
template<typename _Up, typename _Yp, typename = void>
|
||||||
|
struct __sp_is_constructible_arr
|
||||||
|
: false_type
|
||||||
|
{ };
|
||||||
|
|
||||||
|
template<typename _Up, typename _Yp>
|
||||||
|
struct __sp_is_constructible_arr<_Up, _Yp, __void_t<_Yp[]>>
|
||||||
|
: is_convertible<_Yp(*)[], _Up(*)[]>::type
|
||||||
|
{ };
|
||||||
|
|
||||||
|
// Trait to check if shared_ptr<T> can be constructed from Y*.
|
||||||
|
template<typename _Tp, typename _Yp>
|
||||||
|
struct __sp_is_constructible;
|
||||||
|
|
||||||
|
// When T is U[N], Y(*)[N] shall be convertible to T*;
|
||||||
|
template<typename _Up, size_t _Nm, typename _Yp>
|
||||||
|
struct __sp_is_constructible<_Up[_Nm], _Yp>
|
||||||
|
: __sp_is_constructible_arrN<_Up, _Nm, _Yp>::type
|
||||||
|
{ };
|
||||||
|
|
||||||
|
// when T is U[], Y(*)[] shall be convertible to T*;
|
||||||
|
template<typename _Up, typename _Yp>
|
||||||
|
struct __sp_is_constructible<_Up[], _Yp>
|
||||||
|
: __sp_is_constructible_arr<_Up, _Yp>::type
|
||||||
|
{ };
|
||||||
|
|
||||||
|
// otherwise, Y* shall be convertible to T*.
|
||||||
|
template<typename _Tp, typename _Yp>
|
||||||
|
struct __sp_is_constructible
|
||||||
|
: is_convertible<_Yp*, _Tp*>::type
|
||||||
|
{ };
|
||||||
|
|
||||||
|
template<typename _Tp, typename _Yp>
|
||||||
|
constexpr bool __sp_is_constructible_v
|
||||||
|
= __sp_is_constructible<_Tp, _Yp>::value;
|
||||||
|
|
||||||
|
|
||||||
// Partial specialization for base class of experimental::shared_ptr<T[N]>
|
// Partial specialization for base class of experimental::shared_ptr<T[N]>
|
||||||
// and experimental::shared_ptr<T[]> (i.e. the array forms).
|
// and experimental::shared_ptr<T[]> (i.e. the array forms).
|
||||||
template<typename _Tp, _Lock_policy _Lp>
|
template<typename _Tp, _Lock_policy _Lp>
|
||||||
|
|
@ -299,31 +365,46 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
{ delete [] __p; }
|
{ delete [] __p; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Constraint for constructing/resetting with a pointer of type _Yp*:
|
||||||
|
template<typename _Yp>
|
||||||
|
using _SafeConv = enable_if_t<__sp_is_constructible_v<_Tp, _Yp>>;
|
||||||
|
|
||||||
|
// Constraint for constructing/assigning from smart_pointer<_Tp1>:
|
||||||
template<typename _Tp1, typename _Res = void>
|
template<typename _Tp1, typename _Res = void>
|
||||||
using _Compatible
|
using _Compatible = enable_if_t<__sp_compatible_v<_Tp1, _Tp>, _Res>;
|
||||||
= enable_if_t<__sp_compatible<_Tp1, _Tp>::value, _Res>;
|
|
||||||
|
// Constraint for constructing/assigning from unique_ptr<_Tp1, _Del>:
|
||||||
|
template<typename _Tp1, typename _Del,
|
||||||
|
typename _Ptr = typename unique_ptr<_Tp1, _Del>::pointer,
|
||||||
|
typename _Res = void>
|
||||||
|
using _UniqCompatible = enable_if_t<
|
||||||
|
__sp_compatible_v<_Tp1, _Tp>
|
||||||
|
&& experimental::is_convertible_v<_Ptr, element_type*>,
|
||||||
|
_Res>;
|
||||||
|
|
||||||
using _Base_type = __shared_ptr<element_type>;
|
using _Base_type = __shared_ptr<element_type>;
|
||||||
|
|
||||||
_Base_type& _M_get_base() { return *this;}
|
_Base_type& _M_get_base() { return *this; }
|
||||||
const _Base_type& _M_get_base() const { return *this;}
|
const _Base_type& _M_get_base() const { return *this; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr __shared_ptr() noexcept
|
constexpr __shared_ptr() noexcept
|
||||||
: _Base_type()
|
: _Base_type()
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
template<typename _Tp1>
|
template<typename _Tp1, typename = _SafeConv<_Tp1>>
|
||||||
explicit __shared_ptr(_Tp1* __p)
|
explicit
|
||||||
|
__shared_ptr(_Tp1* __p)
|
||||||
: _Base_type(__p, _Array_deleter())
|
: _Base_type(__p, _Array_deleter())
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
template<typename _Tp1, typename _Deleter>
|
template<typename _Tp1, typename _Deleter, typename = _SafeConv<_Tp1>>
|
||||||
__shared_ptr(_Tp1* __p, _Deleter __d)
|
__shared_ptr(_Tp1* __p, _Deleter __d)
|
||||||
: _Base_type(__p, __d)
|
: _Base_type(__p, __d)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
template<typename _Tp1, typename _Deleter, typename _Alloc>
|
template<typename _Tp1, typename _Deleter, typename _Alloc,
|
||||||
|
typename = _SafeConv<_Tp1>>
|
||||||
__shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)
|
__shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)
|
||||||
: _Base_type(__p, __d, __a)
|
: _Base_type(__p, __d, __a)
|
||||||
{ }
|
{ }
|
||||||
|
|
@ -360,22 +441,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
: _Base_type(std::move((__r._M_get_base())))
|
: _Base_type(std::move((__r._M_get_base())))
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
template<typename _Tp1>
|
template<typename _Tp1, typename = _Compatible<_Tp1>>
|
||||||
explicit __shared_ptr(const __weak_ptr<__libfund_v1<_Tp1>, _Lp>& __r)
|
explicit
|
||||||
|
__shared_ptr(const __weak_ptr<__libfund_v1<_Tp1>, _Lp>& __r)
|
||||||
: _Base_type(__r._M_get_base())
|
: _Base_type(__r._M_get_base())
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
template<typename _Tp1, typename _Del, typename
|
template<typename _Tp1, typename _Del,
|
||||||
= _Compatible<remove_pointer_t<
|
typename = _UniqCompatible<_Tp1, _Del>>
|
||||||
typename unique_ptr<_Tp1, _Del>::pointer>>>
|
__shared_ptr(unique_ptr<_Tp1, _Del>&& __r)
|
||||||
__shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r)
|
: _Base_type(std::move(__r))
|
||||||
: _Base_type(std::move(__r))
|
{ }
|
||||||
{ }
|
|
||||||
|
|
||||||
#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 _Tp1, typename = _Compatible<_Tp1>>
|
||||||
__shared_ptr(std::auto_ptr<_Tp1>&& __r)
|
__shared_ptr(auto_ptr<_Tp1>&& __r)
|
||||||
: _Base_type(std::move(__r))
|
: _Base_type(std::move(__r))
|
||||||
{ }
|
{ }
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -388,7 +469,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
{ __shared_ptr(nullptr).swap(*this); }
|
{ __shared_ptr(nullptr).swap(*this); }
|
||||||
|
|
||||||
template<typename _Tp1>
|
template<typename _Tp1>
|
||||||
void
|
_SafeConv<_Tp1>
|
||||||
reset(_Tp1* __p)
|
reset(_Tp1* __p)
|
||||||
{
|
{
|
||||||
_GLIBCXX_DEBUG_ASSERT(__p == 0 || __p != get());
|
_GLIBCXX_DEBUG_ASSERT(__p == 0 || __p != get());
|
||||||
|
|
@ -396,12 +477,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename _Tp1, typename _Deleter>
|
template<typename _Tp1, typename _Deleter>
|
||||||
void
|
_SafeConv<_Tp1>
|
||||||
reset(_Tp1* __p, _Deleter __d)
|
reset(_Tp1* __p, _Deleter __d)
|
||||||
{ __shared_ptr(__p, __d).swap(*this); }
|
{ __shared_ptr(__p, __d).swap(*this); }
|
||||||
|
|
||||||
template<typename _Tp1, typename _Deleter, typename _Alloc>
|
template<typename _Tp1, typename _Deleter, typename _Alloc>
|
||||||
void
|
_SafeConv<_Tp1>
|
||||||
reset(_Tp1* __p, _Deleter __d, _Alloc __a)
|
reset(_Tp1* __p, _Deleter __d, _Alloc __a)
|
||||||
{ __shared_ptr(__p, __d, std::move(__a)).swap(*this); }
|
{ __shared_ptr(__p, __d, std::move(__a)).swap(*this); }
|
||||||
|
|
||||||
|
|
@ -428,9 +509,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename _Tp1>
|
template<typename _Tp1, typename _Del>
|
||||||
_Compatible<_Tp1, __shared_ptr&>
|
_UniqCompatible<_Tp1, _Del, __shared_ptr&>
|
||||||
operator=(std::unique_ptr<_Tp1>&& __r)
|
operator=(unique_ptr<_Tp1, _Del>&& __r)
|
||||||
{
|
{
|
||||||
_Base_type::operator=(std::move(__r));
|
_Base_type::operator=(std::move(__r));
|
||||||
return *this;
|
return *this;
|
||||||
|
|
@ -439,7 +520,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
#if _GLIBCXX_USE_DEPRECATED
|
#if _GLIBCXX_USE_DEPRECATED
|
||||||
template<typename _Tp1>
|
template<typename _Tp1>
|
||||||
_Compatible<_Tp1, __shared_ptr&>
|
_Compatible<_Tp1, __shared_ptr&>
|
||||||
operator=(std::auto_ptr<_Tp1>&& __r)
|
operator=(auto_ptr<_Tp1>&& __r)
|
||||||
{
|
{
|
||||||
_Base_type::operator=(std::move(__r));
|
_Base_type::operator=(std::move(__r));
|
||||||
return *this;
|
return *this;
|
||||||
|
|
@ -501,11 +582,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
{
|
{
|
||||||
template<typename _Tp1, typename _Res = void>
|
template<typename _Tp1, typename _Res = void>
|
||||||
using _Compatible
|
using _Compatible
|
||||||
= enable_if_t<__sp_compatible<_Tp1, _Tp>::value, _Res>;
|
= enable_if_t<__sp_compatible_v<_Tp1, _Tp>, _Res>;
|
||||||
|
|
||||||
using _Base_type = __weak_ptr<remove_extent_t<_Tp>>;
|
using _Base_type = __weak_ptr<remove_extent_t<_Tp>>;
|
||||||
|
|
||||||
_Base_type& _M_get_base() { return *this;}
|
_Base_type& _M_get_base() { return *this; }
|
||||||
const _Base_type& _M_get_base() const { return *this; }
|
const _Base_type& _M_get_base() const { return *this; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -630,26 +711,43 @@ _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 _Tp1, typename _Res = void>
|
|
||||||
using _Compatible
|
|
||||||
= enable_if_t<__sp_compatible<_Tp1, _Tp>::value, _Res>;
|
|
||||||
|
|
||||||
using _Base_type = __shared_ptr<_Tp>;
|
using _Base_type = __shared_ptr<_Tp>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using element_type = typename _Base_type::element_type;
|
using element_type = typename _Base_type::element_type;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Constraint for construction from a pointer of type _Yp*:
|
||||||
|
template<typename _Yp>
|
||||||
|
using _SafeConv = enable_if_t<__sp_is_constructible_v<_Tp, _Yp>>;
|
||||||
|
|
||||||
|
template<typename _Tp1, typename _Res = void>
|
||||||
|
using _Compatible
|
||||||
|
= enable_if_t<__sp_compatible_v<_Tp1, _Tp>, _Res>;
|
||||||
|
|
||||||
|
template<typename _Tp1, typename _Del,
|
||||||
|
typename _Ptr = typename unique_ptr<_Tp1, _Del>::pointer,
|
||||||
|
typename _Res = void>
|
||||||
|
using _UniqCompatible = enable_if_t<
|
||||||
|
__sp_compatible_v<_Tp1, _Tp>
|
||||||
|
&& experimental::is_convertible_v<_Ptr, element_type*>,
|
||||||
|
_Res>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
// 8.2.1.1, shared_ptr constructors
|
// 8.2.1.1, shared_ptr constructors
|
||||||
constexpr shared_ptr() noexcept = default;
|
constexpr shared_ptr() noexcept = default;
|
||||||
|
|
||||||
template<typename _Tp1>
|
template<typename _Tp1, typename = _SafeConv<_Tp1>>
|
||||||
explicit shared_ptr(_Tp1* __p) : _Base_type(__p) { }
|
explicit
|
||||||
|
shared_ptr(_Tp1* __p) : _Base_type(__p) { }
|
||||||
|
|
||||||
template<typename _Tp1, typename _Deleter>
|
template<typename _Tp1, typename _Deleter, typename = _SafeConv<_Tp1>>
|
||||||
shared_ptr(_Tp1* __p, _Deleter __d)
|
shared_ptr(_Tp1* __p, _Deleter __d)
|
||||||
: _Base_type(__p, __d) { }
|
: _Base_type(__p, __d) { }
|
||||||
|
|
||||||
template<typename _Tp1, typename _Deleter, typename _Alloc>
|
template<typename _Tp1, typename _Deleter, typename _Alloc,
|
||||||
|
typename = _SafeConv<_Tp1>>
|
||||||
shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)
|
shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)
|
||||||
: _Base_type(__p, __d, __a) { }
|
: _Base_type(__p, __d, __a) { }
|
||||||
|
|
||||||
|
|
@ -679,20 +777,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
shared_ptr(shared_ptr<_Tp1>&& __r) noexcept
|
shared_ptr(shared_ptr<_Tp1>&& __r) noexcept
|
||||||
: _Base_type(std::move(__r)) { }
|
: _Base_type(std::move(__r)) { }
|
||||||
|
|
||||||
template<typename _Tp1>
|
template<typename _Tp1, typename = _Compatible<_Tp1>>
|
||||||
explicit shared_ptr(const weak_ptr<_Tp1>& __r)
|
explicit
|
||||||
|
shared_ptr(const weak_ptr<_Tp1>& __r)
|
||||||
: _Base_type(__r) { }
|
: _Base_type(__r) { }
|
||||||
|
|
||||||
#if _GLIBCXX_USE_DEPRECATED
|
#if _GLIBCXX_USE_DEPRECATED
|
||||||
template<typename _Tp1>
|
template<typename _Tp1, typename = _Compatible<_Tp1>>
|
||||||
shared_ptr(std::auto_ptr<_Tp1>&& __r)
|
shared_ptr(std::auto_ptr<_Tp1>&& __r)
|
||||||
: _Base_type() { } // TODO
|
: _Base_type(std::move(__r)) { }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template<typename _Tp1, typename _Del, typename
|
template<typename _Tp1, typename _Del,
|
||||||
= _Compatible<remove_pointer_t<
|
typename = _UniqCompatible<_Tp1, _Del>>
|
||||||
typename unique_ptr<_Tp1, _Del>::pointer>>>
|
shared_ptr(unique_ptr<_Tp1, _Del>&& __r)
|
||||||
shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r)
|
|
||||||
: _Base_type(std::move(__r)) { }
|
: _Base_type(std::move(__r)) { }
|
||||||
|
|
||||||
constexpr shared_ptr(nullptr_t __p)
|
constexpr shared_ptr(nullptr_t __p)
|
||||||
|
|
@ -738,7 +836,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename _Tp1, typename _Del>
|
template <typename _Tp1, typename _Del>
|
||||||
_Compatible<_Tp1, shared_ptr&>
|
_UniqCompatible<_Tp1, _Del, shared_ptr&>
|
||||||
operator=(unique_ptr<_Tp1, _Del>&& __r)
|
operator=(unique_ptr<_Tp1, _Del>&& __r)
|
||||||
{
|
{
|
||||||
_Base_type::operator=(std::move(__r));
|
_Base_type::operator=(std::move(__r));
|
||||||
|
|
@ -752,10 +850,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<typename _Alloc, typename... _Args>
|
template<typename _Alloc, typename... _Args>
|
||||||
shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
|
shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
|
||||||
_Args&&... __args)
|
_Args&&... __args)
|
||||||
: _Base_type(__tag, __a, std::forward<_Args>(__args)...)
|
: _Base_type(__tag, __a, std::forward<_Args>(__args)...)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
template<typename _Tp1, typename _Alloc, typename... _Args>
|
template<typename _Tp1, typename _Alloc, typename... _Args>
|
||||||
friend shared_ptr<_Tp1>
|
friend shared_ptr<_Tp1>
|
||||||
|
|
@ -926,8 +1024,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
class weak_ptr : public __weak_ptr<_Tp>
|
class weak_ptr : public __weak_ptr<_Tp>
|
||||||
{
|
{
|
||||||
template<typename _Tp1, typename _Res = void>
|
template<typename _Tp1, typename _Res = void>
|
||||||
using _Compatible
|
using _Compatible = enable_if_t<__sp_compatible_v<_Tp1, _Tp>, _Res>;
|
||||||
= enable_if_t<__sp_compatible<_Tp1, _Tp>::value, _Res>;
|
|
||||||
|
|
||||||
using _Base_type = __weak_ptr<_Tp>;
|
using _Base_type = __weak_ptr<_Tp>;
|
||||||
|
|
||||||
|
|
@ -1147,6 +1244,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
shared_from_this() const
|
shared_from_this() const
|
||||||
{ return shared_ptr<const _Tp>(this->_M_weak_this); }
|
{ return shared_ptr<const _Tp>(this->_M_weak_this); }
|
||||||
|
|
||||||
|
weak_ptr<_Tp>
|
||||||
|
weak_from_this() noexcept
|
||||||
|
{ return _M_weak_this; }
|
||||||
|
|
||||||
|
weak_ptr<const _Tp>
|
||||||
|
weak_from_this() const noexcept
|
||||||
|
{ return _M_weak_this; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<typename _Tp1>
|
template<typename _Tp1>
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -23,40 +23,35 @@
|
||||||
#include <testsuite_hooks.h>
|
#include <testsuite_hooks.h>
|
||||||
|
|
||||||
struct A { };
|
struct A { };
|
||||||
struct B : A { };
|
|
||||||
|
|
||||||
// 8.2.1.1 shared_ptr constructors [memory.smartptr.shared.const]
|
// 8.2.1.1 shared_ptr constructors [memory.smartptr.shared.const]
|
||||||
|
|
||||||
// Construction from pointer
|
// Construction from pointer
|
||||||
int
|
void
|
||||||
test01()
|
test01()
|
||||||
{
|
{
|
||||||
A * const a = 0;
|
A * const a = new A;
|
||||||
std::experimental::shared_ptr<A> p(a);
|
std::experimental::shared_ptr<A> p(a);
|
||||||
VERIFY( p.get() == 0 );
|
VERIFY( p.get() == a );
|
||||||
VERIFY( p.use_count() == 1 );
|
VERIFY( p.use_count() == 1 );
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
void
|
||||||
test02()
|
test02()
|
||||||
{
|
{
|
||||||
A * const a = new A[5];
|
A * const a = new A[5];
|
||||||
std::experimental::shared_ptr<A[5]> p(a);
|
std::experimental::shared_ptr<A[5]> p(a);
|
||||||
VERIFY( p.get() == a );
|
VERIFY( p.get() == a );
|
||||||
VERIFY( p.use_count() == 1 );
|
VERIFY( p.use_count() == 1 );
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
void
|
||||||
test03()
|
test03()
|
||||||
{
|
{
|
||||||
B * const b = new B[5];
|
A * const a = new A[5];
|
||||||
std::experimental::shared_ptr<A[5]> p(b);
|
std::experimental::shared_ptr<A[]> p(a);
|
||||||
VERIFY( p.get() == b );
|
VERIFY( p.get() == a );
|
||||||
VERIFY( p.use_count() == 1 );
|
VERIFY( p.use_count() == 1 );
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
// { dg-do compile { target c++14 } }
|
||||||
|
|
||||||
|
// 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/>.
|
||||||
|
|
||||||
|
// 8.2.1 Class template shared_ptr [memory.smartptr.shared]
|
||||||
|
|
||||||
|
#include <experimental/memory>
|
||||||
|
|
||||||
|
struct A { };
|
||||||
|
struct B : A { };
|
||||||
|
struct C { };
|
||||||
|
struct D { void operator()(B* p) const { delete[] p; } };
|
||||||
|
|
||||||
|
// 8.2.1.1 shared_ptr constructors [memory.smartptr.shared.const]
|
||||||
|
|
||||||
|
// Construction from pointer
|
||||||
|
void
|
||||||
|
test01()
|
||||||
|
{
|
||||||
|
C * const c = nullptr;
|
||||||
|
std::experimental::shared_ptr<A> p(c); // { dg-error "no match" }
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test02()
|
||||||
|
{
|
||||||
|
B * const b = nullptr;
|
||||||
|
std::experimental::shared_ptr<A[5]> p(b); // { dg-error "no match" }
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test03()
|
||||||
|
{
|
||||||
|
B * const b = nullptr;
|
||||||
|
std::experimental::shared_ptr<A[]> p(b); // { dg-error "no match" }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
// { dg-do compile { target c++14 } }
|
||||||
|
|
||||||
|
// 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/>.
|
||||||
|
|
||||||
|
// 8.2.1 Class template shared_ptr [memory.smartptr.shared]
|
||||||
|
|
||||||
|
#include <experimental/memory>
|
||||||
|
|
||||||
|
using namespace std::experimental;
|
||||||
|
|
||||||
|
static_assert( !is_constructible_v<shared_ptr<int>, void*>,
|
||||||
|
"can query constructibility without forming invalid type void[]");
|
||||||
|
static_assert( !is_constructible_v<shared_ptr<int[2]>, void*>,
|
||||||
|
"can query constructibility without forming invalid type void[]");
|
||||||
|
static_assert( !is_constructible_v<shared_ptr<int[]>, void*>,
|
||||||
|
"can query constructibility without forming invalid type void[]");
|
||||||
|
|
||||||
|
static_assert( !is_constructible_v<shared_ptr<int>, void()>,
|
||||||
|
"can query constructibility without forming invalid type void()[]");
|
||||||
|
static_assert( !is_constructible_v<shared_ptr<int[2]>, void()>,
|
||||||
|
"can query constructibility without forming invalid type void()[]");
|
||||||
|
static_assert( !is_constructible_v<shared_ptr<int[]>, void()>,
|
||||||
|
"can query constructibility without forming invalid type void()[]");
|
||||||
|
|
||||||
|
static_assert( !is_constructible_v<shared_ptr<int>, void()>,
|
||||||
|
"can query constructibility without forming invalid type void(*)()[]");
|
||||||
|
static_assert( !is_constructible_v<shared_ptr<int[2]>, void()>,
|
||||||
|
"can query constructibility without forming invalid type void(*)()[]");
|
||||||
|
static_assert( !is_constructible_v<shared_ptr<int[]>, void()>,
|
||||||
|
"can query constructibility without forming invalid type void(*)()[]");
|
||||||
|
|
||||||
|
using A = int[];
|
||||||
|
static_assert( !is_constructible_v<shared_ptr<int>, A*>,
|
||||||
|
"can query constructibility without forming invalid type int[][]");
|
||||||
|
static_assert( !is_constructible_v<shared_ptr<int[2]>, A*>,
|
||||||
|
"can query constructibility without forming invalid type int[][]");
|
||||||
|
static_assert( !is_constructible_v<shared_ptr<int[]>, A*>,
|
||||||
|
"can query constructibility without forming invalid type int[][]");
|
||||||
|
|
@ -26,17 +26,17 @@ int destroyed = 0;
|
||||||
|
|
||||||
struct A : std::experimental::enable_shared_from_this<A>
|
struct A : std::experimental::enable_shared_from_this<A>
|
||||||
{
|
{
|
||||||
~A() { ++destroyed; }
|
~A() { ++destroyed; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// 8.2.1.1 shared_ptr constructors [memory.smartptr.shared.const]
|
// 8.2.1.1 shared_ptr constructors [memory.smartptr.shared.const]
|
||||||
|
|
||||||
// Construction from unique_ptr<A[]>
|
// Construction from unique_ptr<A[]>
|
||||||
|
|
||||||
int
|
void
|
||||||
test01()
|
test01()
|
||||||
{
|
{
|
||||||
std::unique_ptr<A[]> up(new A[5]);
|
std::unique_ptr<A> up(new A);
|
||||||
std::experimental::shared_ptr<A> sp(std::move(up));
|
std::experimental::shared_ptr<A> sp(std::move(up));
|
||||||
VERIFY( up.get() == 0 );
|
VERIFY( up.get() == 0 );
|
||||||
VERIFY( sp.get() != 0 );
|
VERIFY( sp.get() != 0 );
|
||||||
|
|
@ -45,14 +45,28 @@ test01()
|
||||||
VERIFY( sp->shared_from_this() != nullptr );
|
VERIFY( sp->shared_from_this() != nullptr );
|
||||||
|
|
||||||
sp.reset();
|
sp.reset();
|
||||||
VERIFY( destroyed == 5 );
|
VERIFY( destroyed == 1 );
|
||||||
|
destroyed = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
void
|
||||||
|
test02()
|
||||||
|
{
|
||||||
|
std::unique_ptr<A[]> up(new A[5]);
|
||||||
|
std::experimental::shared_ptr<A[]> sp(std::move(up));
|
||||||
|
VERIFY( up.get() == 0 );
|
||||||
|
VERIFY( sp.get() != 0 );
|
||||||
|
VERIFY( sp.use_count() == 1 );
|
||||||
|
|
||||||
|
VERIFY( sp[0].shared_from_this() != nullptr );
|
||||||
|
|
||||||
|
sp.reset();
|
||||||
|
VERIFY( destroyed == 5 );
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
test01();
|
test01();
|
||||||
return 0;
|
test02();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,10 +23,9 @@
|
||||||
#include <testsuite_hooks.h>
|
#include <testsuite_hooks.h>
|
||||||
|
|
||||||
struct A { };
|
struct A { };
|
||||||
struct B : A { };
|
|
||||||
struct D
|
struct D
|
||||||
{
|
{
|
||||||
void operator()(B* p) { delete [] p; ++delete_count; }
|
void operator()(A* p) { delete [] p; ++delete_count; }
|
||||||
static long delete_count;
|
static long delete_count;
|
||||||
};
|
};
|
||||||
long D::delete_count = 0;
|
long D::delete_count = 0;
|
||||||
|
|
@ -51,7 +50,7 @@ int
|
||||||
test02()
|
test02()
|
||||||
{
|
{
|
||||||
A * const a = new A[5];
|
A * const a = new A[5];
|
||||||
B * const b = new B[5];
|
A * const b = new A[5];
|
||||||
std::experimental::shared_ptr<A[5]> p1(a);
|
std::experimental::shared_ptr<A[5]> p1(a);
|
||||||
std::experimental::shared_ptr<A[5]> p2(p1);
|
std::experimental::shared_ptr<A[5]> p2(p1);
|
||||||
p1.reset(b);
|
p1.reset(b);
|
||||||
|
|
@ -66,7 +65,7 @@ test03()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
std::experimental::shared_ptr<A[5]> p1;
|
std::experimental::shared_ptr<A[5]> p1;
|
||||||
p1.reset(new B[5], D());
|
p1.reset(new A[5], D());
|
||||||
}
|
}
|
||||||
VERIFY( D::delete_count == 1 );
|
VERIFY( D::delete_count == 1 );
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
// { dg-do compile { target c++14 } }
|
||||||
|
|
||||||
|
// 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/>.
|
||||||
|
|
||||||
|
// 8.2.1 Class template shared_ptr [memory.smartptr.shared]
|
||||||
|
|
||||||
|
#include <experimental/memory>
|
||||||
|
|
||||||
|
struct A { };
|
||||||
|
struct B : A { };
|
||||||
|
struct D
|
||||||
|
{
|
||||||
|
void operator()(A* p) { delete [] p; ++delete_count; }
|
||||||
|
static long delete_count;
|
||||||
|
};
|
||||||
|
long D::delete_count = 0;
|
||||||
|
|
||||||
|
// C++14 §20.8.2.2.4
|
||||||
|
|
||||||
|
// reset
|
||||||
|
void
|
||||||
|
test01()
|
||||||
|
{
|
||||||
|
std::experimental::shared_ptr<A[5]> p1(new A[5]);
|
||||||
|
p1.reset(new B[1]); // { dg-error "no matching function" }
|
||||||
|
p1.reset(new B[5], D()); // { dg-error "no matching function" }
|
||||||
|
using constA = const A;
|
||||||
|
p1.reset(new constA[5]); // { dg-error "no matching function" }
|
||||||
|
p1.reset(new constA[5], D()); // { dg-error "no matching function" }
|
||||||
|
}
|
||||||
|
|
@ -23,7 +23,6 @@
|
||||||
#include <testsuite_hooks.h>
|
#include <testsuite_hooks.h>
|
||||||
|
|
||||||
struct A { };
|
struct A { };
|
||||||
struct B : A { };
|
|
||||||
|
|
||||||
// 8.2.1.2 shared_ptr observers [memory.smartptr.shared.obs]
|
// 8.2.1.2 shared_ptr observers [memory.smartptr.shared.obs]
|
||||||
|
|
||||||
|
|
@ -52,7 +51,7 @@ test03()
|
||||||
{
|
{
|
||||||
std::experimental::shared_ptr<A[5]> p1(new A[5]);
|
std::experimental::shared_ptr<A[5]> p1(new A[5]);
|
||||||
std::experimental::shared_ptr<A[5]> p2(p1);
|
std::experimental::shared_ptr<A[5]> p2(p1);
|
||||||
p2.reset(new B[5]);
|
p2.reset(new A[5]);
|
||||||
VERIFY( p1.use_count() == 1 );
|
VERIFY( p1.use_count() == 1 );
|
||||||
VERIFY( p2.use_count() == 1 );
|
VERIFY( p2.use_count() == 1 );
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue