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