libstdc++
unique_ptr.h
Go to the documentation of this file.
1 // unique_ptr implementation -*- C++ -*-
2 
3 // Copyright (C) 2008, 2009 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 #ifndef __GXX_EXPERIMENTAL_CXX0X__
34 # include <c++0x_warning.h>
35 #endif
36 
37 #include <bits/c++config.h>
38 #include <debug/debug.h>
39 #include <type_traits>
40 #include <utility>
41 #include <tuple>
42 
43 _GLIBCXX_BEGIN_NAMESPACE(std)
44 
45  /**
46  * @addtogroup pointer_abstractions
47  * @{
48  */
49 
50  /// Primary template, default_delete.
51  template<typename _Tp>
53  {
54  default_delete() { }
55 
56  template<typename _Up>
57  default_delete(const default_delete<_Up>&) { }
58 
59  void
60  operator()(_Tp* __ptr) const
61  {
62  static_assert(sizeof(_Tp)>0,
63  "can't delete pointer to incomplete type");
64  delete __ptr;
65  }
66  };
67 
68  // _GLIBCXX_RESOLVE_LIB_DEFECTS
69  // DR 740 - omit specialization for array objects with a compile time length
70  /// Specialization, default_delete.
71  template<typename _Tp>
72  struct default_delete<_Tp[]>
73  {
74  void
75  operator()(_Tp* __ptr) const
76  {
77  static_assert(sizeof(_Tp)>0,
78  "can't delete pointer to incomplete type");
79  delete [] __ptr;
80  }
81  };
82 
83  /// 20.7.12.2 unique_ptr for single objects.
84  template <typename _Tp, typename _Tp_Deleter = default_delete<_Tp> >
85  class unique_ptr
86  {
88  typedef __tuple_type unique_ptr::* __unspecified_bool_type;
89  typedef _Tp* unique_ptr::* __unspecified_pointer_type;
90 
91  public:
92  typedef _Tp* pointer;
93  typedef _Tp element_type;
94  typedef _Tp_Deleter deleter_type;
95 
96  // Constructors.
97  unique_ptr()
98  : _M_t(pointer(), deleter_type())
99  { static_assert(!std::is_pointer<deleter_type>::value,
100  "constructed with null function pointer deleter"); }
101 
102  explicit
103  unique_ptr(pointer __p)
104  : _M_t(__p, deleter_type())
105  { static_assert(!std::is_pointer<deleter_type>::value,
106  "constructed with null function pointer deleter"); }
107 
108  unique_ptr(pointer __p,
109  typename std::conditional<std::is_reference<deleter_type>::value,
110  deleter_type, const deleter_type&>::type __d)
111  : _M_t(__p, __d) { }
112 
113  unique_ptr(pointer __p,
114  typename std::remove_reference<deleter_type>::type&& __d)
115  : _M_t(std::move(__p), std::move(__d))
116  { static_assert(!std::is_reference<deleter_type>::value,
117  "rvalue deleter bound to reference"); }
118 
119  // Move constructors.
120  unique_ptr(unique_ptr&& __u)
121  : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
122 
123  template<typename _Up, typename _Up_Deleter>
125  : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter()))
126  { }
127 
128  // Destructor.
129  ~unique_ptr() { reset(); }
130 
131  // Assignment.
132  unique_ptr&
133  operator=(unique_ptr&& __u)
134  {
135  reset(__u.release());
136  get_deleter() = std::move(__u.get_deleter());
137  return *this;
138  }
139 
140  template<typename _Up, typename _Up_Deleter>
141  unique_ptr&
142  operator=(unique_ptr<_Up, _Up_Deleter>&& __u)
143  {
144  reset(__u.release());
145  get_deleter() = std::move(__u.get_deleter());
146  return *this;
147  }
148 
149  unique_ptr&
150  operator=(__unspecified_pointer_type)
151  {
152  reset();
153  return *this;
154  }
155 
156  // Observers.
157  typename std::add_lvalue_reference<element_type>::type operator*() const
158  {
159  _GLIBCXX_DEBUG_ASSERT(get() != 0);
160  return *get();
161  }
162 
163  pointer
164  operator->() const
165  {
166  _GLIBCXX_DEBUG_ASSERT(get() != 0);
167  return get();
168  }
169 
170  pointer
171  get() const
172  { return std::get<0>(_M_t); }
173 
174  typename std::add_lvalue_reference<deleter_type>::type
175  get_deleter()
176  { return std::get<1>(_M_t); }
177 
178  typename std::add_lvalue_reference<
179  typename std::add_const<deleter_type>::type
180  >::type
181  get_deleter() const
182  { return std::get<1>(_M_t); }
183 
184  operator __unspecified_bool_type () const
185  { return get() == 0 ? 0 : &unique_ptr::_M_t; }
186 
187  // Modifiers.
188  pointer
189  release()
190  {
191  pointer __p = get();
192  std::get<0>(_M_t) = 0;
193  return __p;
194  }
195 
196  void
197  reset(pointer __p = pointer())
198  {
199  if (__p != get())
200  {
201  get_deleter()(get());
202  std::get<0>(_M_t) = __p;
203  }
204  }
205 
206  void
207  swap(unique_ptr&& __u)
208  {
209  using std::swap;
210  swap(_M_t, __u._M_t);
211  }
212 
213  // Disable copy from lvalue.
214  unique_ptr(const unique_ptr&) = delete;
215 
216  template<typename _Up, typename _Up_Deleter>
217  unique_ptr(const unique_ptr<_Up, _Up_Deleter>&) = delete;
218 
219  unique_ptr& operator=(const unique_ptr&) = delete;
220 
221  template<typename _Up, typename _Up_Deleter>
222  unique_ptr& operator=(const unique_ptr<_Up, _Up_Deleter>&) = delete;
223 
224  private:
225  __tuple_type _M_t;
226  };
227 
228  /// 20.7.12.3 unique_ptr for array objects with a runtime length
229  // [unique.ptr.runtime]
230  // _GLIBCXX_RESOLVE_LIB_DEFECTS
231  // DR 740 - omit specialization for array objects with a compile time length
232  template<typename _Tp, typename _Tp_Deleter>
233  class unique_ptr<_Tp[], _Tp_Deleter>
234  {
236  typedef __tuple_type unique_ptr::* __unspecified_bool_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>
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() != 0);
309  return get()[__i];
310  }
311 
312  pointer
313  get() const
314  { return std::get<0>(_M_t); }
315 
316  typename std::add_lvalue_reference<deleter_type>::type
317  get_deleter()
318  { return std::get<1>(_M_t); }
319 
320  typename std::add_lvalue_reference<
321  typename std::add_const<deleter_type>::type
322  >::type
323  get_deleter() const
324  { return std::get<1>(_M_t); }
325 
326  operator __unspecified_bool_type () const
327  { return get() == 0 ? 0 : &unique_ptr::_M_t; }
328 
329  // Modifiers.
330  pointer
331  release()
332  {
333  pointer __p = get();
334  std::get<0>(_M_t) = 0;
335  return __p;
336  }
337 
338  void
339  reset(pointer __p = pointer())
340  {
341  if (__p != get())
342  {
343  get_deleter()(get());
344  std::get<0>(_M_t) = __p;
345  }
346  }
347 
348  // DR 821.
349  template<typename _Up>
350  void reset(_Up) = delete;
351 
352  void
353  swap(unique_ptr&& __u)
354  {
355  using std::swap;
356  swap(_M_t, __u._M_t);
357  }
358 
359  // Disable copy from lvalue.
360  unique_ptr(const unique_ptr&) = delete;
361  unique_ptr& operator=(const unique_ptr&) = delete;
362 
363  // Disable construction from convertible pointer types.
364  // (N2315 - 20.6.5.3.1)
365  template<typename _Up>
366  unique_ptr(_Up*, typename
368  deleter_type, const deleter_type&>::type,
369  typename std::enable_if<std::is_convertible<_Up*,
370  pointer>::value>::type* = 0) = delete;
371 
372  template<typename _Up>
373  unique_ptr(_Up*, typename std::remove_reference<deleter_type>::type&&,
374  typename std::enable_if<std::is_convertible<_Up*,
375  pointer>::value>::type* = 0) = delete;
376 
377  template<typename _Up>
378  explicit
379  unique_ptr(_Up*, typename std::enable_if<std::is_convertible<_Up*,
380  pointer>::value>::type* = 0) = delete;
381 
382  private:
383  __tuple_type _M_t;
384  };
385 
386  template<typename _Tp, typename _Tp_Deleter>
387  inline void
390  { __x.swap(__y); }
391 
392  template<typename _Tp, typename _Tp_Deleter>
393  inline void
394  swap(unique_ptr<_Tp, _Tp_Deleter>&& __x,
395  unique_ptr<_Tp, _Tp_Deleter>& __y)
396  { __x.swap(__y); }
397 
398  template<typename _Tp, typename _Tp_Deleter>
399  inline void
400  swap(unique_ptr<_Tp, _Tp_Deleter>& __x,
401  unique_ptr<_Tp, _Tp_Deleter>&& __y)
402  { __x.swap(__y); }
403 
404  template<typename _Tp, typename _Tp_Deleter,
405  typename _Up, typename _Up_Deleter>
406  inline bool
407  operator==(const unique_ptr<_Tp, _Tp_Deleter>& __x,
408  const unique_ptr<_Up, _Up_Deleter>& __y)
409  { return __x.get() == __y.get(); }
410 
411  template<typename _Tp, typename _Tp_Deleter,
412  typename _Up, typename _Up_Deleter>
413  inline bool
414  operator!=(const unique_ptr<_Tp, _Tp_Deleter>& __x,
415  const unique_ptr<_Up, _Up_Deleter>& __y)
416  { return !(__x.get() == __y.get()); }
417 
418  template<typename _Tp, typename _Tp_Deleter,
419  typename _Up, typename _Up_Deleter>
420  inline bool
421  operator<(const unique_ptr<_Tp, _Tp_Deleter>& __x,
422  const unique_ptr<_Up, _Up_Deleter>& __y)
423  { return __x.get() < __y.get(); }
424 
425  template<typename _Tp, typename _Tp_Deleter,
426  typename _Up, typename _Up_Deleter>
427  inline bool
428  operator<=(const unique_ptr<_Tp, _Tp_Deleter>& __x,
429  const unique_ptr<_Up, _Up_Deleter>& __y)
430  { return !(__y.get() < __x.get()); }
431 
432  template<typename _Tp, typename _Tp_Deleter,
433  typename _Up, typename _Up_Deleter>
434  inline bool
435  operator>(const unique_ptr<_Tp, _Tp_Deleter>& __x,
436  const unique_ptr<_Up, _Up_Deleter>& __y)
437  { return __y.get() < __x.get(); }
438 
439  template<typename _Tp, typename _Tp_Deleter,
440  typename _Up, typename _Up_Deleter>
441  inline bool
442  operator>=(const unique_ptr<_Tp, _Tp_Deleter>& __x,
443  const unique_ptr<_Up, _Up_Deleter>& __y)
444  { return !(__x.get() < __y.get()); }
445 
446  // @} group pointer_abstractions
447 
448 _GLIBCXX_END_NAMESPACE
449 
450 #endif /* _UNIQUE_PTR_H */
20.7.12.2 unique_ptr for single objects.
Definition: unique_ptr.h:85
add_lvalue_reference
Definition: type_traits:124
is_reference
Definition: type_traits:88
_OI move(_II __first, _II __last, _OI __result)
Moves the range [first,last) into result.
Definition: stl_algobase.h:491
Primary template, default_delete.
Definition: unique_ptr.h:52