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