Line data Source code
1 : // unique_ptr implementation -*- C++ -*-
2 :
3 : // Copyright (C) 2008-2013 Free Software Foundation, Inc.
4 : //
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)
9 : // any later version.
10 :
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.
15 :
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.
19 :
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/>.
24 :
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}
28 : */
29 :
30 : #ifndef _UNIQUE_PTR_H
31 : #define _UNIQUE_PTR_H 1
32 :
33 : #include <bits/c++config.h>
34 : #include <debug/debug.h>
35 : #include <type_traits>
36 : #include <utility>
37 : #include <tuple>
38 :
39 : namespace std _GLIBCXX_VISIBILITY(default)
40 : {
41 : _GLIBCXX_BEGIN_NAMESPACE_VERSION
42 :
43 : /**
44 : * @addtogroup pointer_abstractions
45 : * @{
46 : */
47 :
48 : #if _GLIBCXX_USE_DEPRECATED
49 : template<typename> class auto_ptr;
50 : #endif
51 :
52 : /// Primary template, default_delete.
53 : template<typename _Tp>
54 : struct default_delete
55 : {
56 : constexpr default_delete() noexcept = default;
57 :
58 : template<typename _Up, typename = typename
59 : enable_if<is_convertible<_Up*, _Tp*>::value>::type>
60 12 : default_delete(const default_delete<_Up>&) noexcept { }
61 :
62 : void
63 : operator()(_Tp* __ptr) const
64 : {
65 : static_assert(sizeof(_Tp)>0,
66 : "can't delete pointer to incomplete type");
67 126 : delete __ptr;
68 63 : }
69 : };
70 :
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[]>
76 : {
77 : private:
78 : template<typename _Up>
79 : using __remove_cv = typename remove_cv<_Up>::type;
80 :
81 : // Like is_base_of<_Tp, _Up> but false if unqualified types are the same
82 : template<typename _Up>
83 : using __is_derived_Tp
84 : = __and_< is_base_of<_Tp, _Up>,
85 : __not_<is_same<__remove_cv<_Tp>, __remove_cv<_Up>>> >;
86 :
87 : public:
88 : constexpr default_delete() noexcept = default;
89 :
90 : template<typename _Up, typename = typename
91 : enable_if<!__is_derived_Tp<_Up>::value>::type>
92 : default_delete(const default_delete<_Up[]>&) noexcept { }
93 :
94 : void
95 : operator()(_Tp* __ptr) const
96 : {
97 : static_assert(sizeof(_Tp)>0,
98 : "can't delete pointer to incomplete type");
99 : delete [] __ptr;
100 : }
101 :
102 : template<typename _Up>
103 : typename enable_if<__is_derived_Tp<_Up>::value>::type
104 : operator()(_Up*) const = delete;
105 : };
106 :
107 : /// 20.7.1.2 unique_ptr for single objects.
108 : template <typename _Tp, typename _Dp = default_delete<_Tp> >
109 : class unique_ptr
110 : {
111 : // use SFINAE to determine whether _Del::pointer exists
112 : class _Pointer
113 : {
114 : template<typename _Up>
115 : static typename _Up::pointer __test(typename _Up::pointer*);
116 :
117 : template<typename _Up>
118 : static _Tp* __test(...);
119 :
120 : typedef typename remove_reference<_Dp>::type _Del;
121 :
122 : public:
123 : typedef decltype(__test<_Del>(0)) type;
124 : };
125 :
126 : typedef std::tuple<typename _Pointer::type, _Dp> __tuple_type;
127 : __tuple_type _M_t;
128 :
129 : public:
130 : typedef typename _Pointer::type pointer;
131 : typedef _Tp element_type;
132 : typedef _Dp deleter_type;
133 :
134 : // Constructors.
135 : constexpr unique_ptr() noexcept
136 : : _M_t()
137 : { static_assert(!is_pointer<deleter_type>::value,
138 : "constructed with null function pointer deleter"); }
139 :
140 : explicit
141 : unique_ptr(pointer __p) noexcept
142 35 : : _M_t(__p, deleter_type())
143 : { static_assert(!is_pointer<deleter_type>::value,
144 35 : "constructed with null function pointer deleter"); }
145 :
146 : unique_ptr(pointer __p,
147 : typename conditional<is_reference<deleter_type>::value,
148 : deleter_type, const deleter_type&>::type __d) noexcept
149 : : _M_t(__p, __d) { }
150 :
151 : unique_ptr(pointer __p,
152 : typename remove_reference<deleter_type>::type&& __d) noexcept
153 : : _M_t(std::move(__p), std::move(__d))
154 : { static_assert(!std::is_reference<deleter_type>::value,
155 : "rvalue deleter bound to reference"); }
156 :
157 : constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { }
158 :
159 : // Move constructors.
160 : unique_ptr(unique_ptr&& __u) noexcept
161 : : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
162 :
163 : template<typename _Up, typename _Ep, typename = _Require<
164 : is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>,
165 : __not_<is_array<_Up>>,
166 : typename conditional<is_reference<_Dp>::value,
167 : is_same<_Ep, _Dp>,
168 : is_convertible<_Ep, _Dp>>::type>>
169 : unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
170 12 : : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
171 12 : { }
172 :
173 : #if _GLIBCXX_USE_DEPRECATED
174 : template<typename _Up, typename = _Require<
175 : is_convertible<_Up*, _Tp*>, is_same<_Dp, default_delete<_Tp>>>>
176 : unique_ptr(auto_ptr<_Up>&& __u) noexcept;
177 : #endif
178 :
179 : // Destructor.
180 : ~unique_ptr() noexcept
181 : {
182 75 : auto& __ptr = std::get<0>(_M_t);
183 75 : if (__ptr != nullptr)
184 126 : get_deleter()(__ptr);
185 75 : __ptr = pointer();
186 75 : }
187 :
188 : // Assignment.
189 : unique_ptr&
190 : operator=(unique_ptr&& __u) noexcept
191 : {
192 : reset(__u.release());
193 : get_deleter() = std::forward<deleter_type>(__u.get_deleter());
194 : return *this;
195 : }
196 :
197 : template<typename _Up, typename _Ep>
198 : typename enable_if< __and_<
199 : is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>,
200 : __not_<is_array<_Up>>
201 : >::value,
202 : unique_ptr&>::type
203 : operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
204 : {
205 : reset(__u.release());
206 : get_deleter() = std::forward<_Ep>(__u.get_deleter());
207 : return *this;
208 : }
209 :
210 : unique_ptr&
211 : operator=(nullptr_t) noexcept
212 : {
213 : reset();
214 : return *this;
215 : }
216 :
217 : // Observers.
218 : typename add_lvalue_reference<element_type>::type
219 : operator*() const
220 : {
221 : _GLIBCXX_DEBUG_ASSERT(get() != pointer());
222 23 : return *get();
223 : }
224 :
225 : pointer
226 : operator->() const noexcept
227 : {
228 : _GLIBCXX_DEBUG_ASSERT(get() != pointer());
229 : return get();
230 : }
231 :
232 : pointer
233 : get() const noexcept
234 47 : { return std::get<0>(_M_t); }
235 :
236 : deleter_type&
237 : get_deleter() noexcept
238 75 : { return std::get<1>(_M_t); }
239 :
240 : const deleter_type&
241 : get_deleter() const noexcept
242 : { return std::get<1>(_M_t); }
243 :
244 : explicit operator bool() const noexcept
245 : { return get() == pointer() ? false : true; }
246 :
247 : // Modifiers.
248 : pointer
249 : release() noexcept
250 : {
251 12 : pointer __p = get();
252 12 : std::get<0>(_M_t) = pointer();
253 12 : return __p;
254 : }
255 :
256 : void
257 : reset(pointer __p = pointer()) noexcept
258 : {
259 : using std::swap;
260 : swap(std::get<0>(_M_t), __p);
261 : if (__p != pointer())
262 : get_deleter()(__p);
263 : }
264 :
265 : void
266 : swap(unique_ptr& __u) noexcept
267 : {
268 : using std::swap;
269 : swap(_M_t, __u._M_t);
270 : }
271 :
272 : // Disable copy from lvalue.
273 : unique_ptr(const unique_ptr&) = delete;
274 : unique_ptr& operator=(const unique_ptr&) = delete;
275 : };
276 :
277 : /// 20.7.1.3 unique_ptr for array objects with a runtime length
278 : // [unique.ptr.runtime]
279 : // _GLIBCXX_RESOLVE_LIB_DEFECTS
280 : // DR 740 - omit specialization for array objects with a compile time length
281 : template<typename _Tp, typename _Dp>
282 : class unique_ptr<_Tp[], _Dp>
283 : {
284 : // use SFINAE to determine whether _Del::pointer exists
285 : class _Pointer
286 : {
287 : template<typename _Up>
288 : static typename _Up::pointer __test(typename _Up::pointer*);
289 :
290 : template<typename _Up>
291 : static _Tp* __test(...);
292 :
293 : typedef typename remove_reference<_Dp>::type _Del;
294 :
295 : public:
296 : typedef decltype(__test<_Del>(0)) type;
297 : };
298 :
299 : typedef std::tuple<typename _Pointer::type, _Dp> __tuple_type;
300 : __tuple_type _M_t;
301 :
302 : template<typename _Up>
303 : using __remove_cv = typename remove_cv<_Up>::type;
304 :
305 : // like is_base_of<_Tp, _Up> but false if unqualified types are the same
306 : template<typename _Up>
307 : using __is_derived_Tp
308 : = __and_< is_base_of<_Tp, _Up>,
309 : __not_<is_same<__remove_cv<_Tp>, __remove_cv<_Up>>> >;
310 :
311 : template<typename _Up, typename _Ep,
312 : typename _Tp_pointer = typename _Pointer::type,
313 : typename _Up_pointer = typename unique_ptr<_Up, _Ep>::pointer>
314 : using __safe_conversion = __and_<
315 : is_convertible<_Up_pointer, _Tp_pointer>,
316 : is_array<_Up>,
317 : __or_<__not_<is_pointer<_Up_pointer>>,
318 : __not_<is_pointer<_Tp_pointer>>,
319 : __not_<__is_derived_Tp<typename remove_extent<_Up>::type>>
320 : >
321 : >;
322 :
323 : public:
324 : typedef typename _Pointer::type pointer;
325 : typedef _Tp element_type;
326 : typedef _Dp deleter_type;
327 :
328 : // Constructors.
329 : constexpr unique_ptr() noexcept
330 : : _M_t()
331 : { static_assert(!std::is_pointer<deleter_type>::value,
332 : "constructed with null function pointer deleter"); }
333 :
334 : explicit
335 : unique_ptr(pointer __p) noexcept
336 : : _M_t(__p, deleter_type())
337 : { static_assert(!is_pointer<deleter_type>::value,
338 : "constructed with null function pointer deleter"); }
339 :
340 : template<typename _Up, typename = _Require<is_pointer<pointer>,
341 : is_convertible<_Up*, pointer>, __is_derived_Tp<_Up>>>
342 : explicit
343 : unique_ptr(_Up* __p) = delete;
344 :
345 : unique_ptr(pointer __p,
346 : typename conditional<is_reference<deleter_type>::value,
347 : deleter_type, const deleter_type&>::type __d) noexcept
348 : : _M_t(__p, __d) { }
349 :
350 : unique_ptr(pointer __p, typename
351 : remove_reference<deleter_type>::type&& __d) noexcept
352 : : _M_t(std::move(__p), std::move(__d))
353 : { static_assert(!is_reference<deleter_type>::value,
354 : "rvalue deleter bound to reference"); }
355 :
356 : // Move constructor.
357 : unique_ptr(unique_ptr&& __u) noexcept
358 : : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
359 :
360 : constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { }
361 :
362 : template<typename _Up, typename _Ep,
363 : typename = _Require<__safe_conversion<_Up, _Ep>,
364 : typename conditional<is_reference<_Dp>::value,
365 : is_same<_Ep, _Dp>,
366 : is_convertible<_Ep, _Dp>>::type
367 : >>
368 : unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
369 : : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
370 : { }
371 :
372 : // Destructor.
373 : ~unique_ptr()
374 : {
375 : auto& __ptr = std::get<0>(_M_t);
376 : if (__ptr != nullptr)
377 : get_deleter()(__ptr);
378 : __ptr = pointer();
379 : }
380 :
381 : // Assignment.
382 : unique_ptr&
383 : operator=(unique_ptr&& __u) noexcept
384 : {
385 : reset(__u.release());
386 : get_deleter() = std::forward<deleter_type>(__u.get_deleter());
387 : return *this;
388 : }
389 :
390 : template<typename _Up, typename _Ep>
391 : typename
392 : enable_if<__safe_conversion<_Up, _Ep>::value, unique_ptr&>::type
393 : operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
394 : {
395 : reset(__u.release());
396 : get_deleter() = std::forward<_Ep>(__u.get_deleter());
397 : return *this;
398 : }
399 :
400 : unique_ptr&
401 : operator=(nullptr_t) noexcept
402 : {
403 : reset();
404 : return *this;
405 : }
406 :
407 : // Observers.
408 : typename std::add_lvalue_reference<element_type>::type
409 : operator[](size_t __i) const
410 : {
411 : _GLIBCXX_DEBUG_ASSERT(get() != pointer());
412 : return get()[__i];
413 : }
414 :
415 : pointer
416 : get() const noexcept
417 : { return std::get<0>(_M_t); }
418 :
419 : deleter_type&
420 : get_deleter() noexcept
421 : { return std::get<1>(_M_t); }
422 :
423 : const deleter_type&
424 : get_deleter() const noexcept
425 : { return std::get<1>(_M_t); }
426 :
427 : explicit operator bool() const noexcept
428 : { return get() == pointer() ? false : true; }
429 :
430 : // Modifiers.
431 : pointer
432 : release() noexcept
433 : {
434 : pointer __p = get();
435 : std::get<0>(_M_t) = pointer();
436 : return __p;
437 : }
438 :
439 : void
440 : reset() noexcept
441 : { reset(pointer()); }
442 :
443 : void
444 : reset(pointer __p) noexcept
445 : {
446 : using std::swap;
447 : swap(std::get<0>(_M_t), __p);
448 : if (__p != nullptr)
449 : get_deleter()(__p);
450 : }
451 :
452 : template<typename _Up, typename = _Require<is_pointer<pointer>,
453 : is_convertible<_Up*, pointer>, __is_derived_Tp<_Up>>>
454 : void reset(_Up*) = delete;
455 :
456 : void
457 : swap(unique_ptr& __u) noexcept
458 : {
459 : using std::swap;
460 : swap(_M_t, __u._M_t);
461 : }
462 :
463 : // Disable copy from lvalue.
464 : unique_ptr(const unique_ptr&) = delete;
465 : unique_ptr& operator=(const unique_ptr&) = delete;
466 :
467 : // Disable construction from convertible pointer types.
468 : template<typename _Up, typename = _Require<is_pointer<pointer>,
469 : is_convertible<_Up*, pointer>, __is_derived_Tp<_Up>>>
470 : unique_ptr(_Up*, typename
471 : conditional<is_reference<deleter_type>::value,
472 : deleter_type, const deleter_type&>::type) = delete;
473 :
474 : template<typename _Up, typename = _Require<is_pointer<pointer>,
475 : is_convertible<_Up*, pointer>, __is_derived_Tp<_Up>>>
476 : unique_ptr(_Up*, typename
477 : remove_reference<deleter_type>::type&&) = delete;
478 : };
479 :
480 : template<typename _Tp, typename _Dp>
481 : inline void
482 : swap(unique_ptr<_Tp, _Dp>& __x,
483 : unique_ptr<_Tp, _Dp>& __y) noexcept
484 : { __x.swap(__y); }
485 :
486 : template<typename _Tp, typename _Dp,
487 : typename _Up, typename _Ep>
488 : inline bool
489 : operator==(const unique_ptr<_Tp, _Dp>& __x,
490 : const unique_ptr<_Up, _Ep>& __y)
491 : { return __x.get() == __y.get(); }
492 :
493 : template<typename _Tp, typename _Dp>
494 : inline bool
495 : operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
496 : { return !__x; }
497 :
498 : template<typename _Tp, typename _Dp>
499 : inline bool
500 : operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
501 : { return !__x; }
502 :
503 : template<typename _Tp, typename _Dp,
504 : typename _Up, typename _Ep>
505 : inline bool
506 : operator!=(const unique_ptr<_Tp, _Dp>& __x,
507 : const unique_ptr<_Up, _Ep>& __y)
508 : { return __x.get() != __y.get(); }
509 :
510 : template<typename _Tp, typename _Dp>
511 : inline bool
512 : operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
513 : { return (bool)__x; }
514 :
515 : template<typename _Tp, typename _Dp>
516 : inline bool
517 : operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
518 : { return (bool)__x; }
519 :
520 : template<typename _Tp, typename _Dp,
521 : typename _Up, typename _Ep>
522 : inline bool
523 : operator<(const unique_ptr<_Tp, _Dp>& __x,
524 : const unique_ptr<_Up, _Ep>& __y)
525 : {
526 : typedef typename
527 : std::common_type<typename unique_ptr<_Tp, _Dp>::pointer,
528 : typename unique_ptr<_Up, _Ep>::pointer>::type _CT;
529 : return std::less<_CT>()(__x.get(), __y.get());
530 : }
531 :
532 : template<typename _Tp, typename _Dp>
533 : inline bool
534 : operator<(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
535 : { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(),
536 : nullptr); }
537 :
538 : template<typename _Tp, typename _Dp>
539 : inline bool
540 : operator<(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
541 : { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr,
542 : __x.get()); }
543 :
544 : template<typename _Tp, typename _Dp,
545 : typename _Up, typename _Ep>
546 : inline bool
547 : operator<=(const unique_ptr<_Tp, _Dp>& __x,
548 : const unique_ptr<_Up, _Ep>& __y)
549 : { return !(__y < __x); }
550 :
551 : template<typename _Tp, typename _Dp>
552 : inline bool
553 : operator<=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
554 : { return !(nullptr < __x); }
555 :
556 : template<typename _Tp, typename _Dp>
557 : inline bool
558 : operator<=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
559 : { return !(__x < nullptr); }
560 :
561 : template<typename _Tp, typename _Dp,
562 : typename _Up, typename _Ep>
563 : inline bool
564 : operator>(const unique_ptr<_Tp, _Dp>& __x,
565 : const unique_ptr<_Up, _Ep>& __y)
566 : { return (__y < __x); }
567 :
568 : template<typename _Tp, typename _Dp>
569 : inline bool
570 : operator>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
571 : { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr,
572 : __x.get()); }
573 :
574 : template<typename _Tp, typename _Dp>
575 : inline bool
576 : operator>(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
577 : { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(),
578 : nullptr); }
579 :
580 : template<typename _Tp, typename _Dp,
581 : typename _Up, typename _Ep>
582 : inline bool
583 : operator>=(const unique_ptr<_Tp, _Dp>& __x,
584 : const unique_ptr<_Up, _Ep>& __y)
585 : { return !(__x < __y); }
586 :
587 : template<typename _Tp, typename _Dp>
588 : inline bool
589 : operator>=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
590 : { return !(__x < nullptr); }
591 :
592 : template<typename _Tp, typename _Dp>
593 : inline bool
594 : operator>=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
595 : { return !(nullptr < __x); }
596 :
597 : /// std::hash specialization for unique_ptr.
598 : template<typename _Tp, typename _Dp>
599 : struct hash<unique_ptr<_Tp, _Dp>>
600 : : public __hash_base<size_t, unique_ptr<_Tp, _Dp>>
601 : {
602 : size_t
603 : operator()(const unique_ptr<_Tp, _Dp>& __u) const noexcept
604 : {
605 : typedef unique_ptr<_Tp, _Dp> _UP;
606 : return std::hash<typename _UP::pointer>()(__u.get());
607 : }
608 : };
609 :
610 : // @} group pointer_abstractions
611 :
612 : _GLIBCXX_END_NAMESPACE_VERSION
613 : } // namespace
614 :
615 : #endif /* _UNIQUE_PTR_H */
|