Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[libc++][memory] P1132R8: out_ptr - a scalable output pointer abstraction #73618

Merged
Show file tree
Hide file tree
Changes from 45 commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
84770c8
[libc++][memory] P1132R8: out_ptr - a scalable output pointer abstrac…
Zingam Apr 30, 2023
4bc779e
[out_ptr] Address review comments + new tests
Zingam Nov 30, 2023
b23e91a
[out_ptr] Added tests
Zingam Nov 30, 2023
cb71ea2
Removed tests files
Zingam Nov 30, 2023
c78d2ec
Merge branch 'llvm:main' into hgh/libcxx/P1132R8-out_ptr-a-scalable-o…
H-G-Hristov Nov 30, 2023
d9e04a7
Addressed comments: Renamed test files
Zingam Dec 14, 2023
3405ee5
Addressed comments: Renamed ctr args
Zingam Dec 15, 2023
2b2aaec
Addressed comments: Refactored tests
Zingam Dec 15, 2023
af88c85
Renamed directories
Zingam Dec 15, 2023
ad38d72
Merge branch 'llvm:main' into hgh/libcxx/P1132R8-out_ptr-a-scalable-o…
H-G-Hristov Dec 15, 2023
d7c0439
Addressed comments: Added `MoveOnlyDeleter` test
Zingam Dec 16, 2023
54c2a41
Tweaked convert.pass tests
Zingam Dec 16, 2023
1a4e2e8
Try to fix CI
Zingam Dec 16, 2023
378b374
Try to fix CI
Zingam Dec 16, 2023
1515a3d
Refactored if constexpr else case
Zingam Dec 17, 2023
a7fa18c
Merge branch 'llvm:main' into hgh/libcxx/P1132R8-out_ptr-a-scalable-o…
H-G-Hristov Dec 17, 2023
da7d5e5
Refactored verify.cpp
Zingam Dec 17, 2023
df87f89
WIP
Zingam Dec 17, 2023
49fa86f
Cleanup
Zingam Dec 17, 2023
e4215e7
Merge branch 'llvm:main' into hgh/libcxx/P1132R8-out_ptr-a-scalable-o…
H-G-Hristov Dec 17, 2023
da17720
Merge branch 'main' into hgh/libcxx/P1132R8-out_ptr-a-scalable-output…
Zingam Dec 20, 2023
73c36a1
Fixed test
Zingam Dec 20, 2023
3b0a0c0
Merge branch 'main' into hgh/libcxx/P1132R8-out_ptr-a-scalable-output…
Zingam Jan 1, 2024
3073b70
Merge branch 'main' into hgh/libcxx/P1132R8-out_ptr-a-scalable-output…
Zingam Jan 22, 2024
ae04dfb
Run generator script
Zingam Jan 22, 2024
202889f
Merge branch 'main' into hgh/libcxx/P1132R8-out_ptr-a-scalable-output…
Zingam Jan 22, 2024
8dad901
Merge branch 'main' into hgh/libcxx/P1132R8-out_ptr-a-scalable-output…
H-G-Hristov Jan 29, 2024
c0541c6
Updated release notes
H-G-Hristov Jan 29, 2024
2902fe5
Try to fix CI: added `#include <__utility/move.h>`
H-G-Hristov Jan 29, 2024
398914a
Try to fix CI: added `#include <__utility/forward.h>`
H-G-Hristov Jan 29, 2024
a68df29
Merge branch 'main' into hgh/libcxx/P1132R8-out_ptr-a-scalable-output…
H-G-Hristov Jan 29, 2024
fbc5a81
Added `__LIBCPP_PUSH_MACROS` and `__LIBCPP_POP_MACROS`
H-G-Hristov Jan 30, 2024
cfd8356
Added `__LIBCPP_PUSH_MACROS` and `__LIBCPP_POP_MACROS`
H-G-Hristov Jan 30, 2024
2b300c9
Merge branch 'main' into hgh/libcxx/P1132R8-out_ptr-a-scalable-output…
H-G-Hristov Jan 30, 2024
2f859d4
Merge branch 'main' into hgh/libcxx/P1132R8-out_ptr-a-scalable-output…
H-G-Hristov Mar 1, 2024
8d19f94
Merge branch 'main' into hgh/libcxx/P1132R8-out_ptr-a-scalable-output…
H-G-Hristov Jul 10, 2024
7d59cf6
Update: run generator scripts
H-G-Hristov Jul 10, 2024
8fcbddc
Update libcxx/docs/Status/Cxx23Issues.csv
H-G-Hristov Jul 10, 2024
34387e2
Fixed formatting
H-G-Hristov Jul 10, 2024
d321e86
Merge branch 'main' into hgh/libcxx/P1132R8-out_ptr-a-scalable-output…
H-G-Hristov Jul 10, 2024
3969659
Fixed *.verify.cpp tests
H-G-Hristov Jul 12, 2024
f914c63
Merge branch 'main' into hgh/libcxx/P1132R8-out_ptr-a-scalable-output…
H-G-Hristov Jul 12, 2024
1f496d5
Merge branch 'main' into hgh/libcxx/P1132R8-out_ptr-a-scalable-output…
H-G-Hristov Jul 12, 2024
d4eed77
Try to fix CI
H-G-Hristov Jul 12, 2024
198d222
Merge branch 'main' into hgh/libcxx/P1132R8-out_ptr-a-scalable-output…
H-G-Hristov Jul 12, 2024
0fa9266
Merge branch 'main' into hgh/libcxx/P1132R8-out_ptr-a-scalable-output…
H-G-Hristov Jul 15, 2024
d46ef50
Addressed some feedback
H-G-Hristov Jul 15, 2024
a2a453b
Merge branch 'main' into hgh/libcxx/P1132R8-out_ptr-a-scalable-output…
H-G-Hristov Jul 15, 2024
b0d0413
Try to fix CI
H-G-Hristov Jul 15, 2024
4d9dc5e
Added comments to tests in plain English
H-G-Hristov Jul 17, 2024
409f66a
Added error messages
H-G-Hristov Jul 17, 2024
8d31e72
Merge branch 'main' into hgh/libcxx/P1132R8-out_ptr-a-scalable-output…
Zingam Jul 17, 2024
ebe9e9d
Added minimal runtime tests
H-G-Hristov Jul 17, 2024
2c4042e
Merge branch 'main' into hgh/libcxx/P1132R8-out_ptr-a-scalable-output…
H-G-Hristov Jul 17, 2024
5abf091
Addressed the final comment
H-G-Hristov Jul 17, 2024
9866adc
Fix
H-G-Hristov Jul 17, 2024
d89e6eb
Merge branch 'main' into hgh/libcxx/P1132R8-out_ptr-a-scalable-output…
H-G-Hristov Jul 17, 2024
38640f1
Merge branch 'main' into hgh/libcxx/P1132R8-out_ptr-a-scalable-output…
H-G-Hristov Jul 18, 2024
a42fe5f
Merge branch 'main' into hgh/libcxx/P1132R8-out_ptr-a-scalable-output…
Zingam Jul 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions libcxx/docs/FeatureTestMacroTable.rst
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_optional`` ``202110L``
---------------------------------------------------------- -----------------
``__cpp_lib_out_ptr`` *unimplemented*
``__cpp_lib_out_ptr`` ``202106L``
---------------------------------------------------------- -----------------
``__cpp_lib_print`` ``202207L``
---------------------------------------------------------- -----------------
Expand Down Expand Up @@ -448,7 +448,7 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_optional_range_support`` *unimplemented*
---------------------------------------------------------- -----------------
``__cpp_lib_out_ptr`` *unimplemented*
``__cpp_lib_out_ptr`` ``202311L``
---------------------------------------------------------- -----------------
``__cpp_lib_philox_engine`` *unimplemented*
---------------------------------------------------------- -----------------
Expand Down
1 change: 1 addition & 0 deletions libcxx/docs/ReleaseNotes/19.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ What's New in Libc++ 19.0.0?
Implemented Papers
------------------

