libstdc++
unique_ptr.h
Go to the documentation of this file.
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>
51  {
52  constexpr default_delete() = default;
53 
54  template<typename _Up, typename = typename
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  template<typename _Up> void operator()(_Up*) const = delete;
84  };
85 
86  /// 20.7.12.2 unique_ptr for single objects.
87  template <typename _Tp, typename _Dp = default_delete<_Tp> >
88  class unique_ptr
89  {
90  // use SFINAE to determine whether _Del::pointer exists
91  class _Pointer
92  {
93  template<typename _Up>
94  static typename _Up::pointer __test(typename _Up::pointer*);
95 
96  template<typename _Up>
97  static _Tp* __test(...);
98 
99  typedef typename remove_reference<_Dp>::type _Del;
100 
101  public:
102  typedef decltype( __test<_Del>(0)) type;
103  };
104 
106  __tuple_type _M_t;
107 
108  public:
109  typedef typename _Pointer::type pointer;
110  typedef _Tp element_type;
111  typedef _Dp deleter_type;
112 
113  // Constructors.
114  constexpr unique_ptr()
115  : _M_t()
116  { static_assert(!std::is_pointer<deleter_type>::value,
117  "constructed with null function pointer deleter"); }
118 
119  explicit
120  unique_ptr(pointer __p)
121  : _M_t(__p, deleter_type())
122  { static_assert(!std::is_pointer<deleter_type>::value,
123  "constructed with null function pointer deleter"); }
124 
125  unique_ptr(pointer __p,
127  deleter_type, const deleter_type&>::type __d)
128  : _M_t(__p, __d) { }
129 
130  unique_ptr(pointer __p,
131  typename std::remove_reference<deleter_type>::type&& __d)
132  : _M_t(std::move(__p), std::move(__d))
134  "rvalue deleter bound to reference"); }
135 
136  constexpr unique_ptr(nullptr_t)
137  : _M_t()
138  { static_assert(!std::is_pointer<deleter_type>::value,
139  "constructed with null function pointer deleter"); }
140 
141  // Move constructors.
142  unique_ptr(unique_ptr&& __u)
143  : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
144 
145  template<typename _Up, typename _Ep, typename = typename
148  pointer>::value
154  ::type>
155  unique_ptr(unique_ptr<_Up, _Ep>&& __u)
156  : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
157  { }
158 
159 #if _GLIBCXX_USE_DEPRECATED
160  template<typename _Up, typename = typename
162  && std::is_same<_Dp,
163  default_delete<_Tp>>::value>::type>
164  unique_ptr(auto_ptr<_Up>&& __u)
165  : _M_t(__u.release(), deleter_type()) { }
166 #endif
167 
168  // Destructor.
169  ~unique_ptr() { reset(); }
170 
171  // Assignment.
172  unique_ptr&
173  operator=(unique_ptr&& __u)
174  {
175  reset(__u.release());
176  get_deleter() = std::forward<deleter_type>(__u.get_deleter());
177  return *this;
178  }
179 
180  template<typename _Up, typename _Ep, typename = typename
183  pointer>::value
184  && !std::is_array<_Up>::value>::type>
185  unique_ptr&
186  operator=(unique_ptr<_Up, _Ep>&& __u)
187  {
188  reset(__u.release());
189  get_deleter() = std::forward<_Ep>(__u.get_deleter());
190  return *this;
191  }
192 
193  unique_ptr&
194  operator=(nullptr_t)
195  {
196  reset();
197  return *this;
198  }
199 
200  // Observers.
201  typename std::add_lvalue_reference<element_type>::type
202  operator*() const
203  {
204  _GLIBCXX_DEBUG_ASSERT(get() != pointer());
205  return *get();
206  }
207 
208  pointer
209  operator->() const
210  {
211  _GLIBCXX_DEBUG_ASSERT(get() != pointer());
212  return get();
213  }
214 
215  pointer
216  get() const
217  { return std::get<0>(_M_t); }
218 
219  deleter_type&
220  get_deleter()
221  { return std::get<1>(_M_t); }
222 
223  const deleter_type&
224  get_deleter() const
225  { return std::get<1>(_M_t); }
226 
227  explicit operator bool() const
228  { return get() == pointer() ? false : true; }
229 
230  // Modifiers.
231  pointer
232  release()
233  {
234  pointer __p = get();
235  std::get<0>(_M_t) = pointer();
236  return __p;
237  }
238 
239  void
240  reset(pointer __p = pointer())
241  {
242  using std::swap;
243  swap(std::get<0>(_M_t), __p);
244  if (__p != pointer())
245  get_deleter()(__p);
246  }
247 
248  void
249  swap(unique_ptr& __u)
250  {
251  using std::swap;
252  swap(_M_t, __u._M_t);
253  }
254 
255  // Disable copy from lvalue.
256  unique_ptr(const unique_ptr&) = delete;
257  unique_ptr& operator=(const unique_ptr&) = delete;
258  };
259 
260  /// 20.7.12.3 unique_ptr for array objects with a runtime length
261  // [unique.ptr.runtime]
262  // _GLIBCXX_RESOLVE_LIB_DEFECTS
263  // DR 740 - omit specialization for array objects with a compile time length
264  template<typename _Tp, typename _Dp>
265  class unique_ptr<_Tp[], _Dp>
266  {
268  __tuple_type _M_t;
269 
270  public:
271  typedef _Tp* pointer;
272  typedef _Tp element_type;
273  typedef _Dp deleter_type;
274 
275  // Constructors.
276  constexpr unique_ptr()
277  : _M_t()
278  { static_assert(!std::is_pointer<deleter_type>::value,
279  "constructed with null function pointer deleter"); }
280 
281  explicit
282  unique_ptr(pointer __p)
283  : _M_t(__p, deleter_type())
284  { static_assert(!std::is_pointer<deleter_type>::value,
285  "constructed with null function pointer deleter"); }
286 
287  unique_ptr(pointer __p,
289  deleter_type, const deleter_type&>::type __d)
290  : _M_t(__p, __d) { }
291 
292  unique_ptr(pointer __p,
293  typename std::remove_reference<deleter_type>::type && __d)
294  : _M_t(std::move(__p), std::move(__d))
296  "rvalue deleter bound to reference"); }
297 
298  constexpr unique_ptr(nullptr_t)
299  : _M_t()
300  { static_assert(!std::is_pointer<deleter_type>::value,
301  "constructed with null function pointer deleter"); }
302 
303  // Move constructors.
304  unique_ptr(unique_ptr&& __u)
305  : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
306 
307  template<typename _Up, typename _Ep>
308  unique_ptr(unique_ptr<_Up, _Ep>&& __u)
309  : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
310  { }
311 
312  // Destructor.
313  ~unique_ptr() { reset(); }
314 
315  // Assignment.
316  unique_ptr&
317  operator=(unique_ptr&& __u)
318  {
319  reset(__u.release());
320  get_deleter() = std::forward<deleter_type>(__u.get_deleter());
321  return *this;
322  }
323 
324  template<typename _Up, typename _Ep>
325  unique_ptr&
326  operator=(unique_ptr<_Up, _Ep>&& __u)
327  {
328  reset(__u.release());
329  get_deleter() = std::forward<_Ep>(__u.get_deleter());
330  return *this;
331  }
332 
333  unique_ptr&
334  operator=(nullptr_t)
335  {
336  reset();
337  return *this;
338  }
339 
340  // Observers.
341  typename std::add_lvalue_reference<element_type>::type
342  operator[](size_t __i) const
343  {
344  _GLIBCXX_DEBUG_ASSERT(get() != pointer());
345  return get()[__i];
346  }
347 
348  pointer
349  get() const
350  { return std::get<0>(_M_t); }
351 
352  deleter_type&
353  get_deleter()
354  { return std::get<1>(_M_t); }
355 
356  const deleter_type&
357  get_deleter() const
358  { return std::get<1>(_M_t); }
359 
360  explicit operator bool() const
361  { return get() == pointer() ? false : true; }
362 
363  // Modifiers.
364  pointer
365  release()
366  {
367  pointer __p = get();
368  std::get<0>(_M_t) = pointer();
369  return __p;
370  }
371 
372  void
373  reset(pointer __p = pointer())
374  {
375  using std::swap;
376  swap(std::get<0>(_M_t), __p);
377  if (__p != nullptr)
378  get_deleter()(__p);
379  }
380 
381  void
382  reset(nullptr_t)
383  {
384  pointer __p = get();
385  std::get<0>(_M_t) = pointer();
386  if (__p != nullptr)
387  get_deleter()(__p);
388  }
389 
390  // DR 821.
391  template<typename _Up>
392  void reset(_Up) = delete;
393 
394  void
395  swap(unique_ptr& __u)
396  {
397  using std::swap;
398  swap(_M_t, __u._M_t);
399  }
400 
401  // Disable copy from lvalue.
402  unique_ptr(const unique_ptr&) = delete;
403  unique_ptr& operator=(const unique_ptr&) = delete;
404 
405  // Disable construction from convertible pointer types.
406  // (N2315 - 20.6.5.3.1)
407  template<typename _Up>
408  unique_ptr(_Up*, typename
410  deleter_type, const deleter_type&>::type,
411  typename std::enable_if<std::is_convertible<_Up*,
412  pointer>::value>::type* = 0) = delete;
413 
414  template<typename _Up>
415  unique_ptr(_Up*, typename std::remove_reference<deleter_type>::type&&,
416  typename std::enable_if<std::is_convertible<_Up*,
417  pointer>::value>::type* = 0) = delete;
418 
419  template<typename _Up>
420  explicit
421  unique_ptr(_Up*, typename std::enable_if<std::is_convertible<_Up*,
422  pointer>::value>::type* = 0) = delete;
423  };
424 
425  template<typename _Tp, typename _Dp>
426  inline void
427  swap(unique_ptr<_Tp, _Dp>& __x,
429  { __x.swap(__y); }
430 
431  template<typename _Tp, typename _Dp,
432  typename _Up, typename _Ep>
433  inline bool
434  operator==(const unique_ptr<_Tp, _Dp>& __x,
435  const unique_ptr<_Up, _Ep>& __y)
436  { return __x.get() == __y.get(); }
437 
438  template<typename _Tp, typename _Dp>
439  inline bool
440  operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
441  { return __x.get() == nullptr; }
442 
443  template<typename _Tp, typename _Dp>
444  inline bool
445  operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __y)
446  { return nullptr == __y.get(); }
447 
448  template<typename _Tp, typename _Dp,
449  typename _Up, typename _Ep>
450  inline bool
451  operator!=(const unique_ptr<_Tp, _Dp>& __x,
452  const unique_ptr<_Up, _Ep>& __y)
453  { return !(__x.get() == __y.get()); }
454 
455  template<typename _Tp, typename _Dp>
456  inline bool
457  operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
458  { return __x.get() != nullptr; }
459 
460  template<typename _Tp, typename _Dp>
461  inline bool
462  operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __y)
463  { return nullptr != __y.get(); }
464 
465  template<typename _Tp, typename _Dp,
466  typename _Up, typename _Ep>
467  inline bool
468  operator<(const unique_ptr<_Tp, _Dp>& __x,
469  const unique_ptr<_Up, _Ep>& __y)
470  { return __x.get() < __y.get(); }
471 
472  template<typename _Tp, typename _Dp,
473  typename _Up, typename _Ep>
474  inline bool
475  operator<=(const unique_ptr<_Tp, _Dp>& __x,
476  const unique_ptr<_Up, _Ep>& __y)
477  { return !(__y.get() < __x.get()); }
478 
479  template<typename _Tp, typename _Dp,
480  typename _Up, typename _Ep>
481  inline bool
482  operator>(const unique_ptr<_Tp, _Dp>& __x,
483  const unique_ptr<_Up, _Ep>& __y)
484  { return __y.get() < __x.get(); }
485 
486  template<typename _Tp, typename _Dp,
487  typename _Up, typename _Ep>
488  inline bool
489  operator>=(const unique_ptr<_Tp, _Dp>& __x,
490  const unique_ptr<_Up, _Ep>& __y)
491  { return !(__x.get() < __y.get()); }
492 
493  /// std::hash specialization for unique_ptr.
494  template<typename _Tp, typename _Dp>
495  struct hash<unique_ptr<_Tp, _Dp>>
496  : public std::unary_function<unique_ptr<_Tp, _Dp>, size_t>
497  {
498  size_t
499  operator()(const unique_ptr<_Tp, _Dp>& __u) const
500  {
501  typedef unique_ptr<_Tp, _Dp> _UP;
502  return std::hash<typename _UP::pointer>()(__u.get());
503  }
504  };
505 
506  // @} group pointer_abstractions
507 
508 _GLIBCXX_END_NAMESPACE_VERSION
509 } // namespace
510 
511 #endif /* _UNIQUE_PTR_H */