]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | ////////////////////////////////////////////////////////////////////////////// |
2 | // | |
3 | // (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost | |
4 | // Software License, Version 1.0. (See accompanying file | |
5 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
6 | // | |
7 | // See http://www.boost.org/libs/intrusive for documentation. | |
8 | // | |
9 | ////////////////////////////////////////////////////////////////////////////// | |
10 | ||
11 | #ifndef BOOST_INTRUSIVE_SMART_PTR_HPP | |
12 | #define BOOST_INTRUSIVE_SMART_PTR_HPP | |
13 | ||
14 | #include <boost/intrusive/pointer_plus_bits.hpp> | |
15 | #include <boost/intrusive/pointer_traits.hpp> | |
16 | #include <boost/intrusive/detail/iterator.hpp> | |
17 | #include <boost/move/adl_move_swap.hpp> | |
18 | ||
19 | #if (defined _MSC_VER) | |
20 | # pragma once | |
21 | #endif | |
22 | ||
23 | namespace boost{ | |
24 | namespace intrusive{ | |
25 | ||
26 | namespace detail { | |
27 | ||
28 | struct static_cast_tag {}; | |
29 | struct const_cast_tag {}; | |
30 | struct dynamic_cast_tag {}; | |
31 | struct reinterpret_cast_tag {}; | |
32 | ||
33 | } //namespace detail { | |
34 | ||
35 | //Empty class | |
36 | struct empty_type{}; | |
37 | ||
38 | template<class T> | |
39 | struct random_it | |
40 | : public iterator<std::random_access_iterator_tag, T, std::ptrdiff_t, T*, T&> | |
41 | { | |
42 | typedef const T* const_pointer; | |
43 | typedef const T& const_reference; | |
44 | }; | |
45 | ||
46 | template<> struct random_it<void> | |
47 | { | |
48 | typedef const void * const_pointer; | |
49 | typedef empty_type& reference; | |
50 | typedef const empty_type& const_reference; | |
51 | typedef empty_type difference_type; | |
52 | typedef empty_type iterator_category; | |
53 | }; | |
54 | ||
55 | template<> struct random_it<const void> | |
56 | { | |
57 | typedef const void * const_pointer; | |
58 | typedef const empty_type & reference; | |
59 | typedef const empty_type & const_reference; | |
60 | typedef empty_type difference_type; | |
61 | typedef empty_type iterator_category; | |
62 | }; | |
63 | ||
64 | template<> struct random_it<volatile void> | |
65 | { | |
66 | typedef const volatile void * const_pointer; | |
67 | typedef empty_type& reference; | |
68 | typedef const empty_type& const_reference; | |
69 | typedef empty_type difference_type; | |
70 | typedef empty_type iterator_category; | |
71 | }; | |
72 | ||
73 | template<> struct random_it<const volatile void> | |
74 | { | |
75 | typedef const volatile void * const_pointer; | |
76 | typedef const empty_type & reference; | |
77 | typedef const empty_type & const_reference; | |
78 | typedef empty_type difference_type; | |
79 | typedef empty_type iterator_category; | |
80 | }; | |
81 | ||
82 | } //namespace intrusive { | |
83 | } //namespace boost { | |
84 | ||
85 | ||
86 | namespace boost { | |
87 | namespace intrusive { | |
88 | ||
89 | template <class PointedType> | |
90 | class smart_ptr | |
91 | { | |
92 | typedef random_it<PointedType> random_it_t; | |
93 | typedef smart_ptr<PointedType> self_t; | |
94 | typedef typename random_it_t::const_pointer const_pointer_t; | |
95 | typedef typename random_it_t::const_reference const_reference_t; | |
96 | ||
97 | void unspecified_bool_type_func() const {} | |
98 | typedef void (self_t::*unspecified_bool_type)() const; | |
99 | ||
100 | public: | |
101 | typedef PointedType * pointer; | |
102 | typedef typename random_it_t::reference reference; | |
103 | typedef PointedType value_type; | |
104 | typedef typename random_it_t::difference_type difference_type; | |
105 | typedef typename random_it_t::iterator_category iterator_category; | |
106 | ||
107 | PointedType *m_ptr; | |
108 | ||
109 | public: //Public Functions | |
110 | ||
111 | smart_ptr() | |
112 | : m_ptr(0) | |
113 | {} | |
114 | ||
115 | //!Constructor from other smart_ptr | |
116 | smart_ptr(const smart_ptr& ptr) | |
117 | : m_ptr(ptr.m_ptr) | |
118 | {} | |
119 | ||
120 | static smart_ptr pointer_to(reference r) | |
121 | { smart_ptr p; p.m_ptr = &r; return p; } | |
122 | ||
123 | //!Constructor from other smart_ptr. If pointers of pointee types are | |
124 | //!convertible, offset_ptrs will be convertibles. Never throws. | |
125 | template<class T2> | |
126 | smart_ptr(const smart_ptr<T2> &ptr) | |
127 | : m_ptr(ptr.m_ptr) | |
128 | {} | |
129 | ||
130 | pointer get() const | |
131 | { return m_ptr; } | |
132 | ||
133 | void set(pointer p) | |
134 | { m_ptr = p; } | |
135 | ||
136 | //!Pointer-like -> operator. It can return 0 pointer. Never throws. | |
137 | pointer operator->() const | |
138 | { return m_ptr; } | |
139 | ||
140 | //!Dereferencing operator, if it is a null smart_ptr behavior | |
141 | //! is undefined. Never throws. | |
142 | reference operator* () const | |
143 | { return *m_ptr; } | |
144 | ||
145 | //!Indexing operator. Never throws. | |
146 | reference operator[](std::ptrdiff_t idx) const | |
147 | { return m_ptr[idx]; } | |
148 | ||
149 | //!Assignment from other smart_ptr. Never throws. | |
150 | smart_ptr& operator= (const smart_ptr & pt) | |
151 | { m_ptr = pt.m_ptr; return *this; } | |
152 | ||
153 | //!Assignment from related smart_ptr. If pointers of pointee types | |
154 | //! are assignable, offset_ptrs will be assignable. Never throws. | |
155 | template <class T2> | |
156 | smart_ptr& operator= (const smart_ptr<T2> & pt) | |
157 | { m_ptr = pt.m_ptr; return *this; } | |
158 | ||
159 | //!smart_ptr + std::ptrdiff_t. Never throws. | |
160 | smart_ptr operator+ (std::ptrdiff_t offset) const | |
161 | { smart_ptr s; s.m_ptr = m_ptr + offset; return s; } | |
162 | ||
163 | //!smart_ptr - std::ptrdiff_t. Never throws. | |
164 | smart_ptr operator- (std::ptrdiff_t offset) const | |
165 | { smart_ptr s; s.m_ptr = m_ptr - offset; return s; } | |
166 | ||
167 | //!smart_ptr += std::ptrdiff_t. Never throws. | |
168 | smart_ptr &operator+= (std::ptrdiff_t offset) | |
169 | { m_ptr += offset; return *this; } | |
170 | ||
171 | //!smart_ptr -= std::ptrdiff_t. Never throws. | |
172 | smart_ptr &operator-= (std::ptrdiff_t offset) | |
173 | { m_ptr -= offset; return *this; } | |
174 | ||
175 | //!++smart_ptr. Never throws. | |
176 | smart_ptr& operator++ (void) | |
177 | { ++m_ptr; return *this; } | |
178 | ||
179 | //!smart_ptr++. Never throws. | |
180 | smart_ptr operator++ (int) | |
181 | { smart_ptr temp(*this); ++*this; return temp; } | |
182 | ||
183 | //!--smart_ptr. Never throws. | |
184 | smart_ptr& operator-- (void) | |
185 | { --m_ptr; return *this; } | |
186 | ||
187 | //!smart_ptr--. Never throws. | |
188 | smart_ptr operator-- (int) | |
189 | { smart_ptr temp(*this); --*this; return temp; } | |
190 | ||
191 | //!safe bool conversion operator. Never throws. | |
192 | operator unspecified_bool_type() const | |
193 | { return m_ptr? &self_t::unspecified_bool_type_func : 0; } | |
194 | ||
195 | //!Not operator. Not needed in theory, but improves portability. | |
196 | //!Never throws. | |
197 | bool operator! () const | |
198 | { return m_ptr == 0; } | |
199 | ||
200 | //!swap | |
201 | friend void swap(smart_ptr& x, smart_ptr& y) | |
202 | { boost::adl_move_swap(x.m_ptr, y.m_ptr); } | |
203 | }; | |
204 | ||
205 | //!smart_ptr<T1> == smart_ptr<T2>. Never throws. | |
206 | template<class T1, class T2> | |
207 | inline bool operator== (const smart_ptr<T1> &pt1, | |
208 | const smart_ptr<T2> &pt2) | |
209 | { return pt1.operator->() == pt2.operator->(); } | |
210 | ||
211 | //!smart_ptr<T1> != smart_ptr<T2>. Never throws. | |
212 | template<class T1, class T2> | |
213 | inline bool operator!= (const smart_ptr<T1> &pt1, | |
214 | const smart_ptr<T2> &pt2) | |
215 | { return pt1.operator->() != pt2.operator->(); } | |
216 | ||
217 | //!smart_ptr<T1> < smart_ptr<T2>. Never throws. | |
218 | template<class T1, class T2> | |
219 | inline bool operator< (const smart_ptr<T1> &pt1, | |
220 | const smart_ptr<T2> &pt2) | |
221 | { return pt1.operator->() < pt2.operator->(); } | |
222 | ||
223 | //!smart_ptr<T1> <= smart_ptr<T2>. Never throws. | |
224 | template<class T1, class T2> | |
225 | inline bool operator<= (const smart_ptr<T1> &pt1, | |
226 | const smart_ptr<T2> &pt2) | |
227 | { return pt1.operator->() <= pt2.operator->(); } | |
228 | ||
229 | //!smart_ptr<T1> > smart_ptr<T2>. Never throws. | |
230 | template<class T1, class T2> | |
231 | inline bool operator> (const smart_ptr<T1> &pt1, | |
232 | const smart_ptr<T2> &pt2) | |
233 | { return pt1.operator->() > pt2.operator->(); } | |
234 | ||
235 | //!smart_ptr<T1> >= smart_ptr<T2>. Never throws. | |
236 | template<class T1, class T2> | |
237 | inline bool operator>= (const smart_ptr<T1> &pt1, | |
238 | const smart_ptr<T2> &pt2) | |
239 | { return pt1.operator->() >= pt2.operator->(); } | |
240 | ||
241 | //!operator<< | |
242 | template<class E, class T, class Y> | |
243 | inline std::basic_ostream<E, T> & operator<< | |
244 | (std::basic_ostream<E, T> & os, smart_ptr<Y> const & p) | |
245 | { return os << p.operator->(); } | |
246 | ||
247 | //!operator>> | |
248 | template<class E, class T, class Y> | |
249 | inline std::basic_istream<E, T> & operator>> | |
250 | (std::basic_istream<E, T> & os, smart_ptr<Y> & p) | |
251 | { Y * tmp; return os >> tmp; p = tmp; } | |
252 | ||
253 | //!std::ptrdiff_t + smart_ptr | |
254 | template<class T> | |
255 | inline smart_ptr<T> operator+(std::ptrdiff_t diff, const smart_ptr<T>& right) | |
256 | { return right + diff; } | |
257 | ||
258 | //!smart_ptr - smart_ptr | |
259 | template<class T, class T2> | |
260 | inline std::ptrdiff_t operator- (const smart_ptr<T> &pt, const smart_ptr<T2> &pt2) | |
261 | { return pt.operator->()- pt2.operator->(); } | |
262 | ||
263 | } //namespace intrusive { | |
264 | } //namespace boost { | |
265 | ||
266 | namespace boost{ | |
267 | ||
268 | //This is to support embedding a bit in the pointer | |
269 | //for intrusive containers, saving space | |
270 | namespace intrusive { | |
271 | ||
272 | template<std::size_t Alignment> | |
273 | struct max_pointer_plus_bits<smart_ptr<void>, Alignment> | |
274 | { | |
275 | static const std::size_t value = max_pointer_plus_bits<void*, Alignment>::value; | |
276 | }; | |
277 | ||
278 | template<class T, std::size_t NumBits> | |
279 | struct pointer_plus_bits<smart_ptr<T>, NumBits> | |
280 | { | |
281 | typedef smart_ptr<T> pointer; | |
282 | ||
283 | static pointer get_pointer(const pointer &n) | |
284 | { | |
285 | pointer p; | |
286 | p.set(pointer_plus_bits<T*, NumBits>::get_pointer(n.get())); | |
287 | return p; | |
288 | } | |
289 | ||
290 | static void set_pointer(pointer &n, pointer p) | |
291 | { | |
292 | T *raw_n = n.get(); | |
293 | pointer_plus_bits<T*, NumBits>::set_pointer(raw_n, p.operator->()); | |
294 | n.set(raw_n); | |
295 | } | |
296 | ||
297 | static std::size_t get_bits(const pointer &n) | |
298 | { return pointer_plus_bits<T*, NumBits>::get_bits(n.get()); } | |
299 | ||
300 | static void set_bits(pointer &n, std::size_t c) | |
301 | { | |
302 | T *raw_n = n.operator->(); | |
303 | pointer_plus_bits<T*, NumBits>::set_bits(raw_n, c); | |
304 | n.set(raw_n); | |
305 | } | |
306 | }; | |
307 | ||
308 | } //namespace intrusive | |
309 | } //namespace boost{ | |
310 | ||
311 | #endif //#ifndef BOOST_INTRUSIVE_SMART_PTR_HPP |