source: NonGTP/Boost/boost/intrusive_ptr.hpp @ 857

Revision 857, 6.0 KB checked in by igarcia, 19 years ago (diff)
RevLine 
[857]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
30namespace 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
48template<class T> class intrusive_ptr
49{
50private:
51
52    typedef intrusive_ptr this_type;
53
54public:
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
162private:
163
164    T * p_;
165};
166
167template<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
172template<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
177template<class T> inline bool operator==(intrusive_ptr<T> const & a, T * b)
178{
179    return a.get() == b;
180}
181
182template<class T> inline bool operator!=(intrusive_ptr<T> const & a, T * b)
183{
184    return a.get() != b;
185}
186
187template<class T> inline bool operator==(T * a, intrusive_ptr<T> const & b)
188{
189    return a == b.get();
190}
191
192template<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
201template<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
208template<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
213template<class T> void swap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs)
214{
215    lhs.swap(rhs);
216}
217
218// mem_fn support
219
220template<class T> T * get_pointer(intrusive_ptr<T> const & p)
221{
222    return p.get();
223}
224
225template<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
230template<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
235template<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
244template<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
254using std::basic_ostream;
255template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, intrusive_ptr<Y> const & p)
256# else
257template<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
Note: See TracBrowser for help on using the repository browser.