1 // unique_ptr implementation -*- C++ -*-
3 // Copyright (C) 2008 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
)
50 /// Primary template, default_delete.
51 template<typename _Tp
>
56 template<typename _Up
>
57 default_delete(const default_delete
<_Up
>&) { }
60 operator()(_Tp
* __ptr
) const
62 static_assert(sizeof(_Tp
)>0,
63 "can't delete pointer to incomplete type");
68 // _GLIBCXX_RESOLVE_LIB_DEFECTS
69 // DR 740 - omit specialization for array objects with a compile time length
70 /// Specialization, default_delete.
71 template<typename _Tp
>
72 struct default_delete
<_Tp
[]>
75 operator()(_Tp
* __ptr
) const
77 static_assert(sizeof(_Tp
)>0,
78 "can't delete pointer to incomplete type");
83 /// 20.6.11.2 unique_ptr for single objects.
84 template <typename _Tp
, typename _Tp_Deleter
= default_delete
<_Tp
> >
88 typedef unique_ptr
<_Tp
, _Tp_Deleter
> __this_type
;
89 typedef std::tuple
<pointer
, _Tp_Deleter
> __tuple_type
;
90 typedef __tuple_type
__this_type::* __unspecified_bool_type
;
91 typedef pointer
__this_type::* __unspecified_pointer_type
;
94 typedef _Tp element_type
;
95 typedef _Tp_Deleter deleter_type
;
99 : _M_t(pointer(), deleter_type())
100 { static_assert(!std::is_pointer
<deleter_type
>::value
,
101 "constructed with null function pointer deleter"); }
104 unique_ptr(pointer __p
)
105 : _M_t(__p
, deleter_type())
106 { static_assert(!std::is_pointer
<deleter_type
>::value
,
107 "constructed with null function pointer deleter"); }
109 unique_ptr(pointer __p
,
110 typename
std::conditional
<std::is_reference
<deleter_type
>::value
,
111 deleter_type
, const deleter_type
&>::type __d
)
114 unique_ptr(pointer __p
,
115 typename
std::remove_reference
<deleter_type
>::type
&& __d
)
116 : _M_t(std::move(__p
), std::move(__d
))
117 { static_assert(!std::is_reference
<deleter_type
>::value
,
118 "rvalue deleter bound to reference"); }
121 unique_ptr(unique_ptr
&& __u
)
122 : _M_t(__u
.release(), std::forward
<deleter_type
>(__u
.get_deleter())) { }
124 template<typename _Up
, typename _Up_Deleter
>
125 unique_ptr(unique_ptr
<_Up
, _Up_Deleter
>&& __u
)
126 : _M_t(__u
.release(), std::forward
<deleter_type
>(__u
.get_deleter()))
130 ~unique_ptr() { reset(); }
134 operator=(unique_ptr
&& __u
)
136 reset(__u
.release());
137 get_deleter() = std::move(__u
.get_deleter());
141 template<typename _Up
, typename _Up_Deleter
>
143 operator=(unique_ptr
<_Up
, _Up_Deleter
>&& __u
)
145 reset(__u
.release());
146 get_deleter() = std::move(__u
.get_deleter());
151 operator=(__unspecified_pointer_type
)
158 typename
std::add_lvalue_reference
<element_type
>::type
operator*() const
160 _GLIBCXX_DEBUG_ASSERT(get() != 0);
167 _GLIBCXX_DEBUG_ASSERT(get() != 0);
173 { return std::get
<0>(_M_t
); }
175 typename
std::add_lvalue_reference
<deleter_type
>::type
177 { return std::get
<1>(_M_t
); }
179 typename
std::add_lvalue_reference
<
180 typename
std::add_const
<deleter_type
>::type
183 { return std::get
<1>(_M_t
); }
185 operator __unspecified_bool_type () const
186 { return get() == 0 ? 0 : &__this_type::_M_t
; }
193 std::get
<0>(_M_t
) = 0;
198 reset(pointer __p
= 0)
202 get_deleter()(get());
203 std::get
<0>(_M_t
) = __p
;
208 swap(unique_ptr
&& __u
)
210 swap(_M_t
, __u
._M_t
);
214 // disable copy from lvalue
215 unique_ptr(const unique_ptr
&);
217 template<typename _Up
, typename _Up_Deleter
>
218 unique_ptr(const unique_ptr
<_Up
, _Up_Deleter
>&);
220 // disable assignment from lvalue
221 unique_ptr
& operator=(const unique_ptr
&);
223 template<typename _Up
, typename _Up_Deleter
>
224 unique_ptr
& operator=(const unique_ptr
<_Up
, _Up_Deleter
>&);
230 /// 20.6.11.3 unique_ptr for array objects with a runtime length
231 // [unique.ptr.runtime]
232 // _GLIBCXX_RESOLVE_LIB_DEFECTS
233 // DR 740 - omit specialization for array objects with a compile time length
234 template<typename _Tp
, typename _Tp_Deleter
>
235 class unique_ptr
<_Tp
[], _Tp_Deleter
>
237 typedef _Tp
* pointer
;
238 typedef unique_ptr
<_Tp
[], _Tp_Deleter
> __this_type
;
239 typedef std::tuple
<pointer
, _Tp_Deleter
> __tuple_type
;
240 typedef __tuple_type
__this_type::* __unspecified_bool_type
;
241 typedef pointer
__this_type::* __unspecified_pointer_type
;
243 typedef _Tp element_type
;
244 typedef _Tp_Deleter deleter_type
;
248 : _M_t(pointer(), deleter_type())
249 { static_assert(!std::is_pointer
<deleter_type
>::value
,
250 "constructed with null function pointer deleter"); }
253 unique_ptr(pointer __p
)
254 : _M_t(__p
, deleter_type())
255 { static_assert(!std::is_pointer
<deleter_type
>::value
,
256 "constructed with null function pointer deleter"); }
258 unique_ptr(pointer __p
,
259 typename
std::conditional
<std::is_reference
<deleter_type
>::value
,
260 deleter_type
, const deleter_type
&>::type __d
)
263 unique_ptr(pointer __p
,
264 typename
std::remove_reference
<deleter_type
>::type
&& __d
)
265 : _M_t(std::move(__p
), std::move(__d
))
266 { static_assert(!std::is_reference
<deleter_type
>::value
,
267 "rvalue deleter bound to reference"); }
270 unique_ptr(unique_ptr
&& __u
)
271 : _M_t(__u
.release(), std::forward
<deleter_type
>(__u
.get_deleter())) { }
273 template<typename _Up
, typename _Up_Deleter
>
274 unique_ptr(unique_ptr
<_Up
, _Up_Deleter
>&& __u
)
275 : _M_t(__u
.release(), std::forward
<deleter_type
>(__u
.get_deleter()))
279 ~unique_ptr() { reset(); }
283 operator=(unique_ptr
&& __u
)
285 reset(__u
.release());
286 get_deleter() = std::move(__u
.get_deleter());
290 template<typename _Up
, typename _Up_Deleter
>
292 operator=(unique_ptr
<_Up
, _Up_Deleter
>&& __u
)
294 reset(__u
.release());
295 get_deleter() = std::move(__u
.get_deleter());
300 operator=(__unspecified_pointer_type
)
307 typename
std::add_lvalue_reference
<element_type
>::type
308 operator[](size_t __i
) const
310 _GLIBCXX_DEBUG_ASSERT(get() != 0);
316 { return std::get
<0>(_M_t
); }
318 typename
std::add_lvalue_reference
<deleter_type
>::type
320 { return std::get
<1>(_M_t
); }
322 typename
std::add_lvalue_reference
<
323 typename
std::add_const
<deleter_type
>::type
326 { return std::get
<1>(_M_t
); }
328 operator __unspecified_bool_type () const
329 { return get() == 0 ? 0 : &__this_type::_M_t
; }
336 std::get
<0>(_M_t
) = 0;
341 reset(pointer __p
= 0)
345 get_deleter()(get());
346 std::get
<0>(_M_t
) = __p
;
351 swap(unique_ptr
&& __u
)
354 swap(_M_t
, __u
._M_t
);
358 // disable copy from lvalue
359 unique_ptr(const unique_ptr
&);
360 unique_ptr
& operator=(const unique_ptr
&);
362 // disable construction from convertible pointer types
363 // (N2315 - 20.6.5.3.1)
364 template<typename _Up
> unique_ptr(_Up
*,
365 typename
std::conditional
<std::is_reference
<deleter_type
>::value
,
366 deleter_type
, const deleter_type
&>::type
,
367 typename
std::enable_if
<std::is_convertible
<_Up
*,
368 pointer
>::value
>::type
* = 0);
370 template<typename _Up
> unique_ptr(_Up
*,
371 typename
std::remove_reference
<deleter_type
>::type
&&,
372 typename
std::enable_if
<std::is_convertible
<_Up
*,
373 pointer
>::value
>::type
* = 0);
375 template<typename _Up
> explicit unique_ptr(_Up
*,
376 typename
std::enable_if
<std::is_convertible
<_Up
*,
377 pointer
>::value
>::type
* = 0);
379 // disable reset with convertible pointer types (N2315 - 20.6.5.3.3)
380 template<typename _Up
>
381 typename
std::enable_if
<std::is_convertible
<_Up
*,
382 pointer
>::value
>::type
reset(_Up
*);
388 template<typename _Tp
, typename _Tp_Deleter
>
390 swap(unique_ptr
<_Tp
, _Tp_Deleter
>& __x
,
391 unique_ptr
<_Tp
, _Tp_Deleter
>& __y
)
394 template<typename _Tp
, typename _Tp_Deleter
>
396 swap(unique_ptr
<_Tp
, _Tp_Deleter
>&& __x
,
397 unique_ptr
<_Tp
, _Tp_Deleter
>& __y
)
400 template<typename _Tp
, typename _Tp_Deleter
>
402 swap(unique_ptr
<_Tp
, _Tp_Deleter
>& __x
,
403 unique_ptr
<_Tp
, _Tp_Deleter
>&& __y
)
406 template<typename _Tp
, typename _Tp_Deleter
,
407 typename _Up
, typename _Up_Deleter
>
409 operator==(const unique_ptr
<_Tp
, _Tp_Deleter
>& __x
,
410 const unique_ptr
<_Up
, _Up_Deleter
>& __y
)
411 { return __x
.get() == __y
.get(); }
413 template<typename _Tp
, typename _Tp_Deleter
,
414 typename _Up
, typename _Up_Deleter
>
416 operator!=(const unique_ptr
<_Tp
, _Tp_Deleter
>& __x
,
417 const unique_ptr
<_Up
, _Up_Deleter
>& __y
)
418 { return !(__x
.get() == __y
.get()); }
420 template<typename _Tp
, typename _Tp_Deleter
,
421 typename _Up
, typename _Up_Deleter
>
423 operator<(const unique_ptr
<_Tp
, _Tp_Deleter
>& __x
,
424 const unique_ptr
<_Up
, _Up_Deleter
>& __y
)
425 { return __x
.get() < __y
.get(); }
427 template<typename _Tp
, typename _Tp_Deleter
,
428 typename _Up
, typename _Up_Deleter
>
430 operator<=(const unique_ptr
<_Tp
, _Tp_Deleter
>& __x
,
431 const unique_ptr
<_Up
, _Up_Deleter
>& __y
)
432 { return !(__y
.get() < __x
.get()); }
434 template<typename _Tp
, typename _Tp_Deleter
,
435 typename _Up
, typename _Up_Deleter
>
437 operator>(const unique_ptr
<_Tp
, _Tp_Deleter
>& __x
,
438 const unique_ptr
<_Up
, _Up_Deleter
>& __y
)
439 { return __y
.get() < __x
.get(); }
441 template<typename _Tp
, typename _Tp_Deleter
,
442 typename _Up
, typename _Up_Deleter
>
444 operator>=(const unique_ptr
<_Tp
, _Tp_Deleter
>& __x
,
445 const unique_ptr
<_Up
, _Up_Deleter
>& __y
)
446 { return !(__x
.get() < __y
.get()); }
448 _GLIBCXX_END_NAMESPACE
450 #endif /* _UNIQUE_PTR_H */