libstdc++

unique_ptr.h
Go to the documentation of this file.
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 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 delete __ptr;
68 }
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 : _M_t(__p, deleter_type())
143 { static_assert(!is_pointer<deleter_type>::value,
144 "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 : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
171 { }
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 auto& __ptr = std::get<0>(_M_t);
183 if (__ptr != nullptr)
184 get_deleter()(__ptr);
185 __ptr = pointer();
186 }
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 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 { return std::get<0>(_M_t); }
235
236 deleter_type&
237 get_deleter() noexcept
238 { 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 pointer __p = get();
252 std::get<0>(_M_t) = pointer();
253 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 */