libstdc++: Implement constexpr std::unique_ptr for C++23 (P2273R3)
libstdc++-v3/ChangeLog: * include/bits/ptr_traits.h (__cpp_lib_constexpr_memory): Define conditionally. * include/bits/unique_ptr.h (__cpp_lib_constexpr_memory): Define for C++23. (default_delete, default_delete<T[]>, __uniq_ptr_impl) (unique_ptr, unique_ptr<T[], D>): Add constexpr to all member functions. * include/std/version (__cpp_lib_constexpr_memory): Define new value for C++23. * testsuite/20_util/unique_ptr/assign/constexpr.cc: New test. * testsuite/20_util/unique_ptr/comparison/constexpr.cc: New test. * testsuite/20_util/unique_ptr/cons/constexpr_c++20.cc: New test. * testsuite/20_util/unique_ptr/creation/constexpr.cc: New test. * testsuite/20_util/unique_ptr/modifiers/constexpr.cc: New test. * testsuite/20_util/unique_ptr/specialized_algorithms/constexpr.cc: New test.
This commit is contained in:
parent
a5cee0480c
commit
2fbdcf5e58
@ -36,7 +36,10 @@
|
||||
|
||||
#if __cplusplus > 201703L
|
||||
#include <concepts>
|
||||
#define __cpp_lib_constexpr_memory 201811L
|
||||
# ifndef __cpp_lib_constexpr_memory
|
||||
// Defined to a newer value in bits/unique_ptr.h for C++23
|
||||
# define __cpp_lib_constexpr_memory 201811L
|
||||
# endif
|
||||
namespace __gnu_debug { struct _Safe_iterator_base; }
|
||||
#endif
|
||||
|
||||
|
@ -41,6 +41,14 @@
|
||||
# include <ostream>
|
||||
#endif
|
||||
|
||||
#if __cplusplus > 202002L && __cpp_constexpr_dynamic_alloc
|
||||
# if __cpp_lib_constexpr_memory < 202202L
|
||||
// Defined with older value in bits/ptr_traits.h for C++20
|
||||
# undef __cpp_lib_constexpr_memory
|
||||
# define __cpp_lib_constexpr_memory 202202L
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
@ -72,9 +80,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
*/
|
||||
template<typename _Up,
|
||||
typename = _Require<is_convertible<_Up*, _Tp*>>>
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
default_delete(const default_delete<_Up>&) noexcept { }
|
||||
|
||||
/// Calls `delete __ptr`
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
void
|
||||
operator()(_Tp* __ptr) const
|
||||
{
|
||||
@ -108,10 +118,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
*/
|
||||
template<typename _Up,
|
||||
typename = _Require<is_convertible<_Up(*)[], _Tp(*)[]>>>
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
default_delete(const default_delete<_Up[]>&) noexcept { }
|
||||
|
||||
/// Calls `delete[] __ptr`
|
||||
template<typename _Up>
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
typename enable_if<is_convertible<_Up(*)[], _Tp(*)[]>::value>::type
|
||||
operator()(_Up* __ptr) const
|
||||
{
|
||||
@ -152,16 +164,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
" or an lvalue reference type" );
|
||||
|
||||
__uniq_ptr_impl() = default;
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
__uniq_ptr_impl(pointer __p) : _M_t() { _M_ptr() = __p; }
|
||||
|
||||
template<typename _Del>
|
||||
__uniq_ptr_impl(pointer __p, _Del&& __d)
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
__uniq_ptr_impl(pointer __p, _Del&& __d)
|
||||
: _M_t(__p, std::forward<_Del>(__d)) { }
|
||||
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
__uniq_ptr_impl(__uniq_ptr_impl&& __u) noexcept
|
||||
: _M_t(std::move(__u._M_t))
|
||||
{ __u._M_ptr() = nullptr; }
|
||||
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
__uniq_ptr_impl& operator=(__uniq_ptr_impl&& __u) noexcept
|
||||
{
|
||||
reset(__u.release());
|
||||
@ -169,11 +185,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
return *this;
|
||||
}
|
||||
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
pointer& _M_ptr() noexcept { return std::get<0>(_M_t); }
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
pointer _M_ptr() const noexcept { return std::get<0>(_M_t); }
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
_Dp& _M_deleter() noexcept { return std::get<1>(_M_t); }
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
const _Dp& _M_deleter() const noexcept { return std::get<1>(_M_t); }
|
||||
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
void reset(pointer __p) noexcept
|
||||
{
|
||||
const pointer __old_p = _M_ptr();
|
||||
@ -182,6 +203,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
_M_deleter()(__old_p);
|
||||
}
|
||||
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
pointer release() noexcept
|
||||
{
|
||||
pointer __p = _M_ptr();
|
||||
@ -189,6 +211,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
return __p;
|
||||
}
|
||||
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
void
|
||||
swap(__uniq_ptr_impl& __rhs) noexcept
|
||||
{
|
||||
@ -281,6 +304,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
* The deleter will be value-initialized.
|
||||
*/
|
||||
template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>>
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
explicit
|
||||
unique_ptr(pointer __p) noexcept
|
||||
: _M_t(__p)
|
||||
@ -295,6 +319,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
*/
|
||||
template<typename _Del = deleter_type,
|
||||
typename = _Require<is_copy_constructible<_Del>>>
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
unique_ptr(pointer __p, const deleter_type& __d) noexcept
|
||||
: _M_t(__p, __d) { }
|
||||
|
||||
@ -307,6 +332,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
*/
|
||||
template<typename _Del = deleter_type,
|
||||
typename = _Require<is_move_constructible<_Del>>>
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
unique_ptr(pointer __p,
|
||||
__enable_if_t<!is_lvalue_reference<_Del>::value,
|
||||
_Del&&> __d) noexcept
|
||||
@ -315,6 +341,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
template<typename _Del = deleter_type,
|
||||
typename _DelUnref = typename remove_reference<_Del>::type>
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
unique_ptr(pointer,
|
||||
__enable_if_t<is_lvalue_reference<_Del>::value,
|
||||
_DelUnref&&>) = delete;
|
||||
@ -341,6 +368,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
__conditional_t<is_reference<_Dp>::value,
|
||||
is_same<_Ep, _Dp>,
|
||||
is_convertible<_Ep, _Dp>>>>
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
|
||||
: _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
|
||||
{ }
|
||||
@ -356,6 +384,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
#endif
|
||||
|
||||
/// Destructor, invokes the deleter if the stored pointer is not null.
|
||||
#if __cplusplus > 202002L && __cpp_constexpr_dynamic_alloc
|
||||
constexpr
|
||||
#endif
|
||||
~unique_ptr() noexcept
|
||||
{
|
||||
static_assert(__is_invocable<deleter_type&, pointer>::value,
|
||||
@ -382,6 +413,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
* Invokes the deleter if this object owns a pointer.
|
||||
*/
|
||||
template<typename _Up, typename _Ep>
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
typename enable_if< __and_<
|
||||
__safe_conversion_up<_Up, _Ep>,
|
||||
is_assignable<deleter_type&, _Ep&&>
|
||||
@ -395,6 +427,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
/// Reset the %unique_ptr to empty, invoking the deleter if necessary.
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
unique_ptr&
|
||||
operator=(nullptr_t) noexcept
|
||||
{
|
||||
@ -405,6 +438,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
// Observers.
|
||||
|
||||
/// Dereference the stored pointer.
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
typename add_lvalue_reference<element_type>::type
|
||||
operator*() const noexcept(noexcept(*std::declval<pointer>()))
|
||||
{
|
||||
@ -413,6 +447,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
/// Return the stored pointer.
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
pointer
|
||||
operator->() const noexcept
|
||||
{
|
||||
@ -421,27 +456,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
/// Return the stored pointer.
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
pointer
|
||||
get() const noexcept
|
||||
{ return _M_t._M_ptr(); }
|
||||
|
||||
/// Return a reference to the stored deleter.
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
deleter_type&
|
||||
get_deleter() noexcept
|
||||
{ return _M_t._M_deleter(); }
|
||||
|
||||
/// Return a reference to the stored deleter.
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
const deleter_type&
|
||||
get_deleter() const noexcept
|
||||
{ return _M_t._M_deleter(); }
|
||||
|
||||
/// Return @c true if the stored pointer is not null.
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
explicit operator bool() const noexcept
|
||||
{ return get() == pointer() ? false : true; }
|
||||
|
||||
// Modifiers.
|
||||
|
||||
/// Release ownership of any stored pointer.
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
pointer
|
||||
release() noexcept
|
||||
{ return _M_t.release(); }
|
||||
@ -452,6 +492,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
*
|
||||
* The deleter will be invoked if a pointer is already owned.
|
||||
*/
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
void
|
||||
reset(pointer __p = pointer()) noexcept
|
||||
{
|
||||
@ -461,6 +502,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
/// Exchange the pointer and deleter with another object.
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
void
|
||||
swap(unique_ptr& __u) noexcept
|
||||
{
|
||||
@ -551,6 +593,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
typename = _DeleterConstraint<_Vp>,
|
||||
typename = typename enable_if<
|
||||
__safe_conversion_raw<_Up>::value, bool>::type>
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
explicit
|
||||
unique_ptr(_Up __p) noexcept
|
||||
: _M_t(__p)
|
||||
@ -567,8 +610,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
template<typename _Up, typename _Del = deleter_type,
|
||||
typename = _Require<__safe_conversion_raw<_Up>,
|
||||
is_copy_constructible<_Del>>>
|
||||
unique_ptr(_Up __p, const deleter_type& __d) noexcept
|
||||
: _M_t(__p, __d) { }
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
unique_ptr(_Up __p, const deleter_type& __d) noexcept
|
||||
: _M_t(__p, __d) { }
|
||||
|
||||
/** Takes ownership of a pointer.
|
||||
*
|
||||
@ -581,6 +625,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
template<typename _Up, typename _Del = deleter_type,
|
||||
typename = _Require<__safe_conversion_raw<_Up>,
|
||||
is_move_constructible<_Del>>>
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
unique_ptr(_Up __p,
|
||||
__enable_if_t<!is_lvalue_reference<_Del>::value,
|
||||
_Del&&> __d) noexcept
|
||||
@ -608,11 +653,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
__conditional_t<is_reference<_Dp>::value,
|
||||
is_same<_Ep, _Dp>,
|
||||
is_convertible<_Ep, _Dp>>>>
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
|
||||
: _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
|
||||
{ }
|
||||
|
||||
/// Destructor, invokes the deleter if the stored pointer is not null.
|
||||
#if __cplusplus > 202002L && __cpp_constexpr_dynamic_alloc
|
||||
constexpr
|
||||
#endif
|
||||
~unique_ptr()
|
||||
{
|
||||
auto& __ptr = _M_t._M_ptr();
|
||||
@ -638,6 +687,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
* Invokes the deleter if this object owns a pointer.
|
||||
*/
|
||||
template<typename _Up, typename _Ep>
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
typename
|
||||
enable_if<__and_<__safe_conversion_up<_Up, _Ep>,
|
||||
is_assignable<deleter_type&, _Ep&&>
|
||||
@ -651,6 +701,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
/// Reset the %unique_ptr to empty, invoking the deleter if necessary.
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
unique_ptr&
|
||||
operator=(nullptr_t) noexcept
|
||||
{
|
||||
@ -661,6 +712,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
// Observers.
|
||||
|
||||
/// Access an element of owned array.
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
typename std::add_lvalue_reference<element_type>::type
|
||||
operator[](size_t __i) const
|
||||
{
|
||||
@ -669,27 +721,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
}
|
||||
|
||||
/// Return the stored pointer.
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
pointer
|
||||
get() const noexcept
|
||||
{ return _M_t._M_ptr(); }
|
||||
|
||||
/// Return a reference to the stored deleter.
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
deleter_type&
|
||||
get_deleter() noexcept
|
||||
{ return _M_t._M_deleter(); }
|
||||
|
||||
/// Return a reference to the stored deleter.
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
const deleter_type&
|
||||
get_deleter() const noexcept
|
||||
{ return _M_t._M_deleter(); }
|
||||
|
||||
/// Return @c true if the stored pointer is not null.
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
explicit operator bool() const noexcept
|
||||
{ return get() == pointer() ? false : true; }
|
||||
|
||||
// Modifiers.
|
||||
|
||||
/// Release ownership of any stored pointer.
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
pointer
|
||||
release() noexcept
|
||||
{ return _M_t.release(); }
|
||||
@ -712,14 +769,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
>
|
||||
>
|
||||
>>
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
void
|
||||
reset(_Up __p) noexcept
|
||||
{ _M_t.reset(std::move(__p)); }
|
||||
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
void reset(nullptr_t = nullptr) noexcept
|
||||
{ reset(pointer()); }
|
||||
|
||||
/// Exchange the pointer and deleter with another object.
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
void
|
||||
swap(unique_ptr& __u) noexcept
|
||||
{
|
||||
@ -740,6 +800,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
inline
|
||||
#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
|
||||
// Constrained free swap overload, see p0185r1
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
typename enable_if<__is_swappable<_Dp>::value>::type
|
||||
#else
|
||||
void
|
||||
@ -758,41 +819,47 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
/// Equality operator for unique_ptr objects, compares the owned pointers
|
||||
template<typename _Tp, typename _Dp,
|
||||
typename _Up, typename _Ep>
|
||||
_GLIBCXX_NODISCARD inline bool
|
||||
_GLIBCXX_NODISCARD _GLIBCXX23_CONSTEXPR
|
||||
inline bool
|
||||
operator==(const unique_ptr<_Tp, _Dp>& __x,
|
||||
const unique_ptr<_Up, _Ep>& __y)
|
||||
{ return __x.get() == __y.get(); }
|
||||
|
||||
/// unique_ptr comparison with nullptr
|
||||
template<typename _Tp, typename _Dp>
|
||||
_GLIBCXX_NODISCARD inline bool
|
||||
_GLIBCXX_NODISCARD _GLIBCXX23_CONSTEXPR
|
||||
inline bool
|
||||
operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
|
||||
{ return !__x; }
|
||||
|
||||
#ifndef __cpp_lib_three_way_comparison
|
||||
/// unique_ptr comparison with nullptr
|
||||
template<typename _Tp, typename _Dp>
|
||||
_GLIBCXX_NODISCARD inline bool
|
||||
_GLIBCXX_NODISCARD
|
||||
inline bool
|
||||
operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
|
||||
{ return !__x; }
|
||||
|
||||
/// Inequality operator for unique_ptr objects, compares the owned pointers
|
||||
template<typename _Tp, typename _Dp,
|
||||
typename _Up, typename _Ep>
|
||||
_GLIBCXX_NODISCARD inline bool
|
||||
_GLIBCXX_NODISCARD
|
||||
inline bool
|
||||
operator!=(const unique_ptr<_Tp, _Dp>& __x,
|
||||
const unique_ptr<_Up, _Ep>& __y)
|
||||
{ return __x.get() != __y.get(); }
|
||||
|
||||
/// unique_ptr comparison with nullptr
|
||||
template<typename _Tp, typename _Dp>
|
||||
_GLIBCXX_NODISCARD inline bool
|
||||
_GLIBCXX_NODISCARD
|
||||
inline bool
|
||||
operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
|
||||
{ return (bool)__x; }
|
||||
|
||||
/// unique_ptr comparison with nullptr
|
||||
template<typename _Tp, typename _Dp>
|
||||
_GLIBCXX_NODISCARD inline bool
|
||||
_GLIBCXX_NODISCARD
|
||||
inline bool
|
||||
operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
|
||||
{ return (bool)__x; }
|
||||
#endif // three way comparison
|
||||
@ -800,7 +867,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
/// Relational operator for unique_ptr objects, compares the owned pointers
|
||||
template<typename _Tp, typename _Dp,
|
||||
typename _Up, typename _Ep>
|
||||
_GLIBCXX_NODISCARD inline bool
|
||||
_GLIBCXX_NODISCARD _GLIBCXX23_CONSTEXPR
|
||||
inline bool
|
||||
operator<(const unique_ptr<_Tp, _Dp>& __x,
|
||||
const unique_ptr<_Up, _Ep>& __y)
|
||||
{
|
||||
@ -812,7 +880,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
/// unique_ptr comparison with nullptr
|
||||
template<typename _Tp, typename _Dp>
|
||||
_GLIBCXX_NODISCARD inline bool
|
||||
_GLIBCXX_NODISCARD _GLIBCXX23_CONSTEXPR
|
||||
inline bool
|
||||
operator<(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
|
||||
{
|
||||
return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(),
|
||||
@ -821,7 +890,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
/// unique_ptr comparison with nullptr
|
||||
template<typename _Tp, typename _Dp>
|
||||
_GLIBCXX_NODISCARD inline bool
|
||||
_GLIBCXX_NODISCARD _GLIBCXX23_CONSTEXPR
|
||||
inline bool
|
||||
operator<(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
|
||||
{
|
||||
return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr,
|
||||
@ -831,34 +901,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
/// Relational operator for unique_ptr objects, compares the owned pointers
|
||||
template<typename _Tp, typename _Dp,
|
||||
typename _Up, typename _Ep>
|
||||
_GLIBCXX_NODISCARD inline bool
|
||||
_GLIBCXX_NODISCARD _GLIBCXX23_CONSTEXPR
|
||||
inline bool
|
||||
operator<=(const unique_ptr<_Tp, _Dp>& __x,
|
||||
const unique_ptr<_Up, _Ep>& __y)
|
||||
{ return !(__y < __x); }
|
||||
|
||||
/// unique_ptr comparison with nullptr
|
||||
template<typename _Tp, typename _Dp>
|
||||
_GLIBCXX_NODISCARD inline bool
|
||||
_GLIBCXX_NODISCARD _GLIBCXX23_CONSTEXPR
|
||||
inline bool
|
||||
operator<=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
|
||||
{ return !(nullptr < __x); }
|
||||
|
||||
/// unique_ptr comparison with nullptr
|
||||
template<typename _Tp, typename _Dp>
|
||||
_GLIBCXX_NODISCARD inline bool
|
||||
_GLIBCXX_NODISCARD _GLIBCXX23_CONSTEXPR
|
||||
inline bool
|
||||
operator<=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
|
||||
{ return !(__x < nullptr); }
|
||||
|
||||
/// Relational operator for unique_ptr objects, compares the owned pointers
|
||||
template<typename _Tp, typename _Dp,
|
||||
typename _Up, typename _Ep>
|
||||
_GLIBCXX_NODISCARD inline bool
|
||||
_GLIBCXX_NODISCARD _GLIBCXX23_CONSTEXPR
|
||||
inline bool
|
||||
operator>(const unique_ptr<_Tp, _Dp>& __x,
|
||||
const unique_ptr<_Up, _Ep>& __y)
|
||||
{ return (__y < __x); }
|
||||
|
||||
/// unique_ptr comparison with nullptr
|
||||
template<typename _Tp, typename _Dp>
|
||||
_GLIBCXX_NODISCARD inline bool
|
||||
_GLIBCXX_NODISCARD _GLIBCXX23_CONSTEXPR
|
||||
inline bool
|
||||
operator>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
|
||||
{
|
||||
return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr,
|
||||
@ -867,7 +942,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
/// unique_ptr comparison with nullptr
|
||||
template<typename _Tp, typename _Dp>
|
||||
_GLIBCXX_NODISCARD inline bool
|
||||
_GLIBCXX_NODISCARD _GLIBCXX23_CONSTEXPR
|
||||
inline bool
|
||||
operator>(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
|
||||
{
|
||||
return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(),
|
||||
@ -877,14 +953,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
/// Relational operator for unique_ptr objects, compares the owned pointers
|
||||
template<typename _Tp, typename _Dp,
|
||||
typename _Up, typename _Ep>
|
||||
_GLIBCXX_NODISCARD inline bool
|
||||
_GLIBCXX_NODISCARD _GLIBCXX23_CONSTEXPR
|
||||
inline bool
|
||||
operator>=(const unique_ptr<_Tp, _Dp>& __x,
|
||||
const unique_ptr<_Up, _Ep>& __y)
|
||||
{ return !(__x < __y); }
|
||||
|
||||
/// unique_ptr comparison with nullptr
|
||||
template<typename _Tp, typename _Dp>
|
||||
_GLIBCXX_NODISCARD inline bool
|
||||
_GLIBCXX_NODISCARD _GLIBCXX23_CONSTEXPR
|
||||
inline bool
|
||||
operator>=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
|
||||
{ return !(__x < nullptr); }
|
||||
|
||||
@ -898,6 +976,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
template<typename _Tp, typename _Dp, typename _Up, typename _Ep>
|
||||
requires three_way_comparable_with<typename unique_ptr<_Tp, _Dp>::pointer,
|
||||
typename unique_ptr<_Up, _Ep>::pointer>
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
inline
|
||||
compare_three_way_result_t<typename unique_ptr<_Tp, _Dp>::pointer,
|
||||
typename unique_ptr<_Up, _Ep>::pointer>
|
||||
@ -907,6 +986,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
template<typename _Tp, typename _Dp>
|
||||
requires three_way_comparable<typename unique_ptr<_Tp, _Dp>::pointer>
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
inline
|
||||
compare_three_way_result_t<typename unique_ptr<_Tp, _Dp>::pointer>
|
||||
operator<=>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
|
||||
@ -979,6 +1059,7 @@ namespace __detail
|
||||
* @relates unique_ptr
|
||||
*/
|
||||
template<typename _Tp, typename... _Args>
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
inline __detail::__unique_ptr_t<_Tp>
|
||||
make_unique(_Args&&... __args)
|
||||
{ return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
|
||||
@ -993,6 +1074,7 @@ namespace __detail
|
||||
* The array elements are value-initialized.
|
||||
*/
|
||||
template<typename _Tp>
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
inline __detail::__unique_ptr_array_t<_Tp>
|
||||
make_unique(size_t __num)
|
||||
{ return unique_ptr<_Tp>(new remove_extent_t<_Tp>[__num]()); }
|
||||
@ -1014,6 +1096,7 @@ namespace __detail
|
||||
* @relates unique_ptr
|
||||
*/
|
||||
template<typename _Tp>
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
inline __detail::__unique_ptr_t<_Tp>
|
||||
make_unique_for_overwrite()
|
||||
{ return unique_ptr<_Tp>(new _Tp); }
|
||||
@ -1026,6 +1109,7 @@ namespace __detail
|
||||
* @relates unique_ptr
|
||||
*/
|
||||
template<typename _Tp>
|
||||
_GLIBCXX23_CONSTEXPR
|
||||
inline __detail::__unique_ptr_array_t<_Tp>
|
||||
make_unique_for_overwrite(size_t __num)
|
||||
{ return unique_ptr<_Tp>(new remove_extent_t<_Tp>[__num]); }
|
||||
|
@ -307,6 +307,10 @@
|
||||
|
||||
#if _GLIBCXX_HOSTED
|
||||
#define __cpp_lib_adaptor_iterator_pair_constructor 202106L
|
||||
#if __cpp_constexpr_dynamic_alloc
|
||||
# undef __cpp_lib_constexpr_memory
|
||||
# define __cpp_lib_constexpr_memory 202202L
|
||||
#endif
|
||||
#if __cpp_concepts >= 202002L
|
||||
# define __cpp_lib_expected 202202L
|
||||
#endif
|
||||
|
@ -0,0 +1,48 @@
|
||||
// { dg-options "-std=gnu++23" }
|
||||
// { dg-do compile { target c++23 } }
|
||||
|
||||
#include <memory>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
constexpr bool
|
||||
test_move()
|
||||
{
|
||||
std::unique_ptr<int> p1(new int(2));
|
||||
std::unique_ptr<int> p2;
|
||||
p2 = std::move(p1);
|
||||
VERIFY( *p2 == 2 );
|
||||
std::unique_ptr<int[]> a1(new int[]{0, 1, 2});
|
||||
std::unique_ptr<int[]> a2;
|
||||
a2 = std::move(a1);
|
||||
VERIFY( a2[2] == 2 );
|
||||
|
||||
return true;
|
||||
}
|
||||
static_assert( test_move() );
|
||||
|
||||
constexpr bool
|
||||
test_convert()
|
||||
{
|
||||
std::unique_ptr<int> p1(new int(2));
|
||||
std::unique_ptr<const int> p2;
|
||||
p2 = std::move(p1);
|
||||
VERIFY( *p2 == 2 );
|
||||
std::unique_ptr<int[]> a1(new int[]{0, 1, 2});
|
||||
std::unique_ptr<const int[]> a2;
|
||||
a2 = std::move(a1);
|
||||
VERIFY( a2[2] == 2 );
|
||||
|
||||
return true;
|
||||
}
|
||||
static_assert( test_convert() );
|
||||
|
||||
constexpr bool
|
||||
test_null()
|
||||
{
|
||||
std::unique_ptr<int> p(new int(2));
|
||||
p = nullptr;
|
||||
VERIFY( !p );
|
||||
p = nullptr;
|
||||
return true;
|
||||
}
|
||||
static_assert( test_null() );
|
@ -0,0 +1,73 @@
|
||||
// { dg-options "-std=gnu++23" }
|
||||
// { dg-do compile { target c++23 } }
|
||||
|
||||
#include <memory>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
constexpr bool
|
||||
test_eq()
|
||||
{
|
||||
std::unique_ptr<int> p1, p2;
|
||||
VERIFY( p1 == p2 );
|
||||
p1.reset(new int(1));
|
||||
VERIFY( p1 == p1 );
|
||||
VERIFY( p1 != p2 );
|
||||
struct null_deleter { constexpr void operator()(const void*) const { } };
|
||||
std::unique_ptr<const int[], null_deleter> p3(p1.get());
|
||||
VERIFY( p3 == p3 );
|
||||
VERIFY( p1 == p3 );
|
||||
VERIFY( p3 != p2 );
|
||||
|
||||
return true;
|
||||
}
|
||||
static_assert( test_eq() );
|
||||
|
||||
constexpr bool
|
||||
test_rel()
|
||||
{
|
||||
std::unique_ptr<int> p1, p2;
|
||||
VERIFY( !(p1 < p2) );
|
||||
VERIFY( !(p1 > p2) );
|
||||
VERIFY( p1 <= p2 );
|
||||
VERIFY( p1 >= p2 );
|
||||
p1.reset(new int(1));
|
||||
VERIFY( p1 <= p1 );
|
||||
VERIFY( p1 >= p1 );
|
||||
VERIFY( p1 > p2 );
|
||||
VERIFY( p2 < p1 );
|
||||
VERIFY( p2 <= p1 );
|
||||
VERIFY( p1 >= p2 );
|
||||
struct null_deleter { constexpr void operator()(const void*) const { } };
|
||||
std::unique_ptr<const int[], null_deleter> p3(p1.get());
|
||||
VERIFY( p3 <= p3 );
|
||||
VERIFY( p3 >= p3 );
|
||||
VERIFY( p1 <= p3 );
|
||||
VERIFY( p3 > p2 );
|
||||
VERIFY( p3 >= p2 );
|
||||
VERIFY( p2 < p3 );
|
||||
VERIFY( p2 <= p3 );
|
||||
|
||||
return true;
|
||||
}
|
||||
static_assert( test_rel() );
|
||||
|
||||
constexpr bool
|
||||
test_3way()
|
||||
{
|
||||
std::unique_ptr<int> p1, p2;
|
||||
VERIFY( (p1 <=> p1) == 0 );
|
||||
VERIFY( (p1 <=> p2) == 0 );
|
||||
p1.reset(new int(1));
|
||||
VERIFY( (p1 <=> p1) == 0 );
|
||||
VERIFY( (p1 <=> p2) > 0 );
|
||||
VERIFY( (p2 <=> p1) < 0 );
|
||||
struct null_deleter { constexpr void operator()(const void*) const { } };
|
||||
std::unique_ptr<const int[], null_deleter> p3(p1.get());
|
||||
VERIFY( (p3 <=> p3) == 0 );
|
||||
VERIFY( (p1 <=> p3) == 0 );
|
||||
VERIFY( (p3 <=> p2) > 0 );
|
||||
VERIFY( (p2 <=> p3) < 0 );
|
||||
|
||||
return true;
|
||||
}
|
||||
static_assert( test_3way() );
|
@ -0,0 +1,85 @@
|
||||
// { dg-options "-std=gnu++23" }
|
||||
// { dg-do compile { target c++23 } }
|
||||
|
||||
#include <memory>
|
||||
|
||||
#ifndef __cpp_lib_constexpr_memory
|
||||
# error "Feature test macro for constexpr unique_ptr is missing in <memory>"
|
||||
#elif __cpp_lib_constexpr_memory < 202202L
|
||||
# error "Feature test macro for constexpr unique_ptr has wrong value in <memory>"
|
||||
#endif
|
||||
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
constexpr bool
|
||||
test_default()
|
||||
{
|
||||
std::unique_ptr<int> p;
|
||||
std::unique_ptr<int> np(nullptr);
|
||||
VERIFY( p == np );
|
||||
|
||||
std::unique_ptr<int[]> a;
|
||||
std::unique_ptr<int[]> na(nullptr);
|
||||
VERIFY( a == na );
|
||||
|
||||
return true;
|
||||
}
|
||||
static_assert( test_default() );
|
||||
|
||||
constexpr bool
|
||||
test_ptr()
|
||||
{
|
||||
std::unique_ptr<int> p(new int(2));
|
||||
VERIFY( *p == 2 );
|
||||
std::unique_ptr<int[]> a(new int[]{0, 1, 2});
|
||||
VERIFY( a[2] == 2 );
|
||||
|
||||
return true;
|
||||
}
|
||||
static_assert( test_ptr() );
|
||||
|
||||
constexpr bool
|
||||
test_del()
|
||||
{
|
||||
const std::default_delete<int> pd;
|
||||
std::unique_ptr<int> p1(new int(1), pd);
|
||||
VERIFY( *p1 == 1 );
|
||||
std::unique_ptr<int> p2(new int(2), std::default_delete<int>{});
|
||||
VERIFY( *p2 == 2 );
|
||||
const std::default_delete<int[]> ad;
|
||||
std::unique_ptr<int[]> a1(new int[]{3, 4}, ad);
|
||||
VERIFY( a1[0] == 3 );
|
||||
std::unique_ptr<int[]> a2(new int[]{5, 6}, std::default_delete<int[]>{});
|
||||
VERIFY( a2[1] == 6 );
|
||||
|
||||
return true;
|
||||
}
|
||||
static_assert( test_del() );
|
||||
|
||||
constexpr bool
|
||||
test_move()
|
||||
{
|
||||
std::unique_ptr<int> p1(new int(2));
|
||||
std::unique_ptr<int> p2 = std::move(p1);
|
||||
VERIFY( *p2 == 2 );
|
||||
std::unique_ptr<int[]> a1(new int[]{0, 1, 2});
|
||||
std::unique_ptr<int[]> a2 = std::move(a1);
|
||||
VERIFY( a2[2] == 2 );
|
||||
|
||||
return true;
|
||||
}
|
||||
static_assert( test_move() );
|
||||
|
||||
constexpr bool
|
||||
test_convert()
|
||||
{
|
||||
std::unique_ptr<int> p1(new int(2));
|
||||
std::unique_ptr<const int> p2 = std::move(p1);
|
||||
VERIFY( *p2 == 2 );
|
||||
std::unique_ptr<int[]> a1(new int[]{0, 1, 2});
|
||||
std::unique_ptr<const int[]> a2 = std::move(a1);
|
||||
VERIFY( a2[2] == 2 );
|
||||
|
||||
return true;
|
||||
}
|
||||
static_assert( test_convert() );
|
@ -0,0 +1,34 @@
|
||||
// { dg-options "-std=gnu++23" }
|
||||
// { dg-do compile { target c++23 } }
|
||||
|
||||
#include <memory>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
constexpr bool
|
||||
test_creation_single()
|
||||
{
|
||||
std::unique_ptr<int> p = std::make_unique<int>(1);
|
||||
VERIFY( *p == 1 );
|
||||
p = std::make_unique_for_overwrite<int>();
|
||||
*p = 2;
|
||||
VERIFY( *p == 2 );
|
||||
|
||||
return true;
|
||||
}
|
||||
static_assert( test_creation_single() );
|
||||
|
||||
constexpr bool
|
||||
test_creation_array()
|
||||
{
|
||||
std::unique_ptr<int[]> a = std::make_unique<int[]>(2);
|
||||
VERIFY( a[0] == 0 );
|
||||
VERIFY( a[1] == 0 );
|
||||
a = std::make_unique_for_overwrite<int[]>(2);
|
||||
a[0] = 1;
|
||||
a[1] = 2;
|
||||
VERIFY( a[0] == 1 );
|
||||
VERIFY( a[1] == 2 );
|
||||
|
||||
return true;
|
||||
}
|
||||
static_assert( test_creation_array() );
|
@ -0,0 +1,68 @@
|
||||
// { dg-options "-std=gnu++23" }
|
||||
// { dg-do compile { target c++23 } }
|
||||
|
||||
#include <memory>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
constexpr bool
|
||||
test_release()
|
||||
{
|
||||
std::unique_ptr<int> p1;
|
||||
int* r = p1.release();
|
||||
VERIFY( !r );
|
||||
VERIFY( !p1 );
|
||||
|
||||
std::unique_ptr<int> p2(new int(2));
|
||||
r = p2.release();
|
||||
VERIFY( r );
|
||||
VERIFY( !p2 );
|
||||
delete r;
|
||||
|
||||
std::unique_ptr<int[]> a1;
|
||||
r = a1.release();
|
||||
VERIFY( !r );
|
||||
VERIFY( !a1 );
|
||||
|
||||
std::unique_ptr<int[]> a2(new int[2]{});
|
||||
r = a2.release();
|
||||
VERIFY( r );
|
||||
VERIFY( !a2 );
|
||||
delete[] r;
|
||||
|
||||
return true;
|
||||
}
|
||||
static_assert( test_release() );
|
||||
|
||||
constexpr bool
|
||||
test_reset()
|
||||
{
|
||||
std::unique_ptr<int> p1;
|
||||
p1.reset();
|
||||
VERIFY( !p1 );
|
||||
p1.reset(nullptr);
|
||||
VERIFY( !p1 );
|
||||
p1.reset(new int(2));
|
||||
VERIFY( *p1 == 2 );
|
||||
p1.reset(new int(3));
|
||||
VERIFY( *p1 == 3 );
|
||||
p1.reset(nullptr);
|
||||
VERIFY( !p1 );
|
||||
|
||||
std::unique_ptr<int[]> a1;
|
||||
a1.reset();
|
||||
VERIFY( !a1 );
|
||||
a1.reset(nullptr);
|
||||
VERIFY( !a1 );
|
||||
a1.reset(new int[]{2,3});
|
||||
VERIFY( a1[0] == 2 );
|
||||
a1.reset(new int[]{4,5,6});
|
||||
VERIFY( a1[1] == 5 );
|
||||
a1.reset(nullptr);
|
||||
VERIFY( !a1 );
|
||||
|
||||
std::unique_ptr<const int[]> a2;
|
||||
a2.reset(new int[2]{});
|
||||
|
||||
return true;
|
||||
}
|
||||
static_assert( test_reset() );
|
@ -0,0 +1,46 @@
|
||||
// { dg-options "-std=gnu++23" }
|
||||
// { dg-do compile { target c++23 } }
|
||||
|
||||
#include <memory>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
constexpr bool
|
||||
test_swap_single()
|
||||
{
|
||||
std::unique_ptr<int> p1;
|
||||
swap(p1, p1);
|
||||
VERIFY( !p1 );
|
||||
std::unique_ptr<int> p2;
|
||||
swap(p1, p2);
|
||||
VERIFY( !p1 && !p2 );
|
||||
std::unique_ptr<int> p3(new int(3));
|
||||
swap(p3, p3);
|
||||
VERIFY( *p3 == 3 );
|
||||
swap(p1, p3);
|
||||
VERIFY( *p1 == 3 );
|
||||
std::unique_ptr<int> p4(new int(4));
|
||||
swap(p4, p1);
|
||||
VERIFY( *p4 == 3 );
|
||||
VERIFY( *p1 == 4 );
|
||||
|
||||
return true;
|
||||
}
|
||||
static_assert( test_swap_single() );
|
||||
|
||||
constexpr bool
|
||||
test_swap_array()
|
||||
{
|
||||
std::unique_ptr<int[]> a1;
|
||||
std::unique_ptr<int[]> a2;
|
||||
swap(a1, a2);
|
||||
VERIFY( !a1 && !a2 );
|
||||
std::unique_ptr<int[]> a3(new int[]{3});
|
||||
swap(a1, a3);
|
||||
VERIFY( a1[0] == 3 );
|
||||
std::unique_ptr<int[]> a4(new int[]{4, 5});
|
||||
swap(a1, a4);
|
||||
VERIFY( a1[1] == 5 );
|
||||
|
||||
return true;
|
||||
}
|
||||
static_assert( test_swap_array() );
|
Loading…
Reference in New Issue
Block a user