30#ifndef _GLIBCXX_OUT_PTR_H
31#define _GLIBCXX_OUT_PTR_H 1
33#pragma GCC system_header
37#ifdef __glibcxx_out_ptr
42namespace std _GLIBCXX_VISIBILITY(default)
44_GLIBCXX_BEGIN_NAMESPACE_VERSION
54 template<
typename _Smart,
typename _Pointer,
typename... _Args>
58 static_assert(!__is_shared_ptr<_Smart> ||
sizeof...(_Args) != 0,
59 "a deleter must be used when adapting std::shared_ptr "
65 out_ptr_t(_Smart& __smart, _Args... __args)
66 : _M_impl{__smart,
std::
forward<_Args>(__args)...}
68 if constexpr (
requires { _M_impl._M_out_init(); })
69 _M_impl._M_out_init();
72 out_ptr_t(
const out_ptr_t&) =
delete;
74 ~out_ptr_t() =
default;
76 operator _Pointer*()
const noexcept
77 {
return _M_impl._M_get(); }
79 operator void**()
const noexcept requires (!same_as<_Pointer, void*>)
81 static_assert(is_pointer_v<_Pointer>);
82 _Pointer* __p = *
this;
83 return static_cast<void**
>(
static_cast<void*
>(__p));
88 template<
typename,
typename,
typename...>
94 _Impl(_Smart& __s, _Args&&... __args)
95 : _M_smart(__s), _M_args(
std::
forward<_Args>(__args)...)
104 if constexpr (
requires { _M_smart.reset(); })
114 { _M_ptr = _M_smart.release(); }
119 {
return __builtin_addressof(
const_cast<_Pointer&
>(_M_ptr)); }
122 ~_Impl() noexcept(false);
125 [[no_unique_address]] _Pointer _M_ptr{};
126 [[no_unique_address]] tuple<_Args...> _M_args;
130 template<
typename _Tp>
131 struct _Impl<_Tp*, _Tp*>
143 {
return __builtin_addressof(
const_cast<_Tp*&
>(_M_p)); }
149 template<
typename _Tp,
typename _Ptr>
requires (!is_same_v<_Ptr, _Tp*>)
150 struct _Impl<_Tp*, _Ptr>
167 {
return __builtin_addressof(
const_cast<_Pointer&
>(_M_ptr)); }
169 ~_Impl() { _M_p =
static_cast<_Tp*
>(_M_ptr); }
181 template<
typename _Tp,
typename _Del>
182 struct _Impl<unique_ptr<_Tp, _Del>,
183 typename unique_ptr<_Tp, _Del>::pointer>
187 { _M_smart.reset(); }
190 _M_get() const noexcept
191 {
return __builtin_addressof(_M_smart._M_t._M_ptr()); }
199 template<
typename _Tp,
typename _Del,
typename _Del2>
200 struct _Impl<unique_ptr<_Tp, _Del>,
201 typename unique_ptr<_Tp, _Del>::pointer, _Del2>
205 { _M_smart.reset(); }
208 _M_get() const noexcept
209 {
return __builtin_addressof(_M_smart._M_t._M_ptr()); }
218 [[no_unique_address]] _Del2 _M_del;
228 template<
typename _Tp,
typename _Del,
typename _Alloc>
229 requires (is_base_of_v<__shared_ptr<_Tp>, shared_ptr<_Tp>>)
230 struct _Impl<shared_ptr<_Tp>,
231 typename shared_ptr<_Tp>::element_type*, _Del, _Alloc>
233 _Impl(_Smart& __s, _Del __d, _Alloc __a = _Alloc())
242 typename _Scd::__allocator_type __a2(__a);
243 auto __mem = __a2.allocate(1);
246 _M_smart._M_refcount._M_pi = __mem;
250 _M_get() const noexcept
251 {
return __builtin_addressof(_M_smart._M_ptr); }
255 auto& __pi = _M_smart._M_refcount._M_pi;
257 if (_Sp __ptr = _M_smart.get())
258 static_cast<_Scd*
>(__pi)->_M_impl._M_ptr = __ptr;
260 std::__exchange(__pi,
nullptr)->_M_destroy();
265 using _Sp =
typename _Smart::element_type*;
266 using _Scd = _Sp_counted_deleter<_Sp, decay_t<_Del>,
267 remove_cvref_t<_Alloc>,
268 __default_lock_policy>;
272 template<
typename _Tp,
typename _Del>
273 requires (is_base_of_v<__shared_ptr<_Tp>, shared_ptr<_Tp>>)
274 struct _Impl<shared_ptr<_Tp>,
275 typename shared_ptr<_Tp>::element_type*, _Del>
276 : _Impl<_Smart, _Pointer, _Del, allocator<void>>
278 using _Impl<_Smart, _Pointer, _Del, allocator<void>>::_Impl;
282 using _Impl_t = _Impl<_Smart, _Pointer, _Args...>;
286 template<
typename,
typename,
typename...>
friend class inout_ptr_t;
297 template<
typename _Smart,
typename _Pointer,
typename... _Args>
301 static_assert(!__is_shared_ptr<_Smart>,
302 "std::inout_ptr can not be used to wrap std::shared_ptr");
307 inout_ptr_t(_Smart& __smart, _Args... __args)
308 : _M_impl{__smart,
std::
forward<_Args>(__args)...}
310 if constexpr (
requires { _M_impl._M_inout_init(); })
311 _M_impl._M_inout_init();
314 inout_ptr_t(
const inout_ptr_t&) =
delete;
316 ~inout_ptr_t() =
default;
318 operator _Pointer*()
const noexcept
319 {
return _M_impl._M_get(); }
321 operator void**()
const noexcept requires (!same_as<_Pointer, void*>)
323 static_assert(is_pointer_v<_Pointer>);
324 _Pointer* __p = *
this;
325 return static_cast<void**
>(
static_cast<void*
>(__p));
332 = __conditional_t<__is_shared_ptr<_Smart>,
333 out_ptr_t<void*, void*>,
334 out_ptr_t<_Smart, _Pointer, _Args...>>;
336 using _Out_ptr_t = out_ptr_t<_Smart, _Pointer, _Args...>;
338 using _Impl_t =
typename _Out_ptr_t::_Impl_t;
346 template<
typename _Tp>
350 if constexpr (
requires {
typename _Tp::pointer; })
351 return type_identity<typename _Tp::pointer>{};
352 else if constexpr (
requires {
typename _Tp::element_type; })
353 return type_identity<typename _Tp::element_type*>{};
356 using _Traits = pointer_traits<_Tp>;
357 if constexpr (
requires {
typename _Traits::element_type; })
358 return type_identity<typename _Traits::element_type*>{};
364 template<
typename _Smart,
typename _Ptr>
368 using _TypeId =
decltype(__detail::__pointer_of<_Smart>());
369 if constexpr (is_void_v<_TypeId>)
370 return type_identity<_Ptr>{};
376 template<
typename _Ptr,
typename _Smart>
380 if constexpr (!is_void_v<_Ptr>)
381 return type_identity<_Ptr>{};
383 return __detail::__pointer_of<_Smart>();
386 template<
typename _Smart,
typename _Sp,
typename... _Args>
387 concept __resettable =
requires (_Smart& __s) {
402 template<
typename _Pointer = void,
typename _Smart,
typename... _Args>
404 out_ptr(_Smart& __s, _Args&&... __args)
406 using _TypeId =
decltype(__detail::__choose_ptr<_Pointer, _Smart>());
407 static_assert(!is_void_v<_TypeId>,
"first argument to std::out_ptr "
408 "must be a pointer-like type");
410 using _Ret = out_ptr_t<_Smart,
typename _TypeId::type, _Args&&...>;
423 template<
typename _Pointer = void,
typename _Smart,
typename... _Args>
425 inout_ptr(_Smart& __s, _Args&&... __args)
427 using _TypeId =
decltype(__detail::__choose_ptr<_Pointer, _Smart>());
428 static_assert(!is_void_v<_TypeId>,
"first argument to std::inout_ptr "
429 "must be a pointer-like type");
431 using _Ret = inout_ptr_t<_Smart,
typename _TypeId::type, _Args&&...>;
436 template<
typename _Smart,
typename _Pointer,
typename... _Args>
437 template<
typename _Smart2,
typename _Pointer2,
typename... _Args2>
439 out_ptr_t<_Smart, _Pointer, _Args...>::
440 _Impl<_Smart2, _Pointer2, _Args2...>::~_Impl()
442 using _TypeId =
decltype(__detail::__pointer_of_or<_Smart, _Pointer>());
443 using _Sp =
typename _TypeId::type;
448 _Smart& __s = _M_smart;
449 _Pointer& __p = _M_ptr;
451 auto __reset = [&](
auto&&... __args) {
452 if constexpr (__detail::__resettable<_Smart, _Sp, _Args...>)
454 else if constexpr (is_constructible_v<_Smart, _Sp, _Args...>)
457 static_assert(is_constructible_v<_Smart, _Sp, _Args...>);
460 if constexpr (
sizeof...(_Args) >= 2)
462 else if constexpr (
sizeof...(_Args) == 1)
463 __reset(std::get<0>(
std::move(_M_args)));
469_GLIBCXX_END_NAMESPACE_VERSION
auto declval() noexcept -> decltype(__declval< _Tp >(0))
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
constexpr _Tp && forward(typename std::remove_reference< _Tp >::type &__t) noexcept
Forward an lvalue.
ISO C++ entities toplevel namespace is std.