- P1132R8 - ``out_ptr`` - a scalable output pointer abstraction
- P2637R3 - Member ``visit``
- P2652R2 - Disallow User Specialization of ``allocator_traits``
- P2819R2 - Add ``tuple`` protocol to ``complex``
Expand Down
4 changes: 2 additions & 2 deletions libcxx/docs/Status/Cxx23Issues.csv
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@
"`3515 <https://wg21.link/LWG3515>`__","§[stacktrace.basic.nonmem]: ``operator<<`` should be less templatized", "November 2022","","",""
"`3545 <https://wg21.link/LWG3545>`__","``std::pointer_traits`` should be SFINAE-friendly", "November 2022","|Complete|","18.0",""
"`3569 <https://wg21.link/LWG3569>`__","``join_view`` fails to support ranges of ranges with non-default_initializable iterators", "November 2022","","","|ranges|"
"`3594 <https://wg21.link/LWG3594>`__","``inout_ptr`` — inconsistent ``release()`` in destructor", "November 2022","","",""
"`3594 <https://wg21.link/LWG3594>`__","``inout_ptr`` — inconsistent ``release()`` in destructor", "November 2022","|Complete|","19.0",""
"`3597 <https://wg21.link/LWG3597>`__","Unsigned integer types don't model advanceable", "November 2022","","","|ranges|"
"`3600 <https://wg21.link/LWG3600>`__","Making ``istream_iterator`` copy constructor trivial is an ABI break", "November 2022","","",""
"`3629 <https://wg21.link/LWG3629>`__","``make_error_code`` and ``make_error_condition`` are customization points","November 2022","|Complete|","16.0",""
Expand Down Expand Up @@ -282,7 +282,7 @@
"`3645 <https://wg21.link/LWG3645>`__","``resize_and_overwrite`` is overspecified to call its callback with lvalues","February 2023","|Complete|","14.0",""
"`3655 <https://wg21.link/LWG3655>`__","The ``INVOKE`` operation and union types","February 2023","|Complete|","18.0",""
"`3723 <https://wg21.link/LWG3723>`__","``priority_queue::push_range`` needs to ``append_range``","February 2023","","","|ranges|"
"`3734 <https://wg21.link/LWG3734>`__","Inconsistency in ``inout_ptr`` and ``out_ptr`` for empty case","February 2023","","",""
"`3734 <https://wg21.link/LWG3734>`__","Inconsistency in ``inout_ptr`` and ``out_ptr`` for empty case","February 2023","|Complete|","19.0",""
"`3772 <https://wg21.link/LWG3772>`__","``repeat_view``'s ``piecewise`` constructor is missing Postconditions","February 2023","|Complete|","17.0","|ranges|"
"`3786 <https://wg21.link/LWG3786>`__","Flat maps' deduction guide needs to default ``Allocator`` to be useful","February 2023","","",""
"`3803 <https://wg21.link/LWG3803>`__","``flat_foo`` constructors taking ``KeyContainer`` lack ``KeyCompare`` parameter","February 2023","","",""
Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx23Papers.csv
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"","","","","","",""
"`P0401R6 <https://wg21.link/P0401R6>`__","LWG","Providing size feedback in the Allocator interface","June 2021","|Complete|","15.0"
"`P0448R4 <https://wg21.link/P0448R4>`__","LWG","A strstream replacement using span<charT> as buffer","June 2021","",""
"`P1132R8 <https://wg21.link/P1132R8>`__","LWG","out_ptr - a scalable output pointer abstraction","June 2021","",""
"`P1132R8 <https://wg21.link/P1132R8>`__","LWG","out_ptr - a scalable output pointer abstraction","June 2021","|Complete|","19.0"
"`P1328R1 <https://wg21.link/P1328R1>`__","LWG","Making std::type_info::operator== constexpr","June 2021","|Complete|","17.0"
"`P1425R4 <https://wg21.link/P1425R4>`__","LWG","Iterators pair constructors for stack and queue","June 2021","|Complete|","14.0","|ranges|"
"`P1518R2 <https://wg21.link/P1518R2>`__","LWG","Stop overconstraining allocators in container deduction guides","June 2021","|Complete|","13.0"
Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx2cIssues.csv
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"`3749 <https://wg21.link/LWG3749>`__","``common_iterator`` should handle integer-class difference types","Kona November 2023","","",""
"`3809 <https://wg21.link/LWG3809>`__","Is ``std::subtract_with_carry_engine<uint16_t>`` supposed to work","Kona November 2023","","",""
"`3892 <https://wg21.link/LWG3892>`__","Incorrect formatting of nested ranges and tuples","Kona November 2023","|Complete|","17.0","|format|"
"`3897 <https://wg21.link/LWG3897>`__","``inout_ptr`` will not update raw pointer to 0","Kona November 2023","","",""
"`3897 <https://wg21.link/LWG3897>`__","``inout_ptr`` will not update raw pointer to 0","Kona November 2023","|Complete|","19.0",""
"`3946 <https://wg21.link/LWG3946>`__","The definition of ``const_iterator_t`` should be reworked","Kona November 2023","","",""
"`3947 <https://wg21.link/LWG3947>`__","Unexpected constraints on ``adjacent_transform_view::base()``","Kona November 2023","","","|ranges|"
"`3948 <https://wg21.link/LWG3948>`__","``possibly-const-range and as-const-pointer`` should be ``noexcept``","Kona November 2023","","","|ranges|"
Expand Down
2 changes: 2 additions & 0 deletions libcxx/include/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,8 @@ set(files
__memory/concepts.h
__memory/construct_at.h
__memory/destruct_n.h
__memory/inout_ptr.h
__memory/out_ptr.h
__memory/pointer_traits.h
__memory/ranges_construct_at.h
__memory/ranges_uninitialized_algorithms.h
Expand Down
1 change: 0 additions & 1 deletion libcxx/include/__memory/allocator_traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD
struct NAME<_Tp, __void_t<typename _Tp::PROPERTY > > : true_type {}

// __pointer
_LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_pointer, pointer);
template <class _Tp,
class _Alloc,
class _RawAlloc = __libcpp_remove_reference_t<_Alloc>,
Expand Down
108 changes: 108 additions & 0 deletions libcxx/include/__memory/inout_ptr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef _LIBCPP___INOUT_PTR_H
#define _LIBCPP___INOUT_PTR_H

