unique_ptr.h

Go to the documentation of this file.
00001 // unique_ptr implementation -*- C++ -*-
00002 
00003 // Copyright (C) 2008, 2009 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 #ifndef __GXX_EXPERIMENTAL_CXX0X__
00034 # include <c++0x_warning.h>
00035 #endif
00036 
00037 #include <bits/c++config.h>
00038 #include <debug/debug.h>
00039 #include <type_traits>
00040 #include <utility>
00041 #include <tuple>
00042 
00043 _GLIBCXX_BEGIN_NAMESPACE(std)
00044 
00045   /**
00046    * @addtogroup pointer_abstractions
00047    * @{
00048    */
00049 
00050   /// Primary template, default_delete.
00051   template<typename _Tp> 
00052     struct default_delete
00053       {
00054     default_delete() { }
00055 
00056     template<typename _Up>
00057       default_delete(const default_delete<_Up>&) { }
00058 
00059     void
00060     operator()(_Tp* __ptr) const
00061     {
00062       static_assert(sizeof(_Tp)>0,
00063             "can't delete pointer to incomplete type");
00064       delete __ptr;
00065     }
00066     };
00067 
00068   // _GLIBCXX_RESOLVE_LIB_DEFECTS
00069   // DR 740 - omit specialization for array objects with a compile time length
00070   /// Specialization, default_delete.
00071   template<typename _Tp> 
00072     struct default_delete<_Tp[]>
00073     {
00074       void
00075       operator()(_Tp* __ptr) const
00076       {
00077     static_assert(sizeof(_Tp)>0,
00078               "can't delete pointer to incomplete type");
00079     delete [] __ptr;
00080       }
00081     };
00082 
00083   /// 20.7.12.2 unique_ptr for single objects.
00084   template <typename _Tp, typename _Tp_Deleter = default_delete<_Tp> > 
00085     class unique_ptr
00086     {
00087       typedef std::tuple<_Tp*, _Tp_Deleter>  __tuple_type;
00088       typedef __tuple_type unique_ptr::*     __unspecified_bool_type;
00089       typedef _Tp* unique_ptr::*             __unspecified_pointer_type;
00090 
00091     public:
00092       typedef _Tp*               pointer;
00093       typedef _Tp                element_type;      
00094       typedef _Tp_Deleter        deleter_type;
00095 
00096       // Constructors.
00097       unique_ptr()
00098       : _M_t(pointer(), deleter_type())
00099       { static_assert(!std::is_pointer<deleter_type>::value,
00100               "constructed with null function pointer deleter"); }
00101 
00102       explicit
00103       unique_ptr(pointer __p)
00104       : _M_t(__p, deleter_type())
00105       { static_assert(!std::is_pointer<deleter_type>::value,
00106              "constructed with null function pointer deleter"); }
00107 
00108       unique_ptr(pointer __p,
00109           typename std::conditional<std::is_reference<deleter_type>::value, 
00110             deleter_type, const deleter_type&>::type __d)
00111       : _M_t(__p, __d) { }
00112 
00113       unique_ptr(pointer __p,
00114           typename std::remove_reference<deleter_type>::type&& __d)
00115       : _M_t(std::move(__p), std::move(__d))
00116       { static_assert(!std::is_reference<deleter_type>::value, 
00117               "rvalue deleter bound to reference"); }
00118 
00119       // Move constructors.
00120       unique_ptr(unique_ptr&& __u) 
00121       : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
00122 
00123       template<typename _Up, typename _Up_Deleter> 
00124         unique_ptr(unique_ptr<_Up, _Up_Deleter>&& __u) 
00125         : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter()))
00126     { }
00127 
00128       // Destructor.
00129       ~unique_ptr() { reset(); }
00130     
00131       // Assignment.
00132       unique_ptr&
00133       operator=(unique_ptr&& __u)
00134       { 
00135         reset(__u.release()); 
00136         get_deleter() = std::move(__u.get_deleter()); 
00137         return *this;
00138       }
00139 
00140       template<typename _Up, typename _Up_Deleter> 
00141         unique_ptr&
00142         operator=(unique_ptr<_Up, _Up_Deleter>&& __u)
00143     {
00144           reset(__u.release()); 
00145           get_deleter() = std::move(__u.get_deleter()); 
00146           return *this;
00147         }
00148 
00149       unique_ptr&
00150       operator=(__unspecified_pointer_type) 
00151       {
00152     reset();
00153     return *this;
00154       }
00155 
00156       // Observers.
00157       typename std::add_lvalue_reference<element_type>::type operator*() const
00158       {
00159     _GLIBCXX_DEBUG_ASSERT(get() != 0);
00160     return *get();
00161       }
00162 
00163       pointer
00164       operator->() const
00165       {
00166     _GLIBCXX_DEBUG_ASSERT(get() != 0);
00167     return get();
00168       }
00169 
00170       pointer
00171       get() const
00172       { return std::get<0>(_M_t); }
00173 
00174       typename std::add_lvalue_reference<deleter_type>::type
00175       get_deleter()
00176       { return std::get<1>(_M_t); }
00177 
00178       typename std::add_lvalue_reference<
00179           typename std::add_const<deleter_type>::type
00180               >::type
00181       get_deleter() const
00182       { return std::get<1>(_M_t); }
00183 
00184       operator __unspecified_bool_type () const
00185       { return get() == 0 ? 0 : &unique_ptr::_M_t; }
00186 
00187       // Modifiers.
00188       pointer
00189       release() 
00190       {
00191     pointer __p = get();
00192     std::get<0>(_M_t) = 0;
00193     return __p;
00194       }
00195 
00196       void
00197       reset(pointer __p = pointer())
00198       {
00199     if (__p != get())
00200       {
00201         get_deleter()(get());
00202         std::get<0>(_M_t) = __p;
00203       }
00204       }
00205 
00206       void
00207       swap(unique_ptr&& __u)
00208       {
00209     using std::swap;
00210     swap(_M_t, __u._M_t);
00211       }
00212 
00213       // Disable copy from lvalue.
00214       unique_ptr(const unique_ptr&) = delete;
00215 
00216       template<typename _Up, typename _Up_Deleter> 
00217         unique_ptr(const unique_ptr<_Up, _Up_Deleter>&) = delete;
00218 
00219       unique_ptr& operator=(const unique_ptr&) = delete;
00220 
00221       template<typename _Up, typename _Up_Deleter> 
00222         unique_ptr& operator=(const unique_ptr<_Up, _Up_Deleter>&) = delete;
00223 
00224     private:
00225       __tuple_type _M_t;
00226   };
00227  
00228   /// 20.7.12.3 unique_ptr for array objects with a runtime length
00229   // [unique.ptr.runtime]
00230   // _GLIBCXX_RESOLVE_LIB_DEFECTS
00231   // DR 740 - omit specialization for array objects with a compile time length
00232   template<typename _Tp, typename _Tp_Deleter> 
00233     class unique_ptr<_Tp[], _Tp_Deleter>
00234     {
00235       typedef std::tuple<_Tp*, _Tp_Deleter>  __tuple_type;
00236       typedef __tuple_type unique_ptr::*     __unspecified_bool_type;
00237       typedef _Tp* unique_ptr::*             __unspecified_pointer_type;
00238 
00239     public:
00240       typedef _Tp*               pointer;
00241       typedef _Tp                element_type;      
00242       typedef _Tp_Deleter        deleter_type;
00243 
00244       // Constructors.
00245       unique_ptr()
00246       : _M_t(pointer(), deleter_type())
00247       { static_assert(!std::is_pointer<deleter_type>::value,
00248               "constructed with null function pointer deleter"); }
00249 
00250       explicit
00251       unique_ptr(pointer __p)
00252       : _M_t(__p, deleter_type())
00253       { static_assert(!std::is_pointer<deleter_type>::value,
00254               "constructed with null function pointer deleter"); }
00255 
00256       unique_ptr(pointer __p,
00257           typename std::conditional<std::is_reference<deleter_type>::value, 
00258               deleter_type, const deleter_type&>::type __d) 
00259       : _M_t(__p, __d) { }
00260 
00261       unique_ptr(pointer __p,
00262          typename std::remove_reference<deleter_type>::type && __d)
00263       : _M_t(std::move(__p), std::move(__d))
00264       { static_assert(!std::is_reference<deleter_type>::value, 
00265               "rvalue deleter bound to reference"); }
00266 
00267       // Move constructors.
00268       unique_ptr(unique_ptr&& __u) 
00269       : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
00270 
00271       template<typename _Up, typename _Up_Deleter> 
00272         unique_ptr(unique_ptr<_Up, _Up_Deleter>&& __u) 
00273     : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter()))
00274     { }
00275 
00276       // Destructor.
00277       ~unique_ptr() { reset(); }
00278 
00279       // Assignment.
00280       unique_ptr&
00281       operator=(unique_ptr&& __u)
00282       {
00283     reset(__u.release());
00284     get_deleter() = std::move(__u.get_deleter()); 
00285     return *this; 
00286       }
00287 
00288       template<typename _Up, typename _Up_Deleter> 
00289         unique_ptr&
00290         operator=(unique_ptr<_Up, _Up_Deleter>&& __u)
00291     {
00292           reset(__u.release());
00293           get_deleter() = std::move(__u.get_deleter()); 
00294           return *this;
00295         }
00296 
00297       unique_ptr&
00298       operator=(__unspecified_pointer_type)
00299       {
00300     reset();
00301     return *this;
00302       }
00303 
00304       // Observers.
00305       typename std::add_lvalue_reference<element_type>::type 
00306       operator[](size_t __i) const 
00307       {
00308     _GLIBCXX_DEBUG_ASSERT(get() != 0);
00309     return get()[__i];
00310       }
00311 
00312       pointer
00313       get() const
00314       { return std::get<0>(_M_t); }
00315 
00316       typename std::add_lvalue_reference<deleter_type>::type 
00317       get_deleter()
00318       { return std::get<1>(_M_t); }
00319 
00320       typename std::add_lvalue_reference<
00321           typename std::add_const<deleter_type>::type
00322               >::type 
00323       get_deleter() const
00324       { return std::get<1>(_M_t); }    
00325 
00326       operator __unspecified_bool_type () const 
00327       { return get() == 0 ? 0 : &unique_ptr::_M_t; }
00328     
00329       // Modifiers.
00330       pointer
00331       release() 
00332       {
00333     pointer __p = get();
00334     std::get<0>(_M_t) = 0;
00335     return __p;
00336       }
00337 
00338       void
00339       reset(pointer __p = pointer()) 
00340       {
00341     if (__p != get())
00342     {
00343       get_deleter()(get());
00344       std::get<0>(_M_t) = __p;
00345     }
00346       }
00347 
00348       // DR 821.
00349       template<typename _Up>
00350         void reset(_Up) = delete;
00351 
00352       void
00353       swap(unique_ptr&& __u)
00354       {
00355     using std::swap;
00356     swap(_M_t, __u._M_t);
00357       }
00358 
00359       // Disable copy from lvalue.
00360       unique_ptr(const unique_ptr&) = delete;
00361       unique_ptr& operator=(const unique_ptr&) = delete;
00362 
00363       // Disable construction from convertible pointer types.
00364       // (N2315 - 20.6.5.3.1)
00365       template<typename _Up>
00366         unique_ptr(_Up*, typename
00367            std::conditional<std::is_reference<deleter_type>::value,
00368            deleter_type, const deleter_type&>::type,
00369            typename std::enable_if<std::is_convertible<_Up*, 
00370            pointer>::value>::type* = 0) = delete;
00371 
00372       template<typename _Up>
00373         unique_ptr(_Up*, typename std::remove_reference<deleter_type>::type&&,
00374            typename std::enable_if<std::is_convertible<_Up*, 
00375            pointer>::value>::type* = 0) = delete;
00376 
00377       template<typename _Up>
00378         explicit
00379         unique_ptr(_Up*, typename std::enable_if<std::is_convertible<_Up*, 
00380            pointer>::value>::type* = 0) = delete;
00381 
00382     private:
00383       __tuple_type _M_t;
00384   };
00385   
00386   template<typename _Tp, typename _Tp_Deleter> 
00387     inline void
00388     swap(unique_ptr<_Tp, _Tp_Deleter>& __x,
00389      unique_ptr<_Tp, _Tp_Deleter>& __y)
00390     { __x.swap(__y); }
00391 
00392   template<typename _Tp, typename _Tp_Deleter> 
00393     inline void
00394     swap(unique_ptr<_Tp, _Tp_Deleter>&& __x,
00395      unique_ptr<_Tp, _Tp_Deleter>& __y)
00396     { __x.swap(__y); }
00397 
00398   template<typename _Tp, typename _Tp_Deleter> 
00399     inline void
00400     swap(unique_ptr<_Tp, _Tp_Deleter>& __x,
00401      unique_ptr<_Tp, _Tp_Deleter>&& __y)
00402     { __x.swap(__y); }
00403   
00404   template<typename _Tp, typename _Tp_Deleter,
00405        typename _Up, typename _Up_Deleter>
00406     inline bool
00407     operator==(const unique_ptr<_Tp, _Tp_Deleter>& __x,
00408            const unique_ptr<_Up, _Up_Deleter>& __y)
00409     { return __x.get() == __y.get(); }
00410 
00411   template<typename _Tp, typename _Tp_Deleter,
00412        typename _Up, typename _Up_Deleter>
00413     inline bool
00414     operator!=(const unique_ptr<_Tp, _Tp_Deleter>& __x,
00415            const unique_ptr<_Up, _Up_Deleter>& __y)
00416     { return !(__x.get() == __y.get()); }
00417 
00418   template<typename _Tp, typename _Tp_Deleter,
00419        typename _Up, typename _Up_Deleter>
00420     inline bool
00421     operator<(const unique_ptr<_Tp, _Tp_Deleter>& __x,
00422           const unique_ptr<_Up, _Up_Deleter>& __y)
00423     { return __x.get() < __y.get(); }
00424 
00425   template<typename _Tp, typename _Tp_Deleter,
00426        typename _Up, typename _Up_Deleter>
00427     inline bool
00428     operator<=(const unique_ptr<_Tp, _Tp_Deleter>& __x,
00429            const unique_ptr<_Up, _Up_Deleter>& __y)
00430     { return !(__y.get() < __x.get()); }
00431 
00432   template<typename _Tp, typename _Tp_Deleter,
00433        typename _Up, typename _Up_Deleter>
00434     inline bool
00435     operator>(const unique_ptr<_Tp, _Tp_Deleter>& __x,
00436           const unique_ptr<_Up, _Up_Deleter>& __y)
00437     { return __y.get() < __x.get(); }
00438 
00439   template<typename _Tp, typename _Tp_Deleter,
00440        typename _Up, typename _Up_Deleter>
00441     inline bool
00442     operator>=(const unique_ptr<_Tp, _Tp_Deleter>& __x,
00443            const unique_ptr<_Up, _Up_Deleter>& __y)
00444     { return !(__x.get() < __y.get()); }
00445 
00446   // @} group pointer_abstractions
00447 
00448 _GLIBCXX_END_NAMESPACE
00449 
00450 #endif /* _UNIQUE_PTR_H */

Generated on Thu Jul 23 21:16:29 2009 for libstdc++ by  doxygen 1.5.8