forked from OSchip/llvm-project
[libc++] Fix LWG 2874: Constructor shared_ptr::shared_ptr(Y*) should be constrained.
This patch fixes LWG2874. It is based on the original patch by Zoe Carver originally uploaded at D81417. Differential Revision: https://reviews.llvm.org/D81417
This commit is contained in:
parent
caa159f044
commit
1f8a6dcf12
|
@ -299,7 +299,7 @@
|
|||
"`2868 <https://wg21.link/LWG2868>`__","Missing specification of bad_any_cast::what()","Kona","|Complete|",""
|
||||
"`2872 <https://wg21.link/LWG2872>`__","Add definition for direct-non-list-initialization","Kona","|Complete|",""
|
||||
"`2873 <https://wg21.link/LWG2873>`__","Add noexcept to several shared_ptr related functions","Kona","|Complete|",""
|
||||
"`2874 <https://wg21.link/LWG2874>`__","Constructor ``shared_ptr::shared_ptr(Y*)``\ should be constrained","Kona","",""
|
||||
"`2874 <https://wg21.link/LWG2874>`__","Constructor ``shared_ptr::shared_ptr(Y*)``\ should be constrained","Kona","|Complete|","13.0"
|
||||
"`2875 <https://wg21.link/LWG2875>`__","shared_ptr::shared_ptr(Y\*, D, [|hellip|\ ]) constructors should be constrained","Kona","|Complete|",""
|
||||
"`2876 <https://wg21.link/LWG2876>`__","``shared_ptr::shared_ptr(const weak_ptr<Y>&)``\ constructor should be constrained","Kona","",""
|
||||
"`2878 <https://wg21.link/LWG2878>`__","Missing DefaultConstructible requirement for istream_iterator default constructor","Kona","|Complete|",""
|
||||
|
|
|
|
@ -379,6 +379,16 @@ struct __compatible_with
|
|||
: is_convertible<_Tp*, _Up*> {};
|
||||
#endif // _LIBCPP_STD_VER > 14
|
||||
|
||||
template <class _Ptr, class = void>
|
||||
struct __is_deletable : false_type { };
|
||||
template <class _Ptr>
|
||||
struct __is_deletable<_Ptr, decltype(delete _VSTD::declval<_Ptr>())> : true_type { };
|
||||
|
||||
template <class _Ptr, class = void>
|
||||
struct __is_array_deletable : false_type { };
|
||||
template <class _Ptr>
|
||||
struct __is_array_deletable<_Ptr, decltype(delete[] _VSTD::declval<_Ptr>())> : true_type { };
|
||||
|
||||
template <class _Dp, class _Pt,
|
||||
class = decltype(_VSTD::declval<_Dp>()(_VSTD::declval<_Pt>()))>
|
||||
static true_type __well_formed_deleter_test(int);
|
||||
|
@ -424,9 +434,27 @@ public:
|
|||
_LIBCPP_CONSTEXPR shared_ptr() _NOEXCEPT;
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_CONSTEXPR shared_ptr(nullptr_t) _NOEXCEPT;
|
||||
template<class _Yp>
|
||||
explicit shared_ptr(_Yp* __p,
|
||||
typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type = __nat());
|
||||
|
||||
template<class _Yp, class = _EnableIf<
|
||||
_And<
|
||||
__compatible_with<_Yp, _Tp>
|
||||
// In C++03 we get errors when trying to do SFINAE with the
|
||||
// delete operator, so we always pretend that it's deletable.
|
||||
// The same happens on GCC.
|
||||
#if !defined(_LIBCPP_CXX03_LANG) && !defined(_LIBCPP_COMPILER_GCC)
|
||||
, _If<is_array<_Tp>::value, __is_array_deletable<_Yp*>, __is_deletable<_Yp*> >
|
||||
#endif
|
||||
>::value
|
||||
> >
|
||||
explicit shared_ptr(_Yp* __p) : __ptr_(__p) {
|
||||
unique_ptr<_Yp> __hold(__p);
|
||||
typedef typename __shared_ptr_default_allocator<_Yp>::type _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);
|
||||
}
|
||||
|
||||
template<class _Yp, class _Dp>
|
||||
shared_ptr(_Yp* __p, _Dp __d,
|
||||
typename enable_if<__shared_ptr_deleter_ctor_reqs<_Dp, _Yp, element_type>::value, __nat>::type = __nat());
|
||||
|
@ -678,20 +706,6 @@ shared_ptr<_Tp>::shared_ptr(nullptr_t) _NOEXCEPT
|
|||
{
|
||||
}
|
||||
|
||||
template<class _Tp>
|
||||
template<class _Yp>
|
||||
shared_ptr<_Tp>::shared_ptr(_Yp* __p,
|
||||
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*, __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);
|
||||
}
|
||||
|
||||
template<class _Tp>
|
||||
template<class _Yp, class _Dp>
|
||||
shared_ptr<_Tp>::shared_ptr(_Yp* __p, _Dp __d,
|
||||
|
|
|
@ -52,6 +52,28 @@ struct C
|
|||
|
||||
int C::count = 0;
|
||||
|
||||
class private_delete_op
|
||||
{
|
||||
static void operator delete (void *p) {
|
||||
return delete static_cast<char*>(p);
|
||||
}
|
||||
public:
|
||||
static void operator delete[] (void *p) {
|
||||
return delete[] static_cast<char*>(p);
|
||||
}
|
||||
};
|
||||
|
||||
class private_delete_arr_op
|
||||
{
|
||||
static void operator delete[] (void *p) {
|
||||
return delete[] static_cast<char*>(p);
|
||||
}
|
||||
public:
|
||||
static void operator delete (void *p) {
|
||||
return delete static_cast<char*>(p);
|
||||
}
|
||||
};
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
static_assert(( std::is_convertible<std::shared_ptr<A>, std::shared_ptr<B> >::value), "");
|
||||
|
@ -96,5 +118,19 @@ int main(int, char**)
|
|||
assert(B::count == 0);
|
||||
assert(A::count == 0);
|
||||
|
||||
return 0;
|
||||
// This should work in C++03 but we get errors when trying to do SFINAE with the delete operator.
|
||||
// GCC also complains about this.
|
||||
#if TEST_STD_VER >= 11 && !defined(TEST_COMPILER_GCC)
|
||||
{
|
||||
// LWG2874: Make sure that when T (for std::shared_ptr<T>) is an array type,
|
||||
// this constructor only participates in overload resolution when
|
||||
// `delete[] p` is well formed. And when T is not an array type,
|
||||
// this constructor only participates in overload resolution when
|
||||
// `delete p` is well formed.
|
||||
static_assert(!std::is_constructible<std::shared_ptr<private_delete_op>,
|
||||
private_delete_op*>::value, "");
|
||||
static_assert(!std::is_constructible<std::shared_ptr<private_delete_arr_op[4]>,
|
||||
private_delete_arr_op*>::value, "");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue