]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | #ifndef BOOST_SMART_PTR_SHARED_ARRAY_HPP_INCLUDED |
2 | #define BOOST_SMART_PTR_SHARED_ARRAY_HPP_INCLUDED | |
3 | ||
4 | // | |
5 | // shared_array.hpp | |
6 | // | |
7 | // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. | |
8 | // Copyright (c) 2001, 2002, 2012 Peter Dimov | |
9 | // | |
10 | // Distributed under the Boost Software License, Version 1.0. (See | |
11 | // accompanying file LICENSE_1_0.txt or copy at | |
12 | // http://www.boost.org/LICENSE_1_0.txt) | |
13 | // | |
b32b8144 | 14 | // See http://www.boost.org/libs/smart_ptr/ for documentation. |
7c673cae FG |
15 | // |
16 | ||
17 | #include <boost/config.hpp> // for broken compiler workarounds | |
18 | ||
19 | #include <memory> // TR1 cyclic inclusion fix | |
20 | ||
21 | #include <boost/assert.hpp> | |
22 | #include <boost/checked_delete.hpp> | |
23 | ||
24 | #include <boost/smart_ptr/shared_ptr.hpp> | |
25 | #include <boost/smart_ptr/detail/shared_count.hpp> | |
26 | #include <boost/smart_ptr/detail/sp_nullptr_t.hpp> | |
b32b8144 | 27 | #include <boost/smart_ptr/detail/sp_noexcept.hpp> |
7c673cae FG |
28 | #include <boost/detail/workaround.hpp> |
29 | ||
30 | #include <cstddef> // for std::ptrdiff_t | |
31 | #include <algorithm> // for std::swap | |
32 | #include <functional> // for std::less | |
33 | ||
34 | namespace boost | |
35 | { | |
36 | ||
37 | // | |
38 | // shared_array | |
39 | // | |
40 | // shared_array extends shared_ptr to arrays. | |
41 | // The array pointed to is deleted when the last shared_array pointing to it | |
42 | // is destroyed or reset. | |
43 | // | |
44 | ||
45 | template<class T> class shared_array | |
46 | { | |
47 | private: | |
48 | ||
49 | // Borland 5.5.1 specific workarounds | |
50 | typedef checked_array_deleter<T> deleter; | |
51 | typedef shared_array<T> this_type; | |
52 | ||
53 | public: | |
54 | ||
55 | typedef T element_type; | |
56 | ||
b32b8144 | 57 | shared_array() BOOST_SP_NOEXCEPT : px( 0 ), pn() |
7c673cae FG |
58 | { |
59 | } | |
60 | ||
61 | #if !defined( BOOST_NO_CXX11_NULLPTR ) | |
62 | ||
b32b8144 | 63 | shared_array( boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT : px( 0 ), pn() |
7c673cae FG |
64 | { |
65 | } | |
66 | ||
67 | #endif | |
68 | ||
69 | template<class Y> | |
70 | explicit shared_array( Y * p ): px( p ), pn( p, checked_array_deleter<Y>() ) | |
71 | { | |
72 | boost::detail::sp_assert_convertible< Y[], T[] >(); | |
73 | } | |
74 | ||
75 | // | |
76 | // Requirements: D's copy constructor must not throw | |
77 | // | |
78 | // shared_array will release p by calling d(p) | |
79 | // | |
80 | ||
81 | template<class Y, class D> shared_array( Y * p, D d ): px( p ), pn( p, d ) | |
82 | { | |
83 | boost::detail::sp_assert_convertible< Y[], T[] >(); | |
84 | } | |
85 | ||
86 | // As above, but with allocator. A's copy constructor shall not throw. | |
87 | ||
88 | template<class Y, class D, class A> shared_array( Y * p, D d, A a ): px( p ), pn( p, d, a ) | |
89 | { | |
90 | boost::detail::sp_assert_convertible< Y[], T[] >(); | |
91 | } | |
92 | ||
93 | // generated copy constructor, destructor are fine... | |
94 | ||
95 | #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) | |
96 | ||
97 | // ... except in C++0x, move disables the implicit copy | |
98 | ||
b32b8144 | 99 | shared_array( shared_array const & r ) BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn ) |
7c673cae FG |
100 | { |
101 | } | |
102 | ||
b32b8144 | 103 | shared_array( shared_array && r ) BOOST_SP_NOEXCEPT : px( r.px ), pn() |
7c673cae FG |
104 | { |
105 | pn.swap( r.pn ); | |
106 | r.px = 0; | |
107 | } | |
108 | ||
109 | #endif | |
110 | ||
111 | // conversion | |
112 | ||
113 | template<class Y> | |
114 | #if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) | |
115 | ||
116 | shared_array( shared_array<Y> const & r, typename boost::detail::sp_enable_if_convertible< Y[], T[] >::type = boost::detail::sp_empty() ) | |
117 | ||
118 | #else | |
119 | ||
120 | shared_array( shared_array<Y> const & r ) | |
121 | ||
122 | #endif | |
b32b8144 | 123 | BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn ) |
7c673cae FG |
124 | { |
125 | boost::detail::sp_assert_convertible< Y[], T[] >(); | |
126 | } | |
127 | ||
128 | // aliasing | |
129 | ||
130 | template< class Y > | |
b32b8144 | 131 | shared_array( shared_array<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPT : px( p ), pn( r.pn ) |
7c673cae FG |
132 | { |
133 | } | |
134 | ||
135 | // assignment | |
136 | ||
b32b8144 | 137 | shared_array & operator=( shared_array const & r ) BOOST_SP_NOEXCEPT |
7c673cae FG |
138 | { |
139 | this_type( r ).swap( *this ); | |
140 | return *this; | |
141 | } | |
142 | ||
143 | #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1400) | |
144 | ||
145 | template<class Y> | |
b32b8144 | 146 | shared_array & operator=( shared_array<Y> const & r ) BOOST_SP_NOEXCEPT |
7c673cae FG |
147 | { |
148 | this_type( r ).swap( *this ); | |
149 | return *this; | |
150 | } | |
151 | ||
152 | #endif | |
153 | ||
154 | #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) | |
155 | ||
b32b8144 | 156 | shared_array & operator=( shared_array && r ) BOOST_SP_NOEXCEPT |
7c673cae FG |
157 | { |
158 | this_type( static_cast< shared_array && >( r ) ).swap( *this ); | |
159 | return *this; | |
160 | } | |
161 | ||
162 | template<class Y> | |
b32b8144 | 163 | shared_array & operator=( shared_array<Y> && r ) BOOST_SP_NOEXCEPT |
7c673cae FG |
164 | { |
165 | this_type( static_cast< shared_array<Y> && >( r ) ).swap( *this ); | |
166 | return *this; | |
167 | } | |
168 | ||
169 | #endif | |
170 | ||
b32b8144 | 171 | void reset() BOOST_SP_NOEXCEPT |
7c673cae FG |
172 | { |
173 | this_type().swap( *this ); | |
174 | } | |
175 | ||
176 | template<class Y> void reset( Y * p ) // Y must be complete | |
177 | { | |
178 | BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors | |
179 | this_type( p ).swap( *this ); | |
180 | } | |
181 | ||
182 | template<class Y, class D> void reset( Y * p, D d ) | |
183 | { | |
184 | this_type( p, d ).swap( *this ); | |
185 | } | |
186 | ||
187 | template<class Y, class D, class A> void reset( Y * p, D d, A a ) | |
188 | { | |
189 | this_type( p, d, a ).swap( *this ); | |
190 | } | |
191 | ||
b32b8144 | 192 | template<class Y> void reset( shared_array<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPT |
7c673cae FG |
193 | { |
194 | this_type( r, p ).swap( *this ); | |
195 | } | |
196 | ||
b32b8144 | 197 | T & operator[] (std::ptrdiff_t i) const BOOST_SP_NOEXCEPT_WITH_ASSERT |
7c673cae FG |
198 | { |
199 | BOOST_ASSERT(px != 0); | |
200 | BOOST_ASSERT(i >= 0); | |
201 | return px[i]; | |
202 | } | |
203 | ||
b32b8144 | 204 | T * get() const BOOST_SP_NOEXCEPT |
7c673cae FG |
205 | { |
206 | return px; | |
207 | } | |
208 | ||
209 | // implicit conversion to "bool" | |
210 | #include <boost/smart_ptr/detail/operator_bool.hpp> | |
211 | ||
b32b8144 | 212 | bool unique() const BOOST_SP_NOEXCEPT |
7c673cae FG |
213 | { |
214 | return pn.unique(); | |
215 | } | |
216 | ||
b32b8144 | 217 | long use_count() const BOOST_SP_NOEXCEPT |
7c673cae FG |
218 | { |
219 | return pn.use_count(); | |
220 | } | |
221 | ||
b32b8144 | 222 | void swap(shared_array<T> & other) BOOST_SP_NOEXCEPT |
7c673cae FG |
223 | { |
224 | std::swap(px, other.px); | |
225 | pn.swap(other.pn); | |
226 | } | |
227 | ||
b32b8144 | 228 | void * _internal_get_deleter( boost::detail::sp_typeinfo const & ti ) const BOOST_SP_NOEXCEPT |
7c673cae FG |
229 | { |
230 | return pn.get_deleter( ti ); | |
231 | } | |
232 | ||
233 | private: | |
234 | ||
235 | template<class Y> friend class shared_array; | |
236 | ||
237 | T * px; // contained pointer | |
238 | detail::shared_count pn; // reference counter | |
239 | ||
240 | }; // shared_array | |
241 | ||
b32b8144 | 242 | template<class T> inline bool operator==(shared_array<T> const & a, shared_array<T> const & b) BOOST_SP_NOEXCEPT |
7c673cae FG |
243 | { |
244 | return a.get() == b.get(); | |
245 | } | |
246 | ||
b32b8144 | 247 | template<class T> inline bool operator!=(shared_array<T> const & a, shared_array<T> const & b) BOOST_SP_NOEXCEPT |
7c673cae FG |
248 | { |
249 | return a.get() != b.get(); | |
250 | } | |
251 | ||
252 | #if !defined( BOOST_NO_CXX11_NULLPTR ) | |
253 | ||
b32b8144 | 254 | template<class T> inline bool operator==( shared_array<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT |
7c673cae FG |
255 | { |
256 | return p.get() == 0; | |
257 | } | |
258 | ||
b32b8144 | 259 | template<class T> inline bool operator==( boost::detail::sp_nullptr_t, shared_array<T> const & p ) BOOST_SP_NOEXCEPT |
7c673cae FG |
260 | { |
261 | return p.get() == 0; | |
262 | } | |
263 | ||
b32b8144 | 264 | template<class T> inline bool operator!=( shared_array<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT |
7c673cae FG |
265 | { |
266 | return p.get() != 0; | |
267 | } | |
268 | ||
b32b8144 | 269 | template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, shared_array<T> const & p ) BOOST_SP_NOEXCEPT |
7c673cae FG |
270 | { |
271 | return p.get() != 0; | |
272 | } | |
273 | ||
274 | #endif | |
275 | ||
b32b8144 | 276 | template<class T> inline bool operator<(shared_array<T> const & a, shared_array<T> const & b) BOOST_SP_NOEXCEPT |
7c673cae FG |
277 | { |
278 | return std::less<T*>()(a.get(), b.get()); | |
279 | } | |
280 | ||
b32b8144 | 281 | template<class T> void swap(shared_array<T> & a, shared_array<T> & b) BOOST_SP_NOEXCEPT |
7c673cae FG |
282 | { |
283 | a.swap(b); | |
284 | } | |
285 | ||
b32b8144 | 286 | template< class D, class T > D * get_deleter( shared_array<T> const & p ) BOOST_SP_NOEXCEPT |
7c673cae FG |
287 | { |
288 | return static_cast< D * >( p._internal_get_deleter( BOOST_SP_TYPEID(D) ) ); | |
289 | } | |
290 | ||
291 | } // namespace boost | |
292 | ||
293 | #endif // #ifndef BOOST_SMART_PTR_SHARED_ARRAY_HPP_INCLUDED |