Ugly, not-to-be-pushed sucking in of all of Boost to get windows to work.
[dyninst.git] / external / boost / intrusive_ptr.hpp
1 #ifndef BOOST_INTRUSIVE_PTR_HPP_INCLUDED
2 #define BOOST_INTRUSIVE_PTR_HPP_INCLUDED
3
4 //
5 //  intrusive_ptr.hpp
6 //
7 //  Copyright (c) 2001, 2002 Peter Dimov
8 //
9 // Distributed under the Boost Software License, Version 1.0. (See
10 // accompanying file LICENSE_1_0.txt or copy at
11 // http://www.boost.org/LICENSE_1_0.txt)
12 //
13 //  See http://www.boost.org/libs/smart_ptr/intrusive_ptr.html for documentation.
14 //
15
16 #include <boost/config.hpp>
17
18 #ifdef BOOST_MSVC  // moved here to work around VC++ compiler crash
19 # pragma warning(push)
20 # pragma warning(disable:4284) // odd return type for operator->
21 #endif
22
23 #include <boost/assert.hpp>
24 #include <boost/detail/workaround.hpp>
25
26 #include <functional>           // for std::less
27 #include <iosfwd>               // for std::basic_ostream
28
29
30 namespace boost
31 {
32
33 //
34 //  intrusive_ptr
35 //
36 //  A smart pointer that uses intrusive reference counting.
37 //
38 //  Relies on unqualified calls to
39 //  
40 //      void intrusive_ptr_add_ref(T * p);
41 //      void intrusive_ptr_release(T * p);
42 //
43 //          (p != 0)
44 //
45 //  The object is responsible for destroying itself.
46 //
47
48 template<class T> class intrusive_ptr
49 {
50 private:
51
52     typedef intrusive_ptr this_type;
53
54 public:
55
56     typedef T element_type;
57
58     intrusive_ptr(): p_(0)
59     {
60     }
61
62     intrusive_ptr(T * p, bool add_ref = true): p_(p)
63     {
64         if(p_ != 0 && add_ref) intrusive_ptr_add_ref(p_);
65     }
66
67 #if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES)
68
69     template<class U> intrusive_ptr(intrusive_ptr<U> const & rhs): p_(rhs.get())
70     {
71         if(p_ != 0) intrusive_ptr_add_ref(p_);
72     }
73
74 #endif
75
76     intrusive_ptr(intrusive_ptr const & rhs): p_(rhs.p_)
77     {
78         if(p_ != 0) intrusive_ptr_add_ref(p_);
79     }
80
81     ~intrusive_ptr()
82     {
83         if(p_ != 0) intrusive_ptr_release(p_);
84     }
85
86 #if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES)
87
88     template<class U> intrusive_ptr & operator=(intrusive_ptr<U> const & rhs)
89     {
90         this_type(rhs).swap(*this);
91         return *this;
92     }
93
94 #endif
95
96     intrusive_ptr & operator=(intrusive_ptr const & rhs)
97     {
98         this_type(rhs).swap(*this);
99         return *this;
100     }
101
102     intrusive_ptr & operator=(T * rhs)
103     {
104         this_type(rhs).swap(*this);
105         return *this;
106     }
107
108     T * get() const
109     {
110         return p_;
111     }
112
113     T & operator*() const
114     {
115         return *p_;
116     }
117
118     T * operator->() const
119     {
120         return p_;
121     }
122
123 #if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530)
124
125     operator bool () const
126     {
127         return p_ != 0;
128     }
129
130 #elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
131     typedef T * (this_type::*unspecified_bool_type)() const;
132     
133     operator unspecified_bool_type() const // never throws
134     {
135         return p_ == 0? 0: &this_type::get;
136     }
137
138 #else 
139
140     typedef T * this_type::*unspecified_bool_type;
141
142     operator unspecified_bool_type () const
143     {
144         return p_ == 0? 0: &this_type::p_;
145     }
146
147 #endif
148
149     // operator! is a Borland-specific workaround
150     bool operator! () const
151     {
152         return p_ == 0;
153     }
154
155     void swap(intrusive_ptr & rhs)
156     {
157         T * tmp = p_;
158         p_ = rhs.p_;
159         rhs.p_ = tmp;
160     }
161
162 private:
163
164     T * p_;
165 };
166
167 template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b)
168 {
169     return a.get() == b.get();
170 }
171
172 template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b)
173 {
174     return a.get() != b.get();
175 }
176
177 template<class T> inline bool operator==(intrusive_ptr<T> const & a, T * b)
178 {
179     return a.get() == b;
180 }
181
182 template<class T> inline bool operator!=(intrusive_ptr<T> const & a, T * b)
183 {
184     return a.get() != b;
185 }
186
187 template<class T> inline bool operator==(T * a, intrusive_ptr<T> const & b)
188 {
189     return a == b.get();
190 }
191
192 template<class T> inline bool operator!=(T * a, intrusive_ptr<T> const & b)
193 {
194     return a != b.get();
195 }
196
197 #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
198
199 // Resolve the ambiguity between our op!= and the one in rel_ops
200
201 template<class T> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b)
202 {
203     return a.get() != b.get();
204 }
205
206 #endif
207
208 template<class T> inline bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b)
209 {
210     return std::less<T *>()(a.get(), b.get());
211 }
212
213 template<class T> void swap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs)
214 {
215     lhs.swap(rhs);
216 }
217
218 // mem_fn support
219
220 template<class T> T * get_pointer(intrusive_ptr<T> const & p)
221 {
222     return p.get();
223 }
224
225 template<class T, class U> intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & p)
226 {
227     return static_cast<T *>(p.get());
228 }
229
230 template<class T, class U> intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & p)
231 {
232     return const_cast<T *>(p.get());
233 }
234
235 template<class T, class U> intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & p)
236 {
237     return dynamic_cast<T *>(p.get());
238 }
239
240 // operator<<
241
242 #if defined(__GNUC__) &&  (__GNUC__ < 3)
243
244 template<class Y> std::ostream & operator<< (std::ostream & os, intrusive_ptr<Y> const & p)
245 {
246     os << p.get();
247     return os;
248 }
249
250 #else
251
252 # if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, <= 1200 && __SGI_STL_PORT)
253 // MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL
254 using std::basic_ostream;
255 template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, intrusive_ptr<Y> const & p)
256 # else
257 template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, intrusive_ptr<Y> const & p)
258 # endif 
259 {
260     os << p.get();
261     return os;
262 }
263
264 #endif
265
266 } // namespace boost
267
268 #ifdef BOOST_MSVC
269 # pragma warning(pop)
270 #endif    
271
272 #endif  // #ifndef BOOST_INTRUSIVE_PTR_HPP_INCLUDED