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() noexcept = default;
53 
54  template<typename _Up, typename = typename
56  default_delete(const default_delete<_Up>&) noexcept { }
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() noexcept = 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() noexcept
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) noexcept
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) noexcept
128  : _M_t(__p, __d) { }
129 
130  unique_ptr(pointer __p,
131  typename std::remove_reference<deleter_type>::type&& __d) noexcept
132  : _M_t(std::move(__p), std::move(__d))
134  "rvalue deleter bound to reference"); }
135 
136  constexpr unique_ptr(nullptr_t) noexcept
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) noexcept
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) noexcept
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) noexcept
165  : _M_t(__u.release(), deleter_type()) { }
166 #endif
167 
168  // Destructor.
169  ~unique_ptr() noexcept
170  {
171  auto& __ptr = std::get<0>(_M_t);
172  if (__ptr != nullptr)
173  get_deleter()(__ptr);
174  __ptr = pointer();
175  }
176 
177  // Assignment.
178  unique_ptr&
179  operator=(unique_ptr&& __u) noexcept
180  {
181  reset(__u.release());
182  get_deleter() = std::forward<deleter_type>(__u.get_deleter());
183  return *this;
184  }
185 
186  template<typename _Up, typename _Ep, typename = typename
189  pointer>::value
190  && !std::is_array<_Up>::value>::type>
191  unique_ptr&
192  operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
193  {
194  reset(__u.release());
195  get_deleter() = std::forward<_Ep>(__u.get_deleter());
196  return *this;
197  }
198 
199  unique_ptr&
200  operator=(nullptr_t) noexcept
201  {
202  reset();
203  return *this;
204  }
205 
206  // Observers.
207  typename std::add_lvalue_reference<element_type>::type
208  operator*() const
209  {
210  _GLIBCXX_DEBUG_ASSERT(get() != pointer());
211  return *get();
212  }
213 
214  pointer
215  operator->() const noexcept
216  {
217  _GLIBCXX_DEBUG_ASSERT(get() != pointer());
218  return get();
219  }
220 
221  pointer
222  get() const noexcept
223  { return std::get<0>(_M_t); }
224 
225  deleter_type&
226  get_deleter() noexcept
227  { return std::get<1>(_M_t); }
228 
229  const deleter_type&
230  get_deleter() const noexcept
231  { return std::get<1>(_M_t); }
232 
233  explicit operator bool() const noexcept
234  { return get() == pointer() ? false : true; }
235 
236  // Modifiers.
237  pointer
238  release() noexcept
239  {
240  pointer __p = get();
241  std::get<0>(_M_t) = pointer();
242  return __p;
243  }
244 
245  void
246  reset(pointer __p = pointer()) noexcept
247  {
248  using std::swap;
249  swap(std::get<0>(_M_t), __p);
250  if (__p != pointer())
251  get_deleter()(__p);
252  }
253 
254  void
255  swap(unique_ptr& __u) noexcept
256  {
257  using std::swap;
258  swap(_M_t, __u._M_t);
259  }
260 
261  // Disable copy from lvalue.
262  unique_ptr(const unique_ptr&) = delete;
263  unique_ptr& operator=(const unique_ptr&) = delete;
264  };
265 
266  /// 20.7.12.3 unique_ptr for array objects with a runtime length
267  // [unique.ptr.runtime]
268  // _GLIBCXX_RESOLVE_LIB_DEFECTS
269  // DR 740 - omit specialization for array objects with a compile time length
270  template<typename _Tp, typename _Dp>
271  class unique_ptr<_Tp[], _Dp>
272  {
274  __tuple_type _M_t;
275 
276  public:
277  typedef _Tp* pointer;
278  typedef _Tp element_type;
279  typedef _Dp deleter_type;
280 
281  // Constructors.
282  constexpr unique_ptr() noexcept
283  : _M_t()
284  { static_assert(!std::is_pointer<deleter_type>::value,
285  "constructed with null function pointer deleter"); }
286 
287  explicit
288  unique_ptr(pointer __p) noexcept
289  : _M_t(__p, deleter_type())
290  { static_assert(!std::is_pointer<deleter_type>::value,
291  "constructed with null function pointer deleter"); }
292 
293  unique_ptr(pointer __p,
295  deleter_type, const deleter_type&>::type __d) noexcept
296  : _M_t(__p, __d) { }
297 
298  unique_ptr(pointer __p, typename
299  std::remove_reference<deleter_type>::type && __d) noexcept
300  : _M_t(std::move(__p), std::move(__d))
302  "rvalue deleter bound to reference"); }
303 
304  constexpr unique_ptr(nullptr_t) noexcept
305  : _M_t()
306  { static_assert(!std::is_pointer<deleter_type>::value,
307  "constructed with null function pointer deleter"); }
308 
309  // Move constructors.
310  unique_ptr(unique_ptr&& __u) noexcept
311  : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
312 
313  template<typename _Up, typename _Ep>
314  unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
315  : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
316  { }
317 
318  // Destructor.
319  ~unique_ptr()
320  {
321  auto& __ptr = std::get<0>(_M_t);
322  if (__ptr != nullptr)
323  get_deleter()(__ptr);
324  __ptr = pointer();
325  }
326 
327  // Assignment.
328  unique_ptr&
329  operator=(unique_ptr&& __u) noexcept
330  {
331  reset(__u.release());
332  get_deleter() = std::forward<deleter_type>(__u.get_deleter());
333  return *this;
334  }
335 
336  template<typename _Up, typename _Ep>
337  unique_ptr&
338  operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
339  {
340  reset(__u.release());
341  get_deleter() = std::forward<_Ep>(__u.get_deleter());
342  return *this;
343  }
344 
345  unique_ptr&
346  operator=(nullptr_t) noexcept
347  {
348  reset();
349  return *this;
350  }
351 
352  // Observers.
353  typename std::add_lvalue_reference<element_type>::type
354  operator[](size_t __i) const
355  {
356  _GLIBCXX_DEBUG_ASSERT(get() != pointer());
357  return get()[__i];
358  }
359 
360  pointer
361  get() const noexcept
362  { return std::get<0>(_M_t); }
363 
364  deleter_type&
365  get_deleter() noexcept
366  { return std::get<1>(_M_t); }
367 
368  const deleter_type&
369  get_deleter() const noexcept
370  { return std::get<1>(_M_t); }
371 
372  explicit operator bool() const noexcept
373  { return get() == pointer() ? false : true; }
374 
375  // Modifiers.
376  pointer
377  release() noexcept
378  {
379  pointer __p = get();
380  std::get<0>(_M_t) = pointer();
381  return __p;
382  }
383 
384  void
385  reset(pointer __p = pointer()) noexcept
386  {
387  using std::swap;
388  swap(std::get<0>(_M_t), __p);
389  if (__p != nullptr)
390  get_deleter()(__p);
391  }
392 
393  void
394  reset(nullptr_t) noexcept
395  {
396  pointer __p = get();
397  std::get<0>(_M_t) = pointer();
398  if (__p != nullptr)
399  get_deleter()(__p);
400  }
401 
402  // DR 821.
403  template<typename _Up>
404  void reset(_Up) = delete;
405 
406  void
407  swap(unique_ptr& __u) noexcept
408  {
409  using std::swap;
410  swap(_M_t, __u._M_t);
411  }
412 
413  // Disable copy from lvalue.
414  unique_ptr(const unique_ptr&) = delete;
415  unique_ptr& operator=(const unique_ptr&) = delete;
416 
417  // Disable construction from convertible pointer types.
418  // (N2315 - 20.6.5.3.1)
419  template<typename _Up>
420  unique_ptr(_Up*, typename
422  deleter_type, const deleter_type&>::type,
423  typename std::enable_if<std::is_convertible<_Up*,
424  pointer>::value>::type* = 0) = delete;
425 
426  template<typename _Up>
427  unique_ptr(_Up*, typename std::remove_reference<deleter_type>::type&&,
428  typename std::enable_if<std::is_convertible<_Up*,
429  pointer>::value>::type* = 0) = delete;
430 
431  template<typename _Up>
432  explicit
433  unique_ptr(_Up*, typename std::enable_if<std::is_convertible<_Up*,
434  pointer>::value>::type* = 0) = delete;
435  };
436 
437  template<typename _Tp, typename _Dp>
438  inline void
439  swap(unique_ptr<_Tp, _Dp>& __x,
440  unique_ptr<_Tp, _Dp>& __y) noexcept
441  { __x.swap(__y); }
442 
443  template<typename _Tp, typename _Dp,
444  typename _Up, typename _Ep>
445  inline bool
446  operator==(const unique_ptr<_Tp, _Dp>& __x,
447  const unique_ptr<_Up, _Ep>& __y)
448  { return __x.get() == __y.get(); }
449 
450  template<typename _Tp, typename _Dp>
451  inline bool
452  operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
453  { return !__x; }
454 
455  template<typename _Tp, typename _Dp>
456  inline bool
457  operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
458  { return !__x; }
459 
460  template<typename _Tp, typename _Dp,
461  typename _Up, typename _Ep>
462  inline bool
463  operator!=(const unique_ptr<_Tp, _Dp>& __x,
464  const unique_ptr<_Up, _Ep>& __y)
465  { return __x.get() != __y.get(); }
466 
467  template<typename _Tp, typename _Dp>
468  inline bool
469  operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
470  { return (bool)__x; }
471 
472  template<typename _Tp, typename _Dp>
473  inline bool
474  operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
475  { return (bool)__x; }
476 
477  template<typename _Tp, typename _Dp,
478  typename _Up, typename _Ep>
479  inline bool
480  operator<(const unique_ptr<_Tp, _Dp>& __x,
481  const unique_ptr<_Up, _Ep>& __y)
482  {
483  typedef typename
484  std::common_type<typename unique_ptr<_Tp, _Dp>::pointer,
485  typename unique_ptr<_Up, _Ep>::pointer>::type _CT;
486  return std::less<_CT>()(__x.get(), __y.get());
487  }
488 
489  template<typename _Tp, typename _Dp>
490  inline bool
491  operator<(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
493  nullptr); }
494 
495  template<typename _Tp, typename _Dp>
496  inline bool
497  operator<(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
499  __x.get()); }
500 
501  template<typename _Tp, typename _Dp,
502  typename _Up, typename _Ep>
503  inline bool
504  operator<=(const unique_ptr<_Tp, _Dp>& __x,
505  const unique_ptr<_Up, _Ep>& __y)
506  { return !(__y < __x); }
507 
508  template<typename _Tp, typename _Dp>
509  inline bool
510  operator<=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
511  { return !(nullptr < __x); }
512 
513  template<typename _Tp, typename _Dp>
514  inline bool
515  operator<=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
516  { return !(__x < nullptr); }
517 
518  template<typename _Tp, typename _Dp,
519  typename _Up, typename _Ep>
520  inline bool
521  operator>(const unique_ptr<_Tp, _Dp>& __x,
522  const unique_ptr<_Up, _Ep>& __y)
523  { return (__y < __x); }
524 
525  template<typename _Tp, typename _Dp>
526  inline bool
527  operator>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
529  __x.get()); }
530 
531  template<typename _Tp, typename _Dp>
532  inline bool
533  operator>(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
535  nullptr); }
536 
537  template<typename _Tp, typename _Dp,
538  typename _Up, typename _Ep>
539  inline bool
540  operator>=(const unique_ptr<_Tp, _Dp>& __x,
541  const unique_ptr<_Up, _Ep>& __y)
542  { return !(__x < __y); }
543 
544  template<typename _Tp, typename _Dp>
545  inline bool
546  operator>=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
547  { return !(__x < nullptr); }
548 
549  template<typename _Tp, typename _Dp>
550  inline bool
551  operator>=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
552  { return !(nullptr < __x); }
553 
554  /// std::hash specialization for unique_ptr.
555  template<typename _Tp, typename _Dp>
556  struct hash<unique_ptr<_Tp, _Dp>>
557  : public __hash_base<size_t, unique_ptr<_Tp, _Dp>>
558  {
559  size_t
560  operator()(const unique_ptr<_Tp, _Dp>& __u) const noexcept
561  {
562  typedef unique_ptr<_Tp, _Dp> _UP;
563  return std::hash<typename _UP::pointer>()(__u.get());
564  }
565  };
566 
567  // @} group pointer_abstractions
568 
569 _GLIBCXX_END_NAMESPACE_VERSION
570 } // namespace
571 
572 #endif /* _UNIQUE_PTR_H */