[libc++] LWG3001: add `remove_extent_t` to `weak_ptr::element_type`.

Also fix a few places in the `shared_ptr` implementation where
`element_type` was passed to the `__is_compatible` helper. This could
result in `remove_extent` being applied twice to the pointer's template
type (first by the definition of `element_type` and then by the helper),
potentially leading to somewhat less readable error messages for some
incorrect code.

Differential Revision: https://reviews.llvm.org/D112092
This commit is contained in:
Konstantin Varlamov 2021-10-25 11:15:38 -04:00 committed by Louis Dionne
parent a5435844f0
commit 065ac30026
10 changed files with 171 additions and 41 deletions

View File

@ -37,7 +37,7 @@
"`2988 <https://wg21.link/LWG2988>`__","Clause 32 cleanup missed one typename","Albuquerque","|Complete|","13.0"
"`2993 <https://wg21.link/LWG2993>`__","reference_wrapper<T> conversion from T&&","Albuquerque","|Complete|","13.0"
"`2998 <https://wg21.link/LWG2998>`__","Requirements on function objects passed to {``forward_``,}list-specific algorithms","Albuquerque","|Nothing To Do|",""
"`3001 <https://wg21.link/LWG3001>`__","weak_ptr::element_type needs remove_extent_t","Albuquerque","",""
"`3001 <https://wg21.link/LWG3001>`__","weak_ptr::element_type needs remove_extent_t","Albuquerque","|Complete|","14.0"
"`3024 <https://wg21.link/LWG3024>`__","variant's copies must be deleted instead of disabled via SFINAE","Albuquerque","|Complete|",""
"","","","",""
"`2164 <https://wg21.link/LWG2164>`__","What are the semantics of ``vector.emplace(vector.begin(), vector.back())``\ ?","Jacksonville","|Complete|",""

Can't render this file because it has a wrong number of fields in line 2.

View File

