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

Generated on 9 Feb 2010 for libstdc++ by  doxygen 1.6.1