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