#include <__config>
#include <__memory/addressof.h>
#include <__memory/pointer_traits.h>
#include <__memory/shared_ptr.h>
#include <__memory/unique_ptr.h>
#include <__type_traits/is_same.h>
#include <__type_traits/is_specialization.h>
#include <__type_traits/is_void.h>
#include <__utility/forward.h>
#include <__utility/move.h>
#include <tuple>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif

_LIBCPP_PUSH_MACROS
#include <__undef_macros>

_LIBCPP_BEGIN_NAMESPACE_STD

#if _LIBCPP_STD_VER >= 23

template <class _Smart, class _Pointer, class... _Args>
class _LIBCPP_TEMPLATE_VIS inout_ptr_t {
static_assert(!__is_specialization_v<_Smart, shared_ptr>, "std::shared_ptr<> is not supported");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
static_assert(!__is_specialization_v<_Smart, shared_ptr>, "std::shared_ptr<> is not supported");
static_assert(!__is_specialization_v<_Smart, shared_ptr>, "std::shared_ptr<> is not supported with std::inout_ptr");


public:
_LIBCPP_HIDE_FROM_ABI explicit inout_ptr_t(_Smart& __smart, _Args... __args)
: __s_(__smart), __a_(std::forward<_Args>(__args)...), __p_([&__smart] {
if constexpr (is_pointer_v<_Smart>) {
return __smart;
} else {
return __smart.get();
}
}()) {
if constexpr (requires { __s_.release(); }) {
__s_.release();
} else {
__s_ = _Smart();
}
}

_LIBCPP_HIDE_FROM_ABI inout_ptr_t(const inout_ptr_t&) = delete;

_LIBCPP_HIDE_FROM_ABI ~inout_ptr_t() {
// LWG-3897 inout_ptr will not update raw pointer to null
if constexpr (!is_pointer_v<_Smart>) {
H-G-Hristov marked this conversation as resolved.
Show resolved Hide resolved
if (!__p_) {
return;
}
}

using _SP = __pointer_of_or_t<_Smart, _Pointer>;
if constexpr (is_pointer_v<_Smart>) {
std::apply([&](auto&&... __args) { __s_ = _Smart(static_cast<_SP>(__p_), std::forward<_Args>(__args)...); },
std::move(__a_));
} else if constexpr (__resettable_smart_pointer_with_args<_Smart, _Pointer, _Args...>) {
std::apply([&](auto&&... __args) { __s_.reset(static_cast<_SP>(__p_), std::forward<_Args>(__args)...); },
std::move(__a_));
} else {
static_assert(is_constructible_v<_Smart, _SP, _Args...>);
std::apply([&](auto&&... __args) { __s_ = _Smart(static_cast<_SP>(__p_), std::forward<_Args>(__args)...); },
std::move(__a_));
}
}

_LIBCPP_HIDE_FROM_ABI operator _Pointer*() const noexcept { return std::addressof(const_cast<_Pointer&>(__p_)); }

_LIBCPP_HIDE_FROM_ABI operator void**() const noexcept
requires(!is_same_v<_Pointer, void*>)
{
static_assert(is_pointer_v<_Pointer>);

return reinterpret_cast<void**>(static_cast<_Pointer*>(*this));
}

private:
_Smart& __s_;
tuple<_Args...> __a_;
_Pointer __p_;
};

