xref: /llvm-project/libcxx/include/__cxx03/__memory/out_ptr.h (revision ce7771902dc50d900de639d499a60486b83f70e0)
1e78f53d1SNikolas Klauser // -*- C++ -*-
2e78f53d1SNikolas Klauser //===----------------------------------------------------------------------===//
3e78f53d1SNikolas Klauser //
4e78f53d1SNikolas Klauser // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5e78f53d1SNikolas Klauser // See https://llvm.org/LICENSE.txt for license information.
6e78f53d1SNikolas Klauser // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7e78f53d1SNikolas Klauser //
8e78f53d1SNikolas Klauser //===----------------------------------------------------------------------===//
9e78f53d1SNikolas Klauser 
10*ce777190SNikolas Klauser #ifndef _LIBCPP___CXX03___OUT_PTR_H
11*ce777190SNikolas Klauser #define _LIBCPP___CXX03___OUT_PTR_H
12e78f53d1SNikolas Klauser 
1373fbae83SNikolas Klauser #include <__cxx03/__config>
1473fbae83SNikolas Klauser #include <__cxx03/__memory/addressof.h>
1573fbae83SNikolas Klauser #include <__cxx03/__memory/pointer_traits.h>
1673fbae83SNikolas Klauser #include <__cxx03/__memory/shared_ptr.h>
1773fbae83SNikolas Klauser #include <__cxx03/__memory/unique_ptr.h>
1873fbae83SNikolas Klauser #include <__cxx03/__type_traits/is_specialization.h>
1973fbae83SNikolas Klauser #include <__cxx03/__type_traits/is_void.h>
2073fbae83SNikolas Klauser #include <__cxx03/__utility/forward.h>
2173fbae83SNikolas Klauser #include <__cxx03/__utility/move.h>
2273fbae83SNikolas Klauser #include <__cxx03/tuple>
23e78f53d1SNikolas Klauser 
24e78f53d1SNikolas Klauser #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
25e78f53d1SNikolas Klauser #  pragma GCC system_header
26e78f53d1SNikolas Klauser #endif
27e78f53d1SNikolas Klauser 
28e78f53d1SNikolas Klauser _LIBCPP_PUSH_MACROS
2973fbae83SNikolas Klauser #include <__cxx03/__undef_macros>
30e78f53d1SNikolas Klauser 
31e78f53d1SNikolas Klauser _LIBCPP_BEGIN_NAMESPACE_STD
32e78f53d1SNikolas Klauser 
33e78f53d1SNikolas Klauser #if _LIBCPP_STD_VER >= 23
34e78f53d1SNikolas Klauser 
35e78f53d1SNikolas Klauser template <class _Smart, class _Pointer, class... _Args>
36e78f53d1SNikolas Klauser class _LIBCPP_TEMPLATE_VIS out_ptr_t {
37e78f53d1SNikolas Klauser   static_assert(!__is_specialization_v<_Smart, shared_ptr> || sizeof...(_Args) > 0,
38e78f53d1SNikolas Klauser                 "Using std::shared_ptr<> without a deleter in std::out_ptr is not supported.");
39e78f53d1SNikolas Klauser 
40e78f53d1SNikolas Klauser public:
41e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI explicit out_ptr_t(_Smart& __smart, _Args... __args)
42e78f53d1SNikolas Klauser       : __s_(__smart), __a_(std::forward<_Args>(__args)...), __p_() {
43e78f53d1SNikolas Klauser     using _Ptr = decltype(__smart);
44e78f53d1SNikolas Klauser     if constexpr (__resettable_smart_pointer<_Ptr>) {
45e78f53d1SNikolas Klauser       __s_.reset();
46e78f53d1SNikolas Klauser     } else if constexpr (is_constructible_v<_Smart>) {
47e78f53d1SNikolas Klauser       __s_ = _Smart();
48e78f53d1SNikolas Klauser     } else {
49e78f53d1SNikolas Klauser       static_assert(__resettable_smart_pointer<_Ptr> || is_constructible_v<_Smart>,
50e78f53d1SNikolas Klauser                     "The adapted pointer type must have a reset() member function or be default constructible.");
51e78f53d1SNikolas Klauser     }
52e78f53d1SNikolas Klauser   }
53e78f53d1SNikolas Klauser 
54e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI out_ptr_t(const out_ptr_t&) = delete;
55e78f53d1SNikolas Klauser 
56e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI ~out_ptr_t() {
57e78f53d1SNikolas Klauser     if (!__p_) {
58e78f53d1SNikolas Klauser       return;
59e78f53d1SNikolas Klauser     }
60e78f53d1SNikolas Klauser 
61e78f53d1SNikolas Klauser     using _SmartPtr = __pointer_of_or_t<_Smart, _Pointer>;
62e78f53d1SNikolas Klauser     if constexpr (__resettable_smart_pointer_with_args<_Smart, _Pointer, _Args...>) {
63e78f53d1SNikolas Klauser       std::apply([&](auto&&... __args) { __s_.reset(static_cast<_SmartPtr>(__p_), std::forward<_Args>(__args)...); },
64e78f53d1SNikolas Klauser                  std::move(__a_));
65e78f53d1SNikolas Klauser     } else {
66e78f53d1SNikolas Klauser       static_assert(is_constructible_v<_Smart, _SmartPtr, _Args...>,
67e78f53d1SNikolas Klauser                     "The smart pointer must be constructible from arguments of types _Smart, _Pointer, _Args...");
68e78f53d1SNikolas Klauser       std::apply([&](auto&&... __args) { __s_ = _Smart(static_cast<_SmartPtr>(__p_), std::forward<_Args>(__args)...); },
69e78f53d1SNikolas Klauser                  std::move(__a_));
70e78f53d1SNikolas Klauser     }
71e78f53d1SNikolas Klauser   }
72e78f53d1SNikolas Klauser 
73e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI operator _Pointer*() const noexcept { return std::addressof(const_cast<_Pointer&>(__p_)); }
74e78f53d1SNikolas Klauser 
75e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI operator void**() const noexcept
76e78f53d1SNikolas Klauser     requires(!is_same_v<_Pointer, void*>)
77e78f53d1SNikolas Klauser   {
78e78f53d1SNikolas Klauser     static_assert(is_pointer_v<_Pointer>, "The conversion to void** requires _Pointer to be a raw pointer.");
79e78f53d1SNikolas Klauser 
80e78f53d1SNikolas Klauser     return reinterpret_cast<void**>(static_cast<_Pointer*>(*this));
81e78f53d1SNikolas Klauser   }
82e78f53d1SNikolas Klauser 
83e78f53d1SNikolas Klauser private:
84e78f53d1SNikolas Klauser   _Smart& __s_;
85e78f53d1SNikolas Klauser   tuple<_Args...> __a_;
86e78f53d1SNikolas Klauser   _Pointer __p_ = _Pointer();
87e78f53d1SNikolas Klauser };
88e78f53d1SNikolas Klauser 
89e78f53d1SNikolas Klauser template <class _Pointer = void, class _Smart, class... _Args>
90e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI auto out_ptr(_Smart& __s, _Args&&... __args) {
91e78f53d1SNikolas Klauser   using _Ptr = conditional_t<is_void_v<_Pointer>, __pointer_of_t<_Smart>, _Pointer>;
92e78f53d1SNikolas Klauser   return std::out_ptr_t<_Smart, _Ptr, _Args&&...>(__s, std::forward<_Args>(__args)...);
93e78f53d1SNikolas Klauser }
94e78f53d1SNikolas Klauser 
95e78f53d1SNikolas Klauser #endif // _LIBCPP_STD_VER >= 23
96e78f53d1SNikolas Klauser 
97e78f53d1SNikolas Klauser _LIBCPP_END_NAMESPACE_STD
98e78f53d1SNikolas Klauser 
99e78f53d1SNikolas Klauser _LIBCPP_POP_MACROS
100e78f53d1SNikolas Klauser 
101*ce777190SNikolas Klauser #endif // _LIBCPP___CXX03___OUT_PTR_H
102