1 // unique_ptr implementation -*- C++ -*-
3 // Copyright (C) 2008, 2009 Free Software Foundation, Inc.
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 2, or (at your option)
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this library; see the file COPYING. If not, write to
18 // the Free Software Foundation, 51 Franklin Street, Fifth Floor,
19 // Boston, MA 02110-1301, USA.
21 // As a special exception, you may use this file as part of a free software
22 // library without restriction. Specifically, if other files instantiate
23 // templates or use macros or inline functions from this file, or you compile
24 // this file and link it with other files to produce an executable, this
25 // file does not by itself cause the resulting executable to be covered by
26 // the GNU General Public License. This exception does not however
27 // invalidate any other reasons why the executable file might be covered by
28 // the GNU General Public License.
30 /** @file unique_ptr.h
31 * This is an internal header file, included by other library headers.
32 * You should not attempt to use it directly.
36 #define _UNIQUE_PTR_H 1
38 #ifndef __GXX_EXPERIMENTAL_CXX0X__
39 # include <c++0x_warning.h>
42 #include <bits/c++config.h>
43 #include <debug/debug.h>
44 #include <type_traits>
48 _GLIBCXX_BEGIN_NAMESPACE(std
)
51 * @addtogroup pointer_abstractions
55 /// Primary template, default_delete.
56 template<typename _Tp
>
61 template<typename _Up
>
62 default_delete(const default_delete
<_Up
>&) { }
65 operator()(_Tp
* __ptr
) const
67 static_assert(sizeof(_Tp
)>0,
68 "can't delete pointer to incomplete type");
73 // _GLIBCXX_RESOLVE_LIB_DEFECTS
74 // DR 740 - omit specialization for array objects with a compile time length
75 /// Specialization, default_delete.
76 template<typename _Tp
>
77 struct default_delete
<_Tp
[]>
80 operator()(_Tp
* __ptr
) const
82 static_assert(sizeof(_Tp
)>0,
83 "can't delete pointer to incomplete type");
88 /// 20.7.12.2 unique_ptr for single objects.
89 template <typename _Tp
, typename _Tp_Deleter
= default_delete
<_Tp
> >
92 typedef std::tuple
<_Tp
*, _Tp_Deleter
> __tuple_type
;
93 typedef __tuple_type
unique_ptr::* __unspecified_bool_type
;
94 typedef _Tp
* unique_ptr::* __unspecified_pointer_type
;
98 typedef _Tp element_type
;
99 typedef _Tp_Deleter deleter_type
;
103 : _M_t(pointer(), deleter_type())
104 { static_assert(!std::is_pointer
<deleter_type
>::value
,
105 "constructed with null function pointer deleter"); }
108 unique_ptr(pointer __p
)
109 : _M_t(__p
, deleter_type())
110 { static_assert(!std::is_pointer
<deleter_type
>::value
,
111 "constructed with null function pointer deleter"); }
113 unique_ptr(pointer __p
,
114 typename
std::conditional
<std::is_reference
<deleter_type
>::value
,
115 deleter_type
, const deleter_type
&>::type __d
)
118 unique_ptr(pointer __p
,
119 typename
std::remove_reference
<deleter_type
>::type
&& __d
)
120 : _M_t(std::move(__p
), std::move(__d
))
121 { static_assert(!std::is_reference
<deleter_type
>::value
,
122 "rvalue deleter bound to reference"); }
124 // Move constructors.
125 unique_ptr(unique_ptr
&& __u
)
126 : _M_t(__u
.release(), std::forward
<deleter_type
>(__u
.get_deleter())) { }
128 template<typename _Up
, typename _Up_Deleter
>
129 unique_ptr(unique_ptr
<_Up
, _Up_Deleter
>&& __u
)
130 : _M_t(__u
.release(), std::forward
<deleter_type
>(__u
.get_deleter()))
134 ~unique_ptr() { reset(); }
138 operator=(unique_ptr
&& __u
)
140 reset(__u
.release());
141 get_deleter() = std::move(__u
.get_deleter());
145 template<typename _Up
, typename _Up_Deleter
>
147 operator=(unique_ptr
<_Up
, _Up_Deleter
>&& __u
)
149 reset(__u
.release());
150 get_deleter() = std::move(__u
.get_deleter());
155 operator=(__unspecified_pointer_type
)
162 typename
std::add_lvalue_reference
<element_type
>::type
operator*() const
164 _GLIBCXX_DEBUG_ASSERT(get() != 0);
171 _GLIBCXX_DEBUG_ASSERT(get() != 0);
177 { return std::get
<0>(_M_t
); }
179 typename
std::add_lvalue_reference
<deleter_type
>::type
181 { return std::get
<1>(_M_t
); }
183 typename
std::add_lvalue_reference
<
184 typename
std::add_const
<deleter_type
>::type
187 { return std::get
<1>(_M_t
); }
189 operator __unspecified_bool_type () const
190 { return get() == 0 ? 0 : &unique_ptr::_M_t
; }
197 std::get
<0>(_M_t
) = 0;
202 reset(pointer __p
= pointer())
206 get_deleter()(get());
207 std::get
<0>(_M_t
) = __p
;
212 swap(unique_ptr
&& __u
)
215 swap(_M_t
, __u
._M_t
);
218 // Disable copy from lvalue.
219 unique_ptr(const unique_ptr
&) = delete;
221 template<typename _Up
, typename _Up_Deleter
>
222 unique_ptr(const unique_ptr
<_Up
, _Up_Deleter
>&) = delete;
224 unique_ptr
& operator=(const unique_ptr
&) = delete;
226 template<typename _Up
, typename _Up_Deleter
>
227 unique_ptr
& operator=(const unique_ptr
<_Up
, _Up_Deleter
>&) = delete;
233 /// 20.7.12.3 unique_ptr for array objects with a runtime length
234 // [unique.ptr.runtime]
235 // _GLIBCXX_RESOLVE_LIB_DEFECTS
236 // DR 740 - omit specialization for array objects with a compile time length
237 template<typename _Tp
, typename _Tp_Deleter
>
238 class unique_ptr
<_Tp
[], _Tp_Deleter
>
240 typedef std::tuple
<_Tp
*, _Tp_Deleter
> __tuple_type
;
241 typedef __tuple_type
unique_ptr::* __unspecified_bool_type
;
242 typedef _Tp
* unique_ptr::* __unspecified_pointer_type
;
245 typedef _Tp
* pointer
;
246 typedef _Tp element_type
;
247 typedef _Tp_Deleter deleter_type
;
251 : _M_t(pointer(), deleter_type())
252 { static_assert(!std::is_pointer
<deleter_type
>::value
,
253 "constructed with null function pointer deleter"); }
256 unique_ptr(pointer __p
)
257 : _M_t(__p
, deleter_type())
258 { static_assert(!std::is_pointer
<deleter_type
>::value
,
259 "constructed with null function pointer deleter"); }
261 unique_ptr(pointer __p
,
262 typename
std::conditional
<std::is_reference
<deleter_type
>::value
,
263 deleter_type
, const deleter_type
&>::type __d
)
266 unique_ptr(pointer __p
,
267 typename
std::remove_reference
<deleter_type
>::type
&& __d
)
268 : _M_t(std::move(__p
), std::move(__d
))
269 { static_assert(!std::is_reference
<deleter_type
>::value
,
270 "rvalue deleter bound to reference"); }
272 // Move constructors.
273 unique_ptr(unique_ptr
&& __u
)
274 : _M_t(__u
.release(), std::forward
<deleter_type
>(__u
.get_deleter())) { }
276 template<typename _Up
, typename _Up_Deleter
>
277 unique_ptr(unique_ptr
<_Up
, _Up_Deleter
>&& __u
)
278 : _M_t(__u
.release(), std::forward
<deleter_type
>(__u
.get_deleter()))
282 ~unique_ptr() { reset(); }
286 operator=(unique_ptr
&& __u
)
288 reset(__u
.release());
289 get_deleter() = std::move(__u
.get_deleter());
293 template<typename _Up
, typename _Up_Deleter
>
295 operator=(unique_ptr
<_Up
, _Up_Deleter
>&& __u
)
297 reset(__u
.release());
298 get_deleter() = std::move(__u
.get_deleter());
303 operator=(__unspecified_pointer_type
)
310 typename
std::add_lvalue_reference
<element_type
>::type
311 operator[](size_t __i
) const
313 _GLIBCXX_DEBUG_ASSERT(get() != 0);
319 { return std::get
<0>(_M_t
); }
321 typename
std::add_lvalue_reference
<deleter_type
>::type
323 { return std::get
<1>(_M_t
); }
325 typename
std::add_lvalue_reference
<
326 typename
std::add_const
<deleter_type
>::type
329 { return std::get
<1>(_M_t
); }
331 operator __unspecified_bool_type () const
332 { return get() == 0 ? 0 : &unique_ptr::_M_t
; }
339 std::get
<0>(_M_t
) = 0;
344 reset(pointer __p
= pointer())
348 get_deleter()(get());
349 std::get
<0>(_M_t
) = __p
;
354 template<typename _Up
>
355 void reset(_Up
) = delete;
358 swap(unique_ptr
&& __u
)
361 swap(_M_t
, __u
._M_t
);
364 // Disable copy from lvalue.
365 unique_ptr(const unique_ptr
&) = delete;
366 unique_ptr
& operator=(const unique_ptr
&) = delete;
368 // Disable construction from convertible pointer types.
369 // (N2315 - 20.6.5.3.1)
370 template<typename _Up
>
371 unique_ptr(_Up
*, typename
372 std::conditional
<std::is_reference
<deleter_type
>::value
,
373 deleter_type
, const deleter_type
&>::type
,
374 typename
std::enable_if
<std::is_convertible
<_Up
*,
375 pointer
>::value
>::type
* = 0) = delete;
377 template<typename _Up
>
378 unique_ptr(_Up
*, typename
std::remove_reference
<deleter_type
>::type
&&,
379 typename
std::enable_if
<std::is_convertible
<_Up
*,
380 pointer
>::value
>::type
* = 0) = delete;
382 template<typename _Up
>
384 unique_ptr(_Up
*, typename
std::enable_if
<std::is_convertible
<_Up
*,
385 pointer
>::value
>::type
* = 0) = delete;
391 template<typename _Tp
, typename _Tp_Deleter
>
393 swap(unique_ptr
<_Tp
, _Tp_Deleter
>& __x
,
394 unique_ptr
<_Tp
, _Tp_Deleter
>& __y
)
397 template<typename _Tp
, typename _Tp_Deleter
>
399 swap(unique_ptr
<_Tp
, _Tp_Deleter
>&& __x
,
400 unique_ptr
<_Tp
, _Tp_Deleter
>& __y
)
403 template<typename _Tp
, typename _Tp_Deleter
>
405 swap(unique_ptr
<_Tp
, _Tp_Deleter
>& __x
,
406 unique_ptr
<_Tp
, _Tp_Deleter
>&& __y
)
409 template<typename _Tp
, typename _Tp_Deleter
,
410 typename _Up
, typename _Up_Deleter
>
412 operator==(const unique_ptr
<_Tp
, _Tp_Deleter
>& __x
,
413 const unique_ptr
<_Up
, _Up_Deleter
>& __y
)
414 { return __x
.get() == __y
.get(); }
416 template<typename _Tp
, typename _Tp_Deleter
,
417 typename _Up
, typename _Up_Deleter
>
419 operator!=(const unique_ptr
<_Tp
, _Tp_Deleter
>& __x
,
420 const unique_ptr
<_Up
, _Up_Deleter
>& __y
)
421 { return !(__x
.get() == __y
.get()); }
423 template<typename _Tp
, typename _Tp_Deleter
,
424 typename _Up
, typename _Up_Deleter
>
426 operator<(const unique_ptr
<_Tp
, _Tp_Deleter
>& __x
,
427 const unique_ptr
<_Up
, _Up_Deleter
>& __y
)
428 { return __x
.get() < __y
.get(); }
430 template<typename _Tp
, typename _Tp_Deleter
,
431 typename _Up
, typename _Up_Deleter
>
433 operator<=(const unique_ptr
<_Tp
, _Tp_Deleter
>& __x
,
434 const unique_ptr
<_Up
, _Up_Deleter
>& __y
)
435 { return !(__y
.get() < __x
.get()); }
437 template<typename _Tp
, typename _Tp_Deleter
,
438 typename _Up
, typename _Up_Deleter
>
440 operator>(const unique_ptr
<_Tp
, _Tp_Deleter
>& __x
,
441 const unique_ptr
<_Up
, _Up_Deleter
>& __y
)
442 { return __y
.get() < __x
.get(); }
444 template<typename _Tp
, typename _Tp_Deleter
,
445 typename _Up
, typename _Up_Deleter
>
447 operator>=(const unique_ptr
<_Tp
, _Tp_Deleter
>& __x
,
448 const unique_ptr
<_Up
, _Up_Deleter
>& __y
)
449 { return !(__x
.get() < __y
.get()); }
451 // @} group pointer_abstractions
453 _GLIBCXX_END_NAMESPACE
455 #endif /* _UNIQUE_PTR_H */