30#ifndef _GLIBCXX_OUT_PTR_H
31#define _GLIBCXX_OUT_PTR_H 1
34#pragma GCC system_header
39#ifdef __glibcxx_out_ptr
44namespace std _GLIBCXX_VISIBILITY(default)
46_GLIBCXX_BEGIN_NAMESPACE_VERSION
56 template<
typename _Smart,
typename _Pointer,
typename... _Args>
60 static_assert(!__is_shared_ptr<_Smart> ||
sizeof...(_Args) != 0,
61 "a deleter must be used when adapting std::shared_ptr "
67 out_ptr_t(_Smart& __smart, _Args... __args)
68 : _M_impl{__smart, std::
forward<_Args>(__args)...}
70 if constexpr (
requires { _M_impl._M_out_init(); })
71 _M_impl._M_out_init();
74 out_ptr_t(
const out_ptr_t&) =
delete;
76 ~out_ptr_t() =
default;
78 operator _Pointer*()
const noexcept
79 {
return _M_impl._M_get(); }
81 operator void**()
const noexcept requires (!same_as<_Pointer, void*>)
83 static_assert(is_pointer_v<_Pointer>);
84 _Pointer* __p = *
this;
85 return static_cast<void**
>(
static_cast<void*
>(__p));
90 template<
typename,
typename,
typename...>
96 _Impl(_Smart& __s, _Args&&... __args)
97 : _M_smart(__s), _M_args(std::
forward<_Args>(__args)...)
106 if constexpr (
requires { _M_smart.reset(); })
116 { _M_ptr = _M_smart.release(); }
121 {
return __builtin_addressof(
const_cast<_Pointer&
>(_M_ptr)); }
124 ~_Impl() noexcept(false);
127 [[no_unique_address]] _Pointer _M_ptr{};
128 [[no_unique_address]] tuple<_Args...> _M_args;
132 template<
typename _Tp>
133 struct _Impl<_Tp*, _Tp*>
145 {
return __builtin_addressof(
const_cast<_Tp*&
>(_M_p)); }
151 template<
typename _Tp,
typename _Ptr>
requires (!is_same_v<_Ptr, _Tp*>)
152 struct _Impl<_Tp*, _Ptr>
169 {
return __builtin_addressof(
const_cast<_Pointer&
>(_M_ptr)); }
171 ~_Impl() { _M_p =
static_cast<_Tp*
>(_M_ptr); }
183 template<
typename _Tp,
typename _Del>
184 struct _Impl<unique_ptr<_Tp, _Del>,
185 typename unique_ptr<_Tp, _Del>::pointer>
189 { _M_smart.reset(); }
192 _M_get() const noexcept
193 {
return __builtin_addressof(_M_smart._M_t._M_ptr()); }
201 template<
typename _Tp,
typename _Del,
typename _Del2>
202 struct _Impl<unique_ptr<_Tp, _Del>,
203 typename unique_ptr<_Tp, _Del>::pointer, _Del2>
207 { _M_smart.reset(); }
210 _M_get() const noexcept
211 {
return __builtin_addressof(_M_smart._M_t._M_ptr()); }
220 [[no_unique_address]] _Del2 _M_del;
230 template<
typename _Tp,
typename _Del,
typename _Alloc>
231 requires (is_base_of_v<__shared_ptr<_Tp>, shared_ptr<_Tp>>)
232 struct _Impl<shared_ptr<_Tp>,
233 typename shared_ptr<_Tp>::element_type*, _Del, _Alloc>
235 _Impl(_Smart& __s, _Del __d, _Alloc __a = _Alloc())
244 typename _Scd::__allocator_type __a2(__a);
245 auto __mem = __a2.allocate(1);
248 _M_smart._M_refcount._M_pi = __mem;
252 _M_get() const noexcept
253 {
return __builtin_addressof(_M_smart._M_ptr); }
257 auto& __pi = _M_smart._M_refcount._M_pi;
259 if (_Sp __ptr = _M_smart.get())
260 static_cast<_Scd*
>(__pi)->_M_impl._M_ptr = __ptr;
262 std::__exchange(__pi,
nullptr)->_M_destroy();
267 using _Sp =
typename _Smart::element_type*;
268 using _Scd = _Sp_counted_deleter<_Sp, decay_t<_Del>,
269 remove_cvref_t<_Alloc>,
270 __default_lock_policy>;
274 template<
typename _Tp,
typename _Del>
275 requires (is_base_of_v<__shared_ptr<_Tp>, shared_ptr<_Tp>>)
276 struct _Impl<shared_ptr<_Tp>,
277 typename shared_ptr<_Tp>::element_type*, _Del>
278 : _Impl<_Smart, _Pointer, _Del, allocator<void>>
280 using _Impl<_Smart, _Pointer, _Del, allocator<void>>::_Impl;
284 using _Impl_t = _Impl<_Smart, _Pointer, _Args...>;
288 template<
typename,
typename,
typename...>
friend class inout_ptr_t;
299 template<
typename _Smart,
typename _Pointer,
typename... _Args>
303 static_assert(!__is_shared_ptr<_Smart>,
304 "std::inout_ptr can not be used to wrap std::shared_ptr");
309 inout_ptr_t(_Smart& __smart, _Args... __args)
310 : _M_impl{__smart, std::
forward<_Args>(__args)...}
312 if constexpr (
requires { _M_impl._M_inout_init(); })
313 _M_impl._M_inout_init();
316 inout_ptr_t(
const inout_ptr_t&) =
delete;
318 ~inout_ptr_t() =
default;
320 operator _Pointer*()
const noexcept
321 {
return _M_impl._M_get(); }
323 operator void**()
const noexcept requires (!same_as<_Pointer, void*>)
325 static_assert(is_pointer_v<_Pointer>);
326 _Pointer* __p = *
this;
327 return static_cast<void**
>(
static_cast<void*
>(__p));
334 = __conditional_t<__is_shared_ptr<_Smart>,
335 out_ptr_t<void*, void*>,
336 out_ptr_t<_Smart, _Pointer, _Args...>>;
338 using _Out_ptr_t = out_ptr_t<_Smart, _Pointer, _Args...>;
340 using _Impl_t =
typename _Out_ptr_t::_Impl_t;
348 template<
typename _Tp>
352 if constexpr (
requires {
typename _Tp::pointer; })
353 return type_identity<typename _Tp::pointer>{};
354 else if constexpr (
requires {
typename _Tp::element_type; })
355 return type_identity<typename _Tp::element_type*>{};
358 using _Traits = pointer_traits<_Tp>;
359 if constexpr (
requires {
typename _Traits::element_type; })
360 return type_identity<typename _Traits::element_type*>{};
366 template<
typename _Smart,
typename _Ptr>
370 using _TypeId =
decltype(__detail::__pointer_of<_Smart>());
371 if constexpr (is_void_v<_TypeId>)
372 return type_identity<_Ptr>{};
378 template<
typename _Ptr,
typename _Smart>
382 if constexpr (!is_void_v<_Ptr>)
383 return type_identity<_Ptr>{};
385 return __detail::__pointer_of<_Smart>();
388 template<
typename _Smart,
typename _Sp,
typename... _Args>
389 concept __resettable =
requires (_Smart& __s) {
404 template<
typename _Pointer = void,
typename _Smart,
typename... _Args>
406 out_ptr(_Smart& __s, _Args&&... __args)
408 using _TypeId =
decltype(__detail::__choose_ptr<_Pointer, _Smart>());
409 static_assert(!is_void_v<_TypeId>,
"first argument to std::out_ptr "
410 "must be a pointer-like type");
412 using _Ret = out_ptr_t<_Smart,
typename _TypeId::type, _Args&&...>;
425 template<
typename _Pointer = void,
typename _Smart,
typename... _Args>
427 inout_ptr(_Smart& __s, _Args&&... __args)
429 using _TypeId =
decltype(__detail::__choose_ptr<_Pointer, _Smart>());
430 static_assert(!is_void_v<_TypeId>,
"first argument to std::inout_ptr "
431 "must be a pointer-like type");
433 using _Ret = inout_ptr_t<_Smart,
typename _TypeId::type, _Args&&...>;
438 template<
typename _Smart,
typename _Pointer,
typename... _Args>
439 template<
typename _Smart2,
typename _Pointer2,
typename... _Args2>
441 out_ptr_t<_Smart, _Pointer, _Args...>::
442 _Impl<_Smart2, _Pointer2, _Args2...>::~_Impl()
444 using _TypeId =
decltype(__detail::__pointer_of_or<_Smart, _Pointer>());
445 using _Sp =
typename _TypeId::type;
450 _Smart& __s = _M_smart;
451 _Pointer& __p = _M_ptr;
453 auto __reset = [&](
auto&&... __args) {
454 if constexpr (__detail::__resettable<_Smart, _Sp, _Args...>)
456 else if constexpr (is_constructible_v<_Smart, _Sp, _Args...>)
459 static_assert(is_constructible_v<_Smart, _Sp, _Args...>);
462 if constexpr (
sizeof...(_Args) >= 2)
464 else if constexpr (
sizeof...(_Args) == 1)
465 __reset(std::get<0>(
std::move(_M_args)));
471_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.
Implementation details not part of the namespace std interface.