30 #ifndef _GLIBCXX_OUT_PTR_H
31 #define _GLIBCXX_OUT_PTR_H 1
33 #ifdef _GLIBCXX_SYSHDR
34 #pragma GCC system_header
39 #ifdef __glibcxx_out_ptr
44 namespace 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();
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>
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()); }
216 _M_smart._M_t._M_deleter() = std::forward<_Del2>(_M_del);
220 [[no_unique_address]] _Del2 _M_del;
230 template<
typename _Tp,
typename _Del,
typename _Alloc>
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);
246 ::new (__mem) _Scd(
nullptr, std::forward<_Del>(__d),
247 std::forward<_Alloc>(__a));
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>
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");
310 : _M_impl{__smart, std::forward<_Args>(__args)...}
312 if constexpr (
requires { _M_impl._M_inout_init(); })
313 _M_impl._M_inout_init();
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>,
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) {
390 __s.reset(std::declval<_Sp>(), std::declval<_Args>()...);
404 template<
typename _Pointer = void,
typename _Smart,
typename... _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&&...>;
413 return _Ret(__s, std::forward<_Args>(__args)...);
425 template<
typename _Pointer = void,
typename _Smart,
typename... _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&&...>;
434 return _Ret(__s, std::forward<_Args>(__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...>)
455 __s.reset(
static_cast<_Sp
>(__p), std::forward<_Args>(__args)...);
456 else if constexpr (is_constructible_v<_Smart, _Sp, _Args...>)
457 __s = _Smart(
static_cast<_Sp
>(__p), std::forward<_Args>(__args)...);
459 static_assert(is_constructible_v<_Smart, _Sp, _Args...>);
462 if constexpr (
sizeof...(_Args) >= 2)
464 else if constexpr (sizeof...(_Args) == 1)
471 _GLIBCXX_END_NAMESPACE_VERSION
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
ISO C++ entities toplevel namespace is std.
auto inout_ptr(_Smart &__s, _Args &&... __args)
Adapt a smart pointer for functions taking an inout pointer parameter.
auto out_ptr(_Smart &__s, _Args &&... __args)
Adapt a smart pointer for functions taking an output pointer parameter.
Primary class template, tuple.
Smart pointer adaptor for functions taking an output pointer parameter.
Smart pointer adaptor for functions taking an inout pointer parameter.
A smart pointer with reference-counted copy semantics.
A move-only smart pointer that manages unique ownership of a resource.