re PR libstdc++/54351 (~unique_ptr() should not set stored pointer to null)
[gcc.git] / libstdc++-v3 / include / bits / unique_ptr.h
1 // unique_ptr implementation -*- C++ -*-
2
3 // Copyright (C) 2008-2012 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 std::enable_if<std::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 constexpr default_delete() noexcept = default;
78
79 void
80 operator()(_Tp* __ptr) const
81 {
82 static_assert(sizeof(_Tp)>0,
83 "can't delete pointer to incomplete type");
84 delete [] __ptr;
85 }
86
87 template<typename _Up> void operator()(_Up*) const = delete;
88 };
89
90 /// 20.7.1.2 unique_ptr for single objects.
91 template <typename _Tp, typename _Dp = default_delete<_Tp> >
92 class unique_ptr
93 {
94 // use SFINAE to determine whether _Del::pointer exists
95 class _Pointer
96 {
97 template<typename _Up>
98 static typename _Up::pointer __test(typename _Up::pointer*);
99
100 template<typename _Up>
101 static _Tp* __test(...);
102
103 typedef typename remove_reference<_Dp>::type _Del;
104
105 public:
106 typedef decltype( __test<_Del>(0)) type;
107 };
108
109 typedef std::tuple<typename _Pointer::type, _Dp> __tuple_type;
110 __tuple_type _M_t;
111
112 public:
113 typedef typename _Pointer::type pointer;
114 typedef _Tp element_type;
115 typedef _Dp deleter_type;
116
117 // Constructors.
118 constexpr unique_ptr() noexcept
119 : _M_t()
120 { static_assert(!std::is_pointer<deleter_type>::value,
121 "constructed with null function pointer deleter"); }
122
123 explicit
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"); }
128
129 unique_ptr(pointer __p,
130 typename std::conditional<std::is_reference<deleter_type>::value,
131 deleter_type, const deleter_type&>::type __d) noexcept
132 : _M_t(__p, __d) { }
133
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"); }
139
140 constexpr unique_ptr(nullptr_t) noexcept
141 : _M_t()
142 { static_assert(!std::is_pointer<deleter_type>::value,
143 "constructed with null function pointer deleter"); }
144
145 // Move constructors.
146 unique_ptr(unique_ptr&& __u) noexcept
147 : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
148
149 template<typename _Up, typename _Ep, typename = typename
150 std::enable_if
151 <std::is_convertible<typename unique_ptr<_Up, _Ep>::pointer,
152 pointer>::value
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))>
158 ::type>
159 unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
160 : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
161 { }
162
163 #if _GLIBCXX_USE_DEPRECATED
164 template<typename _Up, typename = typename
165 std::enable_if<std::is_convertible<_Up*, _Tp*>::value
166 && std::is_same<_Dp,
167 default_delete<_Tp>>::value>::type>
168 unique_ptr(auto_ptr<_Up>&& __u) noexcept;
169 #endif
170
171 // Destructor.
172 ~unique_ptr() noexcept
173 {
174 auto& __ptr = std::get<0>(_M_t);
175 if (__ptr != nullptr)
176 get_deleter()(__ptr);
177 __ptr = pointer();
178 }
179
180 // Assignment.
181 unique_ptr&
182 operator=(unique_ptr&& __u) noexcept
183 {
184 reset(__u.release());
185 get_deleter() = std::forward<deleter_type>(__u.get_deleter());
186 return *this;
187 }
188
189 template<typename _Up, typename _Ep, typename = typename
190 std::enable_if
191 <std::is_convertible<typename unique_ptr<_Up, _Ep>::pointer,
192 pointer>::value
193 && !std::is_array<_Up>::value>::type>
194 unique_ptr&
195 operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
196 {
197 reset(__u.release());
198 get_deleter() = std::forward<_Ep>(__u.get_deleter());
199 return *this;
200 }
201
202 unique_ptr&
203 operator=(nullptr_t) noexcept
204 {
205 reset();
206 return *this;
207 }
208
209 // Observers.
210 typename std::add_lvalue_reference<element_type>::type
211 operator*() const
212 {
213 _GLIBCXX_DEBUG_ASSERT(get() != pointer());
214 return *get();
215 }
216
217 pointer
218 operator->() const noexcept
219 {
220 _GLIBCXX_DEBUG_ASSERT(get() != pointer());
221 return get();
222 }
223
224 pointer
225 get() const noexcept
226 { return std::get<0>(_M_t); }
227
228 deleter_type&
229 get_deleter() noexcept
230 { return std::get<1>(_M_t); }
231
232 const deleter_type&
233 get_deleter() const noexcept
234 { return std::get<1>(_M_t); }
235
236 explicit operator bool() const noexcept
237 { return get() == pointer() ? false : true; }
238
239 // Modifiers.
240 pointer
241 release() noexcept
242 {
243 pointer __p = get();
244 std::get<0>(_M_t) = pointer();
245 return __p;
246 }
247
248 void
249 reset(pointer __p = pointer()) noexcept
250 {
251 using std::swap;
252 swap(std::get<0>(_M_t), __p);
253 if (__p != pointer())
254 get_deleter()(__p);
255 }
256
257 void
258 swap(unique_ptr& __u) noexcept
259 {
260 using std::swap;
261 swap(_M_t, __u._M_t);
262 }
263
264 // Disable copy from lvalue.
265 unique_ptr(const unique_ptr&) = delete;
266 unique_ptr& operator=(const unique_ptr&) = delete;
267 };
268
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>
275 {
276 typedef std::tuple<_Tp*, _Dp> __tuple_type;
277 __tuple_type _M_t;
278
279 public:
280 typedef _Tp* pointer;
281 typedef _Tp element_type;
282 typedef _Dp deleter_type;
283
284 // Constructors.
285 constexpr unique_ptr() noexcept
286 : _M_t()
287 { static_assert(!std::is_pointer<deleter_type>::value,
288 "constructed with null function pointer deleter"); }
289
290 explicit
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"); }
295
296 unique_ptr(pointer __p,
297 typename std::conditional<std::is_reference<deleter_type>::value,
298 deleter_type, const deleter_type&>::type __d) noexcept
299 : _M_t(__p, __d) { }
300
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"); }
306
307 constexpr unique_ptr(nullptr_t) noexcept
308 : _M_t()
309 { static_assert(!std::is_pointer<deleter_type>::value,
310 "constructed with null function pointer deleter"); }
311
312 // Move constructors.
313 unique_ptr(unique_ptr&& __u) noexcept
314 : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
315
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()))
319 { }
320
321 // Destructor.
322 ~unique_ptr()
323 {
324 auto& __ptr = std::get<0>(_M_t);
325 if (__ptr != nullptr)
326 get_deleter()(__ptr);
327 __ptr = pointer();
328 }
329
330 // Assignment.
331 unique_ptr&
332 operator=(unique_ptr&& __u) noexcept
333 {
334 reset(__u.release());
335 get_deleter() = std::forward<deleter_type>(__u.get_deleter());
336 return *this;
337 }
338
339 template<typename _Up, typename _Ep>
340 unique_ptr&
341 operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
342 {
343 reset(__u.release());
344 get_deleter() = std::forward<_Ep>(__u.get_deleter());
345 return *this;
346 }
347
348 unique_ptr&
349 operator=(nullptr_t) noexcept
350 {
351 reset();
352 return *this;
353 }
354
355 // Observers.
356 typename std::add_lvalue_reference<element_type>::type
357 operator[](size_t __i) const
358 {
359 _GLIBCXX_DEBUG_ASSERT(get() != pointer());
360 return get()[__i];
361 }
362
363 pointer
364 get() const noexcept
365 { return std::get<0>(_M_t); }
366
367 deleter_type&
368 get_deleter() noexcept
369 { return std::get<1>(_M_t); }
370
371 const deleter_type&
372 get_deleter() const noexcept
373 { return std::get<1>(_M_t); }
374
375 explicit operator bool() const noexcept
376 { return get() == pointer() ? false : true; }
377
378 // Modifiers.
379 pointer
380 release() noexcept
381 {
382 pointer __p = get();
383 std::get<0>(_M_t) = pointer();
384 return __p;
385 }
386
387 void
388 reset(pointer __p = pointer()) noexcept
389 {
390 using std::swap;
391 swap(std::get<0>(_M_t), __p);
392 if (__p != nullptr)
393 get_deleter()(__p);
394 }
395
396 void
397 reset(nullptr_t) noexcept
398 {
399 pointer __p = get();
400 std::get<0>(_M_t) = pointer();
401 if (__p != nullptr)
402 get_deleter()(__p);
403 }
404
405 // DR 821.
406 template<typename _Up>
407 void reset(_Up) = delete;
408
409 void
410 swap(unique_ptr& __u) noexcept
411 {
412 using std::swap;
413 swap(_M_t, __u._M_t);
414 }
415
416 // Disable copy from lvalue.
417 unique_ptr(const unique_ptr&) = delete;
418 unique_ptr& operator=(const unique_ptr&) = delete;
419
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;
428
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;
433
434 template<typename _Up>
435 explicit
436 unique_ptr(_Up*, typename std::enable_if<std::is_convertible<_Up*,
437 pointer>::value>::type* = 0) = delete;
438 };
439
440 template<typename _Tp, typename _Dp>
441 inline void
442 swap(unique_ptr<_Tp, _Dp>& __x,
443 unique_ptr<_Tp, _Dp>& __y) noexcept
444 { __x.swap(__y); }
445
446 template<typename _Tp, typename _Dp,
447 typename _Up, typename _Ep>
448 inline bool
449 operator==(const unique_ptr<_Tp, _Dp>& __x,
450 const unique_ptr<_Up, _Ep>& __y)
451 { return __x.get() == __y.get(); }
452
453 template<typename _Tp, typename _Dp>
454 inline bool
455 operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
456 { return !__x; }
457
458 template<typename _Tp, typename _Dp>
459 inline bool
460 operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
461 { return !__x; }
462
463 template<typename _Tp, typename _Dp,
464 typename _Up, typename _Ep>
465 inline bool
466 operator!=(const unique_ptr<_Tp, _Dp>& __x,
467 const unique_ptr<_Up, _Ep>& __y)
468 { return __x.get() != __y.get(); }
469
470 template<typename _Tp, typename _Dp>
471 inline bool
472 operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
473 { return (bool)__x; }
474
475 template<typename _Tp, typename _Dp>
476 inline bool
477 operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
478 { return (bool)__x; }
479
480 template<typename _Tp, typename _Dp,
481 typename _Up, typename _Ep>
482 inline bool
483 operator<(const unique_ptr<_Tp, _Dp>& __x,
484 const unique_ptr<_Up, _Ep>& __y)
485 {
486 typedef typename
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());
490 }
491
492 template<typename _Tp, typename _Dp>
493 inline bool
494 operator<(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
495 { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(),
496 nullptr); }
497
498 template<typename _Tp, typename _Dp>
499 inline bool
500 operator<(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
501 { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr,
502 __x.get()); }
503
504 template<typename _Tp, typename _Dp,
505 typename _Up, typename _Ep>
506 inline bool
507 operator<=(const unique_ptr<_Tp, _Dp>& __x,
508 const unique_ptr<_Up, _Ep>& __y)
509 { return !(__y < __x); }
510
511 template<typename _Tp, typename _Dp>
512 inline bool
513 operator<=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
514 { return !(nullptr < __x); }
515
516 template<typename _Tp, typename _Dp>
517 inline bool
518 operator<=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
519 { return !(__x < nullptr); }
520
521 template<typename _Tp, typename _Dp,
522 typename _Up, typename _Ep>
523 inline bool
524 operator>(const unique_ptr<_Tp, _Dp>& __x,
525 const unique_ptr<_Up, _Ep>& __y)
526 { return (__y < __x); }
527
528 template<typename _Tp, typename _Dp>
529 inline bool
530 operator>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
531 { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr,
532 __x.get()); }
533
534 template<typename _Tp, typename _Dp>
535 inline bool
536 operator>(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
537 { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(),
538 nullptr); }
539
540 template<typename _Tp, typename _Dp,
541 typename _Up, typename _Ep>
542 inline bool
543 operator>=(const unique_ptr<_Tp, _Dp>& __x,
544 const unique_ptr<_Up, _Ep>& __y)
545 { return !(__x < __y); }
546
547 template<typename _Tp, typename _Dp>
548 inline bool
549 operator>=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
550 { return !(__x < nullptr); }
551
552 template<typename _Tp, typename _Dp>
553 inline bool
554 operator>=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
555 { return !(nullptr < __x); }
556
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>>
561 {
562 size_t
563 operator()(const unique_ptr<_Tp, _Dp>& __u) const noexcept
564 {
565 typedef unique_ptr<_Tp, _Dp> _UP;
566 return std::hash<typename _UP::pointer>()(__u.get());
567 }
568 };
569
570 // @} group pointer_abstractions
571
572 _GLIBCXX_END_NAMESPACE_VERSION
573 } // namespace
574
575 #endif /* _UNIQUE_PTR_H */