-
Notifications
You must be signed in to change notification settings - Fork 11.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[libc++][memory] P1132R8:
out_ptr
- a scalable output pointer abstr…
…action (#73618) Differential Revision: https://reviews.llvm.org/D150525 Implements: - https://wg21.link/P1132R8 - `out_ptr` - a scalable output pointer abstraction - https://eel.is/c++draft/smartptr.adapt - 20.3.4 Smart pointer adaptors - https://wg21.link/LWG3734 - Inconsistency in `inout_ptr` and `out_ptr` for empty case - https://wg21.link/LWG3897- `inout_ptr` will not update raw pointer to 0 --------- Co-authored-by: Hristo Hristov <[email protected]>
- Loading branch information
1 parent
fe88052
commit 2f3a1ff
Showing
28 changed files
with
1,223 additions
and
62 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
// -*- 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 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>) { | ||
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...>, | ||
"The smart pointer must be constructible from arguments of types _Smart, _Pointer, _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>, "The conversion to void** requires _Pointer to be a raw 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)...); | ||
} | ||
|
||
#endif // _LIBCPP_STD_VER >= 23 | ||
|
||
_LIBCPP_END_NAMESPACE_STD | ||
|
||
_LIBCPP_POP_MACROS | ||
|
||
#endif // _LIBCPP___INOUT_PTR_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
// -*- 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, | ||
"Using std::shared_ptr<> without a deleter in std::out_ptr is not supported."); | ||
|
||
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>, | ||
"The adapted pointer type must have a reset() member function or be default constructible."); | ||
} | ||
} | ||
|
||
_LIBCPP_HIDE_FROM_ABI out_ptr_t(const out_ptr_t&) = delete; | ||
|
||
_LIBCPP_HIDE_FROM_ABI ~out_ptr_t() { | ||
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...>, | ||
"The smart pointer must be constructible from arguments of types _Smart, _Pointer, _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>, "The conversion to void** requires _Pointer to be a raw 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>; | ||
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.