1 | // |
2 | // Boost.Pointer Container |
3 | // |
4 | // Copyright Thorsten Ottosen 2003-2005. Use, modification and |
5 | // distribution is subject to the Boost Software License, Version |
6 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
7 | // http://www.boost.org/LICENSE_1_0.txt) |
8 | // |
9 | // For more information, see http://www.boost.org/libs/ptr_container/ |
10 | // |
11 | |
12 | #ifndef BOOST_PTR_CONTAINER_PTR_ARRAY_HPP |
13 | #define BOOST_PTR_CONTAINER_PTR_ARRAY_HPP |
14 | |
15 | #if defined(_MSC_VER) && (_MSC_VER >= 1200) |
16 | # pragma once |
17 | #endif |
18 | |
19 | #include <boost/array.hpp> |
20 | #include <boost/static_assert.hpp> |
21 | #include <boost/ptr_container/ptr_sequence_adapter.hpp> |
22 | |
23 | namespace boost |
24 | { |
25 | |
26 | namespace ptr_container_detail |
27 | { |
28 | template |
29 | < |
30 | class T, |
31 | size_t N, |
32 | class Allocator = int // dummy |
33 | > |
34 | class ptr_array_impl : public boost::array<T,N> |
35 | { |
36 | public: |
37 | typedef Allocator allocator_type; |
38 | |
39 | ptr_array_impl( Allocator /*a*/ = Allocator() ) |
40 | { |
41 | this->assign( 0 ); |
42 | } |
43 | |
44 | ptr_array_impl( size_t, T*, Allocator /*a*/ = Allocator() ) |
45 | { |
46 | this->assign( 0 ); |
47 | } |
48 | }; |
49 | } |
50 | |
51 | template |
52 | < |
53 | class T, |
54 | size_t N, |
55 | class CloneAllocator = heap_clone_allocator |
56 | > |
57 | class ptr_array : public |
58 | ptr_sequence_adapter< T, |
59 | ptr_container_detail::ptr_array_impl<void*,N>, |
60 | CloneAllocator > |
61 | { |
62 | private: |
63 | typedef ptr_sequence_adapter< T, |
64 | ptr_container_detail::ptr_array_impl<void*,N>, |
65 | CloneAllocator > |
66 | base_class; |
67 | |
68 | typedef BOOST_DEDUCED_TYPENAME remove_nullable<T>::type U; |
69 | |
70 | typedef ptr_array<T,N,CloneAllocator> |
71 | this_type; |
72 | |
73 | public: |
74 | typedef std::size_t size_type; |
75 | typedef U* value_type; |
76 | typedef U* pointer; |
77 | typedef U& reference; |
78 | typedef const U& const_reference; |
79 | typedef BOOST_DEDUCED_TYPENAME base_class::auto_type |
80 | auto_type; |
81 | |
82 | public: // constructors |
83 | ptr_array() : base_class() |
84 | { } |
85 | |
86 | ptr_array( const ptr_array& r ) |
87 | { |
88 | size_t i = 0; |
89 | for( ; i != N; ++i ) |
90 | this->base()[i] = this->null_policy_allocate_clone( |
91 | static_cast<const T*>( &r[i] ) ); |
92 | } |
93 | |
94 | template< class U > |
95 | ptr_array( const ptr_array<U,N>& r ) |
96 | { |
97 | size_t i = 0; |
98 | for( ; i != N; ++i ) |
99 | this->base()[i] = this->null_policy_allocate_clone( |
100 | static_cast<const T*>( &r[i] ) ); |
101 | } |
102 | |
103 | explicit ptr_array( std::auto_ptr<this_type> r ) |
104 | : base_class( r ) { } |
105 | |
106 | ptr_array& operator=( ptr_array r ) |
107 | { |
108 | this->swap( r ); |
109 | return *this; |
110 | } |
111 | |
112 | ptr_array& operator=( std::auto_ptr<this_type> r ) |
113 | { |
114 | base_class::operator=(r); |
115 | return *this; |
116 | } |
117 | |
118 | std::auto_ptr<this_type> release() |
119 | { |
120 | std::auto_ptr<this_type> ptr( new this_type ); |
121 | this->swap( *ptr ); |
122 | return ptr; |
123 | } |
124 | |
125 | std::auto_ptr<this_type> clone() const |
126 | { |
127 | std::auto_ptr<this_type> pa( new this_type ); |
128 | for( size_t i = 0; i != N; ++i ) |
129 | { |
130 | if( ! is_null(i) ) |
131 | pa->replace( i, this->null_policy_allocate_clone( &(*this)[i] ) ); |
132 | } |
133 | return pa; |
134 | } |
135 | |
136 | private: // hide some members |
137 | using base_class::insert; |
138 | using base_class::erase; |
139 | using base_class::push_back; |
140 | using base_class::push_front; |
141 | using base_class::pop_front; |
142 | using base_class::pop_back; |
143 | using base_class::transfer; |
144 | using base_class::get_allocator; |
145 | |
146 | public: // compile-time interface |
147 | |
148 | template< size_t idx > |
149 | auto_type replace( U* r ) // strong |
150 | { |
151 | BOOST_STATIC_ASSERT( idx < N ); |
152 | |
153 | this->enforce_null_policy( r, "Null pointer in 'ptr_array::replace()'" ); |
154 | |
155 | auto_type res( static_cast<U*>( this->base()[idx] ) ); // nothrow |
156 | this->base()[idx] = r; // nothrow |
157 | return boost::ptr_container::move(res); // nothrow |
158 | } |
159 | |
160 | template< size_t idx, class V > |
161 | auto_type replace( std::auto_ptr<V> r ) |
162 | { |
163 | return replace<idx>( r.release() ); |
164 | } |
165 | |
166 | auto_type replace( size_t idx, U* r ) // strong |
167 | { |
168 | this->enforce_null_policy( r, "Null pointer in 'ptr_array::replace()'" ); |
169 | |
170 | auto_type ptr( r ); |
171 | |
172 | BOOST_PTR_CONTAINER_THROW_EXCEPTION( idx >= N, bad_index, |
173 | "'replace()' aout of bounds" ); |
174 | |
175 | auto_type res( static_cast<U*>( this->base()[idx] ) ); // nothrow |
176 | this->base()[idx] = ptr.release(); // nothrow |
177 | return boost::ptr_container::move(res); // nothrow |
178 | } |
179 | |
180 | template< class V > |
181 | auto_type replace( size_t idx, std::auto_ptr<V> r ) |
182 | { |
183 | return replace( idx, r.release() ); |
184 | } |
185 | |
186 | using base_class::at; |
187 | |
188 | template< size_t idx > |
189 | T& at() |
190 | { |
191 | BOOST_STATIC_ASSERT( idx < N ); |
192 | return (*this)[idx]; |
193 | } |
194 | |
195 | template< size_t idx > |
196 | const T& at() const |
197 | { |
198 | BOOST_STATIC_ASSERT( idx < N ); |
199 | return (*this)[idx]; |
200 | } |
201 | |
202 | bool is_null( size_t idx ) const |
203 | { |
204 | return base_class::is_null(idx); |
205 | } |
206 | |
207 | template< size_t idx > |
208 | bool is_null() const |
209 | { |
210 | BOOST_STATIC_ASSERT( idx < N ); |
211 | return this->base()[idx] == 0; |
212 | } |
213 | }; |
214 | |
215 | ////////////////////////////////////////////////////////////////////////////// |
216 | // clonability |
217 | |
218 | template< typename T, size_t size, typename CA > |
219 | inline ptr_array<T,size,CA>* new_clone( const ptr_array<T,size,CA>& r ) |
220 | { |
221 | return r.clone().release(); |
222 | } |
223 | |
224 | ///////////////////////////////////////////////////////////////////////// |
225 | // swap |
226 | |
227 | template< typename T, size_t size, typename CA > |
228 | inline void swap( ptr_array<T,size,CA>& l, ptr_array<T,size,CA>& r ) |
229 | { |
230 | l.swap(r); |
231 | } |
232 | } |
233 | |
234 | #endif |
235 | |