OSDN Git Service

2010-06-05 Magnus Fromreide <magfr@lysator.liu.se>
[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
85       // use SFINAE to determine whether _Del::pointer exists
86       class _Pointer
87       {
88         template<typename _Up>
89           static typename _Up::pointer __test(typename _Up::pointer*);
90
91         template<typename _Up>
92           static _Tp* __test(...);
93
94         typedef typename remove_reference<_Tp_Deleter>::type _Del;
95
96       public:
97         typedef decltype( __test<_Del>(0) ) type;
98       };
99
100     public:
101       typedef typename _Pointer::type   pointer;
102       typedef _Tp                       element_type;
103       typedef _Tp_Deleter               deleter_type;
104
105       // Constructors.
106       unique_ptr()
107       : _M_t(pointer(), deleter_type())
108       { static_assert(!std::is_pointer<deleter_type>::value,
109                       "constructed with null function pointer deleter"); }
110
111       explicit
112       unique_ptr(pointer __p)
113       : _M_t(__p, deleter_type())
114       { static_assert(!std::is_pointer<deleter_type>::value,
115                      "constructed with null function pointer deleter"); }
116
117       unique_ptr(pointer __p,
118           typename std::conditional<std::is_reference<deleter_type>::value, 
119             deleter_type, const deleter_type&>::type __d)
120       : _M_t(__p, __d) { }
121
122       unique_ptr(pointer __p,
123           typename std::remove_reference<deleter_type>::type&& __d)
124       : _M_t(std::move(__p), std::move(__d))
125       { static_assert(!std::is_reference<deleter_type>::value, 
126                       "rvalue deleter bound to reference"); }
127
128       unique_ptr(nullptr_t)
129       : _M_t(pointer(), deleter_type())
130       { }
131
132       // Move constructors.
133       unique_ptr(unique_ptr&& __u) 
134       : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
135
136       template<typename _Up, typename _Up_Deleter> 
137         unique_ptr(unique_ptr<_Up, _Up_Deleter>&& __u) 
138         : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter()))
139         { }
140
141       // Destructor.
142       ~unique_ptr() { reset(); }
143     
144       // Assignment.
145       unique_ptr&
146       operator=(unique_ptr&& __u)
147       { 
148         reset(__u.release()); 
149         get_deleter() = std::move(__u.get_deleter()); 
150         return *this;
151       }
152
153       template<typename _Up, typename _Up_Deleter> 
154         unique_ptr&
155         operator=(unique_ptr<_Up, _Up_Deleter>&& __u)
156         {
157           reset(__u.release()); 
158           get_deleter() = std::move(__u.get_deleter()); 
159           return *this;
160         }
161
162       unique_ptr&
163       operator=(nullptr_t)
164       {
165         reset();
166         return *this;
167       }
168
169       // Observers.
170       typename std::add_lvalue_reference<element_type>::type
171       operator*() const
172       {
173         _GLIBCXX_DEBUG_ASSERT(get() != pointer());
174         return *get();
175       }
176
177       pointer
178       operator->() const
179       {
180         _GLIBCXX_DEBUG_ASSERT(get() != pointer());
181         return get();
182       }
183
184       pointer
185       get() const
186       { return std::get<0>(_M_t); }
187
188       deleter_type&
189       get_deleter()
190       { return std::get<1>(_M_t); }
191
192       const deleter_type&
193       get_deleter() const
194       { return std::get<1>(_M_t); }
195
196       explicit operator bool() const
197       { return get() == pointer() ? false : true; }
198
199       // Modifiers.
200       pointer
201       release() 
202       {
203         pointer __p = get();
204         std::get<0>(_M_t) = pointer();
205         return __p;
206       }
207
208       void
209       reset(pointer __p = pointer())
210       {
211         using std::swap;
212         swap(std::get<0>(_M_t), __p);
213         if (__p != pointer())
214           get_deleter()(__p);
215       }
216
217       void
218       swap(unique_ptr& __u)
219       {
220         using std::swap;
221         swap(_M_t, __u._M_t);
222       }
223
224       // Disable copy from lvalue.
225       unique_ptr(const unique_ptr&) = delete;
226       unique_ptr& operator=(const unique_ptr&) = delete;
227
228     private:
229       __tuple_type _M_t;
230   };
231  
232   /// 20.7.12.3 unique_ptr for array objects with a runtime length
233   // [unique.ptr.runtime]
234   // _GLIBCXX_RESOLVE_LIB_DEFECTS
235   // DR 740 - omit specialization for array objects with a compile time length
236   template<typename _Tp, typename _Tp_Deleter> 
237     class unique_ptr<_Tp[], _Tp_Deleter>
238     {
239       typedef std::tuple<_Tp*, _Tp_Deleter>  __tuple_type;
240
241     public:
242       typedef _Tp*               pointer;
243       typedef _Tp                element_type;      
244       typedef _Tp_Deleter        deleter_type;
245
246       // Constructors.
247       unique_ptr()
248       : _M_t(pointer(), deleter_type())
249       { static_assert(!std::is_pointer<deleter_type>::value,
250                       "constructed with null function pointer deleter"); }
251
252       explicit
253       unique_ptr(pointer __p)
254       : _M_t(__p, deleter_type())
255       { static_assert(!std::is_pointer<deleter_type>::value,
256                       "constructed with null function pointer deleter"); }
257
258       unique_ptr(pointer __p,
259           typename std::conditional<std::is_reference<deleter_type>::value, 
260               deleter_type, const deleter_type&>::type __d) 
261       : _M_t(__p, __d) { }
262
263       unique_ptr(pointer __p,
264                  typename std::remove_reference<deleter_type>::type && __d)
265       : _M_t(std::move(__p), std::move(__d))
266       { static_assert(!std::is_reference<deleter_type>::value, 
267                       "rvalue deleter bound to reference"); }
268
269       /* TODO: use delegating constructor */
270       unique_ptr(nullptr_t)
271       : _M_t(pointer(), deleter_type())
272       { }
273
274       // Move constructors.
275       unique_ptr(unique_ptr&& __u) 
276       : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
277
278       template<typename _Up, typename _Up_Deleter> 
279         unique_ptr(unique_ptr<_Up, _Up_Deleter>&& __u) 
280         : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter()))
281         { }
282
283       // Destructor.
284       ~unique_ptr() { reset(); }
285
286       // Assignment.
287       unique_ptr&
288       operator=(unique_ptr&& __u)
289       {
290         reset(__u.release());
291         get_deleter() = std::move(__u.get_deleter()); 
292         return *this; 
293       }
294
295       template<typename _Up, typename _Up_Deleter> 
296         unique_ptr&
297         operator=(unique_ptr<_Up, _Up_Deleter>&& __u)
298         {
299           reset(__u.release());
300           get_deleter() = std::move(__u.get_deleter()); 
301           return *this;
302         }
303
304       unique_ptr&
305       operator=(nullptr_t)
306       {
307         reset();
308         return *this;
309       }
310
311       // Observers.
312       typename std::add_lvalue_reference<element_type>::type 
313       operator[](size_t __i) const 
314       {
315         _GLIBCXX_DEBUG_ASSERT(get() != pointer());
316         return get()[__i];
317       }
318
319       pointer
320       get() const
321       { return std::get<0>(_M_t); }
322
323       deleter_type& 
324       get_deleter()
325       { return std::get<1>(_M_t); }
326
327       const deleter_type&
328       get_deleter() const
329       { return std::get<1>(_M_t); }    
330
331       explicit operator bool() const 
332       { return get() == pointer() ? false : true; }
333     
334       // Modifiers.
335       pointer
336       release() 
337       {
338         pointer __p = get();
339         std::get<0>(_M_t) = pointer();
340         return __p;
341       }
342
343       void
344       reset(pointer __p = pointer()) 
345       {
346         using std::swap;
347         swap(std::get<0>(_M_t), __p);
348         if (__p != nullptr)
349           get_deleter()(__p);
350       }
351
352       void
353       reset(nullptr_t)
354       {
355         pointer __p = get();
356         std::get<0>(_M_t) = pointer();
357         if (__p != nullptr)
358           get_deleter()(__p);
359       }
360
361       // DR 821.
362       template<typename _Up>
363         void reset(_Up) = delete;
364
365       void
366       swap(unique_ptr& __u)
367       {
368         using std::swap;
369         swap(_M_t, __u._M_t);
370       }
371
372       // Disable copy from lvalue.
373       unique_ptr(const unique_ptr&) = delete;
374       unique_ptr& operator=(const unique_ptr&) = delete;
375
376       // Disable construction from convertible pointer types.
377       // (N2315 - 20.6.5.3.1)
378       template<typename _Up>
379         unique_ptr(_Up*, typename
380                    std::conditional<std::is_reference<deleter_type>::value,
381                    deleter_type, const deleter_type&>::type,
382                    typename std::enable_if<std::is_convertible<_Up*, 
383                    pointer>::value>::type* = 0) = delete;
384
385       template<typename _Up>
386         unique_ptr(_Up*, typename std::remove_reference<deleter_type>::type&&,
387                    typename std::enable_if<std::is_convertible<_Up*, 
388                    pointer>::value>::type* = 0) = delete;
389
390       template<typename _Up>
391         explicit
392         unique_ptr(_Up*, typename std::enable_if<std::is_convertible<_Up*, 
393                    pointer>::value>::type* = 0) = delete;
394
395     private:
396       __tuple_type _M_t;
397   };
398   
399   template<typename _Tp, typename _Tp_Deleter> 
400     inline void
401     swap(unique_ptr<_Tp, _Tp_Deleter>& __x,
402          unique_ptr<_Tp, _Tp_Deleter>& __y)
403     { __x.swap(__y); }
404
405   template<typename _Tp, typename _Tp_Deleter,
406            typename _Up, typename _Up_Deleter>
407     inline bool
408     operator==(const unique_ptr<_Tp, _Tp_Deleter>& __x,
409                const unique_ptr<_Up, _Up_Deleter>& __y)
410     { return __x.get() == __y.get(); }
411
412   template<typename _Tp, typename _Tp_Deleter,
413            typename _Up, typename _Up_Deleter>
414     inline bool
415     operator!=(const unique_ptr<_Tp, _Tp_Deleter>& __x,
416                const unique_ptr<_Up, _Up_Deleter>& __y)
417     { return !(__x.get() == __y.get()); }
418
419   template<typename _Tp, typename _Tp_Deleter,
420            typename _Up, typename _Up_Deleter>
421     inline bool
422     operator<(const unique_ptr<_Tp, _Tp_Deleter>& __x,
423               const unique_ptr<_Up, _Up_Deleter>& __y)
424     { return __x.get() < __y.get(); }
425
426   template<typename _Tp, typename _Tp_Deleter,
427            typename _Up, typename _Up_Deleter>
428     inline bool
429     operator<=(const unique_ptr<_Tp, _Tp_Deleter>& __x,
430                const unique_ptr<_Up, _Up_Deleter>& __y)
431     { return !(__y.get() < __x.get()); }
432
433   template<typename _Tp, typename _Tp_Deleter,
434            typename _Up, typename _Up_Deleter>
435     inline bool
436     operator>(const unique_ptr<_Tp, _Tp_Deleter>& __x,
437               const unique_ptr<_Up, _Up_Deleter>& __y)
438     { return __y.get() < __x.get(); }
439
440   template<typename _Tp, typename _Tp_Deleter,
441            typename _Up, typename _Up_Deleter>
442     inline bool
443     operator>=(const unique_ptr<_Tp, _Tp_Deleter>& __x,
444                const unique_ptr<_Up, _Up_Deleter>& __y)
445     { return !(__x.get() < __y.get()); }
446
447   // @} group pointer_abstractions
448
449 _GLIBCXX_END_NAMESPACE
450
451 #endif /* _UNIQUE_PTR_H */