xref: /dflybsd-src/contrib/gcc-4.7/libstdc++-v3/include/bits/unique_ptr.h (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino // unique_ptr implementation -*- C++ -*-
2*e4b17023SJohn Marino 
3*e4b17023SJohn Marino // Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
4*e4b17023SJohn Marino //
5*e4b17023SJohn Marino // This file is part of the GNU ISO C++ Library.  This library is free
6*e4b17023SJohn Marino // software; you can redistribute it and/or modify it under the
7*e4b17023SJohn Marino // terms of the GNU General Public License as published by the
8*e4b17023SJohn Marino // Free Software Foundation; either version 3, or (at your option)
9*e4b17023SJohn Marino // any later version.
10*e4b17023SJohn Marino 
11*e4b17023SJohn Marino // This library is distributed in the hope that it will be useful,
12*e4b17023SJohn Marino // but WITHOUT ANY WARRANTY; without even the implied warranty of
13*e4b17023SJohn Marino // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*e4b17023SJohn Marino // GNU General Public License for more details.
15*e4b17023SJohn Marino 
16*e4b17023SJohn Marino // Under Section 7 of GPL version 3, you are granted additional
17*e4b17023SJohn Marino // permissions described in the GCC Runtime Library Exception, version
18*e4b17023SJohn Marino // 3.1, as published by the Free Software Foundation.
19*e4b17023SJohn Marino 
20*e4b17023SJohn Marino // You should have received a copy of the GNU General Public License and
21*e4b17023SJohn Marino // a copy of the GCC Runtime Library Exception along with this program;
22*e4b17023SJohn Marino // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23*e4b17023SJohn Marino // <http://www.gnu.org/licenses/>.
24*e4b17023SJohn Marino 
25*e4b17023SJohn Marino /** @file bits/unique_ptr.h
26*e4b17023SJohn Marino  *  This is an internal header file, included by other library headers.
27*e4b17023SJohn Marino  *  Do not attempt to use it directly. @headername{memory}
28*e4b17023SJohn Marino  */
29*e4b17023SJohn Marino 
30*e4b17023SJohn Marino #ifndef _UNIQUE_PTR_H
31*e4b17023SJohn Marino #define _UNIQUE_PTR_H 1
32*e4b17023SJohn Marino 
33*e4b17023SJohn Marino #include <bits/c++config.h>
34*e4b17023SJohn Marino #include <debug/debug.h>
35*e4b17023SJohn Marino #include <type_traits>
36*e4b17023SJohn Marino #include <utility>
37*e4b17023SJohn Marino #include <tuple>
38*e4b17023SJohn Marino 
_GLIBCXX_VISIBILITY(default)39*e4b17023SJohn Marino namespace std _GLIBCXX_VISIBILITY(default)
40*e4b17023SJohn Marino {
41*e4b17023SJohn Marino _GLIBCXX_BEGIN_NAMESPACE_VERSION
42*e4b17023SJohn Marino 
43*e4b17023SJohn Marino   /**
44*e4b17023SJohn Marino    * @addtogroup pointer_abstractions
45*e4b17023SJohn Marino    * @{
46*e4b17023SJohn Marino    */
47*e4b17023SJohn Marino 
48*e4b17023SJohn Marino   /// Primary template, default_delete.
49*e4b17023SJohn Marino   template<typename _Tp>
50*e4b17023SJohn Marino     struct default_delete
51*e4b17023SJohn Marino     {
52*e4b17023SJohn Marino       constexpr default_delete() noexcept = default;
53*e4b17023SJohn Marino 
54*e4b17023SJohn Marino       template<typename _Up, typename = typename
55*e4b17023SJohn Marino 	       std::enable_if<std::is_convertible<_Up*, _Tp*>::value>::type>
56*e4b17023SJohn Marino         default_delete(const default_delete<_Up>&) noexcept { }
57*e4b17023SJohn Marino 
58*e4b17023SJohn Marino       void
59*e4b17023SJohn Marino       operator()(_Tp* __ptr) const
60*e4b17023SJohn Marino       {
61*e4b17023SJohn Marino 	static_assert(sizeof(_Tp)>0,
62*e4b17023SJohn Marino 		      "can't delete pointer to incomplete type");
63*e4b17023SJohn Marino 	delete __ptr;
64*e4b17023SJohn Marino       }
65*e4b17023SJohn Marino     };
66*e4b17023SJohn Marino 
67*e4b17023SJohn Marino   // _GLIBCXX_RESOLVE_LIB_DEFECTS
68*e4b17023SJohn Marino   // DR 740 - omit specialization for array objects with a compile time length
69*e4b17023SJohn Marino   /// Specialization, default_delete.
70*e4b17023SJohn Marino   template<typename _Tp>
71*e4b17023SJohn Marino     struct default_delete<_Tp[]>
72*e4b17023SJohn Marino     {
73*e4b17023SJohn Marino       constexpr default_delete() noexcept = default;
74*e4b17023SJohn Marino 
75*e4b17023SJohn Marino       void
76*e4b17023SJohn Marino       operator()(_Tp* __ptr) const
77*e4b17023SJohn Marino       {
78*e4b17023SJohn Marino 	static_assert(sizeof(_Tp)>0,
79*e4b17023SJohn Marino 		      "can't delete pointer to incomplete type");
80*e4b17023SJohn Marino 	delete [] __ptr;
81*e4b17023SJohn Marino       }
82*e4b17023SJohn Marino 
83*e4b17023SJohn Marino       template<typename _Up> void operator()(_Up*) const = delete;
84*e4b17023SJohn Marino     };
85*e4b17023SJohn Marino 
86*e4b17023SJohn Marino   /// 20.7.12.2 unique_ptr for single objects.
87*e4b17023SJohn Marino   template <typename _Tp, typename _Dp = default_delete<_Tp> >
88*e4b17023SJohn Marino     class unique_ptr
89*e4b17023SJohn Marino     {
90*e4b17023SJohn Marino       // use SFINAE to determine whether _Del::pointer exists
91*e4b17023SJohn Marino       class _Pointer
92*e4b17023SJohn Marino       {
93*e4b17023SJohn Marino 	template<typename _Up>
94*e4b17023SJohn Marino 	  static typename _Up::pointer __test(typename _Up::pointer*);
95*e4b17023SJohn Marino 
96*e4b17023SJohn Marino 	template<typename _Up>
97*e4b17023SJohn Marino 	  static _Tp* __test(...);
98*e4b17023SJohn Marino 
99*e4b17023SJohn Marino 	typedef typename remove_reference<_Dp>::type _Del;
100*e4b17023SJohn Marino 
101*e4b17023SJohn Marino       public:
102*e4b17023SJohn Marino 	typedef decltype( __test<_Del>(0)) type;
103*e4b17023SJohn Marino       };
104*e4b17023SJohn Marino 
105*e4b17023SJohn Marino       typedef std::tuple<typename _Pointer::type, _Dp>  __tuple_type;
106*e4b17023SJohn Marino       __tuple_type                                      _M_t;
107*e4b17023SJohn Marino 
108*e4b17023SJohn Marino     public:
109*e4b17023SJohn Marino       typedef typename _Pointer::type   pointer;
110*e4b17023SJohn Marino       typedef _Tp                       element_type;
111*e4b17023SJohn Marino       typedef _Dp                       deleter_type;
112*e4b17023SJohn Marino 
113*e4b17023SJohn Marino       // Constructors.
114*e4b17023SJohn Marino       constexpr unique_ptr() noexcept
115*e4b17023SJohn Marino       : _M_t()
116*e4b17023SJohn Marino       { static_assert(!std::is_pointer<deleter_type>::value,
117*e4b17023SJohn Marino 		     "constructed with null function pointer deleter"); }
118*e4b17023SJohn Marino 
119*e4b17023SJohn Marino       explicit
120*e4b17023SJohn Marino       unique_ptr(pointer __p) noexcept
121*e4b17023SJohn Marino       : _M_t(__p, deleter_type())
122*e4b17023SJohn Marino       { static_assert(!std::is_pointer<deleter_type>::value,
123*e4b17023SJohn Marino 		     "constructed with null function pointer deleter"); }
124*e4b17023SJohn Marino 
125*e4b17023SJohn Marino       unique_ptr(pointer __p,
126*e4b17023SJohn Marino 	  typename std::conditional<std::is_reference<deleter_type>::value,
127*e4b17023SJohn Marino 	    deleter_type, const deleter_type&>::type __d) noexcept
128*e4b17023SJohn Marino       : _M_t(__p, __d) { }
129*e4b17023SJohn Marino 
130*e4b17023SJohn Marino       unique_ptr(pointer __p,
131*e4b17023SJohn Marino 	  typename std::remove_reference<deleter_type>::type&& __d) noexcept
132*e4b17023SJohn Marino       : _M_t(std::move(__p), std::move(__d))
133*e4b17023SJohn Marino       { static_assert(!std::is_reference<deleter_type>::value,
134*e4b17023SJohn Marino 		      "rvalue deleter bound to reference"); }
135*e4b17023SJohn Marino 
136*e4b17023SJohn Marino       constexpr unique_ptr(nullptr_t) noexcept
137*e4b17023SJohn Marino       : _M_t()
138*e4b17023SJohn Marino       { static_assert(!std::is_pointer<deleter_type>::value,
139*e4b17023SJohn Marino 		     "constructed with null function pointer deleter"); }
140*e4b17023SJohn Marino 
141*e4b17023SJohn Marino       // Move constructors.
142*e4b17023SJohn Marino       unique_ptr(unique_ptr&& __u) noexcept
143*e4b17023SJohn Marino       : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
144*e4b17023SJohn Marino 
145*e4b17023SJohn Marino       template<typename _Up, typename _Ep, typename = typename
146*e4b17023SJohn Marino 	std::enable_if
147*e4b17023SJohn Marino 	  <std::is_convertible<typename unique_ptr<_Up, _Ep>::pointer,
148*e4b17023SJohn Marino 			       pointer>::value
149*e4b17023SJohn Marino 	   && !std::is_array<_Up>::value
150*e4b17023SJohn Marino 	   && ((std::is_reference<_Dp>::value
151*e4b17023SJohn Marino 		&& std::is_same<_Ep, _Dp>::value)
152*e4b17023SJohn Marino 	       || (!std::is_reference<_Dp>::value
153*e4b17023SJohn Marino 		   && std::is_convertible<_Ep, _Dp>::value))>
154*e4b17023SJohn Marino 	     ::type>
155*e4b17023SJohn Marino 	unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
156*e4b17023SJohn Marino 	: _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
157*e4b17023SJohn Marino 	{ }
158*e4b17023SJohn Marino 
159*e4b17023SJohn Marino #if _GLIBCXX_USE_DEPRECATED
160*e4b17023SJohn Marino       template<typename _Up, typename = typename
161*e4b17023SJohn Marino 	std::enable_if<std::is_convertible<_Up*, _Tp*>::value
162*e4b17023SJohn Marino 		       && std::is_same<_Dp,
163*e4b17023SJohn Marino 				       default_delete<_Tp>>::value>::type>
164*e4b17023SJohn Marino 	unique_ptr(auto_ptr<_Up>&& __u) noexcept
165*e4b17023SJohn Marino 	: _M_t(__u.release(), deleter_type()) { }
166*e4b17023SJohn Marino #endif
167*e4b17023SJohn Marino 
168*e4b17023SJohn Marino       // Destructor.
169*e4b17023SJohn Marino       ~unique_ptr() noexcept
170*e4b17023SJohn Marino       {
171*e4b17023SJohn Marino 	auto& __ptr = std::get<0>(_M_t);
172*e4b17023SJohn Marino 	if (__ptr != nullptr)
173*e4b17023SJohn Marino 	  get_deleter()(__ptr);
174*e4b17023SJohn Marino 	__ptr = pointer();
175*e4b17023SJohn Marino       }
176*e4b17023SJohn Marino 
177*e4b17023SJohn Marino       // Assignment.
178*e4b17023SJohn Marino       unique_ptr&
179*e4b17023SJohn Marino       operator=(unique_ptr&& __u) noexcept
180*e4b17023SJohn Marino       {
181*e4b17023SJohn Marino 	reset(__u.release());
182*e4b17023SJohn Marino 	get_deleter() = std::forward<deleter_type>(__u.get_deleter());
183*e4b17023SJohn Marino 	return *this;
184*e4b17023SJohn Marino       }
185*e4b17023SJohn Marino 
186*e4b17023SJohn Marino       template<typename _Up, typename _Ep, typename = typename
187*e4b17023SJohn Marino 	std::enable_if
188*e4b17023SJohn Marino 	  <std::is_convertible<typename unique_ptr<_Up, _Ep>::pointer,
189*e4b17023SJohn Marino 			       pointer>::value
190*e4b17023SJohn Marino 	   && !std::is_array<_Up>::value>::type>
191*e4b17023SJohn Marino 	unique_ptr&
192*e4b17023SJohn Marino 	operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
193*e4b17023SJohn Marino 	{
194*e4b17023SJohn Marino 	  reset(__u.release());
195*e4b17023SJohn Marino 	  get_deleter() = std::forward<_Ep>(__u.get_deleter());
196*e4b17023SJohn Marino 	  return *this;
197*e4b17023SJohn Marino 	}
198*e4b17023SJohn Marino 
199*e4b17023SJohn Marino       unique_ptr&
200*e4b17023SJohn Marino       operator=(nullptr_t) noexcept
201*e4b17023SJohn Marino       {
202*e4b17023SJohn Marino 	reset();
203*e4b17023SJohn Marino 	return *this;
204*e4b17023SJohn Marino       }
205*e4b17023SJohn Marino 
206*e4b17023SJohn Marino       // Observers.
207*e4b17023SJohn Marino       typename std::add_lvalue_reference<element_type>::type
208*e4b17023SJohn Marino       operator*() const
209*e4b17023SJohn Marino       {
210*e4b17023SJohn Marino 	_GLIBCXX_DEBUG_ASSERT(get() != pointer());
211*e4b17023SJohn Marino 	return *get();
212*e4b17023SJohn Marino       }
213*e4b17023SJohn Marino 
214*e4b17023SJohn Marino       pointer
215*e4b17023SJohn Marino       operator->() const noexcept
216*e4b17023SJohn Marino       {
217*e4b17023SJohn Marino 	_GLIBCXX_DEBUG_ASSERT(get() != pointer());
218*e4b17023SJohn Marino 	return get();
219*e4b17023SJohn Marino       }
220*e4b17023SJohn Marino 
221*e4b17023SJohn Marino       pointer
222*e4b17023SJohn Marino       get() const noexcept
223*e4b17023SJohn Marino       { return std::get<0>(_M_t); }
224*e4b17023SJohn Marino 
225*e4b17023SJohn Marino       deleter_type&
226*e4b17023SJohn Marino       get_deleter() noexcept
227*e4b17023SJohn Marino       { return std::get<1>(_M_t); }
228*e4b17023SJohn Marino 
229*e4b17023SJohn Marino       const deleter_type&
230*e4b17023SJohn Marino       get_deleter() const noexcept
231*e4b17023SJohn Marino       { return std::get<1>(_M_t); }
232*e4b17023SJohn Marino 
233*e4b17023SJohn Marino       explicit operator bool() const noexcept
234*e4b17023SJohn Marino       { return get() == pointer() ? false : true; }
235*e4b17023SJohn Marino 
236*e4b17023SJohn Marino       // Modifiers.
237*e4b17023SJohn Marino       pointer
238*e4b17023SJohn Marino       release() noexcept
239*e4b17023SJohn Marino       {
240*e4b17023SJohn Marino 	pointer __p = get();
241*e4b17023SJohn Marino 	std::get<0>(_M_t) = pointer();
242*e4b17023SJohn Marino 	return __p;
243*e4b17023SJohn Marino       }
244*e4b17023SJohn Marino 
245*e4b17023SJohn Marino       void
246*e4b17023SJohn Marino       reset(pointer __p = pointer()) noexcept
247*e4b17023SJohn Marino       {
248*e4b17023SJohn Marino 	using std::swap;
249*e4b17023SJohn Marino 	swap(std::get<0>(_M_t), __p);
250*e4b17023SJohn Marino 	if (__p != pointer())
251*e4b17023SJohn Marino 	  get_deleter()(__p);
252*e4b17023SJohn Marino       }
253*e4b17023SJohn Marino 
254*e4b17023SJohn Marino       void
255*e4b17023SJohn Marino       swap(unique_ptr& __u) noexcept
256*e4b17023SJohn Marino       {
257*e4b17023SJohn Marino 	using std::swap;
258*e4b17023SJohn Marino 	swap(_M_t, __u._M_t);
259*e4b17023SJohn Marino       }
260*e4b17023SJohn Marino 
261*e4b17023SJohn Marino       // Disable copy from lvalue.
262*e4b17023SJohn Marino       unique_ptr(const unique_ptr&) = delete;
263*e4b17023SJohn Marino       unique_ptr& operator=(const unique_ptr&) = delete;
264*e4b17023SJohn Marino   };
265*e4b17023SJohn Marino 
266*e4b17023SJohn Marino   /// 20.7.12.3 unique_ptr for array objects with a runtime length
267*e4b17023SJohn Marino   // [unique.ptr.runtime]
268*e4b17023SJohn Marino   // _GLIBCXX_RESOLVE_LIB_DEFECTS
269*e4b17023SJohn Marino   // DR 740 - omit specialization for array objects with a compile time length
270*e4b17023SJohn Marino   template<typename _Tp, typename _Dp>
271*e4b17023SJohn Marino     class unique_ptr<_Tp[], _Dp>
272*e4b17023SJohn Marino     {
273*e4b17023SJohn Marino       typedef std::tuple<_Tp*, _Dp>  	__tuple_type;
274*e4b17023SJohn Marino       __tuple_type 			_M_t;
275*e4b17023SJohn Marino 
276*e4b17023SJohn Marino     public:
277*e4b17023SJohn Marino       typedef _Tp*		 	pointer;
278*e4b17023SJohn Marino       typedef _Tp		 	element_type;
279*e4b17023SJohn Marino       typedef _Dp                       deleter_type;
280*e4b17023SJohn Marino 
281*e4b17023SJohn Marino       // Constructors.
282*e4b17023SJohn Marino       constexpr unique_ptr() noexcept
283*e4b17023SJohn Marino       : _M_t()
284*e4b17023SJohn Marino       { static_assert(!std::is_pointer<deleter_type>::value,
285*e4b17023SJohn Marino 		     "constructed with null function pointer deleter"); }
286*e4b17023SJohn Marino 
287*e4b17023SJohn Marino       explicit
288*e4b17023SJohn Marino       unique_ptr(pointer __p) noexcept
289*e4b17023SJohn Marino       : _M_t(__p, deleter_type())
290*e4b17023SJohn Marino       { static_assert(!std::is_pointer<deleter_type>::value,
291*e4b17023SJohn Marino 		     "constructed with null function pointer deleter"); }
292*e4b17023SJohn Marino 
293*e4b17023SJohn Marino       unique_ptr(pointer __p,
294*e4b17023SJohn Marino 	  typename std::conditional<std::is_reference<deleter_type>::value,
295*e4b17023SJohn Marino 	      deleter_type, const deleter_type&>::type __d) noexcept
296*e4b17023SJohn Marino       : _M_t(__p, __d) { }
297*e4b17023SJohn Marino 
298*e4b17023SJohn Marino       unique_ptr(pointer __p, typename
299*e4b17023SJohn Marino 		 std::remove_reference<deleter_type>::type && __d) noexcept
300*e4b17023SJohn Marino       : _M_t(std::move(__p), std::move(__d))
301*e4b17023SJohn Marino       { static_assert(!std::is_reference<deleter_type>::value,
302*e4b17023SJohn Marino 		      "rvalue deleter bound to reference"); }
303*e4b17023SJohn Marino 
304*e4b17023SJohn Marino       constexpr unique_ptr(nullptr_t) noexcept
305*e4b17023SJohn Marino       : _M_t()
306*e4b17023SJohn Marino       { static_assert(!std::is_pointer<deleter_type>::value,
307*e4b17023SJohn Marino 		     "constructed with null function pointer deleter"); }
308*e4b17023SJohn Marino 
309*e4b17023SJohn Marino       // Move constructors.
310*e4b17023SJohn Marino       unique_ptr(unique_ptr&& __u) noexcept
311*e4b17023SJohn Marino       : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
312*e4b17023SJohn Marino 
313*e4b17023SJohn Marino       template<typename _Up, typename _Ep>
314*e4b17023SJohn Marino 	unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
315*e4b17023SJohn Marino 	: _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
316*e4b17023SJohn Marino 	{ }
317*e4b17023SJohn Marino 
318*e4b17023SJohn Marino       // Destructor.
319*e4b17023SJohn Marino       ~unique_ptr()
320*e4b17023SJohn Marino       {
321*e4b17023SJohn Marino 	auto& __ptr = std::get<0>(_M_t);
322*e4b17023SJohn Marino 	if (__ptr != nullptr)
323*e4b17023SJohn Marino 	  get_deleter()(__ptr);
324*e4b17023SJohn Marino 	__ptr = pointer();
325*e4b17023SJohn Marino       }
326*e4b17023SJohn Marino 
327*e4b17023SJohn Marino       // Assignment.
328*e4b17023SJohn Marino       unique_ptr&
329*e4b17023SJohn Marino       operator=(unique_ptr&& __u) noexcept
330*e4b17023SJohn Marino       {
331*e4b17023SJohn Marino 	reset(__u.release());
332*e4b17023SJohn Marino 	get_deleter() = std::forward<deleter_type>(__u.get_deleter());
333*e4b17023SJohn Marino 	return *this;
334*e4b17023SJohn Marino       }
335*e4b17023SJohn Marino 
336*e4b17023SJohn Marino       template<typename _Up, typename _Ep>
337*e4b17023SJohn Marino 	unique_ptr&
338*e4b17023SJohn Marino 	operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
339*e4b17023SJohn Marino 	{
340*e4b17023SJohn Marino 	  reset(__u.release());
341*e4b17023SJohn Marino 	  get_deleter() = std::forward<_Ep>(__u.get_deleter());
342*e4b17023SJohn Marino 	  return *this;
343*e4b17023SJohn Marino 	}
344*e4b17023SJohn Marino 
345*e4b17023SJohn Marino       unique_ptr&
346*e4b17023SJohn Marino       operator=(nullptr_t) noexcept
347*e4b17023SJohn Marino       {
348*e4b17023SJohn Marino 	reset();
349*e4b17023SJohn Marino 	return *this;
350*e4b17023SJohn Marino       }
351*e4b17023SJohn Marino 
352*e4b17023SJohn Marino       // Observers.
353*e4b17023SJohn Marino       typename std::add_lvalue_reference<element_type>::type
354*e4b17023SJohn Marino       operator[](size_t __i) const
355*e4b17023SJohn Marino       {
356*e4b17023SJohn Marino 	_GLIBCXX_DEBUG_ASSERT(get() != pointer());
357*e4b17023SJohn Marino 	return get()[__i];
358*e4b17023SJohn Marino       }
359*e4b17023SJohn Marino 
360*e4b17023SJohn Marino       pointer
361*e4b17023SJohn Marino       get() const noexcept
362*e4b17023SJohn Marino       { return std::get<0>(_M_t); }
363*e4b17023SJohn Marino 
364*e4b17023SJohn Marino       deleter_type&
365*e4b17023SJohn Marino       get_deleter() noexcept
366*e4b17023SJohn Marino       { return std::get<1>(_M_t); }
367*e4b17023SJohn Marino 
368*e4b17023SJohn Marino       const deleter_type&
369*e4b17023SJohn Marino       get_deleter() const noexcept
370*e4b17023SJohn Marino       { return std::get<1>(_M_t); }
371*e4b17023SJohn Marino 
372*e4b17023SJohn Marino       explicit operator bool() const noexcept
373*e4b17023SJohn Marino       { return get() == pointer() ? false : true; }
374*e4b17023SJohn Marino 
375*e4b17023SJohn Marino       // Modifiers.
376*e4b17023SJohn Marino       pointer
377*e4b17023SJohn Marino       release() noexcept
378*e4b17023SJohn Marino       {
379*e4b17023SJohn Marino 	pointer __p = get();
380*e4b17023SJohn Marino 	std::get<0>(_M_t) = pointer();
381*e4b17023SJohn Marino 	return __p;
382*e4b17023SJohn Marino       }
383*e4b17023SJohn Marino 
384*e4b17023SJohn Marino       void
385*e4b17023SJohn Marino       reset(pointer __p = pointer()) noexcept
386*e4b17023SJohn Marino       {
387*e4b17023SJohn Marino 	using std::swap;
388*e4b17023SJohn Marino 	swap(std::get<0>(_M_t), __p);
389*e4b17023SJohn Marino 	if (__p != nullptr)
390*e4b17023SJohn Marino 	  get_deleter()(__p);
391*e4b17023SJohn Marino       }
392*e4b17023SJohn Marino 
393*e4b17023SJohn Marino       void
394*e4b17023SJohn Marino       reset(nullptr_t) noexcept
395*e4b17023SJohn Marino       {
396*e4b17023SJohn Marino 	pointer __p = get();
397*e4b17023SJohn Marino 	std::get<0>(_M_t) = pointer();
398*e4b17023SJohn Marino 	if (__p != nullptr)
399*e4b17023SJohn Marino 	  get_deleter()(__p);
400*e4b17023SJohn Marino       }
401*e4b17023SJohn Marino 
402*e4b17023SJohn Marino       // DR 821.
403*e4b17023SJohn Marino       template<typename _Up>
404*e4b17023SJohn Marino 	void reset(_Up) = delete;
405*e4b17023SJohn Marino 
406*e4b17023SJohn Marino       void
407*e4b17023SJohn Marino       swap(unique_ptr& __u) noexcept
408*e4b17023SJohn Marino       {
409*e4b17023SJohn Marino 	using std::swap;
410*e4b17023SJohn Marino 	swap(_M_t, __u._M_t);
411*e4b17023SJohn Marino       }
412*e4b17023SJohn Marino 
413*e4b17023SJohn Marino       // Disable copy from lvalue.
414*e4b17023SJohn Marino       unique_ptr(const unique_ptr&) = delete;
415*e4b17023SJohn Marino       unique_ptr& operator=(const unique_ptr&) = delete;
416*e4b17023SJohn Marino 
417*e4b17023SJohn Marino       // Disable construction from convertible pointer types.
418*e4b17023SJohn Marino       // (N2315 - 20.6.5.3.1)
419*e4b17023SJohn Marino       template<typename _Up>
420*e4b17023SJohn Marino 	unique_ptr(_Up*, typename
421*e4b17023SJohn Marino 		   std::conditional<std::is_reference<deleter_type>::value,
422*e4b17023SJohn Marino 		   deleter_type, const deleter_type&>::type,
423*e4b17023SJohn Marino 		   typename std::enable_if<std::is_convertible<_Up*,
424*e4b17023SJohn Marino 		   pointer>::value>::type* = 0) = delete;
425*e4b17023SJohn Marino 
426*e4b17023SJohn Marino       template<typename _Up>
427*e4b17023SJohn Marino 	unique_ptr(_Up*, typename std::remove_reference<deleter_type>::type&&,
428*e4b17023SJohn Marino 		   typename std::enable_if<std::is_convertible<_Up*,
429*e4b17023SJohn Marino 		   pointer>::value>::type* = 0) = delete;
430*e4b17023SJohn Marino 
431*e4b17023SJohn Marino       template<typename _Up>
432*e4b17023SJohn Marino 	explicit
433*e4b17023SJohn Marino 	unique_ptr(_Up*, typename std::enable_if<std::is_convertible<_Up*,
434*e4b17023SJohn Marino 		   pointer>::value>::type* = 0) = delete;
435*e4b17023SJohn Marino     };
436*e4b17023SJohn Marino 
437*e4b17023SJohn Marino   template<typename _Tp, typename _Dp>
438*e4b17023SJohn Marino     inline void
439*e4b17023SJohn Marino     swap(unique_ptr<_Tp, _Dp>& __x,
440*e4b17023SJohn Marino 	 unique_ptr<_Tp, _Dp>& __y) noexcept
441*e4b17023SJohn Marino     { __x.swap(__y); }
442*e4b17023SJohn Marino 
443*e4b17023SJohn Marino   template<typename _Tp, typename _Dp,
444*e4b17023SJohn Marino 	   typename _Up, typename _Ep>
445*e4b17023SJohn Marino     inline bool
446*e4b17023SJohn Marino     operator==(const unique_ptr<_Tp, _Dp>& __x,
447*e4b17023SJohn Marino 	       const unique_ptr<_Up, _Ep>& __y)
448*e4b17023SJohn Marino     { return __x.get() == __y.get(); }
449*e4b17023SJohn Marino 
450*e4b17023SJohn Marino   template<typename _Tp, typename _Dp>
451*e4b17023SJohn Marino     inline bool
452*e4b17023SJohn Marino     operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
453*e4b17023SJohn Marino     { return !__x; }
454*e4b17023SJohn Marino 
455*e4b17023SJohn Marino   template<typename _Tp, typename _Dp>
456*e4b17023SJohn Marino     inline bool
457*e4b17023SJohn Marino     operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
458*e4b17023SJohn Marino     { return !__x; }
459*e4b17023SJohn Marino 
460*e4b17023SJohn Marino   template<typename _Tp, typename _Dp,
461*e4b17023SJohn Marino 	   typename _Up, typename _Ep>
462*e4b17023SJohn Marino     inline bool
463*e4b17023SJohn Marino     operator!=(const unique_ptr<_Tp, _Dp>& __x,
464*e4b17023SJohn Marino 	       const unique_ptr<_Up, _Ep>& __y)
465*e4b17023SJohn Marino     { return __x.get() != __y.get(); }
466*e4b17023SJohn Marino 
467*e4b17023SJohn Marino   template<typename _Tp, typename _Dp>
468*e4b17023SJohn Marino     inline bool
469*e4b17023SJohn Marino     operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
470*e4b17023SJohn Marino     { return (bool)__x; }
471*e4b17023SJohn Marino 
472*e4b17023SJohn Marino   template<typename _Tp, typename _Dp>
473*e4b17023SJohn Marino     inline bool
474*e4b17023SJohn Marino     operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
475*e4b17023SJohn Marino     { return (bool)__x; }
476*e4b17023SJohn Marino 
477*e4b17023SJohn Marino   template<typename _Tp, typename _Dp,
478*e4b17023SJohn Marino 	   typename _Up, typename _Ep>
479*e4b17023SJohn Marino     inline bool
480*e4b17023SJohn Marino     operator<(const unique_ptr<_Tp, _Dp>& __x,
481*e4b17023SJohn Marino 	      const unique_ptr<_Up, _Ep>& __y)
482*e4b17023SJohn Marino     {
483*e4b17023SJohn Marino       typedef typename
484*e4b17023SJohn Marino 	std::common_type<typename unique_ptr<_Tp, _Dp>::pointer,
485*e4b17023SJohn Marino 	                 typename unique_ptr<_Up, _Ep>::pointer>::type _CT;
486*e4b17023SJohn Marino       return std::less<_CT>()(__x.get(), __y.get());
487*e4b17023SJohn Marino     }
488*e4b17023SJohn Marino 
489*e4b17023SJohn Marino   template<typename _Tp, typename _Dp>
490*e4b17023SJohn Marino     inline bool
491*e4b17023SJohn Marino     operator<(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
492*e4b17023SJohn Marino     { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(),
493*e4b17023SJohn Marino 								 nullptr); }
494*e4b17023SJohn Marino 
495*e4b17023SJohn Marino   template<typename _Tp, typename _Dp>
496*e4b17023SJohn Marino     inline bool
497*e4b17023SJohn Marino     operator<(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
498*e4b17023SJohn Marino     { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr,
499*e4b17023SJohn Marino 								 __x.get()); }
500*e4b17023SJohn Marino 
501*e4b17023SJohn Marino   template<typename _Tp, typename _Dp,
502*e4b17023SJohn Marino 	   typename _Up, typename _Ep>
503*e4b17023SJohn Marino     inline bool
504*e4b17023SJohn Marino     operator<=(const unique_ptr<_Tp, _Dp>& __x,
505*e4b17023SJohn Marino 	       const unique_ptr<_Up, _Ep>& __y)
506*e4b17023SJohn Marino     { return !(__y < __x); }
507*e4b17023SJohn Marino 
508*e4b17023SJohn Marino   template<typename _Tp, typename _Dp>
509*e4b17023SJohn Marino     inline bool
510*e4b17023SJohn Marino     operator<=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
511*e4b17023SJohn Marino     { return !(nullptr < __x); }
512*e4b17023SJohn Marino 
513*e4b17023SJohn Marino   template<typename _Tp, typename _Dp>
514*e4b17023SJohn Marino     inline bool
515*e4b17023SJohn Marino     operator<=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
516*e4b17023SJohn Marino     { return !(__x < nullptr); }
517*e4b17023SJohn Marino 
518*e4b17023SJohn Marino   template<typename _Tp, typename _Dp,
519*e4b17023SJohn Marino 	   typename _Up, typename _Ep>
520*e4b17023SJohn Marino     inline bool
521*e4b17023SJohn Marino     operator>(const unique_ptr<_Tp, _Dp>& __x,
522*e4b17023SJohn Marino 	      const unique_ptr<_Up, _Ep>& __y)
523*e4b17023SJohn Marino     { return (__y < __x); }
524*e4b17023SJohn Marino 
525*e4b17023SJohn Marino   template<typename _Tp, typename _Dp>
526*e4b17023SJohn Marino     inline bool
527*e4b17023SJohn Marino     operator>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
528*e4b17023SJohn Marino     { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr,
529*e4b17023SJohn Marino 								 __x.get()); }
530*e4b17023SJohn Marino 
531*e4b17023SJohn Marino   template<typename _Tp, typename _Dp>
532*e4b17023SJohn Marino     inline bool
533*e4b17023SJohn Marino     operator>(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
534*e4b17023SJohn Marino     { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(),
535*e4b17023SJohn Marino 								 nullptr); }
536*e4b17023SJohn Marino 
537*e4b17023SJohn Marino   template<typename _Tp, typename _Dp,
538*e4b17023SJohn Marino 	   typename _Up, typename _Ep>
539*e4b17023SJohn Marino     inline bool
540*e4b17023SJohn Marino     operator>=(const unique_ptr<_Tp, _Dp>& __x,
541*e4b17023SJohn Marino 	       const unique_ptr<_Up, _Ep>& __y)
542*e4b17023SJohn Marino     { return !(__x < __y); }
543*e4b17023SJohn Marino 
544*e4b17023SJohn Marino   template<typename _Tp, typename _Dp>
545*e4b17023SJohn Marino     inline bool
546*e4b17023SJohn Marino     operator>=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
547*e4b17023SJohn Marino     { return !(__x < nullptr); }
548*e4b17023SJohn Marino 
549*e4b17023SJohn Marino   template<typename _Tp, typename _Dp>
550*e4b17023SJohn Marino     inline bool
551*e4b17023SJohn Marino     operator>=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
552*e4b17023SJohn Marino     { return !(nullptr < __x); }
553*e4b17023SJohn Marino 
554*e4b17023SJohn Marino   /// std::hash specialization for unique_ptr.
555*e4b17023SJohn Marino   template<typename _Tp, typename _Dp>
556*e4b17023SJohn Marino     struct hash<unique_ptr<_Tp, _Dp>>
557*e4b17023SJohn Marino     : public __hash_base<size_t, unique_ptr<_Tp, _Dp>>
558*e4b17023SJohn Marino     {
559*e4b17023SJohn Marino       size_t
560*e4b17023SJohn Marino       operator()(const unique_ptr<_Tp, _Dp>& __u) const noexcept
561*e4b17023SJohn Marino       {
562*e4b17023SJohn Marino 	typedef unique_ptr<_Tp, _Dp> _UP;
563*e4b17023SJohn Marino 	return std::hash<typename _UP::pointer>()(__u.get());
564*e4b17023SJohn Marino       }
565*e4b17023SJohn Marino     };
566*e4b17023SJohn Marino 
567*e4b17023SJohn Marino   // @} group pointer_abstractions
568*e4b17023SJohn Marino 
569*e4b17023SJohn Marino _GLIBCXX_END_NAMESPACE_VERSION
570*e4b17023SJohn Marino } // namespace
571*e4b17023SJohn Marino 
572*e4b17023SJohn Marino #endif /* _UNIQUE_PTR_H */
573