libstdc++
unique_ptr.h
Go to the documentation of this file.
1 // unique_ptr implementation -*- C++ -*-
2 
3 // Copyright (C) 2008-2013 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 #if _GLIBCXX_USE_DEPRECATED
49  template<typename> class auto_ptr;
50 #endif
51 
52  /// Primary template, default_delete.
53  template<typename _Tp>
55  {
56  constexpr default_delete() noexcept = default;
57 
58  template<typename _Up, typename = typename
59  enable_if<is_convertible<_Up*, _Tp*>::value>::type>
60  default_delete(const default_delete<_Up>&) noexcept { }
61 
62  void
63  operator()(_Tp* __ptr) const
64  {
65  static_assert(sizeof(_Tp)>0,
66  "can't delete pointer to incomplete type");
67  delete __ptr;
68  }
69  };
70 
71  // _GLIBCXX_RESOLVE_LIB_DEFECTS
72  // DR 740 - omit specialization for array objects with a compile time length
73  /// Specialization, default_delete.
74  template<typename _Tp>
75  struct default_delete<_Tp[]>
76  {
77  private:
78  template<typename _Up>
79  using __remove_cv = typename remove_cv<_Up>::type;
80 
81  // Like is_base_of<_Tp, _Up> but false if unqualified types are the same
82  template<typename _Up>
83  using __is_derived_Tp
84  = __and_< is_base_of<_Tp, _Up>,
85  __not_<is_same<__remove_cv<_Tp>, __remove_cv<_Up>>> >;
86 
87  public:
88  constexpr default_delete() noexcept = default;
89 
90  template<typename _Up, typename = typename
91  enable_if<!__is_derived_Tp<_Up>::value>::type>
92  default_delete(const default_delete<_Up[]>&) noexcept { }
93 
94  void
95  operator()(_Tp* __ptr) const
96  {
97  static_assert(sizeof(_Tp)>0,
98  "can't delete pointer to incomplete type");
99  delete [] __ptr;
100  }
101 
102  template<typename _Up>
103  typename enable_if<__is_derived_Tp<_Up>::value>::type
104  operator()(_Up*) const = delete;
105  };
106 
107  /// 20.7.1.2 unique_ptr for single objects.
108  template <typename _Tp, typename _Dp = default_delete<_Tp> >
110  {
111  // use SFINAE to determine whether _Del::pointer exists
112  class _Pointer
113  {
114  template<typename _Up>
115  static typename _Up::pointer __test(typename _Up::pointer*);
116 
117  template<typename _Up>
118  static _Tp* __test(...);
119 
120  typedef typename remove_reference<_Dp>::type _Del;
121 
122  public:
123  typedef decltype(__test<_Del>(0)) type;
124  };
125 
126  typedef std::tuple<typename _Pointer::type, _Dp> __tuple_type;
127  __tuple_type _M_t;
128 
129  public:
130  typedef typename _Pointer::type pointer;
131  typedef _Tp element_type;
132  typedef _Dp deleter_type;
133 
134  // Constructors.
135  constexpr unique_ptr() noexcept
136  : _M_t()
137  { static_assert(!is_pointer<deleter_type>::value,
138  "constructed with null function pointer deleter"); }
139 
140  explicit
141  unique_ptr(pointer __p) noexcept
142  : _M_t(__p, deleter_type())
143  { static_assert(!is_pointer<deleter_type>::value,
144  "constructed with null function pointer deleter"); }
145 
146  unique_ptr(pointer __p,
147  typename conditional<is_reference<deleter_type>::value,
148  deleter_type, const deleter_type&>::type __d) noexcept
149  : _M_t(__p, __d) { }
150 
151  unique_ptr(pointer __p,
152  typename remove_reference<deleter_type>::type&& __d) noexcept
153  : _M_t(std::move(__p), std::move(__d))
154  { static_assert(!std::is_reference<deleter_type>::value,
155  "rvalue deleter bound to reference"); }
156 
157  constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { }
158 
159  // Move constructors.
160  unique_ptr(unique_ptr&& __u) noexcept
161  : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
162 
163  template<typename _Up, typename _Ep, typename = _Require<
164  is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>,
165  __not_<is_array<_Up>>,
166  typename conditional<is_reference<_Dp>::value,
167  is_same<_Ep, _Dp>,
168  is_convertible<_Ep, _Dp>>::type>>
169  unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
170  : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
171  { }
172 
173 #if _GLIBCXX_USE_DEPRECATED
174  template<typename _Up, typename = _Require<
175  is_convertible<_Up*, _Tp*>, is_same<_Dp, default_delete<_Tp>>>>
176  unique_ptr(auto_ptr<_Up>&& __u) noexcept;
177 #endif
178 
179  // Destructor.
180  ~unique_ptr() noexcept
181  {
182  auto& __ptr = std::get<0>(_M_t);
183  if (__ptr != nullptr)
184  get_deleter()(__ptr);
185  __ptr = pointer();
186  }
187 
188  // Assignment.
189  unique_ptr&
190  operator=(unique_ptr&& __u) noexcept
191  {
192  reset(__u.release());
193  get_deleter() = std::forward<deleter_type>(__u.get_deleter());
194  return *this;
195  }
196 
197  template<typename _Up, typename _Ep>
198  typename enable_if< __and_<
199  is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>,
200  __not_<is_array<_Up>>
201  >::value,
202  unique_ptr&>::type
203  operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
204  {
205  reset(__u.release());
206  get_deleter() = std::forward<_Ep>(__u.get_deleter());
207  return *this;
208  }
209 
210  unique_ptr&
211  operator=(nullptr_t) noexcept
212  {
213  reset();
214  return *this;
215  }
216 
217  // Observers.
218  typename add_lvalue_reference<element_type>::type
219  operator*() const
220  {
221  _GLIBCXX_DEBUG_ASSERT(get() != pointer());
222  return *get();
223  }
224 
225  pointer
226  operator->() const noexcept
227  {
228  _GLIBCXX_DEBUG_ASSERT(get() != pointer());
229  return get();
230  }
231 
232  pointer
233  get() const noexcept
234  { return std::get<0>(_M_t); }
235 
236  deleter_type&
237  get_deleter() noexcept
238  { return std::get<1>(_M_t); }
239 
240  const deleter_type&
241  get_deleter() const noexcept
242  { return std::get<1>(_M_t); }
243 
244  explicit operator bool() const noexcept
245  { return get() == pointer() ? false : true; }
246 
247  // Modifiers.
248  pointer
249  release() noexcept
250  {
251  pointer __p = get();
252  std::get<0>(_M_t) = pointer();
253  return __p;
254  }
255 
256  void
257  reset(pointer __p = pointer()) noexcept
258  {
259  using std::swap;
260  swap(std::get<0>(_M_t), __p);
261  if (__p != pointer())
262  get_deleter()(__p);
263  }
264 
265  void
266  swap(unique_ptr& __u) noexcept
267  {
268  using std::swap;
269  swap(_M_t, __u._M_t);
270  }
271 
272  // Disable copy from lvalue.
273  unique_ptr(const unique_ptr&) = delete;
274  unique_ptr& operator=(const unique_ptr&) = delete;
275  };
276 
277  /// 20.7.1.3 unique_ptr for array objects with a runtime length
278  // [unique.ptr.runtime]
279  // _GLIBCXX_RESOLVE_LIB_DEFECTS
280  // DR 740 - omit specialization for array objects with a compile time length
281  template<typename _Tp, typename _Dp>
282  class unique_ptr<_Tp[], _Dp>
283  {
284  // use SFINAE to determine whether _Del::pointer exists
285  class _Pointer
286  {
287  template<typename _Up>
288  static typename _Up::pointer __test(typename _Up::pointer*);
289 
290  template<typename _Up>
291  static _Tp* __test(...);
292 
293  typedef typename remove_reference<_Dp>::type _Del;
294 
295  public:
296  typedef decltype(__test<_Del>(0)) type;
297  };
298 
299  typedef std::tuple<typename _Pointer::type, _Dp> __tuple_type;
300  __tuple_type _M_t;
301 
302  template<typename _Up>
303  using __remove_cv = typename remove_cv<_Up>::type;
304 
305  // like is_base_of<_Tp, _Up> but false if unqualified types are the same
306  template<typename _Up>
307  using __is_derived_Tp
308  = __and_< is_base_of<_Tp, _Up>,
309  __not_<is_same<__remove_cv<_Tp>, __remove_cv<_Up>>> >;
310 
311  template<typename _Up, typename _Ep,
312  typename _Tp_pointer = typename _Pointer::type,
313  typename _Up_pointer = typename unique_ptr<_Up, _Ep>::pointer>
314  using __safe_conversion = __and_<
315  is_convertible<_Up_pointer, _Tp_pointer>,
316  is_array<_Up>,
317  __or_<__not_<is_pointer<_Up_pointer>>,
318  __not_<is_pointer<_Tp_pointer>>,
319  __not_<__is_derived_Tp<typename remove_extent<_Up>::type>>
320  >
321  >;
322 
323  public:
324  typedef typename _Pointer::type pointer;
325  typedef _Tp element_type;
326  typedef _Dp deleter_type;
327 
328  // Constructors.
329  constexpr unique_ptr() noexcept
330  : _M_t()
331  { static_assert(!std::is_pointer<deleter_type>::value,
332  "constructed with null function pointer deleter"); }
333 
334  explicit
335  unique_ptr(pointer __p) noexcept
336  : _M_t(__p, deleter_type())
337  { static_assert(!is_pointer<deleter_type>::value,
338  "constructed with null function pointer deleter"); }
339 
340  template<typename _Up, typename = _Require<is_pointer<pointer>,
341  is_convertible<_Up*, pointer>, __is_derived_Tp<_Up>>>
342  explicit
343  unique_ptr(_Up* __p) = delete;
344 
345  unique_ptr(pointer __p,
346  typename conditional<is_reference<deleter_type>::value,
347  deleter_type, const deleter_type&>::type __d) noexcept
348  : _M_t(__p, __d) { }
349 
350  unique_ptr(pointer __p, typename
351  remove_reference<deleter_type>::type&& __d) noexcept
352  : _M_t(std::move(__p), std::move(__d))
353  { static_assert(!is_reference<deleter_type>::value,
354  "rvalue deleter bound to reference"); }
355 
356  // Move constructor.
357  unique_ptr(unique_ptr&& __u) noexcept
358  : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
359 
360  constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { }
361 
362  template<typename _Up, typename _Ep,
363  typename = _Require<__safe_conversion<_Up, _Ep>,
364  typename conditional<is_reference<_Dp>::value,
365  is_same<_Ep, _Dp>,
366  is_convertible<_Ep, _Dp>>::type
367  >>
368  unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
369  : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
370  { }
371 
372  // Destructor.
373  ~unique_ptr()
374  {
375  auto& __ptr = std::get<0>(_M_t);
376  if (__ptr != nullptr)
377  get_deleter()(__ptr);
378  __ptr = pointer();
379  }
380 
381  // Assignment.
382  unique_ptr&
383  operator=(unique_ptr&& __u) noexcept
384  {
385  reset(__u.release());
386  get_deleter() = std::forward<deleter_type>(__u.get_deleter());
387  return *this;
388  }
389 
390  template<typename _Up, typename _Ep>
391  typename
392  enable_if<__safe_conversion<_Up, _Ep>::value, unique_ptr&>::type
393  operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
394  {
395  reset(__u.release());
396  get_deleter() = std::forward<_Ep>(__u.get_deleter());
397  return *this;
398  }
399 
400  unique_ptr&
401  operator=(nullptr_t) noexcept
402  {
403  reset();
404  return *this;
405  }
406 
407  // Observers.
408  typename std::add_lvalue_reference<element_type>::type
409  operator[](size_t __i) const
410  {
411  _GLIBCXX_DEBUG_ASSERT(get() != pointer());
412  return get()[__i];
413  }
414 
415  pointer
416  get() const noexcept
417  { return std::get<0>(_M_t); }
418 
419  deleter_type&
420  get_deleter() noexcept
421  { return std::get<1>(_M_t); }
422 
423  const deleter_type&
424  get_deleter() const noexcept
425  { return std::get<1>(_M_t); }
426 
427  explicit operator bool() const noexcept
428  { return get() == pointer() ? false : true; }
429 
430  // Modifiers.
431  pointer
432  release() noexcept
433  {
434  pointer __p = get();
435  std::get<0>(_M_t) = pointer();
436  return __p;
437  }
438 
439  void
440  reset() noexcept
441  { reset(pointer()); }
442 
443  void
444  reset(pointer __p) noexcept
445  {
446  using std::swap;
447  swap(std::get<0>(_M_t), __p);
448  if (__p != nullptr)
449  get_deleter()(__p);
450  }
451 
452  template<typename _Up, typename = _Require<is_pointer<pointer>,
453  is_convertible<_Up*, pointer>, __is_derived_Tp<_Up>>>
454  void reset(_Up*) = delete;
455 
456  void
457  swap(unique_ptr& __u) noexcept
458  {
459  using std::swap;
460  swap(_M_t, __u._M_t);
461  }
462 
463  // Disable copy from lvalue.
464  unique_ptr(const unique_ptr&) = delete;
465  unique_ptr& operator=(const unique_ptr&) = delete;
466 
467  // Disable construction from convertible pointer types.
468  template<typename _Up, typename = _Require<is_pointer<pointer>,
469  is_convertible<_Up*, pointer>, __is_derived_Tp<_Up>>>
470  unique_ptr(_Up*, typename
471  conditional<is_reference<deleter_type>::value,
472  deleter_type, const deleter_type&>::type) = delete;
473 
474  template<typename _Up, typename = _Require<is_pointer<pointer>,
475  is_convertible<_Up*, pointer>, __is_derived_Tp<_Up>>>
476  unique_ptr(_Up*, typename
477  remove_reference<deleter_type>::type&&) = delete;
478  };
479 
480  template<typename _Tp, typename _Dp>
481  inline void
483  unique_ptr<_Tp, _Dp>& __y) noexcept
484  { __x.swap(__y); }
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  template<typename _Tp, typename _Dp>
494  inline bool
495  operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
496  { return !__x; }
497 
498  template<typename _Tp, typename _Dp>
499  inline bool
500  operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
501  { return !__x; }
502 
503  template<typename _Tp, typename _Dp,
504  typename _Up, typename _Ep>
505  inline bool
506  operator!=(const unique_ptr<_Tp, _Dp>& __x,
507  const unique_ptr<_Up, _Ep>& __y)
508  { return __x.get() != __y.get(); }
509 
510  template<typename _Tp, typename _Dp>
511  inline bool
512  operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
513  { return (bool)__x; }
514 
515  template<typename _Tp, typename _Dp>
516  inline bool
517  operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
518  { return (bool)__x; }
519 
520  template<typename _Tp, typename _Dp,
521  typename _Up, typename _Ep>
522  inline bool
523  operator<(const unique_ptr<_Tp, _Dp>& __x,
524  const unique_ptr<_Up, _Ep>& __y)
525  {
526  typedef typename
527  std::common_type<typename unique_ptr<_Tp, _Dp>::pointer,
528  typename unique_ptr<_Up, _Ep>::pointer>::type _CT;
529  return std::less<_CT>()(__x.get(), __y.get());
530  }
531 
532  template<typename _Tp, typename _Dp>
533  inline bool
534  operator<(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
536  nullptr); }
537 
538  template<typename _Tp, typename _Dp>
539  inline bool
540  operator<(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
542  __x.get()); }
543 
544  template<typename _Tp, typename _Dp,
545  typename _Up, typename _Ep>
546  inline bool
547  operator<=(const unique_ptr<_Tp, _Dp>& __x,
548  const unique_ptr<_Up, _Ep>& __y)
549  { return !(__y < __x); }
550 
551  template<typename _Tp, typename _Dp>
552  inline bool
553  operator<=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
554  { return !(nullptr < __x); }
555 
556  template<typename _Tp, typename _Dp>
557  inline bool
558  operator<=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
559  { return !(__x < nullptr); }
560 
561  template<typename _Tp, typename _Dp,
562  typename _Up, typename _Ep>
563  inline bool
564  operator>(const unique_ptr<_Tp, _Dp>& __x,
565  const unique_ptr<_Up, _Ep>& __y)
566  { return (__y < __x); }
567 
568  template<typename _Tp, typename _Dp>
569  inline bool
570  operator>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
572  __x.get()); }
573 
574  template<typename _Tp, typename _Dp>
575  inline bool
576  operator>(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
578  nullptr); }
579 
580  template<typename _Tp, typename _Dp,
581  typename _Up, typename _Ep>
582  inline bool
583  operator>=(const unique_ptr<_Tp, _Dp>& __x,
584  const unique_ptr<_Up, _Ep>& __y)
585  { return !(__x < __y); }
586 
587  template<typename _Tp, typename _Dp>
588  inline bool
589  operator>=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
590  { return !(__x < nullptr); }
591 
592  template<typename _Tp, typename _Dp>
593  inline bool
594  operator>=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
595  { return !(nullptr < __x); }
596 
597  /// std::hash specialization for unique_ptr.
598  template<typename _Tp, typename _Dp>
599  struct hash<unique_ptr<_Tp, _Dp>>
600  : public __hash_base<size_t, unique_ptr<_Tp, _Dp>>
601  {
602  size_t
603  operator()(const unique_ptr<_Tp, _Dp>& __u) const noexcept
604  {
605  typedef unique_ptr<_Tp, _Dp> _UP;
606  return std::hash<typename _UP::pointer>()(__u.get());
607  }
608  };
609 
610  // @} group pointer_abstractions
611 
612 _GLIBCXX_END_NAMESPACE_VERSION
613 } // namespace
614 
615 #endif /* _UNIQUE_PTR_H */
One of the comparison functors.
Definition: stl_function.h:231
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
Definition: move.h:101
bool operator>=(const basic_string< _CharT, _Traits, _Alloc > &__lhs, const basic_string< _CharT, _Traits, _Alloc > &__rhs)
Test if string doesn't precede string.
ISO C++ entities toplevel namespace is std.
A simple smart pointer providing strict ownership semantics.
Definition: auto_ptr.h:87
void swap(_Tp &, _Tp &) noexcept(__and_< is_nothrow_move_constructible< _Tp >, is_nothrow_move_assignable< _Tp >>::value)
Swaps two values.
Definition: move.h:166
20.7.1.2 unique_ptr for single objects.
Definition: unique_ptr.h:109
Primary class template hash.
Primary template, default_delete.
Definition: unique_ptr.h:54
bool operator>(const basic_string< _CharT, _Traits, _Alloc > &__lhs, const basic_string< _CharT, _Traits, _Alloc > &__rhs)
Test if string follows string.