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>
57 static_assert(!__is_shared_ptr<_Smart> ||
sizeof...(_Args) != 0,
58 "a deleter must be used when adapting std::shared_ptr "
63 out_ptr_t(_Smart& __smart, _Args... __args)
64 : _M_impl{__smart,
std::
forward<_Args>(__args)...}
66 if constexpr (
requires { _M_impl._M_out_init(); })
67 _M_impl._M_out_init();
70 out_ptr_t(
const out_ptr_t&) =
delete;
72 ~out_ptr_t() =
default;
74 operator _Pointer*()
const noexcept
75 {
return _M_impl._M_get(); }
77 operator void**()
const noexcept requires (!same_as<_Pointer, void*>)
79 static_assert(is_pointer_v<_Pointer>);
80 _Pointer* __p = *
this;
81 return static_cast<void**
>(
static_cast<void*
>(__p));
86 template<
typename,
typename,
typename...>
92 _Impl(_Smart& __s, _Args&&... __args)
93 : _M_smart(__s), _M_args(
std::
forward<_Args>(__args)...)
102 if constexpr (
requires { _M_smart.reset(); })
112 { _M_ptr = _M_smart.release(); }
117 {
return __builtin_addressof(
const_cast<_Pointer&
>(_M_ptr)); }
120 ~_Impl() noexcept(false);
123 [[no_unique_address]] _Pointer _M_ptr{};
124 [[no_unique_address]] tuple<_Args...> _M_args;
128 template<
typename _Tp>
129 struct _Impl<_Tp*, _Tp*>
141 {
return __builtin_addressof(
const_cast<_Tp*&
>(_M_p)); }
147 template<
typename _Tp,
typename _Ptr>
requires (!is_same_v<_Ptr, _Tp*>)
148 struct _Impl<_Tp*, _Ptr>
165 {
return __builtin_addressof(
const_cast<_Pointer&
>(_M_ptr)); }
167 ~_Impl() { _M_p =
static_cast<_Tp*
>(_M_ptr); }
179 template<
typename _Tp,
typename _Del>
180 struct _Impl<unique_ptr<_Tp, _Del>,
181 typename unique_ptr<_Tp, _Del>::pointer>
185 { _M_smart.reset(); }
188 _M_get() const noexcept
189 {
return __builtin_addressof(_M_smart._M_t._M_ptr()); }
197 template<
typename _Tp,
typename _Del,
typename _Del2>
198 struct _Impl<unique_ptr<_Tp, _Del>,
199 typename unique_ptr<_Tp, _Del>::pointer, _Del2>
203 { _M_smart.reset(); }
206 _M_get() const noexcept
207 {
return __builtin_addressof(_M_smart._M_t._M_ptr()); }
212 _M_smart._M_t._M_deleter() = std::forward<_Del2>(_M_del);
216 [[no_unique_address]] _Del2 _M_del;
225 template<
typename _Tp,
typename _Del,
typename _Alloc>
226 requires (is_base_of_v<__shared_ptr<_Tp>, shared_ptr<_Tp>>)
227 struct _Impl<shared_ptr<_Tp>,
228 typename shared_ptr<_Tp>::element_type*, _Del, _Alloc>
230 _Impl(_Smart& __s, _Del __d, _Alloc __a = _Alloc())
239 typename _Scd::__allocator_type __a2(__a);
240 auto __mem = __a2.allocate(1);
241 ::new (__mem) _Scd(
nullptr, std::forward<_Del>(__d),
242 std::forward<_Alloc>(__a));
243 _M_smart._M_refcount._M_pi = __mem;
247 _M_get() const noexcept
248 {
return __builtin_addressof(_M_smart._M_ptr); }
252 auto& __pi = _M_smart._M_refcount._M_pi;
254 if (_Sp __ptr = _M_smart.get())
255 static_cast<_Scd*
>(__pi)->_M_impl._M_ptr = __ptr;
257 std::__exchange(__pi,
nullptr)->_M_destroy();
262 using _Sp =
typename _Smart::element_type*;
263 using _Scd = _Sp_counted_deleter<_Sp, decay_t<_Del>,
264 remove_cvref_t<_Alloc>,
265 __default_lock_policy>;
269 template<
typename _Tp,
typename _Del>
270 requires (is_base_of_v<__shared_ptr<_Tp>, shared_ptr<_Tp>>)
271 struct _Impl<shared_ptr<_Tp>,
272 typename shared_ptr<_Tp>::element_type*, _Del>
273 : _Impl<_Smart, _Pointer, _Del, allocator<void>>
275 using _Impl<_Smart, _Pointer, _Del, allocator<void>>::_Impl;
278 using _Impl_t = _Impl<_Smart, _Pointer, _Args...>;
282 template<
typename,
typename,
typename...>
friend class inout_ptr_t;
293 template<
typename _Smart,
typename _Pointer,
typename... _Args>
296 static_assert(!__is_shared_ptr<_Smart>,
297 "std::inout_ptr can not be used to wrap std::shared_ptr");
301 inout_ptr_t(_Smart& __smart, _Args... __args)
302 : _M_impl{__smart,
std::
forward<_Args>(__args)...}
304 if constexpr (
requires { _M_impl._M_inout_init(); })
305 _M_impl._M_inout_init();
308 inout_ptr_t(
const inout_ptr_t&) =
delete;
310 ~inout_ptr_t() =
default;
312 operator _Pointer*()
const noexcept
313 {
return _M_impl._M_get(); }
315 operator void**()
const noexcept requires (!same_as<_Pointer, void*>)
317 static_assert(is_pointer_v<_Pointer>);
318 _Pointer* __p = *
this;
319 return static_cast<void**
>(
static_cast<void*
>(__p));
325 = __conditional_t<__is_shared_ptr<_Smart>,
326 out_ptr_t<void*, void*>,
327 out_ptr_t<_Smart, _Pointer, _Args...>>;
328 using _Impl_t =
typename _Out_ptr_t::_Impl_t;
336 template<
typename _Tp>
340 if constexpr (
requires {
typename _Tp::pointer; })
341 return type_identity<typename _Tp::pointer>{};
342 else if constexpr (
requires {
typename _Tp::element_type; })
343 return type_identity<typename _Tp::element_type*>{};
346 using _Traits = pointer_traits<_Tp>;
347 if constexpr (
requires {
typename _Traits::element_type; })
348 return type_identity<typename _Traits::element_type*>{};
354 template<
typename _Smart,
typename _Ptr>
358 using _TypeId =
decltype(__detail::__pointer_of<_Smart>());
359 if constexpr (is_void_v<_TypeId>)
360 return type_identity<_Ptr>{};
366 template<
typename _Ptr,
typename _Smart>
370 if constexpr (!is_void_v<_Ptr>)
371 return type_identity<_Ptr>{};
373 return __detail::__pointer_of<_Smart>();
376 template<
typename _Smart,
typename _Sp,
typename... _Args>
377 concept __resettable =
requires (_Smart& __s) {
378 __s.reset(std::declval<_Sp>(), std::declval<_Args>()...);
392 template<
typename _Pointer = void,
typename _Smart,
typename... _Args>
394 out_ptr(_Smart& __s, _Args&&... __args)
396 using _TypeId =
decltype(__detail::__choose_ptr<_Pointer, _Smart>());
397 static_assert(!is_void_v<_TypeId>,
"first argument to std::out_ptr "
398 "must be a pointer-like type");
400 using _Ret = out_ptr_t<_Smart,
typename _TypeId::type, _Args&&...>;
401 return _Ret(__s, std::forward<_Args>(__args)...);
413 template<
typename _Pointer = void,
typename _Smart,
typename... _Args>
415 inout_ptr(_Smart& __s, _Args&&... __args)
417 using _TypeId =
decltype(__detail::__choose_ptr<_Pointer, _Smart>());
418 static_assert(!is_void_v<_TypeId>,
"first argument to std::inout_ptr "
419 "must be a pointer-like type");
421 using _Ret = inout_ptr_t<_Smart,
typename _TypeId::type, _Args&&...>;
422 return _Ret(__s, std::forward<_Args>(__args)...);
426 template<
typename _Smart,
typename _Pointer,
typename... _Args>
427 template<
typename _Smart2,
typename _Pointer2,
typename... _Args2>
429 out_ptr_t<_Smart, _Pointer, _Args...>::
430 _Impl<_Smart2, _Pointer2, _Args2...>::~_Impl()
432 using _TypeId =
decltype(__detail::__pointer_of_or<_Smart, _Pointer>());
433 using _Sp =
typename _TypeId::type;
438 _Smart& __s = _M_smart;
439 _Pointer& __p = _M_ptr;
441 auto __reset = [&](
auto&&... __args) {
442 if constexpr (__detail::__resettable<_Smart, _Sp, _Args...>)
443 __s.reset(
static_cast<_Sp
>(__p), std::forward<_Args>(__args)...);
444 else if constexpr (is_constructible_v<_Smart, _Sp, _Args...>)
445 __s = _Smart(
static_cast<_Sp
>(__p), std::forward<_Args>(__args)...);
447 static_assert(is_constructible_v<_Smart, _Sp, _Args...>);
450 if constexpr (
sizeof...(_Args) >= 2)
452 else if constexpr (
sizeof...(_Args) == 1)
453 __reset(std::get<0>(
std::move(_M_args)));
459_GLIBCXX_END_NAMESPACE_VERSION
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.