template <class _Pointer = void, class _Smart, class... _Args>
_LIBCPP_HIDE_FROM_ABI auto inout_ptr(_Smart& __s, _Args&&... __args) {
using _Ptr = conditional_t<is_void_v<_Pointer>, __pointer_of_t<_Smart>, _Pointer>;
return std::inout_ptr_t<_Smart, _Ptr, _Args&&...>(__s, std::forward<_Args>(__args)...);
ldionne marked this conversation as resolved.
Show resolved Hide resolved
}

#endif // _LIBCPP_STD_VER >= 23

_LIBCPP_END_NAMESPACE_STD

_LIBCPP_POP_MACROS

#endif // _LIBCPP___INOUT_PTR_H
99 changes: 99 additions & 0 deletions libcxx/include/__memory/out_ptr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef _LIBCPP___OUT_PTR_H
#define _LIBCPP___OUT_PTR_H

#include <__config>
#include <__memory/addressof.h>
#include <__memory/pointer_traits.h>
#include <__memory/shared_ptr.h>
#include <__memory/unique_ptr.h>
#include <__type_traits/is_specialization.h>
#include <__type_traits/is_void.h>
#include <__utility/forward.h>
#include <__utility/move.h>
#include <tuple>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif

_LIBCPP_PUSH_MACROS
#include <__undef_macros>

