1 // unique_ptr implementation -*- C++ -*-
3 // Copyright (C) 2008-2012 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 3, 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 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
25 /** @file bits/unique_ptr.h
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{memory}
31 #define _UNIQUE_PTR_H 1
33 #include <bits/c++config.h>
34 #include <debug/debug.h>
35 #include <type_traits>
39 namespace std
_GLIBCXX_VISIBILITY(default)
41 _GLIBCXX_BEGIN_NAMESPACE_VERSION
44 * @addtogroup pointer_abstractions
48 #if _GLIBCXX_USE_DEPRECATED
49 template<typename
> class auto_ptr
;
52 /// Primary template, default_delete.
53 template<typename _Tp
>
56 constexpr default_delete() noexcept
= default;
58 template<typename _Up
, typename
= typename
59 std::enable_if
<std::is_convertible
<_Up
*, _Tp
*>::value
>::type
>
60 default_delete(const default_delete
<_Up
>&) noexcept
{ }
63 operator()(_Tp
* __ptr
) const
65 static_assert(sizeof(_Tp
)>0,
66 "can't delete pointer to incomplete type");
71 // _GLIBCXX_RESOLVE_LIB_DEFECTS
72 // DR 740 - omit specialization for array objects with a compile time length
73 /// Specialization, default_delete.
74 template<typename _Tp
>
75 struct default_delete
<_Tp
[]>
77 constexpr default_delete() noexcept
= default;
80 operator()(_Tp
* __ptr
) const
82 static_assert(sizeof(_Tp
)>0,
83 "can't delete pointer to incomplete type");
87 template<typename _Up
> void operator()(_Up
*) const = delete;
90 /// 20.7.1.2 unique_ptr for single objects.
91 template <typename _Tp
, typename _Dp
= default_delete
<_Tp
> >
94 // use SFINAE to determine whether _Del::pointer exists
97 template<typename _Up
>
98 static typename
_Up::pointer
__test(typename
_Up::pointer
*);
100 template<typename _Up
>
101 static _Tp
* __test(...);
103 typedef typename remove_reference
<_Dp
>::type _Del
;
106 typedef decltype( __test
<_Del
>(0)) type
;
109 typedef std::tuple
<typename
_Pointer::type
, _Dp
> __tuple_type
;
113 typedef typename
_Pointer::type pointer
;
114 typedef _Tp element_type
;
115 typedef _Dp deleter_type
;
118 constexpr unique_ptr() noexcept
120 { static_assert(!std::is_pointer
<deleter_type
>::value
,
121 "constructed with null function pointer deleter"); }
124 unique_ptr(pointer __p
) noexcept
125 : _M_t(__p
, deleter_type())
126 { static_assert(!std::is_pointer
<deleter_type
>::value
,
127 "constructed with null function pointer deleter"); }
129 unique_ptr(pointer __p
,
130 typename
std::conditional
<std::is_reference
<deleter_type
>::value
,
131 deleter_type
, const deleter_type
&>::type __d
) noexcept
134 unique_ptr(pointer __p
,
135 typename
std::remove_reference
<deleter_type
>::type
&& __d
) noexcept
136 : _M_t(std::move(__p
), std::move(__d
))
137 { static_assert(!std::is_reference
<deleter_type
>::value
,
138 "rvalue deleter bound to reference"); }
140 constexpr unique_ptr(nullptr_t
) noexcept
142 { static_assert(!std::is_pointer
<deleter_type
>::value
,
143 "constructed with null function pointer deleter"); }
145 // Move constructors.
146 unique_ptr(unique_ptr
&& __u
) noexcept
147 : _M_t(__u
.release(), std::forward
<deleter_type
>(__u
.get_deleter())) { }
149 template<typename _Up
, typename _Ep
, typename
= typename
151 <std::is_convertible
<typename unique_ptr
<_Up
, _Ep
>::pointer
,
153 && !std::is_array
<_Up
>::value
154 && ((std::is_reference
<_Dp
>::value
155 && std::is_same
<_Ep
, _Dp
>::value
)
156 || (!std::is_reference
<_Dp
>::value
157 && std::is_convertible
<_Ep
, _Dp
>::value
))>
159 unique_ptr(unique_ptr
<_Up
, _Ep
>&& __u
) noexcept
160 : _M_t(__u
.release(), std::forward
<_Ep
>(__u
.get_deleter()))
163 #if _GLIBCXX_USE_DEPRECATED
164 template<typename _Up
, typename
= typename
165 std::enable_if
<std::is_convertible
<_Up
*, _Tp
*>::value
167 default_delete
<_Tp
>>::value
>::type
>
168 unique_ptr(auto_ptr
<_Up
>&& __u
) noexcept
;
172 ~unique_ptr() noexcept
174 auto& __ptr
= std::get
<0>(_M_t
);
175 if (__ptr
!= nullptr)
176 get_deleter()(__ptr
);
182 operator=(unique_ptr
&& __u
) noexcept
184 reset(__u
.release());
185 get_deleter() = std::forward
<deleter_type
>(__u
.get_deleter());
189 template<typename _Up
, typename _Ep
, typename
= typename
191 <std::is_convertible
<typename unique_ptr
<_Up
, _Ep
>::pointer
,
193 && !std::is_array
<_Up
>::value
>::type
>
195 operator=(unique_ptr
<_Up
, _Ep
>&& __u
) noexcept
197 reset(__u
.release());
198 get_deleter() = std::forward
<_Ep
>(__u
.get_deleter());
203 operator=(nullptr_t
) noexcept
210 typename
std::add_lvalue_reference
<element_type
>::type
213 _GLIBCXX_DEBUG_ASSERT(get() != pointer());
218 operator->() const noexcept
220 _GLIBCXX_DEBUG_ASSERT(get() != pointer());
226 { return std::get
<0>(_M_t
); }
229 get_deleter() noexcept
230 { return std::get
<1>(_M_t
); }
233 get_deleter() const noexcept
234 { return std::get
<1>(_M_t
); }
236 explicit operator bool() const noexcept
237 { return get() == pointer() ? false : true; }
244 std::get
<0>(_M_t
) = pointer();
249 reset(pointer __p
= pointer()) noexcept
252 swap(std::get
<0>(_M_t
), __p
);
253 if (__p
!= pointer())
258 swap(unique_ptr
& __u
) noexcept
261 swap(_M_t
, __u
._M_t
);
264 // Disable copy from lvalue.
265 unique_ptr(const unique_ptr
&) = delete;
266 unique_ptr
& operator=(const unique_ptr
&) = delete;
269 /// 20.7.1.3 unique_ptr for array objects with a runtime length
270 // [unique.ptr.runtime]
271 // _GLIBCXX_RESOLVE_LIB_DEFECTS
272 // DR 740 - omit specialization for array objects with a compile time length
273 template<typename _Tp
, typename _Dp
>
274 class unique_ptr
<_Tp
[], _Dp
>
276 typedef std::tuple
<_Tp
*, _Dp
> __tuple_type
;
280 typedef _Tp
* pointer
;
281 typedef _Tp element_type
;
282 typedef _Dp deleter_type
;
285 constexpr unique_ptr() noexcept
287 { static_assert(!std::is_pointer
<deleter_type
>::value
,
288 "constructed with null function pointer deleter"); }
291 unique_ptr(pointer __p
) noexcept
292 : _M_t(__p
, deleter_type())
293 { static_assert(!std::is_pointer
<deleter_type
>::value
,
294 "constructed with null function pointer deleter"); }
296 unique_ptr(pointer __p
,
297 typename
std::conditional
<std::is_reference
<deleter_type
>::value
,
298 deleter_type
, const deleter_type
&>::type __d
) noexcept
301 unique_ptr(pointer __p
, typename
302 std::remove_reference
<deleter_type
>::type
&& __d
) noexcept
303 : _M_t(std::move(__p
), std::move(__d
))
304 { static_assert(!std::is_reference
<deleter_type
>::value
,
305 "rvalue deleter bound to reference"); }
307 constexpr unique_ptr(nullptr_t
) noexcept
309 { static_assert(!std::is_pointer
<deleter_type
>::value
,
310 "constructed with null function pointer deleter"); }
312 // Move constructors.
313 unique_ptr(unique_ptr
&& __u
) noexcept
314 : _M_t(__u
.release(), std::forward
<deleter_type
>(__u
.get_deleter())) { }
316 template<typename _Up
, typename _Ep
>
317 unique_ptr(unique_ptr
<_Up
, _Ep
>&& __u
) noexcept
318 : _M_t(__u
.release(), std::forward
<_Ep
>(__u
.get_deleter()))
324 auto& __ptr
= std::get
<0>(_M_t
);
325 if (__ptr
!= nullptr)
326 get_deleter()(__ptr
);
332 operator=(unique_ptr
&& __u
) noexcept
334 reset(__u
.release());
335 get_deleter() = std::forward
<deleter_type
>(__u
.get_deleter());
339 template<typename _Up
, typename _Ep
>
341 operator=(unique_ptr
<_Up
, _Ep
>&& __u
) noexcept
343 reset(__u
.release());
344 get_deleter() = std::forward
<_Ep
>(__u
.get_deleter());
349 operator=(nullptr_t
) noexcept
356 typename
std::add_lvalue_reference
<element_type
>::type
357 operator[](size_t __i
) const
359 _GLIBCXX_DEBUG_ASSERT(get() != pointer());
365 { return std::get
<0>(_M_t
); }
368 get_deleter() noexcept
369 { return std::get
<1>(_M_t
); }
372 get_deleter() const noexcept
373 { return std::get
<1>(_M_t
); }
375 explicit operator bool() const noexcept
376 { return get() == pointer() ? false : true; }
383 std::get
<0>(_M_t
) = pointer();
388 reset(pointer __p
= pointer()) noexcept
391 swap(std::get
<0>(_M_t
), __p
);
397 reset(nullptr_t
) noexcept
400 std::get
<0>(_M_t
) = pointer();
406 template<typename _Up
>
407 void reset(_Up
) = delete;
410 swap(unique_ptr
& __u
) noexcept
413 swap(_M_t
, __u
._M_t
);
416 // Disable copy from lvalue.
417 unique_ptr(const unique_ptr
&) = delete;
418 unique_ptr
& operator=(const unique_ptr
&) = delete;
420 // Disable construction from convertible pointer types.
421 // (N2315 - 20.7.1.3.1)
422 template<typename _Up
>
423 unique_ptr(_Up
*, typename
424 std::conditional
<std::is_reference
<deleter_type
>::value
,
425 deleter_type
, const deleter_type
&>::type
,
426 typename
std::enable_if
<std::is_convertible
<_Up
*,
427 pointer
>::value
>::type
* = 0) = delete;
429 template<typename _Up
>
430 unique_ptr(_Up
*, typename
std::remove_reference
<deleter_type
>::type
&&,
431 typename
std::enable_if
<std::is_convertible
<_Up
*,
432 pointer
>::value
>::type
* = 0) = delete;
434 template<typename _Up
>
436 unique_ptr(_Up
*, typename
std::enable_if
<std::is_convertible
<_Up
*,
437 pointer
>::value
>::type
* = 0) = delete;
440 template<typename _Tp
, typename _Dp
>
442 swap(unique_ptr
<_Tp
, _Dp
>& __x
,
443 unique_ptr
<_Tp
, _Dp
>& __y
) noexcept
446 template<typename _Tp
, typename _Dp
,
447 typename _Up
, typename _Ep
>
449 operator==(const unique_ptr
<_Tp
, _Dp
>& __x
,
450 const unique_ptr
<_Up
, _Ep
>& __y
)
451 { return __x
.get() == __y
.get(); }
453 template<typename _Tp
, typename _Dp
>
455 operator==(const unique_ptr
<_Tp
, _Dp
>& __x
, nullptr_t
) noexcept
458 template<typename _Tp
, typename _Dp
>
460 operator==(nullptr_t
, const unique_ptr
<_Tp
, _Dp
>& __x
) noexcept
463 template<typename _Tp
, typename _Dp
,
464 typename _Up
, typename _Ep
>
466 operator!=(const unique_ptr
<_Tp
, _Dp
>& __x
,
467 const unique_ptr
<_Up
, _Ep
>& __y
)
468 { return __x
.get() != __y
.get(); }
470 template<typename _Tp
, typename _Dp
>
472 operator!=(const unique_ptr
<_Tp
, _Dp
>& __x
, nullptr_t
) noexcept
473 { return (bool)__x
; }
475 template<typename _Tp
, typename _Dp
>
477 operator!=(nullptr_t
, const unique_ptr
<_Tp
, _Dp
>& __x
) noexcept
478 { return (bool)__x
; }
480 template<typename _Tp
, typename _Dp
,
481 typename _Up
, typename _Ep
>
483 operator<(const unique_ptr
<_Tp
, _Dp
>& __x
,
484 const unique_ptr
<_Up
, _Ep
>& __y
)
487 std::common_type
<typename unique_ptr
<_Tp
, _Dp
>::pointer
,
488 typename unique_ptr
<_Up
, _Ep
>::pointer
>::type _CT
;
489 return std::less
<_CT
>()(__x
.get(), __y
.get());
492 template<typename _Tp
, typename _Dp
>
494 operator<(const unique_ptr
<_Tp
, _Dp
>& __x
, nullptr_t
)
495 { return std::less
<typename unique_ptr
<_Tp
, _Dp
>::pointer
>()(__x
.get(),
498 template<typename _Tp
, typename _Dp
>
500 operator<(nullptr_t
, const unique_ptr
<_Tp
, _Dp
>& __x
)
501 { return std::less
<typename unique_ptr
<_Tp
, _Dp
>::pointer
>()(nullptr,
504 template<typename _Tp
, typename _Dp
,
505 typename _Up
, typename _Ep
>
507 operator<=(const unique_ptr
<_Tp
, _Dp
>& __x
,
508 const unique_ptr
<_Up
, _Ep
>& __y
)
509 { return !(__y
< __x
); }
511 template<typename _Tp
, typename _Dp
>
513 operator<=(const unique_ptr
<_Tp
, _Dp
>& __x
, nullptr_t
)
514 { return !(nullptr < __x
); }
516 template<typename _Tp
, typename _Dp
>
518 operator<=(nullptr_t
, const unique_ptr
<_Tp
, _Dp
>& __x
)
519 { return !(__x
< nullptr); }
521 template<typename _Tp
, typename _Dp
,
522 typename _Up
, typename _Ep
>
524 operator>(const unique_ptr
<_Tp
, _Dp
>& __x
,
525 const unique_ptr
<_Up
, _Ep
>& __y
)
526 { return (__y
< __x
); }
528 template<typename _Tp
, typename _Dp
>
530 operator>(const unique_ptr
<_Tp
, _Dp
>& __x
, nullptr_t
)
531 { return std::less
<typename unique_ptr
<_Tp
, _Dp
>::pointer
>()(nullptr,
534 template<typename _Tp
, typename _Dp
>
536 operator>(nullptr_t
, const unique_ptr
<_Tp
, _Dp
>& __x
)
537 { return std::less
<typename unique_ptr
<_Tp
, _Dp
>::pointer
>()(__x
.get(),
540 template<typename _Tp
, typename _Dp
,
541 typename _Up
, typename _Ep
>
543 operator>=(const unique_ptr
<_Tp
, _Dp
>& __x
,
544 const unique_ptr
<_Up
, _Ep
>& __y
)
545 { return !(__x
< __y
); }
547 template<typename _Tp
, typename _Dp
>
549 operator>=(const unique_ptr
<_Tp
, _Dp
>& __x
, nullptr_t
)
550 { return !(__x
< nullptr); }
552 template<typename _Tp
, typename _Dp
>
554 operator>=(nullptr_t
, const unique_ptr
<_Tp
, _Dp
>& __x
)
555 { return !(nullptr < __x
); }
557 /// std::hash specialization for unique_ptr.
558 template<typename _Tp
, typename _Dp
>
559 struct hash
<unique_ptr
<_Tp
, _Dp
>>
560 : public __hash_base
<size_t, unique_ptr
<_Tp
, _Dp
>>
563 operator()(const unique_ptr
<_Tp
, _Dp
>& __u
) const noexcept
565 typedef unique_ptr
<_Tp
, _Dp
> _UP
;
566 return std::hash
<typename
_UP::pointer
>()(__u
.get());
570 // @} group pointer_abstractions
572 _GLIBCXX_END_NAMESPACE_VERSION
575 #endif /* _UNIQUE_PTR_H */