@ -471,15 +471,15 @@ public:
template<class _Yp>
_LIBCPP_INLINE_VISIBILITY
shared_ptr(const shared_ptr<_Yp>& __r,
typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type = __nat())
typename enable_if<__compatible_with<_Yp, _Tp>::value, __nat>::type = __nat())
_NOEXCEPT;
_LIBCPP_INLINE_VISIBILITY
shared_ptr(shared_ptr&& __r) _NOEXCEPT;
template<class _Yp> _LIBCPP_INLINE_VISIBILITY shared_ptr(shared_ptr<_Yp>&& __r,
typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type = __nat())
typename enable_if<__compatible_with<_Yp, _Tp>::value, __nat>::type = __nat())
_NOEXCEPT;
template<class _Yp> explicit shared_ptr(const weak_ptr<_Yp>& __r,
typename enable_if<is_convertible<_Yp*, element_type*>::value, __nat>::type= __nat());
typename enable_if<__compatible_with<_Yp, _Tp>::value, __nat>::type = __nat());
#if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR)
template<class _Yp>
shared_ptr(auto_ptr<_Yp>&& __r,
@ -509,7 +509,7 @@ public:
template<class _Yp>
typename enable_if
<
__compatible_with<_Yp, element_type>::value,
__compatible_with<_Yp, _Tp>::value,
shared_ptr&
>::type
_LIBCPP_INLINE_VISIBILITY
@ -519,7 +519,7 @@ public:
template<class _Yp>
typename enable_if
<
__compatible_with<_Yp, element_type>::value,
__compatible_with<_Yp, _Tp>::value,
shared_ptr&
>::type
_LIBCPP_INLINE_VISIBILITY
@ -551,7 +551,7 @@ public:
template<class _Yp>
typename enable_if
<
__compatible_with<_Yp, element_type>::value,
__compatible_with<_Yp, _Tp>::value,
void
>::type
_LIBCPP_INLINE_VISIBILITY
@ -559,7 +559,7 @@ public:
template<class _Yp, class _Dp>
typename enable_if
<
__compatible_with<_Yp, element_type>::value,
__compatible_with<_Yp, _Tp>::value,
void
>::type
_LIBCPP_INLINE_VISIBILITY
@ -567,7 +567,7 @@ public:
template<class _Yp, class _Dp, class _Alloc>
typename enable_if
<
__compatible_with<_Yp, element_type>::value,
__compatible_with<_Yp, _Tp>::value,
void
>::type
_LIBCPP_INLINE_VISIBILITY
@ -683,7 +683,7 @@ private:
template <class _Up> friend class _LIBCPP_TEMPLATE_VIS weak_ptr;
};
#if _LIBCPP_STD_VER >= 17
#if _LIBCPP_STD_VER > 14
template<class _Tp>
shared_ptr(weak_ptr<_Tp>) -> shared_ptr<_Tp>;
template<class _Tp, class _Dp>
@ -851,7 +851,7 @@ template<class _Tp>
template<class _Yp>
inline
shared_ptr<_Tp>::shared_ptr(const shared_ptr<_Yp>& __r,
typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type)
typename enable_if<__compatible_with<_Yp, _Tp>::value, __nat>::type)
_NOEXCEPT
: __ptr_(__r.__ptr_),
__cntrl_(__r.__cntrl_)
@ -874,7 +874,7 @@ template<class _Tp>
template<class _Yp>
inline
shared_ptr<_Tp>::shared_ptr(shared_ptr<_Yp>&& __r,
typename enable_if<__compatible_with<_Yp, element_type>::value, __nat>::type)
typename enable_if<__compatible_with<_Yp, _Tp>::value, __nat>::type)
_NOEXCEPT
: __ptr_(__r.__ptr_),
__cntrl_(__r.__cntrl_)
@ -970,7 +970,7 @@ template<class _Yp>
inline
typename enable_if
<
__compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value,
__compatible_with<_Yp, _Tp>::value,
shared_ptr<_Tp>&
>::type
shared_ptr<_Tp>::operator=(const shared_ptr<_Yp>& __r) _NOEXCEPT
@ -993,7 +993,7 @@ template<class _Yp>
inline
typename enable_if
<
__compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value,
__compatible_with<_Yp, _Tp>::value,
shared_ptr<_Tp>&
>::type
shared_ptr<_Tp>::operator=(shared_ptr<_Yp>&& __r)
@ -1056,7 +1056,7 @@ template<class _Yp>
inline
typename enable_if
<
__compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value,
__compatible_with<_Yp, _Tp>::value,
void
>::type
shared_ptr<_Tp>::reset(_Yp* __p)
@ -1069,7 +1069,7 @@ template<class _Yp, class _Dp>
inline
typename enable_if
<
__compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value,
__compatible_with<_Yp, _Tp>::value,
void
>::type
shared_ptr<_Tp>::reset(_Yp* __p, _Dp __d)
@ -1082,7 +1082,7 @@ template<class _Yp, class _Dp, class _Alloc>
inline
typename enable_if
<
__compatible_with<_Yp, typename shared_ptr<_Tp>::element_type>::value,
__compatible_with<_Yp, _Tp>::value,
void
>::type
shared_ptr<_Tp>::reset(_Yp* __p, _Dp __d, _Alloc __a)
@ -1323,7 +1323,12 @@ template<class _Tp>
class _LIBCPP_SHARED_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS weak_ptr
{
public:
#if _LIBCPP_STD_VER > 14
typedef remove_extent_t<_Tp> element_type;
#else
typedef _Tp element_type;
#endif
private:
element_type* __ptr_;
__shared_weak_count* __cntrl_;
@ -1332,18 +1337,18 @@ public:
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_CONSTEXPR weak_ptr() _NOEXCEPT;
template<class _Yp> _LIBCPP_INLINE_VISIBILITY weak_ptr(shared_ptr<_Yp> const& __r,
typename enable_if<is_convertible<_Yp*, _Tp*>::value, __nat*>::type = 0)
typename enable_if<__compatible_with<_Yp, _Tp>::value, __nat*>::type = 0)
_NOEXCEPT;
_LIBCPP_INLINE_VISIBILITY
weak_ptr(weak_ptr const& __r) _NOEXCEPT;
template<class _Yp> _LIBCPP_INLINE_VISIBILITY weak_ptr(weak_ptr<_Yp> const& __r,
typename enable_if<is_convertible<_Yp*, _Tp*>::value, __nat*>::type = 0)
typename enable_if<__compatible_with<_Yp, _Tp>::value, __nat*>::type = 0)
_NOEXCEPT;
_LIBCPP_INLINE_VISIBILITY
weak_ptr(weak_ptr&& __r) _NOEXCEPT;
template<class _Yp> _LIBCPP_INLINE_VISIBILITY weak_ptr(weak_ptr<_Yp>&& __r,
typename enable_if<is_convertible<_Yp*, _Tp*>::value, __nat*>::type = 0)
typename enable_if<__compatible_with<_Yp, _Tp>::value, __nat*>::type = 0)
_NOEXCEPT;
~weak_ptr();
@ -1352,7 +1357,7 @@ public:
template<class _Yp>
typename enable_if
<
is_convertible<_Yp*, element_type*>::value,
__compatible_with<_Yp, _Tp>::value,
weak_ptr&
>::type
_LIBCPP_INLINE_VISIBILITY
@ -1363,7 +1368,7 @@ public:
template<class _Yp>
typename enable_if
<
is_convertible<_Yp*, element_type*>::value,
__compatible_with<_Yp, _Tp>::value,
weak_ptr&
>::type
_LIBCPP_INLINE_VISIBILITY
@ -1372,7 +1377,7 @@ public:
template<class _Yp>
typename enable_if
<
is_convertible<_Yp*, element_type*>::value,
__compatible_with<_Yp, _Tp>::value,
weak_ptr&
>::type
_LIBCPP_INLINE_VISIBILITY
@ -1403,7 +1408,7 @@ public:
template <class _Up> friend class _LIBCPP_TEMPLATE_VIS shared_ptr;
};
#if _LIBCPP_STD_VER >= 17
#if _LIBCPP_STD_VER > 14
template<class _Tp>
weak_ptr(shared_ptr<_Tp>) -> weak_ptr<_Tp>;
#endif
@ -1431,7 +1436,7 @@ template<class _Tp>
template<class _Yp>
inline
weak_ptr<_Tp>::weak_ptr(shared_ptr<_Yp> const& __r,
typename enable_if<is_convertible<_Yp*, _Tp*>::value, __nat*>::type)
typename enable_if<__compatible_with<_Yp, _Tp>::value, __nat*>::type)
_NOEXCEPT
: __ptr_(__r.__ptr_),
__cntrl_(__r.__cntrl_)
@ -1444,7 +1449,7 @@ template<class _Tp>
template<class _Yp>
inline
weak_ptr<_Tp>::weak_ptr(weak_ptr<_Yp> const& __r,
typename enable_if<is_convertible<_Yp*, _Tp*>::value, __nat*>::type)
typename enable_if<__compatible_with<_Yp, _Tp>::value, __nat*>::type)
_NOEXCEPT
: __ptr_(__r.__ptr_),
__cntrl_(__r.__cntrl_)
@ -1467,7 +1472,7 @@ template<class _Tp>
template<class _Yp>
inline
weak_ptr<_Tp>::weak_ptr(weak_ptr<_Yp>&& __r,
typename enable_if<is_convertible<_Yp*, _Tp*>::value, __nat*>::type)
typename enable_if<__compatible_with<_Yp, _Tp>::value, __nat*>::type)
_NOEXCEPT
: __ptr_(__r.__ptr_),
__cntrl_(__r.__cntrl_)
@ -1497,7 +1502,7 @@ template<class _Yp>
inline
typename enable_if
<
is_convertible<_Yp*, _Tp*>::value,
__compatible_with<_Yp, _Tp>::value,
weak_ptr<_Tp>&
>::type
weak_ptr<_Tp>::operator=(weak_ptr<_Yp> const& __r) _NOEXCEPT
@ -1520,7 +1525,7 @@ template<class _Yp>
inline
typename enable_if
<
is_convertible<_Yp*, _Tp*>::value,
__compatible_with<_Yp, _Tp>::value,
weak_ptr<_Tp>&
>::type
weak_ptr<_Tp>::operator=(weak_ptr<_Yp>&& __r) _NOEXCEPT
@ -1534,7 +1539,7 @@ template<class _Yp>
inline
typename enable_if
<
is_convertible<_Yp*, _Tp*>::value,
__compatible_with<_Yp, _Tp>::value,
weak_ptr<_Tp>&
>::type
weak_ptr<_Tp>::operator=(shared_ptr<_Yp> const& __r) _NOEXCEPT
@ -1571,7 +1576,7 @@ weak_ptr<_Tp>::reset() _NOEXCEPT
template<class _Tp>
template<class _Yp>
shared_ptr<_Tp>::shared_ptr(const weak_ptr<_Yp>& __r,
typename enable_if<is_convertible<_Yp*, element_type*>::value, __nat>::type)
typename enable_if<__compatible_with<_Yp, _Tp>::value, __nat>::type)
: __ptr_(__r.__ptr_),
__cntrl_(__r.__cntrl_ ? __r.__cntrl_->lock() : __r.__cntrl_)
{

View File

@ -405,7 +405,8 @@ template<class T>
class shared_ptr
{
public:
typedef T element_type;
typedef T element_type; // until C++17
typedef remove_extent_t<T> element_type; // since C++17
typedef weak_ptr<T> weak_type; // C++17
// constructors:
@ -525,7 +526,8 @@ template<class T>
class weak_ptr
{
public:
typedef T element_type;
typedef T element_type; // until C++17
typedef remove_extent_t<T> element_type; // since C++17
// constructors
constexpr weak_ptr() noexcept;

View File

@ -11,12 +11,14 @@
// template<class T> class shared_ptr
// {
// public:
// typedef T element_type;
// typedef T element_type; // until C++17
// typedef remove_extent_t<T> element_type; // since C++17
// typedef weak_ptr<T> weak_type; // C++17
// ...
// };
#include <memory>
#include <type_traits>
#include "test_macros.h"
@ -44,10 +46,8 @@ void test() {
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, "");
ASSERT_SAME_TYPE(typename std::shared_ptr<T[]>::element_type, T);
ASSERT_SAME_TYPE(typename std::shared_ptr<T[8]>::element_type, T);
#endif
}
@ -57,5 +57,9 @@ int main(int, char**) {
test<int>();
test<char*>();
#if TEST_STD_VER > 14
ASSERT_SAME_TYPE(typename std::shared_ptr<int[][2]>::element_type, int[2]);
#endif
return 0;
}

View File

@ -82,5 +82,17 @@ int main(int, char**)
assert(A::count == 0);
#endif
#if TEST_STD_VER > 14
{
std::shared_ptr<A[]> sp0(new A[8]);
std::weak_ptr<A[]> wp(sp0);
std::shared_ptr<const A[]> sp(wp);
assert(sp.use_count() == 2);
assert(sp.get() == sp0.get());
assert(A::count == 8);
}
assert(A::count == 0);
#endif
return 0;
}

View File

@ -11,19 +11,41 @@
// template<class T> class weak_ptr
// {
// public:
// typedef T element_type;
// typedef T element_type; // until C++17
// typedef remove_extent_t<T> element_type; // since C++17
// ...
// };
#include <memory>
#include <type_traits>
#include "test_macros.h"
struct A; // purposefully incomplete
struct B {
int x;
B() = default;
};
template <class T>
void test() {
ASSERT_SAME_TYPE(typename std::weak_ptr<T>::element_type, T);
#if TEST_STD_VER > 14
ASSERT_SAME_TYPE(typename std::weak_ptr<T[]>::element_type, T);
ASSERT_SAME_TYPE(typename std::weak_ptr<T[8]>::element_type, T);
#endif
}
int main(int, char**)
{
static_assert((std::is_same<std::weak_ptr<A>::element_type, A>::value), "");
test<A>();
test<B>();
test<int>();
test<char*>();
#if TEST_STD_VER > 14
ASSERT_SAME_TYPE(typename std::weak_ptr<int[][2]>::element_type, int[2]);
#endif
return 0;
}

View File

@ -61,5 +61,22 @@ int main(int, char**)
assert(B::count == 0);
assert(A::count == 0);
#if TEST_STD_VER > 14
{
const std::shared_ptr<A[]> p1(new A[8]);
assert(p1.use_count() == 1);
{
std::weak_ptr<const A[]> p2;
p2 = p1;
assert(A::count == 8);
assert(p2.use_count() == 1);
assert(p1.use_count() == 1);
}
assert(p1.use_count() == 1);
assert(A::count == 8);
}
assert(A::count == 0);
#endif
return 0;
}

