138fd1498Szrj // unique_ptr implementation -*- C++ -*- 238fd1498Szrj 338fd1498Szrj // Copyright (C) 2008-2018 Free Software Foundation, Inc. 438fd1498Szrj // 538fd1498Szrj // This file is part of the GNU ISO C++ Library. This library is free 638fd1498Szrj // software; you can redistribute it and/or modify it under the 738fd1498Szrj // terms of the GNU General Public License as published by the 838fd1498Szrj // Free Software Foundation; either version 3, or (at your option) 938fd1498Szrj // any later version. 1038fd1498Szrj 1138fd1498Szrj // This library is distributed in the hope that it will be useful, 1238fd1498Szrj // but WITHOUT ANY WARRANTY; without even the implied warranty of 1338fd1498Szrj // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1438fd1498Szrj // GNU General Public License for more details. 1538fd1498Szrj 1638fd1498Szrj // Under Section 7 of GPL version 3, you are granted additional 1738fd1498Szrj // permissions described in the GCC Runtime Library Exception, version 1838fd1498Szrj // 3.1, as published by the Free Software Foundation. 1938fd1498Szrj 2038fd1498Szrj // You should have received a copy of the GNU General Public License and 2138fd1498Szrj // a copy of the GCC Runtime Library Exception along with this program; 2238fd1498Szrj // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 2338fd1498Szrj // <http://www.gnu.org/licenses/>. 2438fd1498Szrj 2538fd1498Szrj /** @file bits/unique_ptr.h 2638fd1498Szrj * This is an internal header file, included by other library headers. 2738fd1498Szrj * Do not attempt to use it directly. @headername{memory} 2838fd1498Szrj */ 2938fd1498Szrj 3038fd1498Szrj #ifndef _UNIQUE_PTR_H 3138fd1498Szrj #define _UNIQUE_PTR_H 1 3238fd1498Szrj 3338fd1498Szrj #include <bits/c++config.h> 3438fd1498Szrj #include <debug/assertions.h> 3538fd1498Szrj #include <type_traits> 3638fd1498Szrj #include <utility> 3738fd1498Szrj #include <tuple> 3838fd1498Szrj #include <bits/stl_function.h> 3938fd1498Szrj #include <bits/functional_hash.h> 4038fd1498Szrj 4138fd1498Szrj namespace std _GLIBCXX_VISIBILITY(default) 4238fd1498Szrj { 4338fd1498Szrj _GLIBCXX_BEGIN_NAMESPACE_VERSION 4438fd1498Szrj 4538fd1498Szrj /** 4638fd1498Szrj * @addtogroup pointer_abstractions 4738fd1498Szrj * @{ 4838fd1498Szrj */ 4938fd1498Szrj 5038fd1498Szrj #if _GLIBCXX_USE_DEPRECATED 5138fd1498Szrj #pragma GCC diagnostic push 5238fd1498Szrj #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 5338fd1498Szrj template<typename> class auto_ptr; 5438fd1498Szrj #pragma GCC diagnostic pop 5538fd1498Szrj #endif 5638fd1498Szrj 5738fd1498Szrj /// Primary template of default_delete, used by unique_ptr 5838fd1498Szrj template<typename _Tp> 5938fd1498Szrj struct default_delete 6038fd1498Szrj { 6138fd1498Szrj /// Default constructor 6238fd1498Szrj constexpr default_delete() noexcept = default; 6338fd1498Szrj 6438fd1498Szrj /** @brief Converting constructor. 6538fd1498Szrj * 6638fd1498Szrj * Allows conversion from a deleter for arrays of another type, @p _Up, 6738fd1498Szrj * only if @p _Up* is convertible to @p _Tp*. 6838fd1498Szrj */ 6938fd1498Szrj template<typename _Up, typename = typename 7038fd1498Szrj enable_if<is_convertible<_Up*, _Tp*>::value>::type> 7138fd1498Szrj default_delete(const default_delete<_Up>&) noexcept { } 7238fd1498Szrj 7338fd1498Szrj /// Calls @c delete @p __ptr 7438fd1498Szrj void 7538fd1498Szrj operator()(_Tp* __ptr) const 7638fd1498Szrj { 7738fd1498Szrj static_assert(!is_void<_Tp>::value, 7838fd1498Szrj "can't delete pointer to incomplete type"); 7938fd1498Szrj static_assert(sizeof(_Tp)>0, 8038fd1498Szrj "can't delete pointer to incomplete type"); 8138fd1498Szrj delete __ptr; 8238fd1498Szrj } 8338fd1498Szrj }; 8438fd1498Szrj 8538fd1498Szrj // _GLIBCXX_RESOLVE_LIB_DEFECTS 8638fd1498Szrj // DR 740 - omit specialization for array objects with a compile time length 8738fd1498Szrj /// Specialization for arrays, default_delete. 8838fd1498Szrj template<typename _Tp> 8938fd1498Szrj struct default_delete<_Tp[]> 9038fd1498Szrj { 9138fd1498Szrj public: 9238fd1498Szrj /// Default constructor 9338fd1498Szrj constexpr default_delete() noexcept = default; 9438fd1498Szrj 9538fd1498Szrj /** @brief Converting constructor. 9638fd1498Szrj * 9738fd1498Szrj * Allows conversion from a deleter for arrays of another type, such as 9838fd1498Szrj * a const-qualified version of @p _Tp. 9938fd1498Szrj * 10038fd1498Szrj * Conversions from types derived from @c _Tp are not allowed because 10138fd1498Szrj * it is unsafe to @c delete[] an array of derived types through a 10238fd1498Szrj * pointer to the base type. 10338fd1498Szrj */ 10438fd1498Szrj template<typename _Up, typename = typename 10538fd1498Szrj enable_if<is_convertible<_Up(*)[], _Tp(*)[]>::value>::type> 10638fd1498Szrj default_delete(const default_delete<_Up[]>&) noexcept { } 10738fd1498Szrj 10838fd1498Szrj /// Calls @c delete[] @p __ptr 10938fd1498Szrj template<typename _Up> 11038fd1498Szrj typename enable_if<is_convertible<_Up(*)[], _Tp(*)[]>::value>::type 11138fd1498Szrj operator()(_Up* __ptr) const 11238fd1498Szrj { 11338fd1498Szrj static_assert(sizeof(_Tp)>0, 11438fd1498Szrj "can't delete pointer to incomplete type"); 11538fd1498Szrj delete [] __ptr; 11638fd1498Szrj } 11738fd1498Szrj }; 11838fd1498Szrj 11938fd1498Szrj template <typename _Tp, typename _Dp> 12038fd1498Szrj class __uniq_ptr_impl 12138fd1498Szrj { 12238fd1498Szrj template <typename _Up, typename _Ep, typename = void> 12338fd1498Szrj struct _Ptr 12438fd1498Szrj { 12538fd1498Szrj using type = _Up*; 12638fd1498Szrj }; 12738fd1498Szrj 12838fd1498Szrj template <typename _Up, typename _Ep> 12938fd1498Szrj struct 13038fd1498Szrj _Ptr<_Up, _Ep, __void_t<typename remove_reference<_Ep>::type::pointer>> 13138fd1498Szrj { 13238fd1498Szrj using type = typename remove_reference<_Ep>::type::pointer; 13338fd1498Szrj }; 13438fd1498Szrj 13538fd1498Szrj public: 13638fd1498Szrj using _DeleterConstraint = enable_if< 13738fd1498Szrj __and_<__not_<is_pointer<_Dp>>, 13838fd1498Szrj is_default_constructible<_Dp>>::value>; 13938fd1498Szrj 14038fd1498Szrj using pointer = typename _Ptr<_Tp, _Dp>::type; 14138fd1498Szrj 14238fd1498Szrj __uniq_ptr_impl() = default; 14338fd1498Szrj __uniq_ptr_impl(pointer __p) : _M_t() { _M_ptr() = __p; } 14438fd1498Szrj 14538fd1498Szrj template<typename _Del> 14638fd1498Szrj __uniq_ptr_impl(pointer __p, _Del&& __d) 14738fd1498Szrj : _M_t(__p, std::forward<_Del>(__d)) { } 14838fd1498Szrj 14938fd1498Szrj pointer& _M_ptr() { return std::get<0>(_M_t); } 15038fd1498Szrj pointer _M_ptr() const { return std::get<0>(_M_t); } 15138fd1498Szrj _Dp& _M_deleter() { return std::get<1>(_M_t); } 15238fd1498Szrj const _Dp& _M_deleter() const { return std::get<1>(_M_t); } 15338fd1498Szrj 15438fd1498Szrj private: 15538fd1498Szrj tuple<pointer, _Dp> _M_t; 15638fd1498Szrj }; 15738fd1498Szrj 15838fd1498Szrj /// 20.7.1.2 unique_ptr for single objects. 15938fd1498Szrj template <typename _Tp, typename _Dp = default_delete<_Tp>> 16038fd1498Szrj class unique_ptr 16138fd1498Szrj { 16238fd1498Szrj template <class _Up> 16338fd1498Szrj using _DeleterConstraint = 16438fd1498Szrj typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type; 16538fd1498Szrj 16638fd1498Szrj __uniq_ptr_impl<_Tp, _Dp> _M_t; 16738fd1498Szrj 16838fd1498Szrj public: 16938fd1498Szrj using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer; 17038fd1498Szrj using element_type = _Tp; 17138fd1498Szrj using deleter_type = _Dp; 17238fd1498Szrj 17338fd1498Szrj // helper template for detecting a safe conversion from another 17438fd1498Szrj // unique_ptr 17538fd1498Szrj template<typename _Up, typename _Ep> 17638fd1498Szrj using __safe_conversion_up = __and_< 17738fd1498Szrj is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>, 17838fd1498Szrj __not_<is_array<_Up>>, 17938fd1498Szrj __or_<__and_<is_reference<deleter_type>, 18038fd1498Szrj is_same<deleter_type, _Ep>>, 18138fd1498Szrj __and_<__not_<is_reference<deleter_type>>, 18238fd1498Szrj is_convertible<_Ep, deleter_type>> 18338fd1498Szrj > 18438fd1498Szrj >; 18538fd1498Szrj 18638fd1498Szrj // Constructors. 18738fd1498Szrj 18838fd1498Szrj /// Default constructor, creates a unique_ptr that owns nothing. 18938fd1498Szrj template <typename _Up = _Dp, 19038fd1498Szrj typename = _DeleterConstraint<_Up>> 19138fd1498Szrj constexpr unique_ptr() noexcept 19238fd1498Szrj : _M_t() 19338fd1498Szrj { } 19438fd1498Szrj 19538fd1498Szrj /** Takes ownership of a pointer. 19638fd1498Szrj * 19738fd1498Szrj * @param __p A pointer to an object of @c element_type 19838fd1498Szrj * 19938fd1498Szrj * The deleter will be value-initialized. 20038fd1498Szrj */ 20138fd1498Szrj template <typename _Up = _Dp, 20238fd1498Szrj typename = _DeleterConstraint<_Up>> 20338fd1498Szrj explicit 20438fd1498Szrj unique_ptr(pointer __p) noexcept 20538fd1498Szrj : _M_t(__p) 20638fd1498Szrj { } 20738fd1498Szrj 20838fd1498Szrj /** Takes ownership of a pointer. 20938fd1498Szrj * 21038fd1498Szrj * @param __p A pointer to an object of @c element_type 21138fd1498Szrj * @param __d A reference to a deleter. 21238fd1498Szrj * 21338fd1498Szrj * The deleter will be initialized with @p __d 21438fd1498Szrj */ 21538fd1498Szrj unique_ptr(pointer __p, 21638fd1498Szrj typename conditional<is_reference<deleter_type>::value, 21738fd1498Szrj deleter_type, const deleter_type&>::type __d) noexcept 21838fd1498Szrj : _M_t(__p, __d) { } 21938fd1498Szrj 22038fd1498Szrj /** Takes ownership of a pointer. 22138fd1498Szrj * 22238fd1498Szrj * @param __p A pointer to an object of @c element_type 22338fd1498Szrj * @param __d An rvalue reference to a deleter. 22438fd1498Szrj * 22538fd1498Szrj * The deleter will be initialized with @p std::move(__d) 22638fd1498Szrj */ 22738fd1498Szrj unique_ptr(pointer __p, 22838fd1498Szrj typename remove_reference<deleter_type>::type&& __d) noexcept 22938fd1498Szrj : _M_t(std::move(__p), std::move(__d)) 23038fd1498Szrj { static_assert(!std::is_reference<deleter_type>::value, 23138fd1498Szrj "rvalue deleter bound to reference"); } 23238fd1498Szrj 23338fd1498Szrj /// Creates a unique_ptr that owns nothing. 23438fd1498Szrj template <typename _Up = _Dp, 23538fd1498Szrj typename = _DeleterConstraint<_Up>> 236*58e805e6Szrj constexpr unique_ptr(nullptr_t) noexcept : _M_t() { } 23738fd1498Szrj 23838fd1498Szrj // Move constructors. 23938fd1498Szrj 24038fd1498Szrj /// Move constructor. 24138fd1498Szrj unique_ptr(unique_ptr&& __u) noexcept 24238fd1498Szrj : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { } 24338fd1498Szrj 24438fd1498Szrj /** @brief Converting constructor from another type 24538fd1498Szrj * 24638fd1498Szrj * Requires that the pointer owned by @p __u is convertible to the 24738fd1498Szrj * type of pointer owned by this object, @p __u does not own an array, 24838fd1498Szrj * and @p __u has a compatible deleter type. 24938fd1498Szrj */ 25038fd1498Szrj template<typename _Up, typename _Ep, typename = _Require< 25138fd1498Szrj __safe_conversion_up<_Up, _Ep>, 25238fd1498Szrj typename conditional<is_reference<_Dp>::value, 25338fd1498Szrj is_same<_Ep, _Dp>, 25438fd1498Szrj is_convertible<_Ep, _Dp>>::type>> 25538fd1498Szrj unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept 25638fd1498Szrj : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter())) 25738fd1498Szrj { } 25838fd1498Szrj 25938fd1498Szrj #if _GLIBCXX_USE_DEPRECATED 26038fd1498Szrj #pragma GCC diagnostic push 26138fd1498Szrj #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 26238fd1498Szrj /// Converting constructor from @c auto_ptr 26338fd1498Szrj template<typename _Up, typename = _Require< 26438fd1498Szrj is_convertible<_Up*, _Tp*>, is_same<_Dp, default_delete<_Tp>>>> 26538fd1498Szrj unique_ptr(auto_ptr<_Up>&& __u) noexcept; 26638fd1498Szrj #pragma GCC diagnostic pop 26738fd1498Szrj #endif 26838fd1498Szrj 26938fd1498Szrj /// Destructor, invokes the deleter if the stored pointer is not null. 27038fd1498Szrj ~unique_ptr() noexcept 27138fd1498Szrj { 27238fd1498Szrj auto& __ptr = _M_t._M_ptr(); 27338fd1498Szrj if (__ptr != nullptr) 27438fd1498Szrj get_deleter()(__ptr); 27538fd1498Szrj __ptr = pointer(); 27638fd1498Szrj } 27738fd1498Szrj 27838fd1498Szrj // Assignment. 27938fd1498Szrj 28038fd1498Szrj /** @brief Move assignment operator. 28138fd1498Szrj * 28238fd1498Szrj * @param __u The object to transfer ownership from. 28338fd1498Szrj * 28438fd1498Szrj * Invokes the deleter first if this object owns a pointer. 28538fd1498Szrj */ 28638fd1498Szrj unique_ptr& 28738fd1498Szrj operator=(unique_ptr&& __u) noexcept 28838fd1498Szrj { 28938fd1498Szrj reset(__u.release()); 29038fd1498Szrj get_deleter() = std::forward<deleter_type>(__u.get_deleter()); 29138fd1498Szrj return *this; 29238fd1498Szrj } 29338fd1498Szrj 29438fd1498Szrj /** @brief Assignment from another type. 29538fd1498Szrj * 29638fd1498Szrj * @param __u The object to transfer ownership from, which owns a 29738fd1498Szrj * convertible pointer to a non-array object. 29838fd1498Szrj * 29938fd1498Szrj * Invokes the deleter first if this object owns a pointer. 30038fd1498Szrj */ 30138fd1498Szrj template<typename _Up, typename _Ep> 30238fd1498Szrj typename enable_if< __and_< 30338fd1498Szrj __safe_conversion_up<_Up, _Ep>, 30438fd1498Szrj is_assignable<deleter_type&, _Ep&&> 30538fd1498Szrj >::value, 30638fd1498Szrj unique_ptr&>::type 30738fd1498Szrj operator=(unique_ptr<_Up, _Ep>&& __u) noexcept 30838fd1498Szrj { 30938fd1498Szrj reset(__u.release()); 31038fd1498Szrj get_deleter() = std::forward<_Ep>(__u.get_deleter()); 31138fd1498Szrj return *this; 31238fd1498Szrj } 31338fd1498Szrj 31438fd1498Szrj /// Reset the %unique_ptr to empty, invoking the deleter if necessary. 31538fd1498Szrj unique_ptr& 31638fd1498Szrj operator=(nullptr_t) noexcept 31738fd1498Szrj { 31838fd1498Szrj reset(); 31938fd1498Szrj return *this; 32038fd1498Szrj } 32138fd1498Szrj 32238fd1498Szrj // Observers. 32338fd1498Szrj 32438fd1498Szrj /// Dereference the stored pointer. 32538fd1498Szrj typename add_lvalue_reference<element_type>::type 32638fd1498Szrj operator*() const 32738fd1498Szrj { 32838fd1498Szrj __glibcxx_assert(get() != pointer()); 32938fd1498Szrj return *get(); 33038fd1498Szrj } 33138fd1498Szrj 33238fd1498Szrj /// Return the stored pointer. 33338fd1498Szrj pointer 33438fd1498Szrj operator->() const noexcept 33538fd1498Szrj { 33638fd1498Szrj _GLIBCXX_DEBUG_PEDASSERT(get() != pointer()); 33738fd1498Szrj return get(); 33838fd1498Szrj } 33938fd1498Szrj 34038fd1498Szrj /// Return the stored pointer. 34138fd1498Szrj pointer 34238fd1498Szrj get() const noexcept 34338fd1498Szrj { return _M_t._M_ptr(); } 34438fd1498Szrj 34538fd1498Szrj /// Return a reference to the stored deleter. 34638fd1498Szrj deleter_type& 34738fd1498Szrj get_deleter() noexcept 34838fd1498Szrj { return _M_t._M_deleter(); } 34938fd1498Szrj 35038fd1498Szrj /// Return a reference to the stored deleter. 35138fd1498Szrj const deleter_type& 35238fd1498Szrj get_deleter() const noexcept 35338fd1498Szrj { return _M_t._M_deleter(); } 35438fd1498Szrj 35538fd1498Szrj /// Return @c true if the stored pointer is not null. 35638fd1498Szrj explicit operator bool() const noexcept 35738fd1498Szrj { return get() == pointer() ? false : true; } 35838fd1498Szrj 35938fd1498Szrj // Modifiers. 36038fd1498Szrj 36138fd1498Szrj /// Release ownership of any stored pointer. 36238fd1498Szrj pointer 36338fd1498Szrj release() noexcept 36438fd1498Szrj { 36538fd1498Szrj pointer __p = get(); 36638fd1498Szrj _M_t._M_ptr() = pointer(); 36738fd1498Szrj return __p; 36838fd1498Szrj } 36938fd1498Szrj 37038fd1498Szrj /** @brief Replace the stored pointer. 37138fd1498Szrj * 37238fd1498Szrj * @param __p The new pointer to store. 37338fd1498Szrj * 37438fd1498Szrj * The deleter will be invoked if a pointer is already owned. 37538fd1498Szrj */ 37638fd1498Szrj void 37738fd1498Szrj reset(pointer __p = pointer()) noexcept 37838fd1498Szrj { 37938fd1498Szrj using std::swap; 38038fd1498Szrj swap(_M_t._M_ptr(), __p); 38138fd1498Szrj if (__p != pointer()) 38238fd1498Szrj get_deleter()(__p); 38338fd1498Szrj } 38438fd1498Szrj 38538fd1498Szrj /// Exchange the pointer and deleter with another object. 38638fd1498Szrj void 38738fd1498Szrj swap(unique_ptr& __u) noexcept 38838fd1498Szrj { 38938fd1498Szrj using std::swap; 39038fd1498Szrj swap(_M_t, __u._M_t); 39138fd1498Szrj } 39238fd1498Szrj 39338fd1498Szrj // Disable copy from lvalue. 39438fd1498Szrj unique_ptr(const unique_ptr&) = delete; 39538fd1498Szrj unique_ptr& operator=(const unique_ptr&) = delete; 39638fd1498Szrj }; 39738fd1498Szrj 39838fd1498Szrj /// 20.7.1.3 unique_ptr for array objects with a runtime length 39938fd1498Szrj // [unique.ptr.runtime] 40038fd1498Szrj // _GLIBCXX_RESOLVE_LIB_DEFECTS 40138fd1498Szrj // DR 740 - omit specialization for array objects with a compile time length 40238fd1498Szrj template<typename _Tp, typename _Dp> 40338fd1498Szrj class unique_ptr<_Tp[], _Dp> 40438fd1498Szrj { 40538fd1498Szrj template <typename _Up> 40638fd1498Szrj using _DeleterConstraint = 40738fd1498Szrj typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type; 40838fd1498Szrj 40938fd1498Szrj __uniq_ptr_impl<_Tp, _Dp> _M_t; 41038fd1498Szrj 41138fd1498Szrj template<typename _Up> 41238fd1498Szrj using __remove_cv = typename remove_cv<_Up>::type; 41338fd1498Szrj 41438fd1498Szrj // like is_base_of<_Tp, _Up> but false if unqualified types are the same 41538fd1498Szrj template<typename _Up> 41638fd1498Szrj using __is_derived_Tp 41738fd1498Szrj = __and_< is_base_of<_Tp, _Up>, 41838fd1498Szrj __not_<is_same<__remove_cv<_Tp>, __remove_cv<_Up>>> >; 41938fd1498Szrj 42038fd1498Szrj public: 42138fd1498Szrj using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer; 42238fd1498Szrj using element_type = _Tp; 42338fd1498Szrj using deleter_type = _Dp; 42438fd1498Szrj 42538fd1498Szrj // helper template for detecting a safe conversion from another 42638fd1498Szrj // unique_ptr 42738fd1498Szrj template<typename _Up, typename _Ep, 42838fd1498Szrj typename _Up_up = unique_ptr<_Up, _Ep>, 42938fd1498Szrj typename _Up_element_type = typename _Up_up::element_type> 43038fd1498Szrj using __safe_conversion_up = __and_< 43138fd1498Szrj is_array<_Up>, 43238fd1498Szrj is_same<pointer, element_type*>, 43338fd1498Szrj is_same<typename _Up_up::pointer, _Up_element_type*>, 43438fd1498Szrj is_convertible<_Up_element_type(*)[], element_type(*)[]>, 43538fd1498Szrj __or_<__and_<is_reference<deleter_type>, is_same<deleter_type, _Ep>>, 43638fd1498Szrj __and_<__not_<is_reference<deleter_type>>, 43738fd1498Szrj is_convertible<_Ep, deleter_type>>> 43838fd1498Szrj >; 43938fd1498Szrj 44038fd1498Szrj // helper template for detecting a safe conversion from a raw pointer 44138fd1498Szrj template<typename _Up> 44238fd1498Szrj using __safe_conversion_raw = __and_< 44338fd1498Szrj __or_<__or_<is_same<_Up, pointer>, 44438fd1498Szrj is_same<_Up, nullptr_t>>, 44538fd1498Szrj __and_<is_pointer<_Up>, 44638fd1498Szrj is_same<pointer, element_type*>, 44738fd1498Szrj is_convertible< 44838fd1498Szrj typename remove_pointer<_Up>::type(*)[], 44938fd1498Szrj element_type(*)[]> 45038fd1498Szrj > 45138fd1498Szrj > 45238fd1498Szrj >; 45338fd1498Szrj 45438fd1498Szrj // Constructors. 45538fd1498Szrj 45638fd1498Szrj /// Default constructor, creates a unique_ptr that owns nothing. 45738fd1498Szrj template <typename _Up = _Dp, 45838fd1498Szrj typename = _DeleterConstraint<_Up>> 45938fd1498Szrj constexpr unique_ptr() noexcept 46038fd1498Szrj : _M_t() 46138fd1498Szrj { } 46238fd1498Szrj 46338fd1498Szrj /** Takes ownership of a pointer. 46438fd1498Szrj * 46538fd1498Szrj * @param __p A pointer to an array of a type safely convertible 46638fd1498Szrj * to an array of @c element_type 46738fd1498Szrj * 46838fd1498Szrj * The deleter will be value-initialized. 46938fd1498Szrj */ 47038fd1498Szrj template<typename _Up, 47138fd1498Szrj typename _Vp = _Dp, 47238fd1498Szrj typename = _DeleterConstraint<_Vp>, 47338fd1498Szrj typename = typename enable_if< 47438fd1498Szrj __safe_conversion_raw<_Up>::value, bool>::type> 47538fd1498Szrj explicit 47638fd1498Szrj unique_ptr(_Up __p) noexcept 47738fd1498Szrj : _M_t(__p) 47838fd1498Szrj { } 47938fd1498Szrj 48038fd1498Szrj /** Takes ownership of a pointer. 48138fd1498Szrj * 48238fd1498Szrj * @param __p A pointer to an array of a type safely convertible 48338fd1498Szrj * to an array of @c element_type 48438fd1498Szrj * @param __d A reference to a deleter. 48538fd1498Szrj * 48638fd1498Szrj * The deleter will be initialized with @p __d 48738fd1498Szrj */ 48838fd1498Szrj template<typename _Up, 48938fd1498Szrj typename = typename enable_if< 49038fd1498Szrj __safe_conversion_raw<_Up>::value, bool>::type> 49138fd1498Szrj unique_ptr(_Up __p, 49238fd1498Szrj typename conditional<is_reference<deleter_type>::value, 49338fd1498Szrj deleter_type, const deleter_type&>::type __d) noexcept 49438fd1498Szrj : _M_t(__p, __d) { } 49538fd1498Szrj 49638fd1498Szrj /** Takes ownership of a pointer. 49738fd1498Szrj * 49838fd1498Szrj * @param __p A pointer to an array of a type safely convertible 49938fd1498Szrj * to an array of @c element_type 50038fd1498Szrj * @param __d A reference to a deleter. 50138fd1498Szrj * 50238fd1498Szrj * The deleter will be initialized with @p std::move(__d) 50338fd1498Szrj */ 50438fd1498Szrj template<typename _Up, 50538fd1498Szrj typename = typename enable_if< 50638fd1498Szrj __safe_conversion_raw<_Up>::value, bool>::type> 50738fd1498Szrj unique_ptr(_Up __p, typename 50838fd1498Szrj remove_reference<deleter_type>::type&& __d) noexcept 50938fd1498Szrj : _M_t(std::move(__p), std::move(__d)) 51038fd1498Szrj { static_assert(!is_reference<deleter_type>::value, 51138fd1498Szrj "rvalue deleter bound to reference"); } 51238fd1498Szrj 51338fd1498Szrj /// Move constructor. 51438fd1498Szrj unique_ptr(unique_ptr&& __u) noexcept 51538fd1498Szrj : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { } 51638fd1498Szrj 51738fd1498Szrj /// Creates a unique_ptr that owns nothing. 51838fd1498Szrj template <typename _Up = _Dp, 51938fd1498Szrj typename = _DeleterConstraint<_Up>> 520*58e805e6Szrj constexpr unique_ptr(nullptr_t) noexcept : _M_t() { } 52138fd1498Szrj 52238fd1498Szrj template<typename _Up, typename _Ep, 52338fd1498Szrj typename = _Require<__safe_conversion_up<_Up, _Ep>>> 52438fd1498Szrj unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept 52538fd1498Szrj : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter())) 52638fd1498Szrj { } 52738fd1498Szrj 52838fd1498Szrj /// Destructor, invokes the deleter if the stored pointer is not null. 52938fd1498Szrj ~unique_ptr() 53038fd1498Szrj { 53138fd1498Szrj auto& __ptr = _M_t._M_ptr(); 53238fd1498Szrj if (__ptr != nullptr) 53338fd1498Szrj get_deleter()(__ptr); 53438fd1498Szrj __ptr = pointer(); 53538fd1498Szrj } 53638fd1498Szrj 53738fd1498Szrj // Assignment. 53838fd1498Szrj 53938fd1498Szrj /** @brief Move assignment operator. 54038fd1498Szrj * 54138fd1498Szrj * @param __u The object to transfer ownership from. 54238fd1498Szrj * 54338fd1498Szrj * Invokes the deleter first if this object owns a pointer. 54438fd1498Szrj */ 54538fd1498Szrj unique_ptr& 54638fd1498Szrj operator=(unique_ptr&& __u) noexcept 54738fd1498Szrj { 54838fd1498Szrj reset(__u.release()); 54938fd1498Szrj get_deleter() = std::forward<deleter_type>(__u.get_deleter()); 55038fd1498Szrj return *this; 55138fd1498Szrj } 55238fd1498Szrj 55338fd1498Szrj /** @brief Assignment from another type. 55438fd1498Szrj * 55538fd1498Szrj * @param __u The object to transfer ownership from, which owns a 55638fd1498Szrj * convertible pointer to an array object. 55738fd1498Szrj * 55838fd1498Szrj * Invokes the deleter first if this object owns a pointer. 55938fd1498Szrj */ 56038fd1498Szrj template<typename _Up, typename _Ep> 56138fd1498Szrj typename 56238fd1498Szrj enable_if<__and_<__safe_conversion_up<_Up, _Ep>, 56338fd1498Szrj is_assignable<deleter_type&, _Ep&&> 56438fd1498Szrj >::value, 56538fd1498Szrj unique_ptr&>::type 56638fd1498Szrj operator=(unique_ptr<_Up, _Ep>&& __u) noexcept 56738fd1498Szrj { 56838fd1498Szrj reset(__u.release()); 56938fd1498Szrj get_deleter() = std::forward<_Ep>(__u.get_deleter()); 57038fd1498Szrj return *this; 57138fd1498Szrj } 57238fd1498Szrj 57338fd1498Szrj /// Reset the %unique_ptr to empty, invoking the deleter if necessary. 57438fd1498Szrj unique_ptr& 57538fd1498Szrj operator=(nullptr_t) noexcept 57638fd1498Szrj { 57738fd1498Szrj reset(); 57838fd1498Szrj return *this; 57938fd1498Szrj } 58038fd1498Szrj 58138fd1498Szrj // Observers. 58238fd1498Szrj 58338fd1498Szrj /// Access an element of owned array. 58438fd1498Szrj typename std::add_lvalue_reference<element_type>::type 58538fd1498Szrj operator[](size_t __i) const 58638fd1498Szrj { 58738fd1498Szrj __glibcxx_assert(get() != pointer()); 58838fd1498Szrj return get()[__i]; 58938fd1498Szrj } 59038fd1498Szrj 59138fd1498Szrj /// Return the stored pointer. 59238fd1498Szrj pointer 59338fd1498Szrj get() const noexcept 59438fd1498Szrj { return _M_t._M_ptr(); } 59538fd1498Szrj 59638fd1498Szrj /// Return a reference to the stored deleter. 59738fd1498Szrj deleter_type& 59838fd1498Szrj get_deleter() noexcept 59938fd1498Szrj { return _M_t._M_deleter(); } 60038fd1498Szrj 60138fd1498Szrj /// Return a reference to the stored deleter. 60238fd1498Szrj const deleter_type& 60338fd1498Szrj get_deleter() const noexcept 60438fd1498Szrj { return _M_t._M_deleter(); } 60538fd1498Szrj 60638fd1498Szrj /// Return @c true if the stored pointer is not null. 60738fd1498Szrj explicit operator bool() const noexcept 60838fd1498Szrj { return get() == pointer() ? false : true; } 60938fd1498Szrj 61038fd1498Szrj // Modifiers. 61138fd1498Szrj 61238fd1498Szrj /// Release ownership of any stored pointer. 61338fd1498Szrj pointer 61438fd1498Szrj release() noexcept 61538fd1498Szrj { 61638fd1498Szrj pointer __p = get(); 61738fd1498Szrj _M_t._M_ptr() = pointer(); 61838fd1498Szrj return __p; 61938fd1498Szrj } 62038fd1498Szrj 62138fd1498Szrj /** @brief Replace the stored pointer. 62238fd1498Szrj * 62338fd1498Szrj * @param __p The new pointer to store. 62438fd1498Szrj * 62538fd1498Szrj * The deleter will be invoked if a pointer is already owned. 62638fd1498Szrj */ 62738fd1498Szrj template <typename _Up, 62838fd1498Szrj typename = _Require< 62938fd1498Szrj __or_<is_same<_Up, pointer>, 63038fd1498Szrj __and_<is_same<pointer, element_type*>, 63138fd1498Szrj is_pointer<_Up>, 63238fd1498Szrj is_convertible< 63338fd1498Szrj typename remove_pointer<_Up>::type(*)[], 63438fd1498Szrj element_type(*)[] 63538fd1498Szrj > 63638fd1498Szrj > 63738fd1498Szrj > 63838fd1498Szrj >> 63938fd1498Szrj void 64038fd1498Szrj reset(_Up __p) noexcept 64138fd1498Szrj { 64238fd1498Szrj pointer __ptr = __p; 64338fd1498Szrj using std::swap; 64438fd1498Szrj swap(_M_t._M_ptr(), __ptr); 64538fd1498Szrj if (__ptr != nullptr) 64638fd1498Szrj get_deleter()(__ptr); 64738fd1498Szrj } 64838fd1498Szrj 64938fd1498Szrj void reset(nullptr_t = nullptr) noexcept 65038fd1498Szrj { 65138fd1498Szrj reset(pointer()); 65238fd1498Szrj } 65338fd1498Szrj 65438fd1498Szrj /// Exchange the pointer and deleter with another object. 65538fd1498Szrj void 65638fd1498Szrj swap(unique_ptr& __u) noexcept 65738fd1498Szrj { 65838fd1498Szrj using std::swap; 65938fd1498Szrj swap(_M_t, __u._M_t); 66038fd1498Szrj } 66138fd1498Szrj 66238fd1498Szrj // Disable copy from lvalue. 66338fd1498Szrj unique_ptr(const unique_ptr&) = delete; 66438fd1498Szrj unique_ptr& operator=(const unique_ptr&) = delete; 66538fd1498Szrj }; 66638fd1498Szrj 66738fd1498Szrj template<typename _Tp, typename _Dp> 66838fd1498Szrj inline 66938fd1498Szrj #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 67038fd1498Szrj // Constrained free swap overload, see p0185r1 67138fd1498Szrj typename enable_if<__is_swappable<_Dp>::value>::type 67238fd1498Szrj #else 67338fd1498Szrj void 67438fd1498Szrj #endif 67538fd1498Szrj swap(unique_ptr<_Tp, _Dp>& __x, 67638fd1498Szrj unique_ptr<_Tp, _Dp>& __y) noexcept 67738fd1498Szrj { __x.swap(__y); } 67838fd1498Szrj 67938fd1498Szrj #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 68038fd1498Szrj template<typename _Tp, typename _Dp> 68138fd1498Szrj typename enable_if<!__is_swappable<_Dp>::value>::type 68238fd1498Szrj swap(unique_ptr<_Tp, _Dp>&, 68338fd1498Szrj unique_ptr<_Tp, _Dp>&) = delete; 68438fd1498Szrj #endif 68538fd1498Szrj 68638fd1498Szrj template<typename _Tp, typename _Dp, 68738fd1498Szrj typename _Up, typename _Ep> 68838fd1498Szrj inline bool 68938fd1498Szrj operator==(const unique_ptr<_Tp, _Dp>& __x, 69038fd1498Szrj const unique_ptr<_Up, _Ep>& __y) 69138fd1498Szrj { return __x.get() == __y.get(); } 69238fd1498Szrj 69338fd1498Szrj template<typename _Tp, typename _Dp> 69438fd1498Szrj inline bool 69538fd1498Szrj operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept 69638fd1498Szrj { return !__x; } 69738fd1498Szrj 69838fd1498Szrj template<typename _Tp, typename _Dp> 69938fd1498Szrj inline bool 70038fd1498Szrj operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept 70138fd1498Szrj { return !__x; } 70238fd1498Szrj 70338fd1498Szrj template<typename _Tp, typename _Dp, 70438fd1498Szrj typename _Up, typename _Ep> 70538fd1498Szrj inline bool 70638fd1498Szrj operator!=(const unique_ptr<_Tp, _Dp>& __x, 70738fd1498Szrj const unique_ptr<_Up, _Ep>& __y) 70838fd1498Szrj { return __x.get() != __y.get(); } 70938fd1498Szrj 71038fd1498Szrj template<typename _Tp, typename _Dp> 71138fd1498Szrj inline bool 71238fd1498Szrj operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept 71338fd1498Szrj { return (bool)__x; } 71438fd1498Szrj 71538fd1498Szrj template<typename _Tp, typename _Dp> 71638fd1498Szrj inline bool 71738fd1498Szrj operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept 71838fd1498Szrj { return (bool)__x; } 71938fd1498Szrj 72038fd1498Szrj template<typename _Tp, typename _Dp, 72138fd1498Szrj typename _Up, typename _Ep> 72238fd1498Szrj inline bool 72338fd1498Szrj operator<(const unique_ptr<_Tp, _Dp>& __x, 72438fd1498Szrj const unique_ptr<_Up, _Ep>& __y) 72538fd1498Szrj { 72638fd1498Szrj typedef typename 72738fd1498Szrj std::common_type<typename unique_ptr<_Tp, _Dp>::pointer, 72838fd1498Szrj typename unique_ptr<_Up, _Ep>::pointer>::type _CT; 72938fd1498Szrj return std::less<_CT>()(__x.get(), __y.get()); 73038fd1498Szrj } 73138fd1498Szrj 73238fd1498Szrj template<typename _Tp, typename _Dp> 73338fd1498Szrj inline bool 73438fd1498Szrj operator<(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) 73538fd1498Szrj { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(), 73638fd1498Szrj nullptr); } 73738fd1498Szrj 73838fd1498Szrj template<typename _Tp, typename _Dp> 73938fd1498Szrj inline bool 74038fd1498Szrj operator<(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) 74138fd1498Szrj { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr, 74238fd1498Szrj __x.get()); } 74338fd1498Szrj 74438fd1498Szrj template<typename _Tp, typename _Dp, 74538fd1498Szrj typename _Up, typename _Ep> 74638fd1498Szrj inline bool 74738fd1498Szrj operator<=(const unique_ptr<_Tp, _Dp>& __x, 74838fd1498Szrj const unique_ptr<_Up, _Ep>& __y) 74938fd1498Szrj { return !(__y < __x); } 75038fd1498Szrj 75138fd1498Szrj template<typename _Tp, typename _Dp> 75238fd1498Szrj inline bool 75338fd1498Szrj operator<=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) 75438fd1498Szrj { return !(nullptr < __x); } 75538fd1498Szrj 75638fd1498Szrj template<typename _Tp, typename _Dp> 75738fd1498Szrj inline bool 75838fd1498Szrj operator<=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) 75938fd1498Szrj { return !(__x < nullptr); } 76038fd1498Szrj 76138fd1498Szrj template<typename _Tp, typename _Dp, 76238fd1498Szrj typename _Up, typename _Ep> 76338fd1498Szrj inline bool 76438fd1498Szrj operator>(const unique_ptr<_Tp, _Dp>& __x, 76538fd1498Szrj const unique_ptr<_Up, _Ep>& __y) 76638fd1498Szrj { return (__y < __x); } 76738fd1498Szrj 76838fd1498Szrj template<typename _Tp, typename _Dp> 76938fd1498Szrj inline bool 77038fd1498Szrj operator>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) 77138fd1498Szrj { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr, 77238fd1498Szrj __x.get()); } 77338fd1498Szrj 77438fd1498Szrj template<typename _Tp, typename _Dp> 77538fd1498Szrj inline bool 77638fd1498Szrj operator>(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) 77738fd1498Szrj { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(), 77838fd1498Szrj nullptr); } 77938fd1498Szrj 78038fd1498Szrj template<typename _Tp, typename _Dp, 78138fd1498Szrj typename _Up, typename _Ep> 78238fd1498Szrj inline bool 78338fd1498Szrj operator>=(const unique_ptr<_Tp, _Dp>& __x, 78438fd1498Szrj const unique_ptr<_Up, _Ep>& __y) 78538fd1498Szrj { return !(__x < __y); } 78638fd1498Szrj 78738fd1498Szrj template<typename _Tp, typename _Dp> 78838fd1498Szrj inline bool 78938fd1498Szrj operator>=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) 79038fd1498Szrj { return !(__x < nullptr); } 79138fd1498Szrj 79238fd1498Szrj template<typename _Tp, typename _Dp> 79338fd1498Szrj inline bool 79438fd1498Szrj operator>=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) 79538fd1498Szrj { return !(nullptr < __x); } 79638fd1498Szrj 79738fd1498Szrj /// std::hash specialization for unique_ptr. 79838fd1498Szrj template<typename _Tp, typename _Dp> 79938fd1498Szrj struct hash<unique_ptr<_Tp, _Dp>> 80038fd1498Szrj : public __hash_base<size_t, unique_ptr<_Tp, _Dp>>, 80138fd1498Szrj private __poison_hash<typename unique_ptr<_Tp, _Dp>::pointer> 80238fd1498Szrj { 80338fd1498Szrj size_t 80438fd1498Szrj operator()(const unique_ptr<_Tp, _Dp>& __u) const noexcept 80538fd1498Szrj { 80638fd1498Szrj typedef unique_ptr<_Tp, _Dp> _UP; 80738fd1498Szrj return std::hash<typename _UP::pointer>()(__u.get()); 80838fd1498Szrj } 80938fd1498Szrj }; 81038fd1498Szrj 81138fd1498Szrj #if __cplusplus > 201103L 81238fd1498Szrj 81338fd1498Szrj #define __cpp_lib_make_unique 201304 81438fd1498Szrj 81538fd1498Szrj template<typename _Tp> 81638fd1498Szrj struct _MakeUniq 81738fd1498Szrj { typedef unique_ptr<_Tp> __single_object; }; 81838fd1498Szrj 81938fd1498Szrj template<typename _Tp> 82038fd1498Szrj struct _MakeUniq<_Tp[]> 82138fd1498Szrj { typedef unique_ptr<_Tp[]> __array; }; 82238fd1498Szrj 82338fd1498Szrj template<typename _Tp, size_t _Bound> 82438fd1498Szrj struct _MakeUniq<_Tp[_Bound]> 82538fd1498Szrj { struct __invalid_type { }; }; 82638fd1498Szrj 82738fd1498Szrj /// std::make_unique for single objects 82838fd1498Szrj template<typename _Tp, typename... _Args> 82938fd1498Szrj inline typename _MakeUniq<_Tp>::__single_object 83038fd1498Szrj make_unique(_Args&&... __args) 83138fd1498Szrj { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); } 83238fd1498Szrj 83338fd1498Szrj /// std::make_unique for arrays of unknown bound 83438fd1498Szrj template<typename _Tp> 83538fd1498Szrj inline typename _MakeUniq<_Tp>::__array 83638fd1498Szrj make_unique(size_t __num) 83738fd1498Szrj { return unique_ptr<_Tp>(new remove_extent_t<_Tp>[__num]()); } 83838fd1498Szrj 83938fd1498Szrj /// Disable std::make_unique for arrays of known bound 84038fd1498Szrj template<typename _Tp, typename... _Args> 84138fd1498Szrj inline typename _MakeUniq<_Tp>::__invalid_type 84238fd1498Szrj make_unique(_Args&&...) = delete; 84338fd1498Szrj #endif 84438fd1498Szrj 84538fd1498Szrj // @} group pointer_abstractions 84638fd1498Szrj 84738fd1498Szrj _GLIBCXX_END_NAMESPACE_VERSION 84838fd1498Szrj } // namespace 84938fd1498Szrj 85038fd1498Szrj #endif /* _UNIQUE_PTR_H */ 851