OSDN Git Service

2011-04-02 Jonathan Wakely <redi@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / include / bits / unique_ptr.h
1 // unique_ptr implementation -*- C++ -*-
2
3 // Copyright (C) 2008, 2009, 2010, 2011 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   /// Primary template, default_delete.
49   template<typename _Tp>
50     struct default_delete
51     {
52       constexpr default_delete() = default;
53
54       template<typename _Up, typename = typename
55                std::enable_if<std::is_convertible<_Up*, _Tp*>::value>::type>
56         default_delete(const default_delete<_Up>&) { }
57
58       void
59       operator()(_Tp* __ptr) const
60       {
61         static_assert(sizeof(_Tp)>0,
62                       "can't delete pointer to incomplete type");
63         delete __ptr;
64       }
65     };
66
67   // _GLIBCXX_RESOLVE_LIB_DEFECTS
68   // DR 740 - omit specialization for array objects with a compile time length
69   /// Specialization, default_delete.
70   template<typename _Tp>
71     struct default_delete<_Tp[]>
72     {
73       constexpr default_delete() = default;
74
75       void
76       operator()(_Tp* __ptr) const
77       {
78         static_assert(sizeof(_Tp)>0,
79                       "can't delete pointer to incomplete type");
80         delete [] __ptr;
81       }
82     };
83
84   /// 20.7.12.2 unique_ptr for single objects.
85   template <typename _Tp, typename _Dp = default_delete<_Tp> >
86     class unique_ptr
87     {
88       // use SFINAE to determine whether _Del::pointer exists
89       class _Pointer
90       {
91         template<typename _Up>
92           static typename _Up::pointer __test(typename _Up::pointer*);
93
94         template<typename _Up>
95           static _Tp* __test(...);
96
97         typedef typename remove_reference<_Dp>::type _Del;
98
99       public:
100         typedef decltype( __test<_Del>(0)) type;
101       };
102
103       typedef std::tuple<typename _Pointer::type, _Dp>  __tuple_type;
104       __tuple_type                                      _M_t;
105
106     public:
107       typedef typename _Pointer::type   pointer;
108       typedef _Tp                       element_type;
109       typedef _Dp                       deleter_type;
110
111       // Constructors.
112       constexpr unique_ptr()
113       : _M_t()
114       { static_assert(!std::is_pointer<deleter_type>::value,
115                      "constructed with null function pointer deleter"); }
116
117       explicit
118       unique_ptr(pointer __p)
119       : _M_t(__p, deleter_type())
120       { static_assert(!std::is_pointer<deleter_type>::value,
121                      "constructed with null function pointer deleter"); }
122
123       unique_ptr(pointer __p,
124           typename std::conditional<std::is_reference<deleter_type>::value,
125             deleter_type, const deleter_type&>::type __d)
126       : _M_t(__p, __d) { }
127
128       unique_ptr(pointer __p,
129           typename std::remove_reference<deleter_type>::type&& __d)
130       : _M_t(std::move(__p), std::move(__d))
131       { static_assert(!std::is_reference<deleter_type>::value,
132                       "rvalue deleter bound to reference"); }
133
134       constexpr unique_ptr(nullptr_t)
135       : _M_t()
136       { static_assert(!std::is_pointer<deleter_type>::value,
137                      "constructed with null function pointer deleter"); }
138
139       // Move constructors.
140       unique_ptr(unique_ptr&& __u)
141       : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
142
143       template<typename _Up, typename _Ep, typename = typename
144         std::enable_if
145           <std::is_convertible<typename unique_ptr<_Up, _Ep>::pointer,
146                                pointer>::value
147            && !std::is_array<_Up>::value
148            && ((std::is_reference<_Dp>::value
149                 && std::is_same<_Ep, _Dp>::value)
150                || (!std::is_reference<_Dp>::value
151                    && std::is_convertible<_Ep, _Dp>::value))>
152              ::type>
153         unique_ptr(unique_ptr<_Up, _Ep>&& __u)
154         : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter()))
155         { }
156
157 #if _GLIBCXX_USE_DEPRECATED
158       template<typename _Up, typename = typename
159         std::enable_if<std::is_convertible<_Up*, _Tp*>::value
160                        && std::is_same<_Dp,
161                                        default_delete<_Tp>>::value>::type>
162         unique_ptr(auto_ptr<_Up>&& __u)
163         : _M_t(__u.release(), deleter_type()) { }
164 #endif
165
166       // Destructor.
167       ~unique_ptr() { reset(); }
168
169       // Assignment.
170       unique_ptr&
171       operator=(unique_ptr&& __u)
172       {
173         reset(__u.release());
174         get_deleter() = std::move(__u.get_deleter());
175         return *this;
176       }
177
178       template<typename _Up, typename _Ep, typename = typename
179         std::enable_if
180           <std::is_convertible<typename unique_ptr<_Up, _Ep>::pointer,
181                                pointer>::value
182            && !std::is_array<_Up>::value>::type>
183         unique_ptr&
184         operator=(unique_ptr<_Up, _Ep>&& __u)
185         {
186           reset(__u.release());
187           get_deleter() = std::move(__u.get_deleter());
188           return *this;
189         }
190
191       unique_ptr&
192       operator=(nullptr_t)
193       {
194         reset();
195         return *this;
196       }
197
198       // Observers.
199       typename std::add_lvalue_reference<element_type>::type
200       operator*() const
201       {
202         _GLIBCXX_DEBUG_ASSERT(get() != pointer());
203         return *get();
204       }
205
206       pointer
207       operator->() const
208       {
209         _GLIBCXX_DEBUG_ASSERT(get() != pointer());
210         return get();
211       }
212
213       pointer
214       get() const
215       { return std::get<0>(_M_t); }
216
217       deleter_type&
218       get_deleter()
219       { return std::get<1>(_M_t); }
220
221       const deleter_type&
222       get_deleter() const
223       { return std::get<1>(_M_t); }
224
225       explicit operator bool() const
226       { return get() == pointer() ? false : true; }
227
228       // Modifiers.
229       pointer
230       release()
231       {
232         pointer __p = get();
233         std::get<0>(_M_t) = pointer();
234         return __p;
235       }
236
237       void
238       reset(pointer __p = pointer())
239       {
240         using std::swap;
241         swap(std::get<0>(_M_t), __p);
242         if (__p != pointer())
243           get_deleter()(__p);
244       }
245
246       void
247       swap(unique_ptr& __u)
248       {
249         using std::swap;
250         swap(_M_t, __u._M_t);
251       }
252
253       // Disable copy from lvalue.
254       unique_ptr(const unique_ptr&) = delete;
255       unique_ptr& operator=(const unique_ptr&) = delete;
256   };
257
258   /// 20.7.12.3 unique_ptr for array objects with a runtime length
259   // [unique.ptr.runtime]
260   // _GLIBCXX_RESOLVE_LIB_DEFECTS
261   // DR 740 - omit specialization for array objects with a compile time length
262   template<typename _Tp, typename _Dp>
263     class unique_ptr<_Tp[], _Dp>
264     {
265       typedef std::tuple<_Tp*, _Dp>     __tuple_type;
266       __tuple_type                      _M_t;
267
268     public:
269       typedef _Tp*                      pointer;
270       typedef _Tp                       element_type;
271       typedef _Dp                       deleter_type;
272
273       // Constructors.
274       constexpr unique_ptr()
275       : _M_t()
276       { static_assert(!std::is_pointer<deleter_type>::value,
277                      "constructed with null function pointer deleter"); }
278
279       explicit
280       unique_ptr(pointer __p)
281       : _M_t(__p, deleter_type())
282       { static_assert(!std::is_pointer<deleter_type>::value,
283                      "constructed with null function pointer deleter"); }
284
285       unique_ptr(pointer __p,
286           typename std::conditional<std::is_reference<deleter_type>::value,
287               deleter_type, const deleter_type&>::type __d)
288       : _M_t(__p, __d) { }
289
290       unique_ptr(pointer __p,
291                  typename std::remove_reference<deleter_type>::type && __d)
292       : _M_t(std::move(__p), std::move(__d))
293       { static_assert(!std::is_reference<deleter_type>::value,
294                       "rvalue deleter bound to reference"); }
295
296       constexpr unique_ptr(nullptr_t)
297       : _M_t()
298       { static_assert(!std::is_pointer<deleter_type>::value,
299                      "constructed with null function pointer deleter"); }
300
301       // Move constructors.
302       unique_ptr(unique_ptr&& __u)
303       : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
304
305       template<typename _Up, typename _Ep>
306         unique_ptr(unique_ptr<_Up, _Ep>&& __u)
307         : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter()))
308         { }
309
310       // Destructor.
311       ~unique_ptr() { reset(); }
312
313       // Assignment.
314       unique_ptr&
315       operator=(unique_ptr&& __u)
316       {
317         reset(__u.release());
318         get_deleter() = std::move(__u.get_deleter());
319         return *this;
320       }
321
322       template<typename _Up, typename _Ep>
323         unique_ptr&
324         operator=(unique_ptr<_Up, _Ep>&& __u)
325         {
326           reset(__u.release());
327           get_deleter() = std::move(__u.get_deleter());
328           return *this;
329         }
330
331       unique_ptr&
332       operator=(nullptr_t)
333       {
334         reset();
335         return *this;
336       }
337
338       // Observers.
339       typename std::add_lvalue_reference<element_type>::type
340       operator[](size_t __i) const
341       {
342         _GLIBCXX_DEBUG_ASSERT(get() != pointer());
343         return get()[__i];
344       }
345
346       pointer
347       get() const
348       { return std::get<0>(_M_t); }
349
350       deleter_type&
351       get_deleter()
352       { return std::get<1>(_M_t); }
353
354       const deleter_type&
355       get_deleter() const
356       { return std::get<1>(_M_t); }
357
358       explicit operator bool() const
359       { return get() == pointer() ? false : true; }
360
361       // Modifiers.
362       pointer
363       release()
364       {
365         pointer __p = get();
366         std::get<0>(_M_t) = pointer();
367         return __p;
368       }
369
370       void
371       reset(pointer __p = pointer())
372       {
373         using std::swap;
374         swap(std::get<0>(_M_t), __p);
375         if (__p != nullptr)
376           get_deleter()(__p);
377       }
378
379       void
380       reset(nullptr_t)
381       {
382         pointer __p = get();
383         std::get<0>(_M_t) = pointer();
384         if (__p != nullptr)
385           get_deleter()(__p);
386       }
387
388       // DR 821.
389       template<typename _Up>
390         void reset(_Up) = delete;
391
392       void
393       swap(unique_ptr& __u)
394       {
395         using std::swap;
396         swap(_M_t, __u._M_t);
397       }
398
399       // Disable copy from lvalue.
400       unique_ptr(const unique_ptr&) = delete;
401       unique_ptr& operator=(const unique_ptr&) = delete;
402
403       // Disable construction from convertible pointer types.
404       // (N2315 - 20.6.5.3.1)
405       template<typename _Up>
406         unique_ptr(_Up*, typename
407                    std::conditional<std::is_reference<deleter_type>::value,
408                    deleter_type, const deleter_type&>::type,
409                    typename std::enable_if<std::is_convertible<_Up*,
410                    pointer>::value>::type* = 0) = delete;
411
412       template<typename _Up>
413         unique_ptr(_Up*, typename std::remove_reference<deleter_type>::type&&,
414                    typename std::enable_if<std::is_convertible<_Up*,
415                    pointer>::value>::type* = 0) = delete;
416
417       template<typename _Up>
418         explicit
419         unique_ptr(_Up*, typename std::enable_if<std::is_convertible<_Up*,
420                    pointer>::value>::type* = 0) = delete;
421   };
422
423   template<typename _Tp, typename _Dp>
424     inline void
425     swap(unique_ptr<_Tp, _Dp>& __x,
426          unique_ptr<_Tp, _Dp>& __y)
427     { __x.swap(__y); }
428
429   template<typename _Tp, typename _Dp,
430            typename _Up, typename _Ep>
431     inline bool
432     operator==(const unique_ptr<_Tp, _Dp>& __x,
433                const unique_ptr<_Up, _Ep>& __y)
434     { return __x.get() == __y.get(); }
435
436   template<typename _Tp, typename _Dp>
437     inline bool
438     operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
439     { return !__x; }
440
441   template<typename _Tp, typename _Dp>
442     inline bool
443     operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
444     { return !__x; }
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 (bool)__x; }
457
458   template<typename _Tp, typename _Dp>
459     inline bool
460     operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
461     { return (bool)__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     {
469       typedef typename
470         std::common_type<typename unique_ptr<_Tp, _Dp>::pointer,
471                          typename unique_ptr<_Up, _Ep>::pointer>::type _CT;
472       return std::less<_CT>()(__x.get(), __y.get());
473     }
474
475   template<typename _Tp, typename _Dp>
476     inline bool
477     operator<(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
478     { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(),
479                                                                  nullptr); }
480
481   template<typename _Tp, typename _Dp>
482     inline bool
483     operator<(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
484     { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr,
485                                                                  __x.get()); }
486
487   template<typename _Tp, typename _Dp,
488            typename _Up, typename _Ep>
489     inline bool
490     operator<=(const unique_ptr<_Tp, _Dp>& __x,
491                const unique_ptr<_Up, _Ep>& __y)
492     { return !(__y < __x); }
493
494   template<typename _Tp, typename _Dp>
495     inline bool
496     operator<=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
497     { return !(nullptr < __x); }
498
499   template<typename _Tp, typename _Dp>
500     inline bool
501     operator<=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
502     { return !(__x < nullptr); }
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 std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr,
515                                                                  __x.get()); }
516
517   template<typename _Tp, typename _Dp>
518     inline bool
519     operator>(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
520     { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(),
521                                                                  nullptr); }
522
523   template<typename _Tp, typename _Dp,
524            typename _Up, typename _Ep>
525     inline bool
526     operator>=(const unique_ptr<_Tp, _Dp>& __x,
527                const unique_ptr<_Up, _Ep>& __y)
528     { return !(__x < __y); }
529
530   template<typename _Tp, typename _Dp>
531     inline bool
532     operator>=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
533     { return !(__x < nullptr); }
534
535   template<typename _Tp, typename _Dp>
536     inline bool
537     operator>=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
538     { return !(nullptr < __x); }
539
540   /// std::hash specialization for unique_ptr.
541   template<typename _Tp, typename _Dp>
542     struct hash<unique_ptr<_Tp, _Dp>>
543     : public std::unary_function<unique_ptr<_Tp, _Dp>, size_t>
544     {
545       size_t
546       operator()(const unique_ptr<_Tp, _Dp>& __u) const
547       {
548         typedef unique_ptr<_Tp, _Dp> _UP;
549         return std::hash<typename _UP::pointer>()(__u.get());
550       }
551     };
552
553   // @} group pointer_abstractions
554
555 _GLIBCXX_END_NAMESPACE_VERSION
556 } // namespace
557
558 #endif /* _UNIQUE_PTR_H */