1 // Boost smart_ptr.hpp header file -----------------------------------------//
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.
9 // See http://www.boost.org for most recent version including documentation.
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
19 // 31 Dec 99 Condition tightened for no member template friend workaround
21 // 30 Dec 99 Moved BOOST_NMEMBER_TEMPLATES compatibility code to config.hpp
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)
48 #ifndef BOOST_SMART_PTR_HPP
49 #define BOOST_SMART_PTR_HPP
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
60 // scoped_ptr --------------------------------------------------------------//
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.
67 template<typename T> class scoped_ptr : noncopyable {
72 typedef T element_type;
74 explicit scoped_ptr( T* p=0 ) : ptr(p) {} // never throws
75 ~scoped_ptr() { delete ptr; }
77 void reset( T* p=0 ) { if ( ptr != p ) { delete ptr; ptr = p; } }
78 T& operator*() const { return *ptr; } // never throws
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
83 T* operator->() const { return ptr; } // never throws
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
94 // scoped_array ------------------------------------------------------------//
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.
100 template<typename T> class scoped_array : noncopyable {
105 typedef T element_type;
107 explicit scoped_array( T* p=0 ) : ptr(p) {} // never throws
108 ~scoped_array() { delete [] ptr; }
110 void reset( T* p=0 ) { if ( ptr != p ) {delete [] ptr; ptr=p;} }
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
117 T& operator[](std::size_t i) const { return ptr[i]; } // never throws
121 // shared_ptr --------------------------------------------------------------//
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.
127 template<typename T> class shared_ptr {
129 typedef T element_type;
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; }
136 shared_ptr(const shared_ptr& r) : px(r.px) { ++*(pn = r.pn); } // never throws
138 ~shared_ptr() { dispose(); }
140 shared_ptr& operator=(const shared_ptr& r) {
145 #if !defined( BOOST_NO_MEMBER_TEMPLATES )
147 shared_ptr(const shared_ptr<Y>& r) : px(r.px) { // never throws
150 #ifndef BOOST_NO_AUTO_PTR
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
159 shared_ptr& operator=(const shared_ptr<Y>& r) {
164 #ifndef BOOST_NO_AUTO_PTR
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
173 } // allocate new reference counter
174 px = r.release(); // fix: moved here so doesn't leak if new throws
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
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
192 } // allocate new reference counter
193 px = r.release(); // fix: moved here so doesn't leak if new throws
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
205 ++*pn; // undo effect of --*pn above to meet effects guarantee
209 } // allocate new reference counter
214 T& operator*() const { return *px; } // never throws
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
219 T* operator->() const { return px; } // never throws
221 # pragma warning(pop)
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
229 long use_count() const { return *pn; } // never throws
230 bool unique() const { return *pn == 1; } // never throws
232 void swap(shared_ptr<T>& other) // never throws
233 { std::swap(px,other.px); std::swap(pn,other.pn); }
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 )
242 T* px; // contained pointer
243 long* pn; // ptr to reference counter
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;
250 void dispose() { if (--*pn == 0) { delete px; delete pn; } }
252 void share(T* rpx, long* rpn) {
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(); }
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(); }
269 // shared_array ------------------------------------------------------------//
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.
275 template<typename T> class shared_array {
277 typedef T element_type;
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; }
284 shared_array(const shared_array& r) : px(r.px) // never throws
287 ~shared_array() { dispose(); }
289 shared_array& operator=(const shared_array& r) {
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
304 ++*pn; // undo effect of --*pn above to meet effects guarantee
308 } // allocate new reference counter
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
318 T& operator[](std::size_t i) const { return px[i]; } // never throws
321 long use_count() const { return *pn; } // never throws
322 bool unique() const { return *pn == 1; } // never throws
324 void swap(shared_array<T>& other) // never throws
325 { std::swap(px,other.px); std::swap(pn,other.pn); }
329 T* px; // contained pointer
330 long* pn; // ptr to reference counter
332 void dispose() { if (--*pn == 0) { delete [] px; delete pn; } }
337 inline bool operator==(const shared_array<T>& a, const shared_array<T>& b)
338 { return a.get() == b.get(); }
341 inline bool operator!=(const shared_array<T>& a, const shared_array<T>& b)
342 { return a.get() != b.get(); }
346 // specializations for things in namespace std -----------------------------//
348 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
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.
357 inline void swap(boost::shared_ptr<T>& a, boost::shared_ptr<T>& b)
361 inline void swap(boost::shared_array<T>& a, boost::shared_array<T>& b)
364 // Specialize std::less so we can use shared pointers and arrays as keys in
365 // associative collections.
367 // It's still a controversial question whether this is better than supplying
368 // a full range of comparison operators (<, >, <=, >=).
371 struct less< boost::shared_ptr<T> >
372 : binary_function<boost::shared_ptr<T>, boost::shared_ptr<T>, bool>
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()); }
380 struct less< boost::shared_array<T> >
381 : binary_function<boost::shared_array<T>, boost::shared_array<T>, bool>
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()); }
390 #endif // ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
392 #endif // BOOST_SMART_PTR_HPP