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       typedef _Tp* unique_ptr::*             __unspecified_pointer_type;
00085 
00086     public:
00087       typedef _Tp*               pointer;
00088       typedef _Tp                element_type;      
00089       typedef _Tp_Deleter        deleter_type;
00090 
00091       // Constructors.
00092       unique_ptr()
00093       : _M_t(pointer(), deleter_type())
00094       { static_assert(!std::is_pointer<deleter_type>::value,
00095               "constructed with null function pointer deleter"); }
00096 
00097       explicit
00098       unique_ptr(pointer __p)
00099       : _M_t(__p, deleter_type())
00100       { static_assert(!std::is_pointer<deleter_type>::value,
00101              "constructed with null function pointer deleter"); }
00102 
00103       unique_ptr(pointer __p,
00104           typename std::conditional<std::is_reference<deleter_type>::value, 
00105             deleter_type, const deleter_type&>::type __d)
00106       : _M_t(__p, __d) { }
00107 
00108       unique_ptr(pointer __p,
00109           typename std::remove_reference<deleter_type>::type&& __d)
00110       : _M_t(std::move(__p), std::move(__d))
00111       { static_assert(!std::is_reference<deleter_type>::value, 
00112               "rvalue deleter bound to reference"); }
00113 
00114       // Move constructors.
00115       unique_ptr(unique_ptr&& __u) 
00116       : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
00117 
00118       template<typename _Up, typename _Up_Deleter> 
00119         unique_ptr(unique_ptr<_Up, _Up_Deleter>&& __u) 
00120         : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter()))
00121     { }
00122 
00123       // Destructor.
00124       ~unique_ptr() { reset(); }
00125     
00126       // Assignment.
00127       unique_ptr&
00128       operator=(unique_ptr&& __u)
00129       { 
00130         reset(__u.release()); 
00131         get_deleter() = std::move(__u.get_deleter()); 
00132         return *this;
00133       }
00134 
00135       template<typename _Up, typename _Up_Deleter> 
00136         unique_ptr&
00137         operator=(unique_ptr<_Up, _Up_Deleter>&& __u)
00138     {
00139           reset(__u.release()); 
00140           get_deleter() = std::move(__u.get_deleter()); 
00141           return *this;
00142         }
00143 
00144       unique_ptr&
00145       operator=(__unspecified_pointer_type) 
00146       {
00147     reset();
00148     return *this;
00149       }
00150 
00151       // Observers.
00152       typename std::add_lvalue_reference<element_type>::type
00153       operator*() const
00154       {
00155     _GLIBCXX_DEBUG_ASSERT(get() != pointer());
00156     return *get();
00157       }
00158 
00159       pointer
00160       operator->() const
00161       {
00162     _GLIBCXX_DEBUG_ASSERT(get() != pointer());
00163     return get();
00164       }
00165 
00166       pointer
00167       get() const
00168       { return std::get<0>(_M_t); }
00169 
00170       deleter_type&
00171       get_deleter()
00172       { return std::get<1>(_M_t); }
00173 
00174       const deleter_type&
00175       get_deleter() const
00176       { return std::get<1>(_M_t); }
00177 
00178       explicit operator bool() const
00179       { return get() == pointer() ? false : true; }
00180 
00181       // Modifiers.
00182       pointer
00183       release() 
00184       {
00185     pointer __p = get();
00186     std::get<0>(_M_t) = pointer();
00187     return __p;
00188       }
00189 
00190       void
00191       reset(pointer __p = pointer())
00192       {
00193     using std::swap;
00194     swap(std::get<0>(_M_t), __p);
00195     if (__p != pointer())
00196       get_deleter()(__p);
00197       }
00198 
00199       void
00200       swap(unique_ptr& __u)
00201       {
00202     using std::swap;
00203     swap(_M_t, __u._M_t);
00204       }
00205 
00206       // Disable copy from lvalue.
00207       unique_ptr(const unique_ptr&) = delete;
00208       unique_ptr& operator=(const unique_ptr&) = delete;
00209 
00210     private:
00211       __tuple_type _M_t;
00212   };
00213  
00214   /// 20.7.12.3 unique_ptr for array objects with a runtime length
00215   // [unique.ptr.runtime]
00216   // _GLIBCXX_RESOLVE_LIB_DEFECTS
00217   // DR 740 - omit specialization for array objects with a compile time length
00218   template<typename _Tp, typename _Tp_Deleter> 
00219     class unique_ptr<_Tp[], _Tp_Deleter>
00220     {
00221       typedef std::tuple<_Tp*, _Tp_Deleter>  __tuple_type;
00222       typedef _Tp* unique_ptr::*             __unspecified_pointer_type;
00223 
00224     public:
00225       typedef _Tp*               pointer;
00226       typedef _Tp                element_type;      
00227       typedef _Tp_Deleter        deleter_type;
00228 
00229       // Constructors.
00230       unique_ptr()
00231       : _M_t(pointer(), deleter_type())
00232       { static_assert(!std::is_pointer<deleter_type>::value,
00233               "constructed with null function pointer deleter"); }
00234 
00235       explicit
00236       unique_ptr(pointer __p)
00237       : _M_t(__p, deleter_type())
00238       { static_assert(!std::is_pointer<deleter_type>::value,
00239               "constructed with null function pointer deleter"); }
00240 
00241       unique_ptr(pointer __p,
00242           typename std::conditional<std::is_reference<deleter_type>::value, 
00243               deleter_type, const deleter_type&>::type __d) 
00244       : _M_t(__p, __d) { }
00245 
00246       unique_ptr(pointer __p,
00247          typename std::remove_reference<deleter_type>::type && __d)
00248       : _M_t(std::move(__p), std::move(__d))
00249       { static_assert(!std::is_reference<deleter_type>::value, 
00250               "rvalue deleter bound to reference"); }
00251 
00252       // Move constructors.
00253       unique_ptr(unique_ptr&& __u) 
00254       : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { }
00255 
00256       template<typename _Up, typename _Up_Deleter> 
00257         unique_ptr(unique_ptr<_Up, _Up_Deleter>&& __u) 
00258     : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter()))
00259     { }
00260 
00261       // Destructor.
00262       ~unique_ptr() { reset(); }
00263 
00264       // Assignment.
00265       unique_ptr&
00266       operator=(unique_ptr&& __u)
00267       {
00268     reset(__u.release());
00269     get_deleter() = std::move(__u.get_deleter()); 
00270     return *this; 
00271       }
00272 
00273       template<typename _Up, typename _Up_Deleter> 
00274         unique_ptr&
00275         operator=(unique_ptr<_Up, _Up_Deleter>&& __u)
00276     {
00277           reset(__u.release());
00278           get_deleter() = std::move(__u.get_deleter()); 
00279           return *this;
00280         }
00281 
00282       unique_ptr&
00283       operator=(__unspecified_pointer_type)
00284       {
00285     reset();
00286     return *this;
00287       }
00288 
00289       // Observers.
00290       typename std::add_lvalue_reference<element_type>::type 
00291       operator[](size_t __i) const 
00292       {
00293     _GLIBCXX_DEBUG_ASSERT(get() != pointer());
00294     return get()[__i];
00295       }
00296 
00297       pointer
00298       get() const
00299       { return std::get<0>(_M_t); }
00300 
00301       deleter_type& 
00302       get_deleter()
00303       { return std::get<1>(_M_t); }
00304 
00305       const deleter_type&
00306       get_deleter() const
00307       { return std::get<1>(_M_t); }    
00308 
00309       explicit operator bool() const 
00310       { return get() == pointer() ? false : true; }
00311     
00312       // Modifiers.
00313       pointer
00314       release() 
00315       {
00316     pointer __p = get();
00317     std::get<0>(_M_t) = pointer();
00318     return __p;
00319       }
00320 
00321       void
00322       reset(pointer __p = pointer()) 
00323       {
00324     using std::swap;
00325     swap(std::get<0>(_M_t), __p);
00326     if (__p != pointer())
00327       get_deleter()(__p);
00328       }
00329 
00330       // DR 821.
00331       template<typename _Up>
00332         void reset(_Up) = delete;
00333 
00334       void
00335       swap(unique_ptr& __u)
00336       {
00337     using std::swap;
00338     swap(_M_t, __u._M_t);
00339       }
00340 
00341       // Disable copy from lvalue.
00342       unique_ptr(const unique_ptr&) = delete;
00343       unique_ptr& operator=(const unique_ptr&) = delete;
00344 
00345       // Disable construction from convertible pointer types.
00346       // (N2315 - 20.6.5.3.1)
00347       template<typename _Up>
00348         unique_ptr(_Up*, typename
00349            std::conditional<std::is_reference<deleter_type>::value,
00350            deleter_type, const deleter_type&>::type,
00351            typename std::enable_if<std::is_convertible<_Up*, 
00352            pointer>::value>::type* = 0) = delete;
00353 
00354       template<typename _Up>
00355         unique_ptr(_Up*, typename std::remove_reference<deleter_type>::type&&,
00356            typename std::enable_if<std::is_convertible<_Up*, 
00357            pointer>::value>::type* = 0) = delete;
00358 
00359       template<typename _Up>
00360         explicit
00361         unique_ptr(_Up*, typename std::enable_if<std::is_convertible<_Up*, 
00362            pointer>::value>::type* = 0) = delete;
00363 
00364     private:
00365       __tuple_type _M_t;
00366   };
00367   
00368   template<typename _Tp, typename _Tp_Deleter> 
00369     inline void
00370     swap(unique_ptr<_Tp, _Tp_Deleter>& __x,
00371      unique_ptr<_Tp, _Tp_Deleter>& __y)
00372     { __x.swap(__y); }
00373 
00374   template<typename _Tp, typename _Tp_Deleter,
00375        typename _Up, typename _Up_Deleter>
00376     inline bool
00377     operator==(const unique_ptr<_Tp, _Tp_Deleter>& __x,
00378            const unique_ptr<_Up, _Up_Deleter>& __y)
00379     { return __x.get() == __y.get(); }
00380 
00381   template<typename _Tp, typename _Tp_Deleter,
00382        typename _Up, typename _Up_Deleter>
00383     inline bool
00384     operator!=(const unique_ptr<_Tp, _Tp_Deleter>& __x,
00385            const unique_ptr<_Up, _Up_Deleter>& __y)
00386     { return !(__x.get() == __y.get()); }
00387 
00388   template<typename _Tp, typename _Tp_Deleter,
00389        typename _Up, typename _Up_Deleter>
00390     inline bool
00391     operator<(const unique_ptr<_Tp, _Tp_Deleter>& __x,
00392           const unique_ptr<_Up, _Up_Deleter>& __y)
00393     { return __x.get() < __y.get(); }
00394 
00395   template<typename _Tp, typename _Tp_Deleter,
00396        typename _Up, typename _Up_Deleter>
00397     inline bool
00398     operator<=(const unique_ptr<_Tp, _Tp_Deleter>& __x,
00399            const unique_ptr<_Up, _Up_Deleter>& __y)
00400     { return !(__y.get() < __x.get()); }
00401 
00402   template<typename _Tp, typename _Tp_Deleter,
00403        typename _Up, typename _Up_Deleter>
00404     inline bool
00405     operator>(const unique_ptr<_Tp, _Tp_Deleter>& __x,
00406           const unique_ptr<_Up, _Up_Deleter>& __y)
00407     { return __y.get() < __x.get(); }
00408 
00409   template<typename _Tp, typename _Tp_Deleter,
00410        typename _Up, typename _Up_Deleter>
00411     inline bool
00412     operator>=(const unique_ptr<_Tp, _Tp_Deleter>& __x,
00413            const unique_ptr<_Up, _Up_Deleter>& __y)
00414     { return !(__x.get() < __y.get()); }
00415 
00416   // @} group pointer_abstractions
00417 
00418 _GLIBCXX_END_NAMESPACE
00419 
00420 #endif /* _UNIQUE_PTR_H */