-
Notifications
You must be signed in to change notification settings - Fork 11.9k
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
Changes from 45 commits
84770c8
4bc779e
b23e91a
cb71ea2
c78d2ec
d9e04a7
3405ee5
2b2aaec
af88c85
ad38d72
d7c0439
54c2a41
1a4e2e8
378b374
1515a3d
a7fa18c
da7d5e5
df87f89
49fa86f
e4215e7
da17720
73c36a1
3b0a0c0
3073b70
ae04dfb
202889f
8dad901
c0541c6
2902fe5
398914a
a68df29
fbc5a81
cfd8356
2b300c9
2f859d4
8d19f94
7d59cf6
8fcbddc
34387e2
d321e86
3969659
f914c63
1f496d5
d4eed77
198d222
0fa9266
d46ef50
a2a453b
b0d0413
4d9dc5e
409f66a
8d31e72
ebe9e9d
2c4042e
5abf091
9866adc
d89e6eb
38640f1
a42fe5f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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"); | ||
|
||
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 |
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
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Or
Suggested change
|
||||||||||
|
||||||||||
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>); | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. An error message would be nice. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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() { | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
||||||||||
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.