_LIBCPP_BEGIN_NAMESPACE_STD

#if _LIBCPP_STD_VER >= 23

template <class _Smart, class _Pointer, class... _Args>
class _LIBCPP_TEMPLATE_VIS out_ptr_t {
static_assert(!__is_specialization_v<_Smart, shared_ptr> || sizeof...(_Args) > 0,
"Specialization of std::shared_ptr<> requires a deleter.");
ldionne marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"Specialization of std::shared_ptr<> requires a deleter.");
"Using std::shared_ptr<> without a deleter in std::out_ptr is not supported.");

Or

Suggested change
"Specialization of std::shared_ptr<> requires a deleter.");
"Using std::shared_ptr<> in std::out_ptr requires a deleter.");


public:
_LIBCPP_HIDE_FROM_ABI explicit out_ptr_t(_Smart& __smart, _Args... __args)
: __s_(__smart), __a_(std::forward<_Args>(__args)...), __p_() {
using _Ptr = decltype(__smart);
if constexpr (__resettable_smart_pointer<_Ptr>) {
__s_.reset();
} else if constexpr (is_constructible_v<_Smart>) {
__s_ = _Smart();
} else {
static_assert(__resettable_smart_pointer<_Ptr> || is_constructible_v<_Smart>);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An error message would be nice.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DONE. Added error messages.

}
}

_LIBCPP_HIDE_FROM_ABI out_ptr_t(const out_ptr_t&) = delete;

_LIBCPP_HIDE_FROM_ABI ~out_ptr_t() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to do something about https://eel.is/c++draft/smartptr#out.ptr.t-7. Otherwise, when we use a shared_ptr here, if we fail to allocate the control block we'll be in trouble, since this is a destructor. So, instead what we could do is allocate a control block in the constructor, then use shared_ptr<T>::__create_with_control_block in the destructor. The simplest way to do this might be to create a specialization for shared_ptr<T>. Do you think that is overkill?

if (!__p_) {
return;
}

using _SP = __pointer_of_or_t<_Smart, _Pointer>;
if constexpr (__resettable_smart_pointer_with_args<_Smart, _Pointer, _Args...>) {
std::apply([&](auto&&... __args) { __s_.reset(static_cast<_SP>(__p_), std::forward<_Args>(__args)...); },
std::move(__a_));
} else {
static_assert(is_constructible_v<_Smart, _SP, _Args...>);
std::apply([&](auto&&... __args) { __s_ = _Smart(static_cast<_SP>(__p_), std::forward<_Args>(__args)...); },
std::move(__a_));
}
}

_LIBCPP_HIDE_FROM_ABI operator _Pointer*() const noexcept { return std::addressof(const_cast<_Pointer&>(__p_)); }
ldionne marked this conversation as resolved.
Show resolved Hide resolved

