Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-03 08:13:57

0001 // -*- C++ -*-
0002 //===----------------------------------------------------------------------===//
0003 //
0004 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0005 // See https://llvm.org/LICENSE.txt for license information.
0006 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0007 //
0008 //===----------------------------------------------------------------------===//
0009 
0010 #ifndef _LIBCPP___MEMORY_UNIQUE_PTR_H
0011 #define _LIBCPP___MEMORY_UNIQUE_PTR_H
0012 
0013 #include <__assert>
0014 #include <__compare/compare_three_way.h>
0015 #include <__compare/compare_three_way_result.h>
0016 #include <__compare/three_way_comparable.h>
0017 #include <__config>
0018 #include <__cstddef/nullptr_t.h>
0019 #include <__cstddef/size_t.h>
0020 #include <__functional/hash.h>
0021 #include <__functional/operations.h>
0022 #include <__memory/allocator_traits.h> // __pointer
0023 #include <__memory/array_cookie.h>
0024 #include <__memory/auto_ptr.h>
0025 #include <__memory/compressed_pair.h>
0026 #include <__memory/pointer_traits.h>
0027 #include <__type_traits/add_lvalue_reference.h>
0028 #include <__type_traits/common_type.h>
0029 #include <__type_traits/conditional.h>
0030 #include <__type_traits/dependent_type.h>
0031 #include <__type_traits/enable_if.h>
0032 #include <__type_traits/integral_constant.h>
0033 #include <__type_traits/is_array.h>
0034 #include <__type_traits/is_assignable.h>
0035 #include <__type_traits/is_bounded_array.h>
0036 #include <__type_traits/is_constant_evaluated.h>
0037 #include <__type_traits/is_constructible.h>
0038 #include <__type_traits/is_convertible.h>
0039 #include <__type_traits/is_function.h>
0040 #include <__type_traits/is_pointer.h>
0041 #include <__type_traits/is_reference.h>
0042 #include <__type_traits/is_same.h>
0043 #include <__type_traits/is_swappable.h>
0044 #include <__type_traits/is_trivially_relocatable.h>
0045 #include <__type_traits/is_unbounded_array.h>
0046 #include <__type_traits/is_void.h>
0047 #include <__type_traits/remove_extent.h>
0048 #include <__type_traits/type_identity.h>
0049 #include <__utility/declval.h>
0050 #include <__utility/forward.h>
0051 #include <__utility/move.h>
0052 #include <__utility/private_constructor_tag.h>
0053 #include <cstdint>
0054 
0055 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0056 #  pragma GCC system_header
0057 #endif
0058 
0059 _LIBCPP_PUSH_MACROS
0060 #include <__undef_macros>
0061 
0062 _LIBCPP_BEGIN_NAMESPACE_STD
0063 
0064 template <class _Tp>
0065 struct _LIBCPP_TEMPLATE_VIS default_delete {
0066   static_assert(!is_function<_Tp>::value, "default_delete cannot be instantiated for function types");
0067 #ifndef _LIBCPP_CXX03_LANG
0068   _LIBCPP_HIDE_FROM_ABI constexpr default_delete() _NOEXCEPT = default;
0069 #else
0070   _LIBCPP_HIDE_FROM_ABI default_delete() {}
0071 #endif
0072   template <class _Up, __enable_if_t<is_convertible<_Up*, _Tp*>::value, int> = 0>
0073   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 default_delete(const default_delete<_Up>&) _NOEXCEPT {}
0074 
0075   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void operator()(_Tp* __ptr) const _NOEXCEPT {
0076     static_assert(sizeof(_Tp) >= 0, "cannot delete an incomplete type");
0077     static_assert(!is_void<_Tp>::value, "cannot delete an incomplete type");
0078     delete __ptr;
0079   }
0080 };
0081 
0082 template <class _Tp>
0083 struct _LIBCPP_TEMPLATE_VIS default_delete<_Tp[]> {
0084 private:
0085   template <class _Up>
0086   struct _EnableIfConvertible : enable_if<is_convertible<_Up (*)[], _Tp (*)[]>::value> {};
0087 
0088 public:
0089 #ifndef _LIBCPP_CXX03_LANG
0090   _LIBCPP_HIDE_FROM_ABI constexpr default_delete() _NOEXCEPT = default;
0091 #else
0092   _LIBCPP_HIDE_FROM_ABI default_delete() {}
0093 #endif
0094 
0095   template <class _Up>
0096   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23
0097   default_delete(const default_delete<_Up[]>&, typename _EnableIfConvertible<_Up>::type* = 0) _NOEXCEPT {}
0098 
0099   template <class _Up>
0100   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 typename _EnableIfConvertible<_Up>::type
0101   operator()(_Up* __ptr) const _NOEXCEPT {
0102     static_assert(sizeof(_Up) >= 0, "cannot delete an incomplete type");
0103     delete[] __ptr;
0104   }
0105 };
0106 
0107 template <class _Deleter>
0108 struct __is_default_deleter : false_type {};
0109 
0110 template <class _Tp>
0111 struct __is_default_deleter<default_delete<_Tp> > : true_type {};
0112 
0113 template <class _Deleter>
0114 struct __unique_ptr_deleter_sfinae {
0115   static_assert(!is_reference<_Deleter>::value, "incorrect specialization");
0116   typedef const _Deleter& __lval_ref_type;
0117   typedef _Deleter&& __good_rval_ref_type;
0118   typedef true_type __enable_rval_overload;
0119 };
0120 
0121 template <class _Deleter>
0122 struct __unique_ptr_deleter_sfinae<_Deleter const&> {
0123   typedef const _Deleter& __lval_ref_type;
0124   typedef const _Deleter&& __bad_rval_ref_type;
0125   typedef false_type __enable_rval_overload;
0126 };
0127 
0128 template <class _Deleter>
0129 struct __unique_ptr_deleter_sfinae<_Deleter&> {
0130   typedef _Deleter& __lval_ref_type;
0131   typedef _Deleter&& __bad_rval_ref_type;
0132   typedef false_type __enable_rval_overload;
0133 };
0134 
0135 #if defined(_LIBCPP_ABI_ENABLE_UNIQUE_PTR_TRIVIAL_ABI)
0136 #  define _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI __attribute__((__trivial_abi__))
0137 #else
0138 #  define _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI
0139 #endif
0140 
0141 template <class _Tp, class _Dp = default_delete<_Tp> >
0142 class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr {
0143 public:
0144   typedef _Tp element_type;
0145   typedef _Dp deleter_type;
0146   using pointer _LIBCPP_NODEBUG = __pointer<_Tp, deleter_type>;
0147 
0148   static_assert(!is_rvalue_reference<deleter_type>::value, "the specified deleter type cannot be an rvalue reference");
0149 
0150   // A unique_ptr contains the following members which may be trivially relocatable:
0151   // - pointer : this may be trivially relocatable, so it's checked
0152   // - deleter_type: this may be trivially relocatable, so it's checked
0153   //
0154   // This unique_ptr implementation only contains a pointer to the unique object and a deleter, so there are no
0155   // references to itself. This means that the entire structure is trivially relocatable if its members are.
0156   using __trivially_relocatable _LIBCPP_NODEBUG = __conditional_t<
0157       __libcpp_is_trivially_relocatable<pointer>::value && __libcpp_is_trivially_relocatable<deleter_type>::value,
0158       unique_ptr,
0159       void>;
0160 
0161 private:
0162   _LIBCPP_COMPRESSED_PAIR(pointer, __ptr_, deleter_type, __deleter_);
0163 
0164   using _DeleterSFINAE _LIBCPP_NODEBUG = __unique_ptr_deleter_sfinae<_Dp>;
0165 
0166   template <bool _Dummy>
0167   using _LValRefType _LIBCPP_NODEBUG = typename __dependent_type<_DeleterSFINAE, _Dummy>::__lval_ref_type;
0168 
0169   template <bool _Dummy>
0170   using _GoodRValRefType _LIBCPP_NODEBUG = typename __dependent_type<_DeleterSFINAE, _Dummy>::__good_rval_ref_type;
0171 
0172   template <bool _Dummy>
0173   using _BadRValRefType _LIBCPP_NODEBUG = typename __dependent_type<_DeleterSFINAE, _Dummy>::__bad_rval_ref_type;
0174 
0175   template <bool _Dummy, class _Deleter = typename __dependent_type< __type_identity<deleter_type>, _Dummy>::type>
0176   using _EnableIfDeleterDefaultConstructible _LIBCPP_NODEBUG =
0177       __enable_if_t<is_default_constructible<_Deleter>::value && !is_pointer<_Deleter>::value>;
0178 
0179   template <class _ArgType>
0180   using _EnableIfDeleterConstructible _LIBCPP_NODEBUG = __enable_if_t<is_constructible<deleter_type, _ArgType>::value>;
0181 
0182   template <class _UPtr, class _Up>
0183   using _EnableIfMoveConvertible _LIBCPP_NODEBUG =
0184       __enable_if_t< is_convertible<typename _UPtr::pointer, pointer>::value && !is_array<_Up>::value >;
0185 
0186   template <class _UDel>
0187   using _EnableIfDeleterConvertible _LIBCPP_NODEBUG =
0188       __enable_if_t< (is_reference<_Dp>::value && is_same<_Dp, _UDel>::value) ||
0189                      (!is_reference<_Dp>::value && is_convertible<_UDel, _Dp>::value) >;
0190 
0191   template <class _UDel>
0192   using _EnableIfDeleterAssignable _LIBCPP_NODEBUG = __enable_if_t< is_assignable<_Dp&, _UDel&&>::value >;
0193 
0194 public:
0195   template <bool _Dummy = true, class = _EnableIfDeleterDefaultConstructible<_Dummy> >
0196   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR unique_ptr() _NOEXCEPT : __ptr_(), __deleter_() {}
0197 
0198   template <bool _Dummy = true, class = _EnableIfDeleterDefaultConstructible<_Dummy> >
0199   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR unique_ptr(nullptr_t) _NOEXCEPT : __ptr_(), __deleter_() {}
0200 
0201   template <bool _Dummy = true, class = _EnableIfDeleterDefaultConstructible<_Dummy> >
0202   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit unique_ptr(pointer __p) _NOEXCEPT
0203       : __ptr_(__p),
0204         __deleter_() {}
0205 
0206   template <bool _Dummy = true, class = _EnableIfDeleterConstructible<_LValRefType<_Dummy> > >
0207   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(pointer __p, _LValRefType<_Dummy> __d) _NOEXCEPT
0208       : __ptr_(__p),
0209         __deleter_(__d) {}
0210 
0211   template <bool _Dummy = true, class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy> > >
0212   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(pointer __p, _GoodRValRefType<_Dummy> __d) _NOEXCEPT
0213       : __ptr_(__p),
0214         __deleter_(std::move(__d)) {
0215     static_assert(!is_reference<deleter_type>::value, "rvalue deleter bound to reference");
0216   }
0217 
0218   template <bool _Dummy = true, class = _EnableIfDeleterConstructible<_BadRValRefType<_Dummy> > >
0219   _LIBCPP_HIDE_FROM_ABI unique_ptr(pointer __p, _BadRValRefType<_Dummy> __d) = delete;
0220 
0221   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(unique_ptr&& __u) _NOEXCEPT
0222       : __ptr_(__u.release()),
0223         __deleter_(std::forward<deleter_type>(__u.get_deleter())) {}
0224 
0225   template <class _Up,
0226             class _Ep,
0227             class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>,
0228             class = _EnableIfDeleterConvertible<_Ep> >
0229   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT
0230       : __ptr_(__u.release()),
0231         __deleter_(std::forward<_Ep>(__u.get_deleter())) {}
0232 
0233 #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR)
0234   template <class _Up,
0235             __enable_if_t<is_convertible<_Up*, _Tp*>::value && is_same<_Dp, default_delete<_Tp> >::value, int> = 0>
0236   _LIBCPP_HIDE_FROM_ABI unique_ptr(auto_ptr<_Up>&& __p) _NOEXCEPT : __ptr_(__p.release()), __deleter_() {}
0237 #endif
0238 
0239   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr& operator=(unique_ptr&& __u) _NOEXCEPT {
0240     reset(__u.release());
0241     __deleter_ = std::forward<deleter_type>(__u.get_deleter());
0242     return *this;
0243   }
0244 
0245   template <class _Up,
0246             class _Ep,
0247             class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>,
0248             class = _EnableIfDeleterAssignable<_Ep> >
0249   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr& operator=(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT {
0250     reset(__u.release());
0251     __deleter_ = std::forward<_Ep>(__u.get_deleter());
0252     return *this;
0253   }
0254 
0255 #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR)
0256   template <class _Up,
0257             __enable_if_t<is_convertible<_Up*, _Tp*>::value && is_same<_Dp, default_delete<_Tp> >::value, int> = 0>
0258   _LIBCPP_HIDE_FROM_ABI unique_ptr& operator=(auto_ptr<_Up> __p) {
0259     reset(__p.release());
0260     return *this;
0261   }
0262 #endif
0263 
0264 #ifdef _LIBCPP_CXX03_LANG
0265   unique_ptr(unique_ptr const&)            = delete;
0266   unique_ptr& operator=(unique_ptr const&) = delete;
0267 #endif
0268 
0269   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 ~unique_ptr() { reset(); }
0270 
0271   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr& operator=(nullptr_t) _NOEXCEPT {
0272     reset();
0273     return *this;
0274   }
0275 
0276   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 __add_lvalue_reference_t<_Tp> operator*() const
0277       _NOEXCEPT_(_NOEXCEPT_(*std::declval<pointer>())) {
0278     return *__ptr_;
0279   }
0280   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer operator->() const _NOEXCEPT { return __ptr_; }
0281   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer get() const _NOEXCEPT { return __ptr_; }
0282   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 deleter_type& get_deleter() _NOEXCEPT { return __deleter_; }
0283   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 const deleter_type& get_deleter() const _NOEXCEPT {
0284     return __deleter_;
0285   }
0286   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit operator bool() const _NOEXCEPT {
0287     return __ptr_ != nullptr;
0288   }
0289 
0290   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer release() _NOEXCEPT {
0291     pointer __t = __ptr_;
0292     __ptr_      = pointer();
0293     return __t;
0294   }
0295 
0296   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void reset(pointer __p = pointer()) _NOEXCEPT {
0297     pointer __tmp = __ptr_;
0298     __ptr_        = __p;
0299     if (__tmp)
0300       __deleter_(__tmp);
0301   }
0302 
0303   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void swap(unique_ptr& __u) _NOEXCEPT {
0304     using std::swap;
0305     swap(__ptr_, __u.__ptr_);
0306     swap(__deleter_, __u.__deleter_);
0307   }
0308 };
0309 
0310 // Bounds checking in unique_ptr<T[]>
0311 // ==================================
0312 //
0313 // We provide some helper classes that allow bounds checking when accessing a unique_ptr<T[]>.
0314 // There are a few cases where bounds checking can be implemented:
0315 //
0316 // 1. When an array cookie (see [1]) exists at the beginning of the array allocation, we are
0317 //    able to reuse that cookie to extract the size of the array and perform bounds checking.
0318 //    An array cookie is a size inserted at the beginning of the allocation by the compiler.
0319 //    That size is inserted implicitly when doing `new T[n]` in some cases (as of writing this
0320 //    exactly when the array elements are not trivially destructible), and its main purpose is
0321 //    to allow the runtime to destroy the `n` array elements when doing `delete[] array`.
0322 //    When we are able to use array cookies, we reuse information already available in the
0323 //    current runtime, so bounds checking does not require changing libc++'s ABI.
0324 //
0325 //    However, note that we cannot assume the presence of an array cookie when a custom deleter
0326 //    is used, because the unique_ptr could have been created from an allocation that wasn't
0327 //    obtained via `new T[n]` (since it may not be deleted with `delete[] arr`).
0328 //
0329 // 2. When the "bounded unique_ptr" ABI configuration (controlled by `_LIBCPP_ABI_BOUNDED_UNIQUE_PTR`)
0330 //    is enabled, we store the size of the allocation (when it is known) so we can check it when
0331 //    indexing into the `unique_ptr`. That changes the layout of `std::unique_ptr<T[]>`, which is
0332 //    an ABI break from the default configuration.
0333 //
0334 //    Note that even under this ABI configuration, we can't always know the size of the unique_ptr.
0335 //    Indeed, the size of the allocation can only be known when the unique_ptr is created via
0336 //    make_unique or a similar API. For example, it can't be known when constructed from an arbitrary
0337 //    pointer, in which case we are not able to check the bounds on access:
0338 //
0339 //      unique_ptr<T[], MyDeleter> ptr(new T[3]);
0340 //
0341 //    When we don't know the size of the allocation via the API used to create the unique_ptr, we
0342 //    try to fall back to using an array cookie when available.
0343 //
0344 //    Finally, note that when this ABI configuration is enabled, we have no choice but to always
0345 //    make space for the size to be stored in the unique_ptr. Indeed, while we might want to avoid
0346 //    storing the size when an array cookie is available, knowing whether an array cookie is available
0347 //    requires the type stored in the unique_ptr to be complete, while unique_ptr can normally
0348 //    accommodate incomplete types.
0349 //
0350 // (1) Implementation where we rely on the array cookie to know the size of the allocation, if
0351 //     an array cookie exists.
0352 struct __unique_ptr_array_bounds_stateless {
0353   __unique_ptr_array_bounds_stateless() = default;
0354   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __unique_ptr_array_bounds_stateless(size_t) {}
0355 
0356   template <class _Deleter,
0357             class _Tp,
0358             __enable_if_t<__is_default_deleter<_Deleter>::value && __has_array_cookie<_Tp>::value, int> = 0>
0359   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool __in_bounds(_Tp* __ptr, size_t __index) const {
0360     // In constant expressions, we can't check the array cookie so we just pretend that the index
0361     // is in-bounds. The compiler catches invalid accesses anyway.
0362     if (__libcpp_is_constant_evaluated())
0363       return true;
0364     size_t __cookie = std::__get_array_cookie(__ptr);
0365     return __index < __cookie;
0366   }
0367 
0368   template <class _Deleter,
0369             class _Tp,
0370             __enable_if_t<!__is_default_deleter<_Deleter>::value || !__has_array_cookie<_Tp>::value, int> = 0>
0371   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool __in_bounds(_Tp*, size_t) const {
0372     return true; // If we don't have an array cookie, we assume the access is in-bounds
0373   }
0374 };
0375 
0376 // (2) Implementation where we store the size in the class whenever we have it.
0377 //
0378 // Semantically, we'd need to store the size as an optional<size_t>. However, since that
0379 // is really heavy weight, we instead store a size_t and use SIZE_MAX as a magic value
0380 // meaning that we don't know the size.
0381 struct __unique_ptr_array_bounds_stored {
0382   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __unique_ptr_array_bounds_stored() : __size_(SIZE_MAX) {}
0383   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __unique_ptr_array_bounds_stored(size_t __size) : __size_(__size) {}
0384 
0385   // Use the array cookie if there's one
0386   template <class _Deleter,
0387             class _Tp,
0388             __enable_if_t<__is_default_deleter<_Deleter>::value && __has_array_cookie<_Tp>::value, int> = 0>
0389   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool __in_bounds(_Tp* __ptr, size_t __index) const {
0390     if (__libcpp_is_constant_evaluated())
0391       return true;
0392     size_t __cookie = std::__get_array_cookie(__ptr);
0393     return __index < __cookie;
0394   }
0395 
0396   // Otherwise, fall back on the stored size (if any)
0397   template <class _Deleter,
0398             class _Tp,
0399             __enable_if_t<!__is_default_deleter<_Deleter>::value || !__has_array_cookie<_Tp>::value, int> = 0>
0400   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool __in_bounds(_Tp*, size_t __index) const {
0401     return __index < __size_;
0402   }
0403 
0404 private:
0405   size_t __size_;
0406 };
0407 
0408 template <class _Tp, class _Dp>
0409 class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp> {
0410 public:
0411   typedef _Tp element_type;
0412   typedef _Dp deleter_type;
0413   using pointer = __pointer<_Tp, deleter_type>;
0414 
0415   // A unique_ptr contains the following members which may be trivially relocatable:
0416   // - pointer: this may be trivially relocatable, so it's checked
0417   // - deleter_type: this may be trivially relocatable, so it's checked
0418   // - (optionally) size: this is trivially relocatable
0419   //
0420   // This unique_ptr implementation only contains a pointer to the unique object and a deleter, so there are no
0421   // references to itself. This means that the entire structure is trivially relocatable if its members are.
0422   using __trivially_relocatable _LIBCPP_NODEBUG = __conditional_t<
0423       __libcpp_is_trivially_relocatable<pointer>::value && __libcpp_is_trivially_relocatable<deleter_type>::value,
0424       unique_ptr,
0425       void>;
0426 
0427 private:
0428   template <class _Up, class _OtherDeleter>
0429   friend class unique_ptr;
0430 
0431   _LIBCPP_COMPRESSED_PAIR(pointer, __ptr_, deleter_type, __deleter_);
0432 #ifdef _LIBCPP_ABI_BOUNDED_UNIQUE_PTR
0433   using _BoundsChecker _LIBCPP_NODEBUG = __unique_ptr_array_bounds_stored;
0434 #else
0435   using _BoundsChecker _LIBCPP_NODEBUG = __unique_ptr_array_bounds_stateless;
0436 #endif
0437   _LIBCPP_NO_UNIQUE_ADDRESS _BoundsChecker __checker_;
0438 
0439   template <class _From>
0440   struct _CheckArrayPointerConversion : is_same<_From, pointer> {};
0441 
0442   template <class _FromElem>
0443   struct _CheckArrayPointerConversion<_FromElem*>
0444       : integral_constant<bool,
0445                           is_same<_FromElem*, pointer>::value ||
0446                               (is_same<pointer, element_type*>::value &&
0447                                is_convertible<_FromElem (*)[], element_type (*)[]>::value) > {};
0448 
0449   typedef __unique_ptr_deleter_sfinae<_Dp> _DeleterSFINAE;
0450 
0451   template <bool _Dummy>
0452   using _LValRefType _LIBCPP_NODEBUG = typename __dependent_type<_DeleterSFINAE, _Dummy>::__lval_ref_type;
0453 
0454   template <bool _Dummy>
0455   using _GoodRValRefType _LIBCPP_NODEBUG = typename __dependent_type<_DeleterSFINAE, _Dummy>::__good_rval_ref_type;
0456 
0457   template <bool _Dummy>
0458   using _BadRValRefType _LIBCPP_NODEBUG = typename __dependent_type<_DeleterSFINAE, _Dummy>::__bad_rval_ref_type;
0459 
0460   template <bool _Dummy, class _Deleter = typename __dependent_type< __type_identity<deleter_type>, _Dummy>::type>
0461   using _EnableIfDeleterDefaultConstructible _LIBCPP_NODEBUG =
0462       __enable_if_t<is_default_constructible<_Deleter>::value && !is_pointer<_Deleter>::value>;
0463 
0464   template <class _ArgType>
0465   using _EnableIfDeleterConstructible _LIBCPP_NODEBUG = __enable_if_t<is_constructible<deleter_type, _ArgType>::value>;
0466 
0467   template <class _Pp>
0468   using _EnableIfPointerConvertible _LIBCPP_NODEBUG = __enable_if_t< _CheckArrayPointerConversion<_Pp>::value >;
0469 
0470   template <class _UPtr, class _Up, class _ElemT = typename _UPtr::element_type>
0471   using _EnableIfMoveConvertible _LIBCPP_NODEBUG =
0472       __enable_if_t< is_array<_Up>::value && is_same<pointer, element_type*>::value &&
0473                      is_same<typename _UPtr::pointer, _ElemT*>::value &&
0474                      is_convertible<_ElemT (*)[], element_type (*)[]>::value >;
0475 
0476   template <class _UDel>
0477   using _EnableIfDeleterConvertible _LIBCPP_NODEBUG =
0478       __enable_if_t< (is_reference<_Dp>::value && is_same<_Dp, _UDel>::value) ||
0479                      (!is_reference<_Dp>::value && is_convertible<_UDel, _Dp>::value) >;
0480 
0481   template <class _UDel>
0482   using _EnableIfDeleterAssignable _LIBCPP_NODEBUG = __enable_if_t< is_assignable<_Dp&, _UDel&&>::value >;
0483 
0484 public:
0485   template <bool _Dummy = true, class = _EnableIfDeleterDefaultConstructible<_Dummy> >
0486   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR unique_ptr() _NOEXCEPT : __ptr_(), __deleter_() {}
0487 
0488   template <bool _Dummy = true, class = _EnableIfDeleterDefaultConstructible<_Dummy> >
0489   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR unique_ptr(nullptr_t) _NOEXCEPT : __ptr_(), __deleter_() {}
0490 
0491   template <class _Pp,
0492             bool _Dummy = true,
0493             class       = _EnableIfDeleterDefaultConstructible<_Dummy>,
0494             class       = _EnableIfPointerConvertible<_Pp> >
0495   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit unique_ptr(_Pp __ptr) _NOEXCEPT
0496       : __ptr_(__ptr),
0497         __deleter_() {}
0498 
0499   // Private constructor used by make_unique & friends to pass the size that was allocated
0500   template <class _Tag, class _Ptr, __enable_if_t<is_same<_Tag, __private_constructor_tag>::value, int> = 0>
0501   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit unique_ptr(_Tag, _Ptr __ptr, size_t __size) _NOEXCEPT
0502       : __ptr_(__ptr),
0503         __checker_(__size) {}
0504 
0505   template <class _Pp,
0506             bool _Dummy = true,
0507             class       = _EnableIfDeleterConstructible<_LValRefType<_Dummy> >,
0508             class       = _EnableIfPointerConvertible<_Pp> >
0509   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(_Pp __ptr, _LValRefType<_Dummy> __deleter) _NOEXCEPT
0510       : __ptr_(__ptr),
0511         __deleter_(__deleter) {}
0512 
0513   template <bool _Dummy = true, class = _EnableIfDeleterConstructible<_LValRefType<_Dummy> > >
0514   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(nullptr_t, _LValRefType<_Dummy> __deleter) _NOEXCEPT
0515       : __ptr_(nullptr),
0516         __deleter_(__deleter) {}
0517 
0518   template <class _Pp,
0519             bool _Dummy = true,
0520             class       = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy> >,
0521             class       = _EnableIfPointerConvertible<_Pp> >
0522   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23
0523   unique_ptr(_Pp __ptr, _GoodRValRefType<_Dummy> __deleter) _NOEXCEPT
0524       : __ptr_(__ptr),
0525         __deleter_(std::move(__deleter)) {
0526     static_assert(!is_reference<deleter_type>::value, "rvalue deleter bound to reference");
0527   }
0528 
0529   template <bool _Dummy = true, class = _EnableIfDeleterConstructible<_GoodRValRefType<_Dummy> > >
0530   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23
0531   unique_ptr(nullptr_t, _GoodRValRefType<_Dummy> __deleter) _NOEXCEPT
0532       : __ptr_(nullptr),
0533         __deleter_(std::move(__deleter)) {
0534     static_assert(!is_reference<deleter_type>::value, "rvalue deleter bound to reference");
0535   }
0536 
0537   template <class _Pp,
0538             bool _Dummy = true,
0539             class       = _EnableIfDeleterConstructible<_BadRValRefType<_Dummy> >,
0540             class       = _EnableIfPointerConvertible<_Pp> >
0541   _LIBCPP_HIDE_FROM_ABI unique_ptr(_Pp __ptr, _BadRValRefType<_Dummy> __deleter) = delete;
0542 
0543   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(unique_ptr&& __u) _NOEXCEPT
0544       : __ptr_(__u.release()),
0545         __deleter_(std::forward<deleter_type>(__u.get_deleter())),
0546         __checker_(std::move(__u.__checker_)) {}
0547 
0548   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr& operator=(unique_ptr&& __u) _NOEXCEPT {
0549     reset(__u.release());
0550     __deleter_ = std::forward<deleter_type>(__u.get_deleter());
0551     __checker_ = std::move(__u.__checker_);
0552     return *this;
0553   }
0554 
0555   template <class _Up,
0556             class _Ep,
0557             class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>,
0558             class = _EnableIfDeleterConvertible<_Ep> >
0559   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT
0560       : __ptr_(__u.release()),
0561         __deleter_(std::forward<_Ep>(__u.get_deleter())),
0562         __checker_(std::move(__u.__checker_)) {}
0563 
0564   template <class _Up,
0565             class _Ep,
0566             class = _EnableIfMoveConvertible<unique_ptr<_Up, _Ep>, _Up>,
0567             class = _EnableIfDeleterAssignable<_Ep> >
0568   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr& operator=(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT {
0569     reset(__u.release());
0570     __deleter_ = std::forward<_Ep>(__u.get_deleter());
0571     __checker_ = std::move(__u.__checker_);
0572     return *this;
0573   }
0574 
0575 #ifdef _LIBCPP_CXX03_LANG
0576   unique_ptr(unique_ptr const&)            = delete;
0577   unique_ptr& operator=(unique_ptr const&) = delete;
0578 #endif
0579 
0580 public:
0581   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 ~unique_ptr() { reset(); }
0582 
0583   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr& operator=(nullptr_t) _NOEXCEPT {
0584     reset();
0585     return *this;
0586   }
0587 
0588   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 __add_lvalue_reference_t<_Tp> operator[](size_t __i) const {
0589     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__checker_.__in_bounds<deleter_type>(std::__to_address(__ptr_), __i),
0590                                         "unique_ptr<T[]>::operator[](index): index out of range");
0591     return __ptr_[__i];
0592   }
0593   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer get() const _NOEXCEPT { return __ptr_; }
0594 
0595   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 deleter_type& get_deleter() _NOEXCEPT { return __deleter_; }
0596 
0597   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 const deleter_type& get_deleter() const _NOEXCEPT {
0598     return __deleter_;
0599   }
0600   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit operator bool() const _NOEXCEPT {
0601     return __ptr_ != nullptr;
0602   }
0603 
0604   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer release() _NOEXCEPT {
0605     pointer __t = __ptr_;
0606     __ptr_      = pointer();
0607     // The deleter and the optional bounds-checker are left unchanged. The bounds-checker
0608     // will be reinitialized appropriately when/if the unique_ptr gets assigned-to or reset.
0609     return __t;
0610   }
0611 
0612   template <class _Pp, __enable_if_t<_CheckArrayPointerConversion<_Pp>::value, int> = 0>
0613   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void reset(_Pp __ptr) _NOEXCEPT {
0614     pointer __tmp = __ptr_;
0615     __ptr_        = __ptr;
0616     __checker_    = _BoundsChecker();
0617     if (__tmp)
0618       __deleter_(__tmp);
0619   }
0620 
0621   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void reset(nullptr_t = nullptr) _NOEXCEPT {
0622     pointer __tmp = __ptr_;
0623     __ptr_        = nullptr;
0624     __checker_    = _BoundsChecker();
0625     if (__tmp)
0626       __deleter_(__tmp);
0627   }
0628 
0629   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void swap(unique_ptr& __u) _NOEXCEPT {
0630     using std::swap;
0631     swap(__ptr_, __u.__ptr_);
0632     swap(__deleter_, __u.__deleter_);
0633     swap(__checker_, __u.__checker_);
0634   }
0635 };
0636 
0637 template <class _Tp, class _Dp, __enable_if_t<__is_swappable_v<_Dp>, int> = 0>
0638 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void
0639 swap(unique_ptr<_Tp, _Dp>& __x, unique_ptr<_Tp, _Dp>& __y) _NOEXCEPT {
0640   __x.swap(__y);
0641 }
0642 
0643 template <class _T1, class _D1, class _T2, class _D2>
0644 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool
0645 operator==(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {
0646   return __x.get() == __y.get();
0647 }
0648 
0649 #if _LIBCPP_STD_VER <= 17
0650 template <class _T1, class _D1, class _T2, class _D2>
0651 inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {
0652   return !(__x == __y);
0653 }
0654 #endif
0655 
0656 template <class _T1, class _D1, class _T2, class _D2>
0657 inline _LIBCPP_HIDE_FROM_ABI bool operator<(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {
0658   typedef typename unique_ptr<_T1, _D1>::pointer _P1;
0659   typedef typename unique_ptr<_T2, _D2>::pointer _P2;
0660   typedef typename common_type<_P1, _P2>::type _Vp;
0661   return less<_Vp>()(__x.get(), __y.get());
0662 }
0663 
0664 template <class _T1, class _D1, class _T2, class _D2>
0665 inline _LIBCPP_HIDE_FROM_ABI bool operator>(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {
0666   return __y < __x;
0667 }
0668 
0669 template <class _T1, class _D1, class _T2, class _D2>
0670 inline _LIBCPP_HIDE_FROM_ABI bool operator<=(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {
0671   return !(__y < __x);
0672 }
0673 
0674 template <class _T1, class _D1, class _T2, class _D2>
0675 inline _LIBCPP_HIDE_FROM_ABI bool operator>=(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {
0676   return !(__x < __y);
0677 }
0678 
0679 #if _LIBCPP_STD_VER >= 20
0680 template <class _T1, class _D1, class _T2, class _D2>
0681   requires three_way_comparable_with<typename unique_ptr<_T1, _D1>::pointer, typename unique_ptr<_T2, _D2>::pointer>
0682 _LIBCPP_HIDE_FROM_ABI
0683 compare_three_way_result_t<typename unique_ptr<_T1, _D1>::pointer, typename unique_ptr<_T2, _D2>::pointer>
0684 operator<=>(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {
0685   return compare_three_way()(__x.get(), __y.get());
0686 }
0687 #endif
0688 
0689 template <class _T1, class _D1>
0690 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool
0691 operator==(const unique_ptr<_T1, _D1>& __x, nullptr_t) _NOEXCEPT {
0692   return !__x;
0693 }
0694 
0695 #if _LIBCPP_STD_VER <= 17
0696 template <class _T1, class _D1>
0697 inline _LIBCPP_HIDE_FROM_ABI bool operator==(nullptr_t, const unique_ptr<_T1, _D1>& __x) _NOEXCEPT {
0698   return !__x;
0699 }
0700 
0701 template <class _T1, class _D1>
0702 inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const unique_ptr<_T1, _D1>& __x, nullptr_t) _NOEXCEPT {
0703   return static_cast<bool>(__x);
0704 }
0705 
0706 template <class _T1, class _D1>
0707 inline _LIBCPP_HIDE_FROM_ABI bool operator!=(nullptr_t, const unique_ptr<_T1, _D1>& __x) _NOEXCEPT {
0708   return static_cast<bool>(__x);
0709 }
0710 #endif // _LIBCPP_STD_VER <= 17
0711 
0712 template <class _T1, class _D1>
0713 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool operator<(const unique_ptr<_T1, _D1>& __x, nullptr_t) {
0714   typedef typename unique_ptr<_T1, _D1>::pointer _P1;
0715   return less<_P1>()(__x.get(), nullptr);
0716 }
0717 
0718 template <class _T1, class _D1>
0719 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool operator<(nullptr_t, const unique_ptr<_T1, _D1>& __x) {
0720   typedef typename unique_ptr<_T1, _D1>::pointer _P1;
0721   return less<_P1>()(nullptr, __x.get());
0722 }
0723 
0724 template <class _T1, class _D1>
0725 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool operator>(const unique_ptr<_T1, _D1>& __x, nullptr_t) {
0726   return nullptr < __x;
0727 }
0728 
0729 template <class _T1, class _D1>
0730 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool operator>(nullptr_t, const unique_ptr<_T1, _D1>& __x) {
0731   return __x < nullptr;
0732 }
0733 
0734 template <class _T1, class _D1>
0735 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool operator<=(const unique_ptr<_T1, _D1>& __x, nullptr_t) {
0736   return !(nullptr < __x);
0737 }
0738 
0739 template <class _T1, class _D1>
0740 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool operator<=(nullptr_t, const unique_ptr<_T1, _D1>& __x) {
0741   return !(__x < nullptr);
0742 }
0743 
0744 template <class _T1, class _D1>
0745 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool operator>=(const unique_ptr<_T1, _D1>& __x, nullptr_t) {
0746   return !(__x < nullptr);
0747 }
0748 
0749 template <class _T1, class _D1>
0750 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool operator>=(nullptr_t, const unique_ptr<_T1, _D1>& __x) {
0751   return !(nullptr < __x);
0752 }
0753 
0754 #if _LIBCPP_STD_VER >= 20
0755 template <class _T1, class _D1>
0756   requires three_way_comparable< typename unique_ptr<_T1, _D1>::pointer>
0757 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 compare_three_way_result_t<typename unique_ptr<_T1, _D1>::pointer>
0758 operator<=>(const unique_ptr<_T1, _D1>& __x, nullptr_t) {
0759   return compare_three_way()(__x.get(), static_cast<typename unique_ptr<_T1, _D1>::pointer>(nullptr));
0760 }
0761 #endif
0762 
0763 #if _LIBCPP_STD_VER >= 14
0764 
0765 template <class _Tp, class... _Args, enable_if_t<!is_array<_Tp>::value, int> = 0>
0766 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr<_Tp> make_unique(_Args&&... __args) {
0767   return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...));
0768 }
0769 
0770 template <class _Tp, enable_if_t<__is_unbounded_array_v<_Tp>, int> = 0>
0771 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr<_Tp> make_unique(size_t __n) {
0772   typedef __remove_extent_t<_Tp> _Up;
0773   return unique_ptr<_Tp>(__private_constructor_tag(), new _Up[__n](), __n);
0774 }
0775 
0776 template <class _Tp, class... _Args, enable_if_t<__is_bounded_array_v<_Tp>, int> = 0>
0777 void make_unique(_Args&&...) = delete;
0778 
0779 #endif // _LIBCPP_STD_VER >= 14
0780 
0781 #if _LIBCPP_STD_VER >= 20
0782 
0783 template <class _Tp, enable_if_t<!is_array_v<_Tp>, int> = 0>
0784 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr<_Tp> make_unique_for_overwrite() {
0785   return unique_ptr<_Tp>(new _Tp);
0786 }
0787 
0788 template <class _Tp, enable_if_t<is_unbounded_array_v<_Tp>, int> = 0>
0789 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr<_Tp> make_unique_for_overwrite(size_t __n) {
0790   return unique_ptr<_Tp>(__private_constructor_tag(), new __remove_extent_t<_Tp>[__n], __n);
0791 }
0792 
0793 template <class _Tp, class... _Args, enable_if_t<is_bounded_array_v<_Tp>, int> = 0>
0794 void make_unique_for_overwrite(_Args&&...) = delete;
0795 
0796 #endif // _LIBCPP_STD_VER >= 20
0797 
0798 template <class _Tp>
0799 struct _LIBCPP_TEMPLATE_VIS hash;
0800 
0801 template <class _Tp, class _Dp>
0802 #ifdef _LIBCPP_CXX03_LANG
0803 struct _LIBCPP_TEMPLATE_VIS hash<unique_ptr<_Tp, _Dp> >
0804 #else
0805 struct _LIBCPP_TEMPLATE_VIS hash<__enable_hash_helper< unique_ptr<_Tp, _Dp>, typename unique_ptr<_Tp, _Dp>::pointer> >
0806 #endif
0807 {
0808 #if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_BINDER_TYPEDEFS)
0809   _LIBCPP_DEPRECATED_IN_CXX17 typedef unique_ptr<_Tp, _Dp> argument_type;
0810   _LIBCPP_DEPRECATED_IN_CXX17 typedef size_t result_type;
0811 #endif
0812 
0813   _LIBCPP_HIDE_FROM_ABI size_t operator()(const unique_ptr<_Tp, _Dp>& __ptr) const {
0814     typedef typename unique_ptr<_Tp, _Dp>::pointer pointer;
0815     return hash<pointer>()(__ptr.get());
0816   }
0817 };
0818 
0819 _LIBCPP_END_NAMESPACE_STD
0820 
0821 _LIBCPP_POP_MACROS
0822 
0823 #endif // _LIBCPP___MEMORY_UNIQUE_PTR_H