• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/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/smart_ptr/detail/sp_noexcept.hpp>
28 #include <boost/config/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 
shared_array()57     shared_array() BOOST_SP_NOEXCEPT : px( 0 ), pn()
58     {
59     }
60 
61 #if !defined( BOOST_NO_CXX11_NULLPTR )
62 
shared_array(boost::detail::sp_nullptr_t)63     shared_array( boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT : px( 0 ), pn()
64     {
65     }
66 
67 #endif
68 
69     template<class Y>
shared_array(Y * p)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 
shared_array(Y * p,D d)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 
shared_array(Y * p,D d,A a)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 
shared_array(shared_array const & r)99     shared_array( shared_array const & r ) BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn )
100     {
101     }
102 
shared_array(shared_array && r)103     shared_array( shared_array && r ) BOOST_SP_NOEXCEPT : px( r.px ), pn()
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 
shared_array(shared_array<Y> const & r,typename boost::detail::sp_enable_if_convertible<Y[],T[]>::type=boost::detail::sp_empty ())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
123     BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn )
124     {
125         boost::detail::sp_assert_convertible< Y[], T[] >();
126     }
127 
128     // aliasing
129 
130     template< class Y >
shared_array(shared_array<Y> const & r,element_type * p)131     shared_array( shared_array<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPT : px( p ), pn( r.pn )
132     {
133     }
134 
135     // assignment
136 
operator =(shared_array const & r)137     shared_array & operator=( shared_array const & r ) BOOST_SP_NOEXCEPT
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>
operator =(shared_array<Y> const & r)146     shared_array & operator=( shared_array<Y> const & r ) BOOST_SP_NOEXCEPT
147     {
148         this_type( r ).swap( *this );
149         return *this;
150     }
151 
152 #endif
153 
154 #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
155 
operator =(shared_array && r)156     shared_array & operator=( shared_array && r ) BOOST_SP_NOEXCEPT
157     {
158         this_type( static_cast< shared_array && >( r ) ).swap( *this );
159         return *this;
160     }
161 
162     template<class Y>
operator =(shared_array<Y> && r)163     shared_array & operator=( shared_array<Y> && r ) BOOST_SP_NOEXCEPT
164     {
165         this_type( static_cast< shared_array<Y> && >( r ) ).swap( *this );
166         return *this;
167     }
168 
169 #endif
170 
reset()171     void reset() BOOST_SP_NOEXCEPT
172     {
173         this_type().swap( *this );
174     }
175 
reset(Y * p)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 
reset(Y * p,D d)182     template<class Y, class D> void reset( Y * p, D d )
183     {
184         this_type( p, d ).swap( *this );
185     }
186 
reset(Y * p,D d,A a)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 
reset(shared_array<Y> const & r,element_type * p)192     template<class Y> void reset( shared_array<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPT
193     {
194         this_type( r, p ).swap( *this );
195     }
196 
operator [](std::ptrdiff_t i) const197     T & operator[] (std::ptrdiff_t i) const BOOST_SP_NOEXCEPT_WITH_ASSERT
198     {
199         BOOST_ASSERT(px != 0);
200         BOOST_ASSERT(i >= 0);
201         return px[i];
202     }
203 
get() const204     T * get() const BOOST_SP_NOEXCEPT
205     {
206         return px;
207     }
208 
209 // implicit conversion to "bool"
210 #include <boost/smart_ptr/detail/operator_bool.hpp>
211 
unique() const212     bool unique() const BOOST_SP_NOEXCEPT
213     {
214         return pn.unique();
215     }
216 
use_count() const217     long use_count() const BOOST_SP_NOEXCEPT
218     {
219         return pn.use_count();
220     }
221 
swap(shared_array<T> & other)222     void swap(shared_array<T> & other) BOOST_SP_NOEXCEPT
223     {
224         std::swap(px, other.px);
225         pn.swap(other.pn);
226     }
227 
_internal_get_deleter(boost::detail::sp_typeinfo_ const & ti) const228     void * _internal_get_deleter( boost::detail::sp_typeinfo_ const & ti ) const BOOST_SP_NOEXCEPT
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 
operator ==(shared_array<T> const & a,shared_array<T> const & b)242 template<class T> inline bool operator==(shared_array<T> const & a, shared_array<T> const & b) BOOST_SP_NOEXCEPT
243 {
244     return a.get() == b.get();
245 }
246 
operator !=(shared_array<T> const & a,shared_array<T> const & b)247 template<class T> inline bool operator!=(shared_array<T> const & a, shared_array<T> const & b) BOOST_SP_NOEXCEPT
248 {
249     return a.get() != b.get();
250 }
251 
252 #if !defined( BOOST_NO_CXX11_NULLPTR )
253 
operator ==(shared_array<T> const & p,boost::detail::sp_nullptr_t)254 template<class T> inline bool operator==( shared_array<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
255 {
256     return p.get() == 0;
257 }
258 
operator ==(boost::detail::sp_nullptr_t,shared_array<T> const & p)259 template<class T> inline bool operator==( boost::detail::sp_nullptr_t, shared_array<T> const & p ) BOOST_SP_NOEXCEPT
260 {
261     return p.get() == 0;
262 }
263 
operator !=(shared_array<T> const & p,boost::detail::sp_nullptr_t)264 template<class T> inline bool operator!=( shared_array<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
265 {
266     return p.get() != 0;
267 }
268 
operator !=(boost::detail::sp_nullptr_t,shared_array<T> const & p)269 template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, shared_array<T> const & p ) BOOST_SP_NOEXCEPT
270 {
271     return p.get() != 0;
272 }
273 
274 #endif
275 
operator <(shared_array<T> const & a,shared_array<T> const & b)276 template<class T> inline bool operator<(shared_array<T> const & a, shared_array<T> const & b) BOOST_SP_NOEXCEPT
277 {
278     return std::less<T*>()(a.get(), b.get());
279 }
280 
swap(shared_array<T> & a,shared_array<T> & b)281 template<class T> void swap(shared_array<T> & a, shared_array<T> & b) BOOST_SP_NOEXCEPT
282 {
283     a.swap(b);
284 }
285 
get_deleter(shared_array<T> const & p)286 template< class D, class T > D * get_deleter( shared_array<T> const & p ) BOOST_SP_NOEXCEPT
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
294