_LIBCPP_HIDE_FROM_ABI operator void**() const noexcept
requires(!is_same_v<_Pointer, void*>)
{
static_assert(is_pointer_v<_Pointer>);

return reinterpret_cast<void**>(static_cast<_Pointer*>(*this));
}

private:
_Smart& __s_;
tuple<_Args...> __a_;
_Pointer __p_ = _Pointer();
};

template <class _Pointer = void, class _Smart, class... _Args>
_LIBCPP_HIDE_FROM_ABI auto out_ptr(_Smart& __s, _Args&&... __args) {
using _Ptr = conditional_t<is_void_v<_Pointer>, __pointer_of_t<_Smart>, _Pointer>;
ldionne marked this conversation as resolved.
Show resolved Hide resolved
return std::out_ptr_t<_Smart, _Ptr, _Args&&...>(__s, std::forward<_Args>(__args)...);
}

#endif // _LIBCPP_STD_VER >= 23

_LIBCPP_END_NAMESPACE_STD

_LIBCPP_POP_MACROS

#endif // _LIBCPP___OUT_PTR_H
70 changes: 66 additions & 4 deletions libcxx/include/__memory/pointer_traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,28 @@
#include <__type_traits/is_void.h>
#include <__type_traits/void_t.h>
#include <__utility/declval.h>
#include <__utility/forward.h>
#include <cstddef>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif

_LIBCPP_PUSH_MACROS
#include <__undef_macros>

_LIBCPP_BEGIN_NAMESPACE_STD

template <class _Tp, class = void>
struct __has_element_type : false_type {};
// clang-format off
#define _LIBCPP_CLASS_TRAITS_HAS_XXX(NAME, PROPERTY) \
template <class _Tp, class = void> \
struct NAME : false_type {}; \
template <class _Tp> \
struct NAME<_Tp, __void_t<typename _Tp::PROPERTY> > : true_type {}
// clang-format on

template <class _Tp>
struct __has_element_type<_Tp, __void_t<typename _Tp::element_type> > : true_type {};
_LIBCPP_CLASS_TRAITS_HAS_XXX(__has_pointer, pointer);
_LIBCPP_CLASS_TRAITS_HAS_XXX(__has_element_type, element_type);

template <class _Ptr, bool = __has_element_type<_Ptr>::value>
struct __pointer_traits_element_type {};
Expand Down Expand Up @@ -240,6 +249,59 @@ to_address(const _Pointer& __p) noexcept -> decltype(std::__to_address(__p)) {
}
#endif

#if _LIBCPP_STD_VER >= 23

template <class _Tp>
struct __pointer_of {};

template <class _Tp>
requires(__has_pointer<_Tp>::value)
struct __pointer_of<_Tp> {
using type = typename _Tp::pointer;
};

template <class _Tp>
requires(!__has_pointer<_Tp>::value && __has_element_type<_Tp>::value)
struct __pointer_of<_Tp> {
using type = typename _Tp::element_type*;
};

template <class _Tp>
requires(!__has_pointer<_Tp>::value && !__has_element_type<_Tp>::value &&
__has_element_type<pointer_traits<_Tp>>::value)
struct __pointer_of<_Tp> {
using type = typename pointer_traits<_Tp>::element_type*;
};

template <typename _Tp>
using __pointer_of_t = typename __pointer_of<_Tp>::type;

template <class _Tp, class _Up>
struct __pointer_of_or {
using type _LIBCPP_NODEBUG = _Up;
};

template <class _Tp, class _Up>
requires requires { typename __pointer_of_t<_Tp>; }
struct __pointer_of_or<_Tp, _Up> {
using type _LIBCPP_NODEBUG = __pointer_of_t<_Tp>;
};

template <typename _Tp, typename _Up>
using __pointer_of_or_t = typename __pointer_of_or<_Tp, _Up>::type;

template <class _Smart>
concept __resettable_smart_pointer = requires(_Smart __s) { __s.reset(); };

template <class _Smart, class _Pointer, class... _Args>
concept __resettable_smart_pointer_with_args = requires(_Smart __s, _Pointer __p, _Args... __args) {
__s.reset(static_cast<__pointer_of_or_t<_Smart, _Pointer>>(__p), std::forward<_Args>(__args)...);
};

#endif

_LIBCPP_END_NAMESPACE_STD

_LIBCPP_POP_MACROS

#endif // _LIBCPP___MEMORY_POINTER_TRAITS_H
Loading