]> git.lyx.org Git - lyx.git/blob - boost/boost/smart_ptr.hpp
some boost changes and updates
[lyx.git] / boost / boost / smart_ptr.hpp
1 //  Boost smart_ptr.hpp header file  -----------------------------------------//
2
3 //  (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. Permission to copy,
4 //  use, modify, sell and distribute this software is granted provided this
5 //  copyright notice appears in all copies. This software is provided "as is"
6 //  without express or implied warranty, and with no claim as to its
7 //  suitability for any purpose.
8
9 //  See http://www.boost.org for most recent version including documentation.
10
11 //  Revision History
12 //  21 Jan 01  Suppress some useless warnings with MSVC (David Abrahams)
13 //  19 Oct 00  Make shared_ptr ctor from auto_ptr explicit. (Robert Vugts) 
14 //  24 Jul 00  Change throw() to // never throws.  See lib guidelines
15 //             Exception-specification rationale. (Beman Dawes)
16 //  22 Jun 00  Remove #if continuations to fix GCC 2.95.2 problem (Beman Dawes)
17 //   1 Feb 00  Additional shared_ptr BOOST_NO_MEMBER_TEMPLATES workarounds
18 //             (Dave Abrahams)
19 //  31 Dec 99  Condition tightened for no member template friend workaround
20 //             (Dave Abrahams)
21 //  30 Dec 99  Moved BOOST_NMEMBER_TEMPLATES compatibility code to config.hpp
22 //             (Dave Abrahams)
23 //  30 Nov 99  added operator ==, operator !=, and std::swap and std::less
24 //             specializations for shared types (Darin Adler)
25 //  11 Oct 99  replaced op[](int) with op[](std::size_t) (Ed Brey, Valentin
26 //             Bonnard), added shared_ptr workaround for no member template
27 //             friends (Matthew Langston)
28 //  25 Sep 99  added shared_ptr::swap and shared_array::swap (Luis Coelho).
29 //  20 Jul 99  changed name to smart_ptr.hpp, #include <boost/config.hpp>,
30 //             #include <boost/utility.hpp> and use boost::noncopyable
31 //  17 May 99  remove scoped_array and shared_array operator*() as
32 //             unnecessary (Beman Dawes)
33 //  14 May 99  reorder code so no effects when bad_alloc thrown (Abrahams/Dawes)
34 //  13 May 99  remove certain throw() specifiers to avoid generated try/catch
35 //             code cost (Beman Dawes)
36 //  11 May 99  get() added, conversion to T* placed in macro guard (Valentin
37 //             Bonnard, Dave Abrahams, and others argued for elimination
38 //             of the automatic conversion)
39 //  28 Apr 99  #include <memory> fix (Valentin Bonnard)
40 //  28 Apr 99  rename transfer() to share() for clarity (Dave Abrahams)
41 //  28 Apr 99  remove unsafe shared_array template conversions(Valentin Bonnard)
42 //  28 Apr 99  p(r) changed to p(r.px) for clarity (Dave Abrahams)
43 //  21 Apr 99  reset() self assignment fix (Valentin Bonnard)
44 //  21 Apr 99  dispose() provided to improve clarity (Valentin Bonnard)
45 //  27 Apr 99  leak when new throws fixes (Dave Abrahams)
46 //  21 Oct 98  initial Version (Greg Colvin/Beman Dawes)
47
48 #ifndef BOOST_SMART_PTR_HPP
49 #define BOOST_SMART_PTR_HPP
50
51 #include <boost/config.hpp>   // for broken compiler workarounds
52 #include <cstddef>            // for std::size_t
53 #include <memory>             // for std::auto_ptr
54 #include <algorithm>          // for std::swap
55 #include <boost/utility.hpp>  // for boost::noncopyable
56 #include <functional>         // for std::less
57
58 namespace boost {
59
60 //  scoped_ptr  --------------------------------------------------------------//
61
62 //  scoped_ptr mimics a built-in pointer except that it guarantees deletion
63 //  of the object pointed to, either on destruction of the scoped_ptr or via
64 //  an explicit reset().  scoped_ptr is a simple solution for simple needs;
65 //  see shared_ptr (below) or std::auto_ptr if your needs are more complex.
66
67 template<typename T> class scoped_ptr : noncopyable {
68
69   T* ptr;
70
71  public:
72   typedef T element_type;
73
74   explicit scoped_ptr( T* p=0 ) : ptr(p) {}  // never throws
75   ~scoped_ptr()                 { delete ptr; }
76
77   void reset( T* p=0 )          { if ( ptr != p ) { delete ptr; ptr = p; } }
78   T& operator*() const          { return *ptr; }  // never throws
79 #ifdef BOOST_MSVC
80 # pragma warning(push)
81 # pragma warning(disable:4284) // return type for 'identifier::operator->' is not a UDT or reference to a UDT. Will produce errors if applied using infix notation
82 #endif    
83   T* operator->() const         { return ptr; }  // never throws
84 #ifdef BOOST_MSVC
85 # pragma warning(pop)
86 #endif    
87   T* get() const                { return ptr; }  // never throws
88 #ifdef BOOST_SMART_PTR_CONVERSION
89   // get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk!
90   operator T*() const           { return ptr; }  // never throws 
91 #endif
92   };  // scoped_ptr
93
94 //  scoped_array  ------------------------------------------------------------//
95
96 //  scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to
97 //  is guaranteed, either on destruction of the scoped_array or via an explicit
98 //  reset(). See shared_array or std::vector if your needs are more complex.
99
100 template<typename T> class scoped_array : noncopyable {
101
102   T* ptr;
103
104  public:
105   typedef T element_type;
106
107   explicit scoped_array( T* p=0 ) : ptr(p) {}  // never throws
108   ~scoped_array()                    { delete [] ptr; }
109
110   void reset( T* p=0 )               { if ( ptr != p ) {delete [] ptr; ptr=p;} }
111
112   T* get() const                     { return ptr; }  // never throws
113 #ifdef BOOST_SMART_PTR_CONVERSION
114   // get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk!
115   operator T*() const                { return ptr; }  // never throws
116 #else 
117   T& operator[](std::size_t i) const { return ptr[i]; }  // never throws
118 #endif
119   };  // scoped_array
120
121 //  shared_ptr  --------------------------------------------------------------//
122
123 //  An enhanced relative of scoped_ptr with reference counted copy semantics.
124 //  The object pointed to is deleted when the last shared_ptr pointing to it
125 //  is destroyed or reset.
126
127 template<typename T> class shared_ptr {
128   public:
129    typedef T element_type;
130
131    explicit shared_ptr(T* p =0) : px(p) {
132       try { pn = new long(1); }  // fix: prevent leak if new throws
133       catch (...) { delete p; throw; } 
134    }
135
136    shared_ptr(const shared_ptr& r) : px(r.px) { ++*(pn = r.pn); }  // never throws
137
138    ~shared_ptr() { dispose(); }
139
140    shared_ptr& operator=(const shared_ptr& r) {
141       share(r.px,r.pn);
142       return *this;
143    }
144
145 #if !defined( BOOST_NO_MEMBER_TEMPLATES )
146    template<typename Y>
147       shared_ptr(const shared_ptr<Y>& r) : px(r.px) {  // never throws 
148          ++*(pn = r.pn); 
149       }
150 #ifndef BOOST_NO_AUTO_PTR
151    template<typename Y>
152       explicit shared_ptr(std::auto_ptr<Y>& r) { 
153          pn = new long(1); // may throw
154          px = r.release(); // fix: moved here to stop leak if new throws
155       }
156 #endif 
157
158    template<typename Y>
159       shared_ptr& operator=(const shared_ptr<Y>& r) { 
160          share(r.px,r.pn);
161          return *this;
162       }
163
164 #ifndef BOOST_NO_AUTO_PTR
165    template<typename Y>
166       shared_ptr& operator=(std::auto_ptr<Y>& r) {
167          // code choice driven by guarantee of "no effect if new throws"
168          if (*pn == 1) { delete px; }
169          else { // allocate new reference counter
170            long * tmp = new long(1); // may throw
171            --*pn; // only decrement once danger of new throwing is past
172            pn = tmp;
173          } // allocate new reference counter
174          px = r.release(); // fix: moved here so doesn't leak if new throws 
175          return *this;
176       }
177 #endif
178 #else
179 #ifndef BOOST_NO_AUTO_PTR
180       explicit shared_ptr(std::auto_ptr<T>& r) { 
181          pn = new long(1); // may throw
182          px = r.release(); // fix: moved here to stop leak if new throws
183       } 
184
185       shared_ptr& operator=(std::auto_ptr<T>& r) {
186          // code choice driven by guarantee of "no effect if new throws"
187          if (*pn == 1) { delete px; }
188          else { // allocate new reference counter
189            long * tmp = new long(1); // may throw
190            --*pn; // only decrement once danger of new throwing is past
191            pn = tmp;
192          } // allocate new reference counter
193          px = r.release(); // fix: moved here so doesn't leak if new throws 
194          return *this;
195       }
196 #endif
197 #endif
198
199    void reset(T* p=0) {
200       if ( px == p ) return;  // fix: self-assignment safe
201       if (--*pn == 0) { delete px; }
202       else { // allocate new reference counter
203         try { pn = new long; }  // fix: prevent leak if new throws
204         catch (...) {
205           ++*pn;  // undo effect of --*pn above to meet effects guarantee 
206           delete p;
207           throw;
208         } // catch
209       } // allocate new reference counter
210       *pn = 1;
211       px = p;
212    } // reset
213
214    T& operator*() const          { return *px; }  // never throws
215 #ifdef BOOST_MSVC
216 # pragma warning(push)
217 # pragma warning(disable:4284) // return type for 'identifier::operator->' is not a UDT or reference to a UDT. Will produce errors if applied using infix notation
218 #endif    
219    T* operator->() const         { return px; }  // never throws
220 #ifdef BOOST_MSVC
221 # pragma warning(pop)
222 #endif    
223    T* get() const                { return px; }  // never throws
224  #ifdef BOOST_SMART_PTR_CONVERSION
225    // get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk!
226    operator T*() const           { return px; }  // never throws 
227  #endif
228
229    long use_count() const        { return *pn; }  // never throws
230    bool unique() const           { return *pn == 1; }  // never throws
231
232    void swap(shared_ptr<T>& other)  // never throws
233      { std::swap(px,other.px); std::swap(pn,other.pn); }
234
235 // Tasteless as this may seem, making all members public allows member templates
236 // to work in the absence of member template friends. (Matthew Langston)
237 // Don't split this line into two; that causes problems for some GCC 2.95.2 builds
238 #if defined(BOOST_NO_MEMBER_TEMPLATES) || !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS )
239    private:
240 #endif
241
242    T*     px;     // contained pointer
243    long*  pn;     // ptr to reference counter
244
245 // Don't split this line into two; that causes problems for some GCC 2.95.2 builds
246 #if !defined( BOOST_NO_MEMBER_TEMPLATES ) && !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS )
247    template<typename Y> friend class shared_ptr;
248 #endif
249
250    void dispose() { if (--*pn == 0) { delete px; delete pn; } }
251
252    void share(T* rpx, long* rpn) {
253       if (pn != rpn) {
254          dispose();
255          px = rpx;
256          ++*(pn = rpn);
257       }
258    } // share
259 };  // shared_ptr
260
261 template<typename T, typename U>
262   inline bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b)
263     { return a.get() == b.get(); }
264
265 template<typename T, typename U>
266   inline bool operator!=(const shared_ptr<T>& a, const shared_ptr<U>& b)
267     { return a.get() != b.get(); }
268
269 //  shared_array  ------------------------------------------------------------//
270
271 //  shared_array extends shared_ptr to arrays.
272 //  The array pointed to is deleted when the last shared_array pointing to it
273 //  is destroyed or reset.
274
275 template<typename T> class shared_array {
276   public:
277    typedef T element_type;
278
279    explicit shared_array(T* p =0) : px(p) {
280       try { pn = new long(1); }  // fix: prevent leak if new throws
281       catch (...) { delete [] p; throw; } 
282    }
283
284    shared_array(const shared_array& r) : px(r.px)  // never throws
285       { ++*(pn = r.pn); }
286
287    ~shared_array() { dispose(); }
288
289    shared_array& operator=(const shared_array& r) {
290       if (pn != r.pn) {
291          dispose();
292          px = r.px;
293          ++*(pn = r.pn);
294       }
295       return *this;
296    } // operator=
297
298    void reset(T* p=0) {
299       if ( px == p ) return;  // fix: self-assignment safe
300       if (--*pn == 0) { delete [] px; }
301       else { // allocate new reference counter
302         try { pn = new long; }  // fix: prevent leak if new throws
303         catch (...) {
304           ++*pn;  // undo effect of --*pn above to meet effects guarantee 
305           delete [] p;
306           throw;
307         } // catch
308       } // allocate new reference counter
309       *pn = 1;
310       px = p;
311    } // reset
312
313    T* get() const                     { return px; }  // never throws
314  #ifdef BOOST_SMART_PTR_CONVERSION
315    // get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk!
316    operator T*() const                { return px; }  // never throws
317  #else 
318    T& operator[](std::size_t i) const { return px[i]; }  // never throws
319  #endif
320
321    long use_count() const             { return *pn; }  // never throws
322    bool unique() const                { return *pn == 1; }  // never throws
323
324    void swap(shared_array<T>& other)  // never throws
325      { std::swap(px,other.px); std::swap(pn,other.pn); }
326
327   private:
328
329    T*     px;     // contained pointer
330    long*  pn;     // ptr to reference counter
331
332    void dispose() { if (--*pn == 0) { delete [] px; delete pn; } }
333
334 };  // shared_array
335
336 template<typename T>
337   inline bool operator==(const shared_array<T>& a, const shared_array<T>& b)
338     { return a.get() == b.get(); }
339
340 template<typename T>
341   inline bool operator!=(const shared_array<T>& a, const shared_array<T>& b)
342     { return a.get() != b.get(); }
343
344 } // namespace boost
345
346 //  specializations for things in namespace std  -----------------------------//
347
348 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
349
350 namespace std {
351
352 // Specialize std::swap to use the fast, non-throwing swap that's provided
353 // as a member function instead of using the default algorithm which creates
354 // a temporary and uses assignment.
355
356 template<typename T>
357   inline void swap(boost::shared_ptr<T>& a, boost::shared_ptr<T>& b)
358     { a.swap(b); }
359
360 template<typename T>
361   inline void swap(boost::shared_array<T>& a, boost::shared_array<T>& b)
362     { a.swap(b); }
363
364 // Specialize std::less so we can use shared pointers and arrays as keys in
365 // associative collections.
366
367 // It's still a controversial question whether this is better than supplying
368 // a full range of comparison operators (<, >, <=, >=).
369
370 template<typename T>
371   struct less< boost::shared_ptr<T> >
372     : binary_function<boost::shared_ptr<T>, boost::shared_ptr<T>, bool>
373   {
374     bool operator()(const boost::shared_ptr<T>& a,
375         const boost::shared_ptr<T>& b) const
376       { return less<T*>()(a.get(),b.get()); }
377   };
378
379 template<typename T>
380   struct less< boost::shared_array<T> >
381     : binary_function<boost::shared_array<T>, boost::shared_array<T>, bool>
382   {
383     bool operator()(const boost::shared_array<T>& a,
384         const boost::shared_array<T>& b) const
385       { return less<T*>()(a.get(),b.get()); }
386   };
387
388 } // namespace std
389
390 #endif  // ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
391
392 #endif  // BOOST_SMART_PTR_HPP
393
394