forked from OSchip/llvm-project
[libcxx] shared_ptr changes from library fundamentals (P0414R2).
Implements P0414R2: * Adds support for array types in std::shared_ptr. * Adds reinterpret_pointer_cast for shared_ptr. Differential Revision: https://reviews.llvm.org/D62259
This commit is contained in:
parent
2aa0217add
commit
e8c13c182a
|
@ -3702,15 +3702,25 @@ public:
|
|||
|
||||
template<class _Tp> class _LIBCPP_TEMPLATE_VIS enable_shared_from_this;
|
||||
|
||||
template<class _Tp, class _Up>
|
||||
struct __compatible_with
|
||||
#if _LIBCPP_STD_VER > 14
|
||||
: is_convertible<remove_extent_t<_Tp>*, remove_extent_t<_Up>*> {};
|
||||
#else
|
||||
: is_convertible<_Tp*, _Up*> {};
|
||||
#endif // _LIBCPP_STD_VER > 14
|
||||
|
||||
template<class _Tp>
|
||||
class _LIBCPP_TEMPLATE_VIS shared_ptr
|
||||
{
|
||||
public:
|
||||
typedef _Tp element_type;
|
||||
|
||||
#if _LIBCPP_STD_VER > 14
|
||||
typedef weak_ptr<_Tp> weak_type;
|
||||
typedef remove_extent_t<_Tp> element_type;
|
||||
#else
|
||||
typedef _Tp element_type;
|
||||
#endif
|
||||
|
||||
private:
|
||||
element_type* __ptr_;
|
||||
__shared_weak_count* __cntrl_;
|
||||
|
@ -3723,13 +3733,13 @@ public:
|
|||
_LIBCPP_CONSTEXPR shared_ptr(nullptr_t) _NOEXCEPT;
|
||||
template<class _Yp>
|
||||
explicit shared_ptr(_Yp* __p,
|
||||
typename enable_if<is_convertible<_Yp*, element_type*>::value, __nat>::type = __nat());
|
||||
typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type = __nat());
|
||||
template<class _Yp, class _Dp>
|
||||
shared_ptr(_Yp* __p, _Dp __d,
|
||||
typename enable_if<is_convertible<_Yp*, element_type*>::value, __nat>::type = __nat());
|
||||
typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type = __nat());
|
||||
template<class _Yp, class _Dp, class _Alloc>
|
||||
shared_ptr(_Yp* __p, _Dp __d, _Alloc __a,
|
||||
typename enable_if<is_convertible<_Yp*, element_type*>::value, __nat>::type = __nat());
|
||||
typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type = __nat());
|
||||
template <class _Dp> shared_ptr(nullptr_t __p, _Dp __d);
|
||||
template <class _Dp, class _Alloc> shared_ptr(nullptr_t __p, _Dp __d, _Alloc __a);
|
||||
template<class _Yp> _LIBCPP_INLINE_VISIBILITY shared_ptr(const shared_ptr<_Yp>& __r, element_type* __p) _NOEXCEPT;
|
||||
|
@ -3738,13 +3748,13 @@ public:
|
|||
template<class _Yp>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
shared_ptr(const shared_ptr<_Yp>& __r,
|
||||
typename enable_if<is_convertible<_Yp*, element_type*>::value, __nat>::type = __nat())
|
||||
typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type = __nat())
|
||||
_NOEXCEPT;
|
||||
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
shared_ptr(shared_ptr&& __r) _NOEXCEPT;
|
||||
template<class _Yp> _LIBCPP_INLINE_VISIBILITY shared_ptr(shared_ptr<_Yp>&& __r,
|
||||
typename enable_if<is_convertible<_Yp*, element_type*>::value, __nat>::type = __nat())
|
||||
typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type = __nat())
|
||||
_NOEXCEPT;
|
||||
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
template<class _Yp> explicit shared_ptr(const weak_ptr<_Yp>& __r,
|
||||
|
@ -3807,7 +3817,7 @@ public:
|
|||
template<class _Yp>
|
||||
typename enable_if
|
||||
<
|
||||
is_convertible<_Yp*, element_type*>::value,
|
||||
__compatible_with<_Yp, element_type>::value,
|
||||
shared_ptr&
|
||||
>::type
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
|
@ -3818,8 +3828,8 @@ public:
|
|||
template<class _Yp>
|
||||
typename enable_if
|
||||
<
|
||||
is_convertible<_Yp*, element_type*>::value,
|
||||
shared_ptr<_Tp>&
|
||||
__compatible_with<_Yp, element_type>::value,
|
||||
shared_ptr&
|
||||
>::type
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
operator=(shared_ptr<_Yp>&& __r);
|
||||
|
@ -3869,7 +3879,7 @@ public:
|
|||
template<class _Yp>
|
||||
typename enable_if
|
||||
<
|
||||
is_convertible<_Yp*, element_type*>::value,
|
||||
__compatible_with<_Yp, element_type>::value,
|
||||
void
|
||||
>::type
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
|
@ -3877,7 +3887,7 @@ public:
|
|||
template<class _Yp, class _Dp>
|
||||
typename enable_if
|
||||
<
|
||||
is_convertible<_Yp*, element_type*>::value,
|
||||
__compatible_with<_Yp, element_type>::value,
|
||||
void
|
||||
>::type
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
|
@ -3885,7 +3895,7 @@ public:
|
|||
template<class _Yp, class _Dp, class _Alloc>
|
||||
typename enable_if
|
||||
<
|
||||
is_convertible<_Yp*, element_type*>::value,
|
||||
__compatible_with<_Yp, element_type>::value,
|
||||
void
|
||||
>::type
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
|
@ -3897,7 +3907,12 @@ public:
|
|||
typename add_lvalue_reference<element_type>::type operator*() const _NOEXCEPT
|
||||
{return *__ptr_;}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
element_type* operator->() const _NOEXCEPT {return __ptr_;}
|
||||
element_type* operator->() const _NOEXCEPT
|
||||
{
|
||||
static_assert(!_VSTD::is_array<_Tp>::value,
|
||||
"std::shared_ptr<T>::operator-> is only valid when T is not an array type.");
|
||||
return __ptr_;
|
||||
}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
long use_count() const _NOEXCEPT {return __cntrl_ ? __cntrl_->use_count() : 0;}
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
|
@ -3917,6 +3932,17 @@ public:
|
|||
__owner_equivalent(const shared_ptr& __p) const
|
||||
{return __cntrl_ == __p.__cntrl_;}
|
||||
|
||||
#if _LIBCPP_STD_VER > 14
|
||||
typename add_lvalue_reference<element_type>::type
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
operator[](ptrdiff_t __i) const
|
||||
{
|
||||
static_assert(_VSTD::is_array<_Tp>::value,
|
||||
"std::shared_ptr<T>::operator[] is only valid when T is an array type.");
|
||||
return __ptr_[__i];
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _LIBCPP_NO_RTTI
|
||||
template <class _Dp>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
|
@ -3969,6 +3995,18 @@ private:
|
|||
|
||||
_LIBCPP_INLINE_VISIBILITY void __enable_weak_this(...) _NOEXCEPT {}
|
||||
|
||||
template <class, class _Yp>
|
||||
struct __shared_ptr_default_delete
|
||||
: default_delete<_Yp> {};
|
||||
|
||||
template <class _Yp, class _Un, size_t _Sz>
|
||||
struct __shared_ptr_default_delete<_Yp[_Sz], _Un>
|
||||
: default_delete<_Yp[]> {};
|
||||
|
||||
template <class _Yp, class _Un>
|
||||
struct __shared_ptr_default_delete<_Yp[], _Un>
|
||||
: default_delete<_Yp[]> {};
|
||||
|
||||
template <class _Up> friend class _LIBCPP_TEMPLATE_VIS shared_ptr;
|
||||
template <class _Up> friend class _LIBCPP_TEMPLATE_VIS weak_ptr;
|
||||
};
|
||||
|
@ -4001,13 +4039,13 @@ shared_ptr<_Tp>::shared_ptr(nullptr_t) _NOEXCEPT
|
|||
template<class _Tp>
|
||||
template<class _Yp>
|
||||
shared_ptr<_Tp>::shared_ptr(_Yp* __p,
|
||||
typename enable_if<is_convertible<_Yp*, element_type*>::value, __nat>::type)
|
||||
typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type)
|
||||
: __ptr_(__p)
|
||||
{
|
||||
unique_ptr<_Yp> __hold(__p);
|
||||
typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT;
|
||||
typedef __shared_ptr_pointer<_Yp*, default_delete<_Yp>, _AllocT > _CntrlBlk;
|
||||
__cntrl_ = new _CntrlBlk(__p, default_delete<_Yp>(), _AllocT());
|
||||
typedef __shared_ptr_pointer<_Yp*, __shared_ptr_default_delete<_Tp, _Yp>, _AllocT > _CntrlBlk;
|
||||
__cntrl_ = new _CntrlBlk(__p, __shared_ptr_default_delete<_Tp, _Yp>(), _AllocT());
|
||||
__hold.release();
|
||||
__enable_weak_this(__p, __p);
|
||||
}
|
||||
|
@ -4015,7 +4053,7 @@ shared_ptr<_Tp>::shared_ptr(_Yp* __p,
|
|||
template<class _Tp>
|
||||
template<class _Yp, class _Dp>
|
||||
shared_ptr<_Tp>::shared_ptr(_Yp* __p, _Dp __d,
|
||||
typename enable_if<is_convertible<_Yp*, element_type*>::value, __nat>::type)
|
||||
typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type)
|
||||
: __ptr_(__p)
|
||||
{
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
|
@ -4061,7 +4099,7 @@ shared_ptr<_Tp>::shared_ptr(nullptr_t __p, _Dp __d)
|
|||
template<class _Tp>
|
||||
template<class _Yp, class _Dp, class _Alloc>
|
||||
shared_ptr<_Tp>::shared_ptr(_Yp* __p, _Dp __d, _Alloc __a,
|
||||
typename enable_if<is_convertible<_Yp*, element_type*>::value, __nat>::type)
|
||||
typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type)
|
||||
: __ptr_(__p)
|
||||
{
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
|
@ -4139,7 +4177,7 @@ template<class _Tp>
|
|||
template<class _Yp>
|
||||
inline
|
||||
shared_ptr<_Tp>::shared_ptr(const shared_ptr<_Yp>& __r,
|
||||
typename enable_if<is_convertible<_Yp*, element_type*>::value, __nat>::type)
|
||||
typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type)
|
||||
_NOEXCEPT
|
||||
: __ptr_(__r.__ptr_),
|
||||
__cntrl_(__r.__cntrl_)
|
||||
|
@ -4164,7 +4202,7 @@ template<class _Tp>
|
|||
template<class _Yp>
|
||||
inline
|
||||
shared_ptr<_Tp>::shared_ptr(shared_ptr<_Yp>&& __r,
|
||||
typename enable_if<is_convertible<_Yp*, element_type*>::value, __nat>::type)
|
||||
typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type)
|
||||
_NOEXCEPT
|
||||
: __ptr_(__r.__ptr_),
|
||||
__cntrl_(__r.__cntrl_)
|
||||
|
@ -4276,7 +4314,7 @@ template<class _Yp>
|
|||
inline
|
||||
typename enable_if
|
||||
<
|
||||
is_convertible<_Yp*, typename shared_ptr<_Tp>::element_type*>::value,
|
||||
__compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value,
|
||||
shared_ptr<_Tp>&
|
||||
>::type
|
||||
shared_ptr<_Tp>::operator=(const shared_ptr<_Yp>& __r) _NOEXCEPT
|
||||
|
@ -4301,7 +4339,7 @@ template<class _Yp>
|
|||
inline
|
||||
typename enable_if
|
||||
<
|
||||
is_convertible<_Yp*, typename shared_ptr<_Tp>::element_type*>::value,
|
||||
__compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value,
|
||||
shared_ptr<_Tp>&
|
||||
>::type
|
||||
shared_ptr<_Tp>::operator=(shared_ptr<_Yp>&& __r)
|
||||
|
@ -4402,7 +4440,7 @@ template<class _Yp>
|
|||
inline
|
||||
typename enable_if
|
||||
<
|
||||
is_convertible<_Yp*, typename shared_ptr<_Tp>::element_type*>::value,
|
||||
__compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value,
|
||||
void
|
||||
>::type
|
||||
shared_ptr<_Tp>::reset(_Yp* __p)
|
||||
|
@ -4415,7 +4453,7 @@ template<class _Yp, class _Dp>
|
|||
inline
|
||||
typename enable_if
|
||||
<
|
||||
is_convertible<_Yp*, typename shared_ptr<_Tp>::element_type*>::value,
|
||||
__compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value,
|
||||
void
|
||||
>::type
|
||||
shared_ptr<_Tp>::reset(_Yp* __p, _Dp __d)
|
||||
|
@ -4428,7 +4466,7 @@ template<class _Yp, class _Dp, class _Alloc>
|
|||
inline
|
||||
typename enable_if
|
||||
<
|
||||
is_convertible<_Yp*, typename shared_ptr<_Tp>::element_type*>::value,
|
||||
__compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value,
|
||||
void
|
||||
>::type
|
||||
shared_ptr<_Tp>::reset(_Yp* __p, _Dp __d, _Alloc __a)
|
||||
|
@ -4642,41 +4680,41 @@ swap(shared_ptr<_Tp>& __x, shared_ptr<_Tp>& __y) _NOEXCEPT
|
|||
|
||||
template<class _Tp, class _Up>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
typename enable_if
|
||||
<
|
||||
!is_array<_Tp>::value && !is_array<_Up>::value,
|
||||
shared_ptr<_Tp>
|
||||
>::type
|
||||
shared_ptr<_Tp>
|
||||
static_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT
|
||||
{
|
||||
return shared_ptr<_Tp>(__r, static_cast<_Tp*>(__r.get()));
|
||||
return shared_ptr<_Tp>(__r,
|
||||
static_cast<
|
||||
typename shared_ptr<_Tp>::element_type*>(__r.get()));
|
||||
}
|
||||
|
||||
template<class _Tp, class _Up>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
typename enable_if
|
||||
<
|
||||
!is_array<_Tp>::value && !is_array<_Up>::value,
|
||||
shared_ptr<_Tp>
|
||||
>::type
|
||||
shared_ptr<_Tp>
|
||||
dynamic_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT
|
||||
{
|
||||
_Tp* __p = dynamic_cast<_Tp*>(__r.get());
|
||||
typedef typename shared_ptr<_Tp>::element_type _ET;
|
||||
_ET* __p = dynamic_cast<_ET*>(__r.get());
|
||||
return __p ? shared_ptr<_Tp>(__r, __p) : shared_ptr<_Tp>();
|
||||
}
|
||||
|
||||
template<class _Tp, class _Up>
|
||||
typename enable_if
|
||||
<
|
||||
is_array<_Tp>::value == is_array<_Up>::value,
|
||||
shared_ptr<_Tp>
|
||||
>::type
|
||||
shared_ptr<_Tp>
|
||||
const_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT
|
||||
{
|
||||
typedef typename remove_extent<_Tp>::type _RTp;
|
||||
typedef typename shared_ptr<_Tp>::element_type _RTp;
|
||||
return shared_ptr<_Tp>(__r, const_cast<_RTp*>(__r.get()));
|
||||
}
|
||||
|
||||
template<class _Tp, class _Up>
|
||||
shared_ptr<_Tp>
|
||||
reinterpret_pointer_cast(const shared_ptr<_Up>& __r) _NOEXCEPT
|
||||
{
|
||||
return shared_ptr<_Tp>(__r,
|
||||
reinterpret_cast<
|
||||
typename shared_ptr<_Tp>::element_type*>(__r.get()));
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_NO_RTTI
|
||||
|
||||
template<class _Dp, class _Tp>
|
||||
|
@ -5080,7 +5118,7 @@ struct _LIBCPP_TEMPLATE_VIS hash<shared_ptr<_Tp> >
|
|||
_LIBCPP_INLINE_VISIBILITY
|
||||
result_type operator()(const argument_type& __ptr) const _NOEXCEPT
|
||||
{
|
||||
return hash<_Tp*>()(__ptr.get());
|
||||
return hash<typename shared_ptr<_Tp>::element_type*>()(__ptr.get());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -20,14 +20,42 @@
|
|||
|
||||
#include "test_macros.h"
|
||||
|
||||
struct A; // purposefully incomplete
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
static_assert((std::is_same<std::shared_ptr<A>::element_type, A>::value), "");
|
||||
#if TEST_STD_VER > 14
|
||||
static_assert((std::is_same<std::shared_ptr<A>::weak_type, std::weak_ptr<A>>::value), "");
|
||||
template <typename T, typename = std::void_t<> >
|
||||
struct has_less : std::false_type {};
|
||||
|
||||
template <typename T>
|
||||
struct has_less<T,
|
||||
std::void_t<decltype(std::declval<T>() < std::declval<T>())> >
|
||||
: std::true_type {};
|
||||
#endif
|
||||
|
||||
struct A; // purposefully incomplete
|
||||
struct B {
|
||||
int x;
|
||||
B() = default;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void test() {
|
||||
ASSERT_SAME_TYPE(typename std::shared_ptr<T>::element_type, T);
|
||||
#if TEST_STD_VER > 14
|
||||
ASSERT_SAME_TYPE(typename std::shared_ptr<T>::weak_type, std::weak_ptr<T>);
|
||||
static_assert(std::is_copy_constructible<std::shared_ptr<T> >::value, "");
|
||||
static_assert(std::is_copy_assignable<std::shared_ptr<T> >::value, "");
|
||||
static_assert(has_less<std::shared_ptr<T> >::value);
|
||||
static_assert(
|
||||
std::is_same<typename std::shared_ptr<T[]>::element_type, T>::value, "");
|
||||
static_assert(
|
||||
std::is_same<typename std::shared_ptr<T[8]>::element_type, T>::value, "");
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test<A>();
|
||||
test<B>();
|
||||
test<int>();
|
||||
test<char*>();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -55,6 +55,14 @@ int main(int, char**)
|
|||
assert(pB.get() == pA.get());
|
||||
assert(!pB.owner_before(pA) && !pA.owner_before(pB));
|
||||
}
|
||||
#if TEST_STD_VER > 14
|
||||
{
|
||||
const std::shared_ptr<const A[8]> pA;
|
||||
std::shared_ptr<A[8]> pB = std::const_pointer_cast<A[8]>(pA);
|
||||
assert(pB.get() == pA.get());
|
||||
assert(!pB.owner_before(pA) && !pA.owner_before(pB));
|
||||
}
|
||||
#endif // TEST_STD_VER > 14
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -55,6 +55,14 @@ int main(int, char**)
|
|||
assert(pA.get() == 0);
|
||||
assert(pA.use_count() == 0);
|
||||
}
|
||||
#if TEST_STD_VER > 14
|
||||
{
|
||||
const std::shared_ptr<B[8]> pB(new B[8]);
|
||||
std::shared_ptr<A[8]> pA = std::dynamic_pointer_cast<A[8]>(pB);
|
||||
assert(pA.get() == 0);
|
||||
assert(pA.use_count() == 0);
|
||||
}
|
||||
#endif // TEST_STD_VER > 14
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// <memory>
|
||||
|
||||
// shared_ptr
|
||||
|
||||
// template<class T, class U>
|
||||
// shared_ptr<T> reinterpret_pointer_cast(const shared_ptr<U>& r) noexcept;
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
struct A {
|
||||
int x;
|
||||
};
|
||||
|
||||
int main(int, char**) {
|
||||
{
|
||||
const std::shared_ptr<A> pA(new A);
|
||||
std::shared_ptr<int> pi = std::reinterpret_pointer_cast<int>(pA);
|
||||
std::shared_ptr<A> pA2 = std::reinterpret_pointer_cast<A>(pi);
|
||||
assert(pA2.get() == pA.get());
|
||||
assert(!pi.owner_before(pA) && !pA.owner_before(pi));
|
||||
}
|
||||
{
|
||||
const std::shared_ptr<A> pA;
|
||||
std::shared_ptr<int> pi = std::reinterpret_pointer_cast<int>(pA);
|
||||
std::shared_ptr<A> pA2 = std::reinterpret_pointer_cast<A>(pi);
|
||||
assert(pA2.get() == pA.get());
|
||||
assert(!pi.owner_before(pA) && !pA.owner_before(pi));
|
||||
}
|
||||
#if TEST_STD_VER > 14
|
||||
{
|
||||
const std::shared_ptr<A[8]> pA;
|
||||
std::shared_ptr<int[8]> pi = std::reinterpret_pointer_cast<int[8]>(pA);
|
||||
std::shared_ptr<A[8]> pA2 = std::reinterpret_pointer_cast<A[8]>(pi);
|
||||
assert(pA2.get() == pA.get());
|
||||
assert(!pi.owner_before(pA) && !pA.owner_before(pi));
|
||||
}
|
||||
#endif // TEST_STD_VER > 14
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -67,6 +67,20 @@ int main(int, char**)
|
|||
assert(pB.get() == pA.get());
|
||||
assert(!pB.owner_before(pA) && !pA.owner_before(pB));
|
||||
}
|
||||
#if TEST_STD_VER > 14
|
||||
{
|
||||
const std::shared_ptr<A[8]> pA;
|
||||
std::shared_ptr<B[8]> pB = std::static_pointer_cast<B[8]>(pA);
|
||||
assert(pB.get() == pA.get());
|
||||
assert(!pB.owner_before(pA) && !pA.owner_before(pB));
|
||||
}
|
||||
{
|
||||
const std::shared_ptr<B[8]> pA;
|
||||
std::shared_ptr<A[8]> pB = std::static_pointer_cast<A[8]>(pA);
|
||||
assert(pB.get() == pA.get());
|
||||
assert(!pB.owner_before(pA) && !pA.owner_before(pB));
|
||||
}
|
||||
#endif // TEST_STD_VER > 14
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -15,11 +15,21 @@
|
|||
|
||||
#include "test_macros.h"
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
std::shared_ptr<int> p;
|
||||
assert(p.use_count() == 0);
|
||||
assert(p.get() == 0);
|
||||
struct A {};
|
||||
|
||||
template <class T>
|
||||
void test() {
|
||||
std::shared_ptr<T> p;
|
||||
assert(p.use_count() == 0);
|
||||
assert(p.get() == 0);
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test<int>();
|
||||
test<A>();
|
||||
test<int*>();
|
||||
test<int[]>();
|
||||
test<int[8]>();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -45,5 +45,21 @@ int main(int, char**)
|
|||
}
|
||||
assert(A::count == 0);
|
||||
|
||||
return 0;
|
||||
#if TEST_STD_VER > 14
|
||||
{
|
||||
std::shared_ptr<A[8]> pA(new A[8]);
|
||||
assert(pA.use_count() == 1);
|
||||
assert(A::count == 8);
|
||||
}
|
||||
assert(A::count == 0);
|
||||
|
||||
{
|
||||
std::shared_ptr<A[]> pA(new A[8]);
|
||||
assert(pA.use_count() == 1);
|
||||
assert(A::count == 8);
|
||||
}
|
||||
assert(A::count == 0);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// <memory>
|
||||
|
||||
// shared_ptr
|
||||
|
||||
// template<class Y> shared_ptr(const shared_ptr<Y>& r);
|
||||
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
struct A {
|
||||
int x = 42;
|
||||
};
|
||||
|
||||
struct ADel : std::default_delete<A> {
|
||||
typedef A* pointer;
|
||||
};
|
||||
|
||||
int main(int, char**) {
|
||||
static_assert(!(std::is_convertible<A, int>::value), "");
|
||||
|
||||
{
|
||||
std::shared_ptr<A> pA;
|
||||
std::shared_ptr<int> pi(pA); // expected-error {{no matching constructor for initialization of 'std::shared_ptr<int>'}}
|
||||
}
|
||||
{
|
||||
std::shared_ptr<A> pA;
|
||||
std::shared_ptr<int> pi(std::move(pA)); // expected-error {{no matching constructor for initialization of 'std::shared_ptr<int>'}}
|
||||
}
|
||||
{
|
||||
std::weak_ptr<A> pA;
|
||||
std::shared_ptr<int> pi(std::move(pA)); // expected-error {{no matching constructor for initialization of 'std::shared_ptr<int>'}}
|
||||
}
|
||||
|
||||
#if TEST_STD_VER > 14
|
||||
{
|
||||
std::unique_ptr<int, ADel> ui;
|
||||
std::shared_ptr<int> pi(std::move(ui)); // expected-error {{no matching constructor for initialization of 'std::shared_ptr<int>'}}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -44,6 +44,7 @@ int main(int, char**)
|
|||
{
|
||||
std::shared_ptr<A> pA(new A);
|
||||
assert(pA.use_count() == 1);
|
||||
|
||||
{
|
||||
B b;
|
||||
std::shared_ptr<B> pB(pA, &b);
|
||||
|
@ -60,5 +61,38 @@ int main(int, char**)
|
|||
assert(A::count == 0);
|
||||
assert(B::count == 0);
|
||||
|
||||
return 0;
|
||||
{
|
||||
std::shared_ptr<int> p1(nullptr);
|
||||
std::shared_ptr<int> p2(p1, new int);
|
||||
assert(p2.get() != nullptr);
|
||||
}
|
||||
{
|
||||
std::shared_ptr<int> p1(new int);
|
||||
std::shared_ptr<int> p2(p1, nullptr);
|
||||
assert(p2.get() == nullptr);
|
||||
}
|
||||
|
||||
#if TEST_STD_VER > 17
|
||||
{
|
||||
std::shared_ptr<A> pA(new A);
|
||||
assert(pA.use_count() == 1);
|
||||
|
||||
{
|
||||
B b;
|
||||
std::shared_ptr<B> pB(std::move(pA), &b);
|
||||
assert(A::count == 1);
|
||||
assert(B::count == 1);
|
||||
assert(pA.use_count() == 2);
|
||||
assert(pB.use_count() == 2);
|
||||
assert(pB.get() == &b);
|
||||
}
|
||||
assert(pA.use_count() == 1);
|
||||
assert(A::count == 1);
|
||||
assert(B::count == 0);
|
||||
}
|
||||
assert(A::count == 0);
|
||||
assert(B::count == 0);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -56,6 +56,19 @@ struct D {
|
|||
void ref(D);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct StatefulDeleter {
|
||||
int state = 0;
|
||||
|
||||
StatefulDeleter(int val = 0) : state(val) {}
|
||||
StatefulDeleter(StatefulDeleter const&) { assert(false); }
|
||||
|
||||
void operator()(T* ptr) {
|
||||
assert(state == 42);
|
||||
delete ptr;
|
||||
}
|
||||
};
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
{
|
||||
|
@ -90,11 +103,29 @@ int main(int, char**)
|
|||
assert(A::count == 0);
|
||||
assert(B::count == 0);
|
||||
assert(ptr.get() == 0);
|
||||
#endif
|
||||
#endif // TEST_STD_VER >= 11
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TEST_STD_VER > 14
|
||||
{
|
||||
std::unique_ptr<int> ptr;
|
||||
std::shared_ptr<int> p(std::move(ptr));
|
||||
assert(p.get() == 0);
|
||||
assert(p.use_count() == 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
StatefulDeleter<A> d;
|
||||
std::unique_ptr<A, StatefulDeleter<A>&> u(new A, d);
|
||||
std::shared_ptr<A> p(std::move(u));
|
||||
d.state = 42;
|
||||
assert(A::count == 1);
|
||||
}
|
||||
assert(A::count == 0);
|
||||
|
||||
{ // LWG 2399
|
||||
fn(std::unique_ptr<int>(new int));
|
||||
}
|
||||
|
|
|
@ -27,7 +27,8 @@ protected:
|
|||
|
||||
int main(int, char**)
|
||||
{
|
||||
std::shared_ptr<S> p = std::make_shared<S>(); // expected-error-re@memory:* {{static_assert failed{{.*}} "Can't construct object in make_shared"}}
|
||||
std::shared_ptr<S> p = std::make_shared<
|
||||
S>(); // expected-error@memory:* {{static_assert failed due to requirement 'is_constructible<S>::value' "Can't construct object in make_shared"}}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// <memory>
|
||||
|
||||
// UNSUPPORTED: c++98, c++03, c++11, c++14
|
||||
|
||||
// shared_ptr
|
||||
|
||||
// element_type& operator[](ptrdiff_t i) const;
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
#include <memory>
|
||||
#include <cassert>
|
||||
|
||||
struct Foo {
|
||||
void call() {}
|
||||
};
|
||||
|
||||
int main(int, char**) {
|
||||
// Check that we get a static assertion when we try to use the bracket
|
||||
// operator on shared_ptr<T> when T is not an array type.
|
||||
const std::shared_ptr<Foo[]> p1;
|
||||
(void)p1
|
||||
->call(); // expected-error@memory:* {{std::shared_ptr<T>::operator-> is only valid when T is not an array type.}}
|
||||
const std::shared_ptr<Foo[4]> p2;
|
||||
(void)p2
|
||||
->call(); // expected-error@memory:* {{std::shared_ptr<T>::operator-> is only valid when T is not an array type.}}
|
||||
return 0;
|
||||
}
|
|
@ -17,16 +17,27 @@
|
|||
|
||||
#include "test_macros.h"
|
||||
|
||||
struct A {
|
||||
int a;
|
||||
virtual ~A(){};
|
||||
};
|
||||
struct B : A {};
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
{
|
||||
const std::shared_ptr<int> p(new int(32));
|
||||
assert(p);
|
||||
const std::shared_ptr<int> p(new int(32));
|
||||
assert(p);
|
||||
}
|
||||
{
|
||||
const std::shared_ptr<int> p;
|
||||
assert(!p);
|
||||
const std::shared_ptr<int> p;
|
||||
assert(!p);
|
||||
}
|
||||
{
|
||||
std::shared_ptr<A> basePtr = std::make_shared<B>();
|
||||
std::shared_ptr<B> sp = std::dynamic_pointer_cast<B>(basePtr);
|
||||
assert(sp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// <memory>
|
||||
|
||||
// UNSUPPORTED: c++98, c++03, c++11, c++14
|
||||
|
||||
// shared_ptr
|
||||
|
||||
// element_type& operator[](ptrdiff_t i) const;
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
#include <memory>
|
||||
#include <cassert>
|
||||
|
||||
int main(int, char**) {
|
||||
// Check that we get a static assertion when we try to use the bracket
|
||||
// operator on shared_ptr<T> when T is not an array type.
|
||||
const std::shared_ptr<int> p;
|
||||
(void)p
|
||||
[0]; // expected-error@memory:* {{std::shared_ptr<T>::operator[] is only valid when T is an array type.}}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// <memory>
|
||||
|
||||
// UNSUPPORTED: c++98, c++03, c++11, c++14
|
||||
|
||||
// shared_ptr
|
||||
|
||||
// element_type& operator[](ptrdiff_t i) const;
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
#include <memory>
|
||||
#include <cassert>
|
||||
|
||||
int main(int, char**) {
|
||||
{
|
||||
const std::shared_ptr<int[8]> p(new int[8]);
|
||||
|
||||
for (int i = 0; i < 8; ++i)
|
||||
p[i] = i;
|
||||
for (int i = 0; i < 8; ++i)
|
||||
assert(p[i] == i);
|
||||
}
|
||||
{
|
||||
int* iptr = new int[8];
|
||||
for (int i = 0; i < 8; ++i)
|
||||
iptr[i] = i;
|
||||
|
||||
const std::shared_ptr<int[8]> p(iptr);
|
||||
|
||||
for (int i = 0; i < 8; ++i)
|
||||
assert(p[i] == i);
|
||||
}
|
||||
{
|
||||
const std::shared_ptr<int[]> p(new int[8]);
|
||||
|
||||
for (int i = 0; i < 8; ++i)
|
||||
p[i] = i;
|
||||
for (int i = 0; i < 8; ++i)
|
||||
assert(p[i] == i);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -45,6 +45,7 @@ int main(int, char**)
|
|||
{
|
||||
{
|
||||
const std::shared_ptr<A> pA(new A);
|
||||
assert(pA.use_count() == 1);
|
||||
{
|
||||
std::weak_ptr<B> pB;
|
||||
pB = pA;
|
||||
|
|
|
@ -128,7 +128,7 @@
|
|||
<tr><td><a href="https://wg21.link/P0003R5">P0003R5</a></td><td>LWG</td><td>Removing Deprecated Exception Specifications from C++17</td><td>Issaquah</td><td>Complete</td><td>5.0</td></tr>
|
||||
<tr><td><a href="https://wg21.link/P0067R5">P0067R5</a></td><td>LWG</td><td>Elementary string conversions, revision 5</td><td>Issaquah</td><td><i>Partially done</i></td><td></td></tr>
|
||||
<tr><td><a href="https://wg21.link/P0403R1">P0403R1</a></td><td>LWG</td><td>Literal suffixes for <tt>basic_string_view</tt></td><td>Issaquah</td><td>Complete</td><td>4.0</td></tr>
|
||||
<tr><td><a href="https://wg21.link/P0414R2">P0414R2</a></td><td>LWG</td><td>Merging shared_ptr changes from Library Fundamentals to C++17</td><td>Issaquah</td><td></td><td></td></tr>
|
||||
<tr><td><a href="https://wg21.link/P0414R2">P0414R2</a></td><td>LWG</td><td>Merging shared_ptr changes from Library Fundamentals to C++17</td><td>Issaquah</td><td>Complete</td><td>11.0</td></tr>
|
||||
<tr><td><a href="https://wg21.link/P0418R2">P0418R2</a></td><td>LWG</td><td>Fail or succeed: there is no atomic lattice</td><td>Issaquah</td><td></td><td></td></tr>
|
||||
<tr><td><a href="https://wg21.link/P0426R1">P0426R1</a></td><td>LWG</td><td>Constexpr for <tt>std::char_traits</tt></td><td>Issaquah</td><td>Complete</td><td>4.0</td></tr>
|
||||
<tr><td><a href="https://wg21.link/P0435R1">P0435R1</a></td><td>LWG</td><td>Resolving LWG Issues re <tt>common_type</tt></td><td>Issaquah</td><td>Complete</td><td>4.0</td></tr>
|
||||
|
|
Loading…
Reference in New Issue