OSDN Git Service

2010-04-24 Jonathan Wakely <jwakely.gcc@gmail.com>
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / include / bits / unique_ptr.h
1 // unique_ptr implementation -*- C++ -*-
2
3 // Copyright (C) 2008, 2009, 2010 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 unique_ptr.h
26  *  This is an internal header file, included by other library headers.
27  *  You should not attempt to use it directly.
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 _GLIBCXX_BEGIN_NAMESPACE(std)
40
41   /**
42    * @addtogroup pointer_abstractions
43    * @{
44    */
45
46   /// Primary template, default_delete.
47   template<typename _Tp> 
48     struct default_delete
49       {
50         default_delete() { }
51
52         template<typename _Up>
53           default_delete(const default_delete<_Up>&) { }
54
55         void
56         operator()(_Tp* __ptr) const
57         {
58           static_assert(sizeof(_Tp)>0,
59                         "can't delete pointer to incomplete type");
60           delete __ptr;
61         }
62     };
63
64   // _GLIBCXX_RESOLVE_LIB_DEFECTS
65   // DR 740 - omit specialization for array objects with a compile time length
66   /// Specialization, default_delete.
67   template<typename _Tp> 
68     struct default_delete<_Tp[]>
69     {
70       void
71       operator()(_Tp* __ptr) const
72       {
73         static_assert(sizeof(_Tp)>0,
74                       "can't delete pointer to incomplete type");
75         delete [] __ptr;
76       }
77     };
78
79   /// 20.7.12.2 unique_ptr for single objects.
80   template <typename _Tp, typename _Tp_Deleter = default_delete<_Tp> > 
81     class unique_ptr
82     {
83       typedef std::tuple<_Tp*, _Tp_Deleter>  __tuple_type;
84       typedef _Tp* unique_ptr::*             __unspecified_pointer_type;
85
86       // use SFINAE to determine whether _Del::pointer exists
87       class _Pointer
88       {
89         template<typename _Up>
90           static typename _Up::pointer __test(typename _Up::pointer*);
91
92         template<typename _Up>
93           static _Tp* __test(...);
94
95         typedef typename remove_reference<_Tp_Deleter>::type _Del;
96
97       public:
98         typedef decltype( __test<_Del>(0) ) type;
99       };
100
101     public:
102       typedef typename _Pointer::type   pointer;
103       typedef _Tp                       element_type;
104       typedef _Tp_Deleter               deleter_type;
105
106       // Constructors.
107       unique_ptr()
108       : _M_t(pointer(), deleter_type())
109       { static_assert(!std::is_pointer<deleter_type>::value,
110                       "constructed with null function pointer deleter"); }
111
112       explicit
113       unique_ptr(pointer __p)
114       : _M_t(__p, deleter_type())
115       { static_assert(!std::is_pointer<deleter_type>::value,
116                      "constructed with null function pointer deleter"); }
117
118       unique_ptr(pointer __p,
119           typename std::conditional<std::is_reference<deleter_type>::value, 
120             deleter_type, const deleter_type&>::type __d)
121       : _M_t(__p, __d) { }
122
123       unique_ptr(pointer __p,
124           typename std::remove_reference<deleter_type>::type&& __d)
125       : _M_t(std::move(__p), std::move(__d))
126       { static_assert(!std::is_reference<deleter_type>::value, 
127                       "rvalue deleter bound to reference"); }
128
129       // Move constructors.
130       unique_ptr(unique_ptr&& __u) 
131       : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
132
133       template<typename _Up, typename _Up_Deleter> 
134         unique_ptr(unique_ptr<_Up, _Up_Deleter>&& __u) 
135         : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter()))
136         { }
137
138       // Destructor.
139       ~unique_ptr() { reset(); }
140     
141       // Assignment.
142       unique_ptr&
143       operator=(unique_ptr&& __u)
144       { 
145         reset(__u.release()); 
146         get_deleter() = std::move(__u.get_deleter()); 
147         return *this;
148       }
149
150       template<typename _Up, typename _Up_Deleter> 
151         unique_ptr&
152         operator=(unique_ptr<_Up, _Up_Deleter>&& __u)
153         {
154           reset(__u.release()); 
155           get_deleter() = std::move(__u.get_deleter()); 
156           return *this;
157         }
158
159       unique_ptr&
160       operator=(__unspecified_pointer_type) 
161       {
162         reset();
163         return *this;
164       }
165
166       // Observers.
167       typename std::add_lvalue_reference<element_type>::type
168       operator*() const
169       {
170         _GLIBCXX_DEBUG_ASSERT(get() != pointer());
171         return *get();
172       }
173
174       pointer
175       operator->() const
176       {
177         _GLIBCXX_DEBUG_ASSERT(get() != pointer());
178         return get();
179       }
180
181       pointer
182       get() const
183       { return std::get<0>(_M_t); }
184
185       deleter_type&
186       get_deleter()
187       { return std::get<1>(_M_t); }
188
189       const deleter_type&
190       get_deleter() const
191       { return std::get<1>(_M_t); }
192
193       explicit operator bool() const
194       { return get() == pointer() ? false : true; }
195
196       // Modifiers.
197       pointer
198       release() 
199       {
200         pointer __p = get();
201         std::get<0>(_M_t) = pointer();
202         return __p;
203       }
204
205       void
206       reset(pointer __p = pointer())
207       {
208         using std::swap;
209         swap(std::get<0>(_M_t), __p);
210         if (__p != pointer())
211           get_deleter()(__p);
212       }
213
214       void
215       swap(unique_ptr& __u)
216       {
217         using std::swap;
218         swap(_M_t, __u._M_t);
219       }
220
221       // Disable copy from lvalue.
222       unique_ptr(const unique_ptr&) = delete;
223       unique_ptr& operator=(const unique_ptr&) = delete;
224
225     private:
226       __tuple_type _M_t;
227   };
228  
229   /// 20.7.12.3 unique_ptr for array objects with a runtime length
230   // [unique.ptr.runtime]
231   // _GLIBCXX_RESOLVE_LIB_DEFECTS
232   // DR 740 - omit specialization for array objects with a compile time length
233   template<typename _Tp, typename _Tp_Deleter> 
234     class unique_ptr<_Tp[], _Tp_Deleter>
235     {
236       typedef std::tuple<_Tp*, _Tp_Deleter>  __tuple_type;
237       typedef _Tp* unique_ptr::*             __unspecified_pointer_type;
238
239     public:
240       typedef _Tp*               pointer;
241       typedef _Tp                element_type;      
242       typedef _Tp_Deleter        deleter_type;
243
244       // Constructors.
245       unique_ptr()
246       : _M_t(pointer(), deleter_type())
247       { static_assert(!std::is_pointer<deleter_type>::value,
248                       "constructed with null function pointer deleter"); }
249
250       explicit
251       unique_ptr(pointer __p)
252       : _M_t(__p, deleter_type())
253       { static_assert(!std::is_pointer<deleter_type>::value,
254                       "constructed with null function pointer deleter"); }
255
256       unique_ptr(pointer __p,
257           typename std::conditional<std::is_reference<deleter_type>::value, 
258               deleter_type, const deleter_type&>::type __d) 
259       : _M_t(__p, __d) { }
260
261       unique_ptr(pointer __p,
262                  typename std::remove_reference<deleter_type>::type && __d)
263       : _M_t(std::move(__p), std::move(__d))
264       { static_assert(!std::is_reference<deleter_type>::value, 
265                       "rvalue deleter bound to reference"); }
266
267       // Move constructors.
268       unique_ptr(unique_ptr&& __u) 
269       : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
270
271       template<typename _Up, typename _Up_Deleter> 
272         unique_ptr(unique_ptr<_Up, _Up_Deleter>&& __u) 
273         : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter()))
274         { }
275
276       // Destructor.
277       ~unique_ptr() { reset(); }
278
279       // Assignment.
280       unique_ptr&
281       operator=(unique_ptr&& __u)
282       {
283         reset(__u.release());
284         get_deleter() = std::move(__u.get_deleter()); 
285         return *this; 
286       }
287
288       template<typename _Up, typename _Up_Deleter> 
289         unique_ptr&
290         operator=(unique_ptr<_Up, _Up_Deleter>&& __u)
291         {
292           reset(__u.release());
293           get_deleter() = std::move(__u.get_deleter()); 
294           return *this;
295         }
296
297       unique_ptr&
298       operator=(__unspecified_pointer_type)
299       {
300         reset();
301         return *this;
302       }
303
304       // Observers.
305       typename std::add_lvalue_reference<element_type>::type 
306       operator[](size_t __i) const 
307       {
308         _GLIBCXX_DEBUG_ASSERT(get() != pointer());
309         return get()[__i];
310       }
311
312       pointer
313       get() const
314       { return std::get<0>(_M_t); }
315
316       deleter_type& 
317       get_deleter()
318       { return std::get<1>(_M_t); }
319
320       const deleter_type&
321       get_deleter() const
322       { return std::get<1>(_M_t); }    
323
324       explicit operator bool() const 
325       { return get() == pointer() ? false : true; }
326     
327       // Modifiers.
328       pointer
329       release() 
330       {
331         pointer __p = get();
332         std::get<0>(_M_t) = pointer();
333         return __p;
334       }
335
336       void
337       reset(pointer __p = pointer()) 
338       {
339         using std::swap;
340         swap(std::get<0>(_M_t), __p);
341         if (__p != pointer())
342           get_deleter()(__p);
343       }
344
345       // DR 821.
346       template<typename _Up>
347         void reset(_Up) = delete;
348
349       void
350       swap(unique_ptr& __u)
351       {
352         using std::swap;
353         swap(_M_t, __u._M_t);
354       }
355
356       // Disable copy from lvalue.
357       unique_ptr(const unique_ptr&) = delete;
358       unique_ptr& operator=(const unique_ptr&) = delete;
359
360       // Disable construction from convertible pointer types.
361       // (N2315 - 20.6.5.3.1)
362       template<typename _Up>
363         unique_ptr(_Up*, typename
364                    std::conditional<std::is_reference<deleter_type>::value,
365                    deleter_type, const deleter_type&>::type,
366                    typename std::enable_if<std::is_convertible<_Up*, 
367                    pointer>::value>::type* = 0) = delete;
368
369       template<typename _Up>
370         unique_ptr(_Up*, typename std::remove_reference<deleter_type>::type&&,
371                    typename std::enable_if<std::is_convertible<_Up*, 
372                    pointer>::value>::type* = 0) = delete;
373
374       template<typename _Up>
375         explicit
376         unique_ptr(_Up*, typename std::enable_if<std::is_convertible<_Up*, 
377                    pointer>::value>::type* = 0) = delete;
378
379     private:
380       __tuple_type _M_t;
381   };
382   
383   template<typename _Tp, typename _Tp_Deleter> 
384     inline void
385     swap(unique_ptr<_Tp, _Tp_Deleter>& __x,
386          unique_ptr<_Tp, _Tp_Deleter>& __y)
387     { __x.swap(__y); }
388
389   template<typename _Tp, typename _Tp_Deleter,
390            typename _Up, typename _Up_Deleter>
391     inline bool
392     operator==(const unique_ptr<_Tp, _Tp_Deleter>& __x,
393                const unique_ptr<_Up, _Up_Deleter>& __y)
394     { return __x.get() == __y.get(); }
395
396   template<typename _Tp, typename _Tp_Deleter,
397            typename _Up, typename _Up_Deleter>
398     inline bool
399     operator!=(const unique_ptr<_Tp, _Tp_Deleter>& __x,
400                const unique_ptr<_Up, _Up_Deleter>& __y)
401     { return !(__x.get() == __y.get()); }
402
403   template<typename _Tp, typename _Tp_Deleter,
404            typename _Up, typename _Up_Deleter>
405     inline bool
406     operator<(const unique_ptr<_Tp, _Tp_Deleter>& __x,
407               const unique_ptr<_Up, _Up_Deleter>& __y)
408     { return __x.get() < __y.get(); }
409
410   template<typename _Tp, typename _Tp_Deleter,
411            typename _Up, typename _Up_Deleter>
412     inline bool
413     operator<=(const unique_ptr<_Tp, _Tp_Deleter>& __x,
414                const unique_ptr<_Up, _Up_Deleter>& __y)
415     { return !(__y.get() < __x.get()); }
416
417   template<typename _Tp, typename _Tp_Deleter,
418            typename _Up, typename _Up_Deleter>
419     inline bool
420     operator>(const unique_ptr<_Tp, _Tp_Deleter>& __x,
421               const unique_ptr<_Up, _Up_Deleter>& __y)
422     { return __y.get() < __x.get(); }
423
424   template<typename _Tp, typename _Tp_Deleter,
425            typename _Up, typename _Up_Deleter>
426     inline bool
427     operator>=(const unique_ptr<_Tp, _Tp_Deleter>& __x,
428                const unique_ptr<_Up, _Up_Deleter>& __y)
429     { return !(__x.get() < __y.get()); }
430
431   // @} group pointer_abstractions
432
433 _GLIBCXX_END_NAMESPACE
434
435 #endif /* _UNIQUE_PTR_H */