View File

@ -11,9 +11,11 @@
// weak_ptr
// template<class Y> weak_ptr& operator=(const weak_ptr<Y>& r);
// template<class Y> weak_ptr& operator=(weak_ptr<Y>&& r);
#include <memory>
#include <type_traits>
#include <utility>
#include <cassert>
#include "test_macros.h"
@ -77,5 +79,35 @@ int main(int, char**)
assert(B::count == 0);
assert(A::count == 0);
#if TEST_STD_VER > 14
{
const std::shared_ptr<A[]> ps(new A[8]);
const std::weak_ptr<A[]> p1(ps);
{
std::weak_ptr<const A[]> p2;
p2 = p1;
assert(A::count == 8);
assert(p2.use_count() == 1);
assert(p1.use_count() == 1);
}
assert(p1.use_count() == 1);
assert(A::count == 8);
}
assert(A::count == 0);
{
const std::shared_ptr<A[]> ps(new A[8]);
std::weak_ptr<A[]> p1(ps);
{
std::weak_ptr<const A[]> p2;
p2 = std::move(p1);
assert(A::count == 8);
assert(p2.use_count() == 1);
}
assert(A::count == 8);
}
assert(A::count == 0);
#endif
return 0;
}

View File

@ -94,5 +94,22 @@ int main(int, char**)
assert(B::count == 0);
assert(A::count == 0);
#if TEST_STD_VER > 14
{
std::shared_ptr<A[]> p1(new A[8]);
assert(p1.use_count() == 1);
assert(A::count == 8);
{
std::weak_ptr<const A[]> p2(p1);
assert(A::count == 8);
assert(p2.use_count() == 1);
assert(p1.use_count() == 1);
}
assert(p1.use_count() == 1);
assert(A::count == 8);
}
assert(A::count == 0);
#endif
return 0;
}

View File

@ -11,10 +11,11 @@
// weak_ptr
// template<class Y> weak_ptr(const weak_ptr<Y>& r);
// template<class Y> weak_ptr(weak_ptr<Y> &&r);
// template<class Y> weak_ptr(weak_ptr<Y>&& r);
#include <memory>
#include <type_traits>
#include <utility>
#include <cassert>
#include "test_macros.h"
@ -107,5 +108,23 @@ int main(int, char**)
assert(B::count == 0);
assert(A::count == 0);
#if TEST_STD_VER > 14
{
std::shared_ptr<A[]> ps(new A[8]);
std::weak_ptr<A[]> p1 = source(ps);
std::weak_ptr<const A[]> p2(p1);
assert(p2.use_count() == 1);
}
assert(A::count == 0);
{
std::shared_ptr<A[]> ps(new A[8]);
std::weak_ptr<A[]> p1 = source(ps);
std::weak_ptr<const A[]> p2(std::move(p1));
assert(p2.use_count() == 1);
}
assert(A::count == 0);
#endif
return 0;
}