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