unique_ptr.h

Go to the documentation of this file.
00001 // unique_ptr implementation -*- C++ -*-
00002 
00003 // Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
00004 //
00005 // This file is part of the GNU ISO C++ Library.  This library is free
00006 // software; you can redistribute it and/or modify it under the
00007 // terms of the GNU General Public License as published by the
00008 // Free Software Foundation; either version 3, or (at your option)
00009 // any later version.
00010 
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 
00016 // Under Section 7 of GPL version 3, you are granted additional
00017 // permissions described in the GCC Runtime Library Exception, version
00018 // 3.1, as published by the Free Software Foundation.
00019 
00020 // You should have received a copy of the GNU General Public License and
00021 // a copy of the GCC Runtime Library Exception along with this program;
00022 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
00023 // <http://www.gnu.org/licenses/>.
00024 
00025 /** @file unique_ptr.h
00026  *  This is an internal header file, included by other library headers.
00027  *  You should not attempt to use it directly.
00028  */
00029 
00030 #ifndef _UNIQUE_PTR_H
00031 #define _UNIQUE_PTR_H 1
00032 
00033 #include <bits/c++config.h>
00034 #include <debug/debug.h>
00035 #include <type_traits>
00036 #include <utility>
00037 #include <tuple>
00038 
00039 _GLIBCXX_BEGIN_NAMESPACE(std)
00040 
00041   /**
00042    * @addtogroup pointer_abstractions
00043    * @{
00044    */
00045 
00046   /// Primary template, default_delete.
00047   template<typename _Tp> 
00048     struct default_delete
00049       {
00050     default_delete() { }
00051 
00052     template<typename _Up>
00053       default_delete(const default_delete<_Up>&) { }
00054 
00055     void
00056     operator()(_Tp* __ptr) const
00057     {
00058       static_assert(sizeof(_Tp)>0,
00059             "can't delete pointer to incomplete type");
00060       delete __ptr;
00061     }
00062     };
00063 
00064   // _GLIBCXX_RESOLVE_LIB_DEFECTS
00065   // DR 740 - omit specialization for array objects with a compile time length
00066   /// Specialization, default_delete.
00067   template<typename _Tp> 
00068     struct default_delete<_Tp[]>
00069     {
00070       void
00071       operator()(_Tp* __ptr) const
00072       {
00073     static_assert(sizeof(_Tp)>0,
00074               "can't delete pointer to incomplete type");
00075     delete [] __ptr;
00076       }
00077     };
00078 
00079   /// 20.7.12.2 unique_ptr for single objects.
00080   template <typename _Tp, typename _Tp_Deleter = default_delete<_Tp> > 
00081     class unique_ptr
00082     {
00083       typedef std::tuple<_Tp*, _Tp_Deleter>  __tuple_type;
00084 
00085       // use SFINAE to determine whether _Del::pointer exists
00086       class _Pointer
00087       {
00088     template<typename _Up>
00089       static typename _Up::pointer __test(typename _Up::pointer*);
00090 
00091     template<typename _Up>
00092       static _Tp* __test(...);
00093 
00094     typedef typename remove_reference<_Tp_Deleter>::type _Del;
00095 
00096       public:
00097     typedef decltype( __test<_Del>(0) ) type;
00098       };
00099 
00100     public:
00101       typedef typename _Pointer::type   pointer;
00102       typedef _Tp                       element_type;
00103       typedef _Tp_Deleter               deleter_type;
00104 
00105       // Constructors.
00106       unique_ptr()
00107       : _M_t(pointer(), deleter_type())
00108       { static_assert(!std::is_pointer<deleter_type>::value,
00109               "constructed with null function pointer deleter"); }
00110 
00111       explicit
00112       unique_ptr(pointer __p)
00113       : _M_t(__p, deleter_type())
00114       { static_assert(!std::is_pointer<deleter_type>::value,
00115              "constructed with null function pointer deleter"); }
00116 
00117       unique_ptr(pointer __p,
00118           typename std::conditional<std::is_reference<deleter_type>::value, 
00119             deleter_type, const deleter_type&>::type __d)
00120       : _M_t(__p, __d) { }
00121 
00122       unique_ptr(pointer __p,
00123           typename std::remove_reference<deleter_type>::type&& __d)
00124       : _M_t(std::move(__p), std::move(__d))
00125       { static_assert(!std::is_reference<deleter_type>::value, 
00126               "rvalue deleter bound to reference"); }
00127 
00128       unique_ptr(nullptr_t)
00129       : _M_t(pointer(), deleter_type())
00130       { }
00131 
00132       // Move constructors.
00133       unique_ptr(unique_ptr&& __u) 
00134       : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
00135 
00136       template<typename _Up, typename _Up_Deleter> 
00137         unique_ptr(unique_ptr<_Up, _Up_Deleter>&& __u) 
00138         : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter()))
00139     { }
00140 
00141       // Destructor.
00142       ~unique_ptr() { reset(); }
00143     
00144       // Assignment.
00145       unique_ptr&
00146       operator=(unique_ptr&& __u)
00147       { 
00148         reset(__u.release()); 
00149         get_deleter() = std::move(__u.get_deleter()); 
00150         return *this;
00151       }
00152 
00153       template<typename _Up, typename _Up_Deleter> 
00154         unique_ptr&
00155         operator=(unique_ptr<_Up, _Up_Deleter>&& __u)
00156     {
00157           reset(__u.release()); 
00158           get_deleter() = std::move(__u.get_deleter()); 
00159           return *this;
00160         }
00161 
00162       unique_ptr&
00163       operator=(nullptr_t)
00164       {
00165     reset();
00166     return *this;
00167       }
00168 
00169       // Observers.
00170       typename std::add_lvalue_reference<element_type>::type
00171       operator*() const
00172       {
00173     _GLIBCXX_DEBUG_ASSERT(get() != pointer());
00174     return *get();
00175       }
00176 
00177       pointer
00178       operator->() const
00179       {
00180     _GLIBCXX_DEBUG_ASSERT(get() != pointer());
00181     return get();
00182       }
00183 
00184       pointer
00185       get() const
00186       { return std::get<0>(_M_t); }
00187 
00188       deleter_type&
00189       get_deleter()
00190       { return std::get<1>(_M_t); }
00191 
00192       const deleter_type&
00193       get_deleter() const
00194       { return std::get<1>(_M_t); }
00195 
00196       explicit operator bool() const
00197       { return get() == pointer() ? false : true; }
00198 
00199       // Modifiers.
00200       pointer
00201       release() 
00202       {
00203     pointer __p = get();
00204     std::get<0>(_M_t) = pointer();
00205     return __p;
00206       }
00207 
00208       void
00209       reset(pointer __p = pointer())
00210       {
00211     using std::swap;
00212     swap(std::get<0>(_M_t), __p);
00213     if (__p != pointer())
00214       get_deleter()(__p);
00215       }
00216 
00217       void
00218       swap(unique_ptr& __u)
00219       {
00220     using std::swap;
00221     swap(_M_t, __u._M_t);
00222       }
00223 
00224       // Disable copy from lvalue.
00225       unique_ptr(const unique_ptr&) = delete;
00226       unique_ptr& operator=(const unique_ptr&) = delete;
00227 
00228     private:
00229       __tuple_type _M_t;
00230   };
00231  
00232   /// 20.7.12.3 unique_ptr for array objects with a runtime length
00233   // [unique.ptr.runtime]
00234   // _GLIBCXX_RESOLVE_LIB_DEFECTS
00235   // DR 740 - omit specialization for array objects with a compile time length
00236   template<typename _Tp, typename _Tp_Deleter>
00237     class unique_ptr<_Tp[], _Tp_Deleter>
00238     {
00239       typedef std::tuple<_Tp*, _Tp_Deleter>  __tuple_type;
00240 
00241     public:
00242       typedef _Tp*               pointer;
00243       typedef _Tp                element_type;      
00244       typedef _Tp_Deleter        deleter_type;
00245 
00246       // Constructors.
00247       unique_ptr()
00248       : _M_t(pointer(), deleter_type())
00249       { static_assert(!std::is_pointer<deleter_type>::value,
00250               "constructed with null function pointer deleter"); }
00251 
00252       explicit
00253       unique_ptr(pointer __p)
00254       : _M_t(__p, deleter_type())
00255       { static_assert(!std::is_pointer<deleter_type>::value,
00256               "constructed with null function pointer deleter"); }
00257 
00258       unique_ptr(pointer __p,
00259           typename std::conditional<std::is_reference<deleter_type>::value, 
00260               deleter_type, const deleter_type&>::type __d) 
00261       : _M_t(__p, __d) { }
00262 
00263       unique_ptr(pointer __p,
00264          typename std::remove_reference<deleter_type>::type && __d)
00265       : _M_t(std::move(__p), std::move(__d))
00266       { static_assert(!std::is_reference<deleter_type>::value, 
00267               "rvalue deleter bound to reference"); }
00268 
00269       /* TODO: use delegating constructor */
00270       unique_ptr(nullptr_t)
00271       : _M_t(pointer(), deleter_type())
00272       { }
00273 
00274       // Move constructors.
00275       unique_ptr(unique_ptr&& __u) 
00276       : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
00277 
00278       template<typename _Up, typename _Up_Deleter> 
00279         unique_ptr(unique_ptr<_Up, _Up_Deleter>&& __u) 
00280     : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter()))
00281     { }
00282 
00283       // Destructor.
00284       ~unique_ptr() { reset(); }
00285 
00286       // Assignment.
00287       unique_ptr&
00288       operator=(unique_ptr&& __u)
00289       {
00290     reset(__u.release());
00291     get_deleter() = std::move(__u.get_deleter()); 
00292     return *this; 
00293       }
00294 
00295       template<typename _Up, typename _Up_Deleter> 
00296         unique_ptr&
00297         operator=(unique_ptr<_Up, _Up_Deleter>&& __u)
00298     {
00299           reset(__u.release());
00300           get_deleter() = std::move(__u.get_deleter()); 
00301           return *this;
00302         }
00303 
00304       unique_ptr&
00305       operator=(nullptr_t)
00306       {
00307     reset();
00308     return *this;
00309       }
00310 
00311       // Observers.
00312       typename std::add_lvalue_reference<element_type>::type 
00313       operator[](size_t __i) const 
00314       {
00315     _GLIBCXX_DEBUG_ASSERT(get() != pointer());
00316     return get()[__i];
00317       }
00318 
00319       pointer
00320       get() const
00321       { return std::get<0>(_M_t); }
00322 
00323       deleter_type& 
00324       get_deleter()
00325       { return std::get<1>(_M_t); }
00326 
00327       const deleter_type&
00328       get_deleter() const
00329       { return std::get<1>(_M_t); }    
00330 
00331       explicit operator bool() const 
00332       { return get() == pointer() ? false : true; }
00333     
00334       // Modifiers.
00335       pointer
00336       release() 
00337       {
00338     pointer __p = get();
00339     std::get<0>(_M_t) = pointer();
00340     return __p;
00341       }
00342 
00343       void
00344       reset(pointer __p = pointer()) 
00345       {
00346     using std::swap;
00347     swap(std::get<0>(_M_t), __p);
00348     if (__p != nullptr)
00349       get_deleter()(__p);
00350       }
00351 
00352       void
00353       reset(nullptr_t)
00354       {
00355     pointer __p = get();
00356     std::get<0>(_M_t) = pointer();
00357     if (__p != nullptr)
00358       get_deleter()(__p);
00359       }
00360 
00361       // DR 821.
00362       template<typename _Up>
00363         void reset(_Up) = delete;
00364 
00365       void
00366       swap(unique_ptr& __u)
00367       {
00368     using std::swap;
00369     swap(_M_t, __u._M_t);
00370       }
00371 
00372       // Disable copy from lvalue.
00373       unique_ptr(const unique_ptr&) = delete;
00374       unique_ptr& operator=(const unique_ptr&) = delete;
00375 
00376       // Disable construction from convertible pointer types.
00377       // (N2315 - 20.6.5.3.1)
00378       template<typename _Up>
00379         unique_ptr(_Up*, typename
00380            std::conditional<std::is_reference<deleter_type>::value,
00381            deleter_type, const deleter_type&>::type,
00382            typename std::enable_if<std::is_convertible<_Up*, 
00383            pointer>::value>::type* = 0) = delete;
00384 
00385       template<typename _Up>
00386         unique_ptr(_Up*, typename std::remove_reference<deleter_type>::type&&,
00387            typename std::enable_if<std::is_convertible<_Up*, 
00388            pointer>::value>::type* = 0) = delete;
00389 
00390       template<typename _Up>
00391         explicit
00392         unique_ptr(_Up*, typename std::enable_if<std::is_convertible<_Up*, 
00393            pointer>::value>::type* = 0) = delete;
00394 
00395     private:
00396       __tuple_type _M_t;
00397   };
00398   
00399   template<typename _Tp, typename _Tp_Deleter> 
00400     inline void
00401     swap(unique_ptr<_Tp, _Tp_Deleter>& __x,
00402      unique_ptr<_Tp, _Tp_Deleter>& __y)
00403     { __x.swap(__y); }
00404 
00405   template<typename _Tp, typename _Tp_Deleter,
00406        typename _Up, typename _Up_Deleter>
00407     inline bool
00408     operator==(const unique_ptr<_Tp, _Tp_Deleter>& __x,
00409            const unique_ptr<_Up, _Up_Deleter>& __y)
00410     { return __x.get() == __y.get(); }
00411 
00412   template<typename _Tp, typename _Tp_Deleter,
00413        typename _Up, typename _Up_Deleter>
00414     inline bool
00415     operator!=(const unique_ptr<_Tp, _Tp_Deleter>& __x,
00416            const unique_ptr<_Up, _Up_Deleter>& __y)
00417     { return !(__x.get() == __y.get()); }
00418 
00419   template<typename _Tp, typename _Tp_Deleter,
00420        typename _Up, typename _Up_Deleter>
00421     inline bool
00422     operator<(const unique_ptr<_Tp, _Tp_Deleter>& __x,
00423           const unique_ptr<_Up, _Up_Deleter>& __y)
00424     { return __x.get() < __y.get(); }
00425 
00426   template<typename _Tp, typename _Tp_Deleter,
00427        typename _Up, typename _Up_Deleter>
00428     inline bool
00429     operator<=(const unique_ptr<_Tp, _Tp_Deleter>& __x,
00430            const unique_ptr<_Up, _Up_Deleter>& __y)
00431     { return !(__y.get() < __x.get()); }
00432 
00433   template<typename _Tp, typename _Tp_Deleter,
00434        typename _Up, typename _Up_Deleter>
00435     inline bool
00436     operator>(const unique_ptr<_Tp, _Tp_Deleter>& __x,
00437           const unique_ptr<_Up, _Up_Deleter>& __y)
00438     { return __y.get() < __x.get(); }
00439 
00440   template<typename _Tp, typename _Tp_Deleter,
00441        typename _Up, typename _Up_Deleter>
00442     inline bool
00443     operator>=(const unique_ptr<_Tp, _Tp_Deleter>& __x,
00444            const unique_ptr<_Up, _Up_Deleter>& __y)
00445     { return !(__x.get() < __y.get()); }
00446 
00447   /// std::hash specialization for unique_ptr.
00448   template<typename _Tp, typename _Tp_Deleter>
00449     struct hash<unique_ptr<_Tp, _Tp_Deleter>>
00450     : public std::unary_function<unique_ptr<_Tp, _Tp_Deleter>, size_t>
00451     {
00452       size_t
00453       operator()(const unique_ptr<_Tp, _Tp_Deleter>& __u) const
00454       {
00455     typedef unique_ptr<_Tp, _Tp_Deleter> _UP;
00456     return std::hash<typename _UP::pointer>()(__u.get());
00457       }
00458     };
00459 
00460   // @} group pointer_abstractions
00461 
00462 _GLIBCXX_END_NAMESPACE
00463 
00464 #endif /* _UNIQUE_PTR_H */