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
_GLIBCXX_VISIBILITY(default)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