williamr@2
|
1 |
//
|
williamr@2
|
2 |
// Boost.Pointer Container
|
williamr@2
|
3 |
//
|
williamr@2
|
4 |
// Copyright Thorsten Ottosen 2003-2005. Use, modification and
|
williamr@2
|
5 |
// distribution is subject to the Boost Software License, Version
|
williamr@2
|
6 |
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
williamr@2
|
7 |
// http://www.boost.org/LICENSE_1_0.txt)
|
williamr@2
|
8 |
//
|
williamr@2
|
9 |
// For more information, see http://www.boost.org/libs/ptr_container/
|
williamr@2
|
10 |
//
|
williamr@2
|
11 |
/*
|
williamr@2
|
12 |
* © Portions copyright (c) 2006-2007 Nokia Corporation. All rights reserved.
|
williamr@2
|
13 |
*/
|
williamr@2
|
14 |
#ifndef BOOST_ptr_container_PTR_SEQUENCE_ADAPTER_HPP
|
williamr@2
|
15 |
#define BOOST_ptr_container_PTR_SEQUENCE_ADAPTER_HPP
|
williamr@2
|
16 |
|
williamr@2
|
17 |
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
williamr@2
|
18 |
# pragma once
|
williamr@2
|
19 |
#endif
|
williamr@2
|
20 |
|
williamr@2
|
21 |
|
williamr@2
|
22 |
#include <boost/ptr_container/detail/reversible_ptr_container.hpp>
|
williamr@2
|
23 |
#include <boost/ptr_container/indirect_fun.hpp>
|
williamr@2
|
24 |
#include <boost/ptr_container/detail/void_ptr_iterator.hpp>
|
williamr@2
|
25 |
#include <boost/type_traits/remove_pointer.hpp>
|
williamr@2
|
26 |
#include <boost/type_traits/is_same.hpp>
|
williamr@2
|
27 |
#include <boost/type_traits/is_pointer.hpp>
|
williamr@2
|
28 |
#include <boost/type_traits/is_integral.hpp>
|
williamr@2
|
29 |
#include <boost/iterator/iterator_categories.hpp>
|
williamr@2
|
30 |
#ifdef __SYMBIAN32__
|
williamr@2
|
31 |
#include <boost/range/begin.hpp>
|
williamr@2
|
32 |
#include <boost/range/end.hpp>
|
williamr@2
|
33 |
#endif
|
williamr@2
|
34 |
|
williamr@2
|
35 |
namespace boost
|
williamr@2
|
36 |
{
|
williamr@2
|
37 |
namespace ptr_container_detail
|
williamr@2
|
38 |
{
|
williamr@2
|
39 |
|
williamr@2
|
40 |
|
williamr@2
|
41 |
|
williamr@2
|
42 |
|
williamr@2
|
43 |
template
|
williamr@2
|
44 |
<
|
williamr@2
|
45 |
class T,
|
williamr@2
|
46 |
class VoidPtrSeq
|
williamr@2
|
47 |
>
|
williamr@2
|
48 |
struct sequence_config
|
williamr@2
|
49 |
{
|
williamr@2
|
50 |
typedef BOOST_DEDUCED_TYPENAME remove_nullable<T>::type
|
williamr@2
|
51 |
U;
|
williamr@2
|
52 |
typedef VoidPtrSeq
|
williamr@2
|
53 |
void_container_type;
|
williamr@2
|
54 |
|
williamr@2
|
55 |
typedef BOOST_DEDUCED_TYPENAME VoidPtrSeq::allocator_type
|
williamr@2
|
56 |
allocator_type;
|
williamr@2
|
57 |
|
williamr@2
|
58 |
typedef U value_type;
|
williamr@2
|
59 |
|
williamr@2
|
60 |
typedef void_ptr_iterator<
|
williamr@2
|
61 |
BOOST_DEDUCED_TYPENAME VoidPtrSeq::iterator, U >
|
williamr@2
|
62 |
iterator;
|
williamr@2
|
63 |
|
williamr@2
|
64 |
typedef void_ptr_iterator<
|
williamr@2
|
65 |
BOOST_DEDUCED_TYPENAME VoidPtrSeq::const_iterator, const U >
|
williamr@2
|
66 |
const_iterator;
|
williamr@2
|
67 |
|
williamr@2
|
68 |
#ifdef BOOST_NO_SFINAE
|
williamr@2
|
69 |
|
williamr@2
|
70 |
template< class Iter >
|
williamr@2
|
71 |
static U* get_pointer( Iter i )
|
williamr@2
|
72 |
{
|
williamr@2
|
73 |
return static_cast<U*>( *i.base() );
|
williamr@2
|
74 |
}
|
williamr@2
|
75 |
|
williamr@2
|
76 |
#else
|
williamr@2
|
77 |
template< class Iter >
|
williamr@2
|
78 |
static U* get_pointer( void_ptr_iterator<Iter,U> i )
|
williamr@2
|
79 |
{
|
williamr@2
|
80 |
return static_cast<U*>( *i.base() );
|
williamr@2
|
81 |
}
|
williamr@2
|
82 |
|
williamr@2
|
83 |
template< class Iter >
|
williamr@2
|
84 |
static U* get_pointer( Iter i )
|
williamr@2
|
85 |
{
|
williamr@2
|
86 |
return &*i;
|
williamr@2
|
87 |
}
|
williamr@2
|
88 |
#endif
|
williamr@2
|
89 |
|
williamr@2
|
90 |
#if defined(BOOST_NO_SFINAE) && !BOOST_WORKAROUND(__MWERKS__, <= 0x3003)
|
williamr@2
|
91 |
|
williamr@2
|
92 |
template< class Iter >
|
williamr@2
|
93 |
static const U* get_const_pointer( Iter i )
|
williamr@2
|
94 |
{
|
williamr@2
|
95 |
return static_cast<const U*>( *i.base() );
|
williamr@2
|
96 |
}
|
williamr@2
|
97 |
|
williamr@2
|
98 |
#else // BOOST_NO_SFINAE
|
williamr@2
|
99 |
|
williamr@2
|
100 |
#if BOOST_WORKAROUND(__MWERKS__, <= 0x3003)
|
williamr@2
|
101 |
template< class Iter >
|
williamr@2
|
102 |
static const U* get_const_pointer( void_ptr_iterator<Iter,U> i )
|
williamr@2
|
103 |
{
|
williamr@2
|
104 |
return static_cast<const U*>( *i.base() );
|
williamr@2
|
105 |
}
|
williamr@2
|
106 |
#else // BOOST_WORKAROUND
|
williamr@2
|
107 |
template< class Iter >
|
williamr@2
|
108 |
static const U* get_const_pointer( void_ptr_iterator<Iter,const U> i )
|
williamr@2
|
109 |
{
|
williamr@2
|
110 |
return static_cast<const U*>( *i.base() );
|
williamr@2
|
111 |
}
|
williamr@2
|
112 |
#endif // BOOST_WORKAROUND
|
williamr@2
|
113 |
|
williamr@2
|
114 |
template< class Iter >
|
williamr@2
|
115 |
static const U* get_const_pointer( Iter i )
|
williamr@2
|
116 |
{
|
williamr@2
|
117 |
return &*i;
|
williamr@2
|
118 |
}
|
williamr@2
|
119 |
#endif // BOOST_NO_SFINAE
|
williamr@2
|
120 |
|
williamr@2
|
121 |
BOOST_STATIC_CONSTANT(bool, allow_null = boost::is_nullable<T>::value );
|
williamr@2
|
122 |
};
|
williamr@2
|
123 |
|
williamr@2
|
124 |
} // ptr_container_detail
|
williamr@2
|
125 |
|
williamr@2
|
126 |
|
williamr@2
|
127 |
template< class Iterator, class T >
|
williamr@2
|
128 |
inline bool is_null( void_ptr_iterator<Iterator,T> i )
|
williamr@2
|
129 |
{
|
williamr@2
|
130 |
return *i.base() == 0;
|
williamr@2
|
131 |
}
|
williamr@2
|
132 |
|
williamr@2
|
133 |
|
williamr@2
|
134 |
|
williamr@2
|
135 |
template
|
williamr@2
|
136 |
<
|
williamr@2
|
137 |
class T,
|
williamr@2
|
138 |
class VoidPtrSeq,
|
williamr@2
|
139 |
class CloneAllocator = heap_clone_allocator
|
williamr@2
|
140 |
>
|
williamr@2
|
141 |
class ptr_sequence_adapter : public
|
williamr@2
|
142 |
ptr_container_detail::reversible_ptr_container< ptr_container_detail::sequence_config<T,VoidPtrSeq>,
|
williamr@2
|
143 |
CloneAllocator >
|
williamr@2
|
144 |
{
|
williamr@2
|
145 |
typedef ptr_container_detail::reversible_ptr_container< ptr_container_detail::sequence_config<T,VoidPtrSeq>,
|
williamr@2
|
146 |
CloneAllocator >
|
williamr@2
|
147 |
base_type;
|
williamr@2
|
148 |
|
williamr@2
|
149 |
typedef BOOST_DEDUCED_TYPENAME base_type::scoped_deleter scoped_deleter;
|
williamr@2
|
150 |
|
williamr@2
|
151 |
typedef ptr_sequence_adapter<T,VoidPtrSeq,CloneAllocator>
|
williamr@2
|
152 |
this_type;
|
williamr@2
|
153 |
|
williamr@2
|
154 |
public:
|
williamr@2
|
155 |
typedef BOOST_DEDUCED_TYPENAME base_type::value_type value_type;
|
williamr@2
|
156 |
typedef BOOST_DEDUCED_TYPENAME base_type::reference reference;
|
williamr@2
|
157 |
typedef BOOST_DEDUCED_TYPENAME base_type::auto_type auto_type;
|
williamr@2
|
158 |
|
williamr@2
|
159 |
BOOST_PTR_CONTAINER_DEFINE_CONSTRUCTORS( ptr_sequence_adapter,
|
williamr@2
|
160 |
base_type )
|
williamr@2
|
161 |
|
williamr@2
|
162 |
template< class PtrContainer >
|
williamr@2
|
163 |
ptr_sequence_adapter( std::auto_ptr<PtrContainer> clone )
|
williamr@2
|
164 |
: base_type( clone )
|
williamr@2
|
165 |
{ }
|
williamr@2
|
166 |
|
williamr@2
|
167 |
template< class PtrContainer >
|
williamr@2
|
168 |
void operator=( std::auto_ptr<PtrContainer> clone )
|
williamr@2
|
169 |
{
|
williamr@2
|
170 |
base_type::operator=( clone );
|
williamr@2
|
171 |
}
|
williamr@2
|
172 |
|
williamr@2
|
173 |
/////////////////////////////////////////////////////////////
|
williamr@2
|
174 |
// modifiers
|
williamr@2
|
175 |
/////////////////////////////////////////////////////////////
|
williamr@2
|
176 |
|
williamr@2
|
177 |
void push_back( value_type x ) // strong
|
williamr@2
|
178 |
{
|
williamr@2
|
179 |
this->enforce_null_policy( x, "Null pointer in 'push_back()'" );
|
williamr@2
|
180 |
|
williamr@2
|
181 |
auto_type ptr( x ); // notrow
|
williamr@2
|
182 |
this->c_private().push_back( x ); // strong, commit
|
williamr@2
|
183 |
ptr.release(); // nothrow
|
williamr@2
|
184 |
}
|
williamr@2
|
185 |
|
williamr@2
|
186 |
template< class U >
|
williamr@2
|
187 |
void push_back( std::auto_ptr<U> x )
|
williamr@2
|
188 |
{
|
williamr@2
|
189 |
push_back( x.release() );
|
williamr@2
|
190 |
}
|
williamr@2
|
191 |
|
williamr@2
|
192 |
void push_front( value_type x )
|
williamr@2
|
193 |
{
|
williamr@2
|
194 |
this->enforce_null_policy( x, "Null pointer in 'push_front()'" );
|
williamr@2
|
195 |
|
williamr@2
|
196 |
auto_type ptr( x ); // nothrow
|
williamr@2
|
197 |
this->c_private().push_front( x ); // strong, commit
|
williamr@2
|
198 |
ptr.release(); // nothrow
|
williamr@2
|
199 |
}
|
williamr@2
|
200 |
|
williamr@2
|
201 |
template< class U >
|
williamr@2
|
202 |
void push_front( std::auto_ptr<U> x )
|
williamr@2
|
203 |
{
|
williamr@2
|
204 |
push_front( x.release() );
|
williamr@2
|
205 |
}
|
williamr@2
|
206 |
|
williamr@2
|
207 |
auto_type pop_back()
|
williamr@2
|
208 |
{
|
williamr@2
|
209 |
BOOST_PTR_CONTAINER_THROW_EXCEPTION( this->empty(),
|
williamr@2
|
210 |
bad_ptr_container_operation,
|
williamr@2
|
211 |
"'pop_back()' on empty container" );
|
williamr@2
|
212 |
auto_type ptr( static_cast<value_type>(
|
williamr@2
|
213 |
this->c_private().back() ) ); // nothrow
|
williamr@2
|
214 |
this->c_private().pop_back(); // nothrow
|
williamr@2
|
215 |
return ptr_container_detail::move( ptr ); // nothrow
|
williamr@2
|
216 |
}
|
williamr@2
|
217 |
|
williamr@2
|
218 |
auto_type pop_front()
|
williamr@2
|
219 |
{
|
williamr@2
|
220 |
BOOST_PTR_CONTAINER_THROW_EXCEPTION( this->empty(),
|
williamr@2
|
221 |
bad_ptr_container_operation,
|
williamr@2
|
222 |
"'pop_front()' on empty container" );
|
williamr@2
|
223 |
auto_type ptr( static_cast<value_type>(
|
williamr@2
|
224 |
this->c_private().front() ) ); // nothrow
|
williamr@2
|
225 |
this->c_private().pop_front(); // nothrow
|
williamr@2
|
226 |
return ptr_container_detail::move( ptr );
|
williamr@2
|
227 |
}
|
williamr@2
|
228 |
|
williamr@2
|
229 |
reference front()
|
williamr@2
|
230 |
{
|
williamr@2
|
231 |
BOOST_PTR_CONTAINER_THROW_EXCEPTION( this->empty(),
|
williamr@2
|
232 |
bad_ptr_container_operation,
|
williamr@2
|
233 |
"accessing 'front()' on empty container" );
|
williamr@2
|
234 |
BOOST_ASSERT( !::boost::is_null( this->begin() ) );
|
williamr@2
|
235 |
return *this->begin();
|
williamr@2
|
236 |
}
|
williamr@2
|
237 |
|
williamr@2
|
238 |
const_reference front() const
|
williamr@2
|
239 |
{
|
williamr@2
|
240 |
BOOST_PTR_CONTAINER_THROW_EXCEPTION( this->empty(),
|
williamr@2
|
241 |
bad_ptr_container_operation,
|
williamr@2
|
242 |
"accessing 'front()' on empty container" );
|
williamr@2
|
243 |
BOOST_ASSERT( !::boost::is_null( this->begin() ) );
|
williamr@2
|
244 |
return *this->begin();
|
williamr@2
|
245 |
}
|
williamr@2
|
246 |
|
williamr@2
|
247 |
reference back()
|
williamr@2
|
248 |
{
|
williamr@2
|
249 |
BOOST_PTR_CONTAINER_THROW_EXCEPTION( this->empty(),
|
williamr@2
|
250 |
bad_ptr_container_operation,
|
williamr@2
|
251 |
"accessing 'back()' on empty container" );
|
williamr@2
|
252 |
BOOST_ASSERT( !::boost::is_null( --this->end() ) );
|
williamr@2
|
253 |
return *--this->end();
|
williamr@2
|
254 |
}
|
williamr@2
|
255 |
|
williamr@2
|
256 |
const_reference back() const
|
williamr@2
|
257 |
{
|
williamr@2
|
258 |
BOOST_PTR_CONTAINER_THROW_EXCEPTION( this->empty(),
|
williamr@2
|
259 |
bad_ptr_container_operation,
|
williamr@2
|
260 |
"accessing 'back()' on empty container" );
|
williamr@2
|
261 |
BOOST_ASSERT( !::boost::is_null( --this->end() ) );
|
williamr@2
|
262 |
return *--this->end();
|
williamr@2
|
263 |
}
|
williamr@2
|
264 |
|
williamr@2
|
265 |
public: // deque/vector inerface
|
williamr@2
|
266 |
|
williamr@2
|
267 |
reference operator[]( size_type n ) // nothrow
|
williamr@2
|
268 |
{
|
williamr@2
|
269 |
BOOST_ASSERT( n < this->size() );
|
williamr@2
|
270 |
BOOST_ASSERT( !this->is_null( n ) );
|
williamr@2
|
271 |
return *static_cast<value_type>( this->c_private()[n] );
|
williamr@2
|
272 |
}
|
williamr@2
|
273 |
|
williamr@2
|
274 |
const_reference operator[]( size_type n ) const // nothrow
|
williamr@2
|
275 |
{
|
williamr@2
|
276 |
BOOST_ASSERT( n < this->size() );
|
williamr@2
|
277 |
BOOST_ASSERT( !this->is_null( n ) );
|
williamr@2
|
278 |
return *static_cast<value_type>( this->c_private()[n] );
|
williamr@2
|
279 |
}
|
williamr@2
|
280 |
|
williamr@2
|
281 |
reference at( size_type n )
|
williamr@2
|
282 |
{
|
williamr@2
|
283 |
BOOST_PTR_CONTAINER_THROW_EXCEPTION( n >= this->size(), bad_index,
|
williamr@2
|
284 |
"'at()' out of bounds" );
|
williamr@2
|
285 |
BOOST_ASSERT( !this->is_null( n ) );
|
williamr@2
|
286 |
return (*this)[n];
|
williamr@2
|
287 |
}
|
williamr@2
|
288 |
|
williamr@2
|
289 |
const_reference at( size_type n ) const
|
williamr@2
|
290 |
{
|
williamr@2
|
291 |
BOOST_PTR_CONTAINER_THROW_EXCEPTION( n >= this->size(), bad_index,
|
williamr@2
|
292 |
"'at()' out of bounds" );
|
williamr@2
|
293 |
BOOST_ASSERT( !this->is_null( n ) );
|
williamr@2
|
294 |
return (*this)[n];
|
williamr@2
|
295 |
}
|
williamr@2
|
296 |
|
williamr@2
|
297 |
public: // vector interface
|
williamr@2
|
298 |
|
williamr@2
|
299 |
size_type capacity() const
|
williamr@2
|
300 |
{
|
williamr@2
|
301 |
return this->c_private().capacity();
|
williamr@2
|
302 |
}
|
williamr@2
|
303 |
|
williamr@2
|
304 |
void reserve( size_type n )
|
williamr@2
|
305 |
{
|
williamr@2
|
306 |
this->c_private().reserve( n );
|
williamr@2
|
307 |
}
|
williamr@2
|
308 |
|
williamr@2
|
309 |
void reverse()
|
williamr@2
|
310 |
{
|
williamr@2
|
311 |
this->c_private().reverse();
|
williamr@2
|
312 |
}
|
williamr@2
|
313 |
|
williamr@2
|
314 |
public: // assign, insert, transfer
|
williamr@2
|
315 |
|
williamr@2
|
316 |
// overhead: 1 heap allocation (very cheap compared to cloning)
|
williamr@2
|
317 |
template< class InputIterator >
|
williamr@2
|
318 |
void assign( InputIterator first, InputIterator last ) // strong
|
williamr@2
|
319 |
{
|
williamr@2
|
320 |
base_type temp( first, last );
|
williamr@2
|
321 |
this->swap( temp );
|
williamr@2
|
322 |
}
|
williamr@2
|
323 |
|
williamr@2
|
324 |
template< class Range >
|
williamr@2
|
325 |
void assign( const Range& r )
|
williamr@2
|
326 |
{
|
williamr@2
|
327 |
assign( boost::begin(r), boost::end(r ) );
|
williamr@2
|
328 |
}
|
williamr@2
|
329 |
|
williamr@2
|
330 |
private:
|
williamr@2
|
331 |
template< class I >
|
williamr@2
|
332 |
void insert_impl( iterator before, I first, I last, std::input_iterator_tag ) // strong
|
williamr@2
|
333 |
{
|
williamr@2
|
334 |
ptr_sequence_adapter temp(first,last); // strong
|
williamr@2
|
335 |
transfer( before, temp ); // strong, commit
|
williamr@2
|
336 |
}
|
williamr@2
|
337 |
|
williamr@2
|
338 |
template< class I >
|
williamr@2
|
339 |
void insert_impl( iterator before, I first, I last, std::forward_iterator_tag ) // strong
|
williamr@2
|
340 |
{
|
williamr@2
|
341 |
if( first == last )
|
williamr@2
|
342 |
return;
|
williamr@2
|
343 |
scoped_deleter sd( first, last ); // strong
|
williamr@2
|
344 |
this->insert_clones_and_release( sd, before ); // strong, commit
|
williamr@2
|
345 |
}
|
williamr@2
|
346 |
|
williamr@2
|
347 |
public:
|
williamr@2
|
348 |
|
williamr@2
|
349 |
using base_type::insert;
|
williamr@2
|
350 |
|
williamr@2
|
351 |
template< class InputIterator >
|
williamr@2
|
352 |
void insert( iterator before, InputIterator first, InputIterator last ) // strong
|
williamr@2
|
353 |
{
|
williamr@2
|
354 |
insert_impl( before, first, last, BOOST_DEDUCED_TYPENAME
|
williamr@2
|
355 |
iterator_category<InputIterator>::type() );
|
williamr@2
|
356 |
}
|
williamr@2
|
357 |
|
williamr@2
|
358 |
#if defined(BOOST_NO_SFINAE) || BOOST_WORKAROUND(__SUNPRO_CC, <= 0x580)
|
williamr@2
|
359 |
#else
|
williamr@2
|
360 |
template< class Range >
|
williamr@2
|
361 |
BOOST_DEDUCED_TYPENAME
|
williamr@2
|
362 |
boost::disable_if< ptr_container_detail::is_pointer_or_integral<Range> >::type
|
williamr@2
|
363 |
insert( iterator before, const Range& r )
|
williamr@2
|
364 |
{
|
williamr@2
|
365 |
insert( before, boost::begin(r), boost::end(r) );
|
williamr@2
|
366 |
}
|
williamr@2
|
367 |
|
williamr@2
|
368 |
#endif
|
williamr@2
|
369 |
|
williamr@2
|
370 |
template< class PtrSeqAdapter >
|
williamr@2
|
371 |
void transfer( iterator before,
|
williamr@2
|
372 |
BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator first,
|
williamr@2
|
373 |
BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator last,
|
williamr@2
|
374 |
PtrSeqAdapter& from ) // strong
|
williamr@2
|
375 |
{
|
williamr@2
|
376 |
BOOST_ASSERT( (void*)&from != (void*)this );
|
williamr@2
|
377 |
if( from.empty() )
|
williamr@2
|
378 |
return;
|
williamr@2
|
379 |
this->c_private().
|
williamr@2
|
380 |
insert( before.base(),
|
williamr@2
|
381 |
first.base(), last.base() ); // strong
|
williamr@2
|
382 |
from.c_private().erase( first.base(),
|
williamr@2
|
383 |
last.base() ); // nothrow
|
williamr@2
|
384 |
}
|
williamr@2
|
385 |
|
williamr@2
|
386 |
template< class PtrSeqAdapter >
|
williamr@2
|
387 |
void transfer( iterator before,
|
williamr@2
|
388 |
BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator object,
|
williamr@2
|
389 |
PtrSeqAdapter& from ) // strong
|
williamr@2
|
390 |
{
|
williamr@2
|
391 |
BOOST_ASSERT( (void*)&from != (void*)this );
|
williamr@2
|
392 |
if( from.empty() )
|
williamr@2
|
393 |
return;
|
williamr@2
|
394 |
this->c_private().
|
williamr@2
|
395 |
insert( before.base(),
|
williamr@2
|
396 |
*object.base() ); // strong
|
williamr@2
|
397 |
from.c_private().erase( object.base() ); // nothrow
|
williamr@2
|
398 |
}
|
williamr@2
|
399 |
|
williamr@2
|
400 |
#if defined(BOOST_NO_SFINAE) || BOOST_WORKAROUND(__SUNPRO_CC, <= 0x580)
|
williamr@2
|
401 |
#else
|
williamr@2
|
402 |
|
williamr@2
|
403 |
template< class PtrSeqAdapter, class Range >
|
williamr@2
|
404 |
BOOST_DEDUCED_TYPENAME boost::disable_if< boost::is_same< Range,
|
williamr@2
|
405 |
BOOST_DEDUCED_TYPENAME PtrSeqAdapter::iterator > >::type
|
williamr@2
|
406 |
transfer( iterator before, const Range& r, PtrSeqAdapter& from ) // strong
|
williamr@2
|
407 |
{
|
williamr@2
|
408 |
transfer( before, boost::begin(r), boost::end(r), from );
|
williamr@2
|
409 |
}
|
williamr@2
|
410 |
|
williamr@2
|
411 |
#endif
|
williamr@2
|
412 |
template< class PtrSeqAdapter >
|
williamr@2
|
413 |
void transfer( iterator before, PtrSeqAdapter& from ) // strong
|
williamr@2
|
414 |
{
|
williamr@2
|
415 |
BOOST_ASSERT( (void*)&from != (void*)this );
|
williamr@2
|
416 |
if( from.empty() )
|
williamr@2
|
417 |
return;
|
williamr@2
|
418 |
this->c_private().
|
williamr@2
|
419 |
insert( before.base(),
|
williamr@2
|
420 |
from.begin().base(), from.end().base() ); // strong
|
williamr@2
|
421 |
from.c_private().clear(); // nothrow
|
williamr@2
|
422 |
}
|
williamr@2
|
423 |
|
williamr@2
|
424 |
public: // null functions
|
williamr@2
|
425 |
|
williamr@2
|
426 |
bool is_null( size_type idx ) const
|
williamr@2
|
427 |
{
|
williamr@2
|
428 |
BOOST_ASSERT( idx < this->size() );
|
williamr@2
|
429 |
return this->c_private()[idx] == 0;
|
williamr@2
|
430 |
}
|
williamr@2
|
431 |
|
williamr@2
|
432 |
public: // algorithms
|
williamr@2
|
433 |
|
williamr@2
|
434 |
void sort( iterator first, iterator last )
|
williamr@2
|
435 |
{
|
williamr@2
|
436 |
sort( first, last, std::less<T>() );
|
williamr@2
|
437 |
}
|
williamr@2
|
438 |
|
williamr@2
|
439 |
void sort()
|
williamr@2
|
440 |
{
|
williamr@2
|
441 |
sort( this->begin(), this->end() );
|
williamr@2
|
442 |
}
|
williamr@2
|
443 |
|
williamr@2
|
444 |
template< class Compare >
|
williamr@2
|
445 |
void sort( iterator first, iterator last, Compare comp )
|
williamr@2
|
446 |
{
|
williamr@2
|
447 |
BOOST_ASSERT( first <= last && "out of range sort()" );
|
williamr@2
|
448 |
BOOST_ASSERT( this->begin() <= first && "out of range sort()" );
|
williamr@2
|
449 |
BOOST_ASSERT( last <= this->end() && "out of range sort()" );
|
williamr@2
|
450 |
// some static assert on the arguments of the comparison
|
williamr@2
|
451 |
std::sort( first.base(), last.base(),
|
williamr@2
|
452 |
void_ptr_indirect_fun<Compare,T>(comp) );
|
williamr@2
|
453 |
}
|
williamr@2
|
454 |
|
williamr@2
|
455 |
template< class Compare >
|
williamr@2
|
456 |
void sort( Compare comp )
|
williamr@2
|
457 |
{
|
williamr@2
|
458 |
sort( this->begin(), this->end(), comp );
|
williamr@2
|
459 |
}
|
williamr@2
|
460 |
|
williamr@2
|
461 |
void unique( iterator first, iterator last )
|
williamr@2
|
462 |
{
|
williamr@2
|
463 |
unique( first, last, std::equal_to<T>() );
|
williamr@2
|
464 |
}
|
williamr@2
|
465 |
|
williamr@2
|
466 |
void unique()
|
williamr@2
|
467 |
{
|
williamr@2
|
468 |
unique( this->begin(), this->end() );
|
williamr@2
|
469 |
}
|
williamr@2
|
470 |
|
williamr@2
|
471 |
private:
|
williamr@2
|
472 |
struct is_not_zero_ptr
|
williamr@2
|
473 |
{
|
williamr@2
|
474 |
template< class U >
|
williamr@2
|
475 |
bool operator()( const U* r ) const
|
williamr@2
|
476 |
{
|
williamr@2
|
477 |
return r != 0;
|
williamr@2
|
478 |
}
|
williamr@2
|
479 |
};
|
williamr@2
|
480 |
|
williamr@2
|
481 |
void compact_and_erase_nulls( iterator first, iterator last ) // nothrow
|
williamr@2
|
482 |
{
|
williamr@2
|
483 |
|
williamr@2
|
484 |
typename base_type::ptr_iterator p = std::stable_partition(
|
williamr@2
|
485 |
first.base(),
|
williamr@2
|
486 |
last.base(),
|
williamr@2
|
487 |
is_not_zero_ptr() );
|
williamr@2
|
488 |
this->c_private().erase( p, this->end().base() );
|
williamr@2
|
489 |
|
williamr@2
|
490 |
}
|
williamr@2
|
491 |
|
williamr@2
|
492 |
void range_check_impl( iterator first, iterator last,
|
williamr@2
|
493 |
std::bidirectional_iterator_tag )
|
williamr@2
|
494 |
{ /* do nothing */ }
|
williamr@2
|
495 |
|
williamr@2
|
496 |
void range_check_impl( iterator first, iterator last,
|
williamr@2
|
497 |
std::random_access_iterator_tag )
|
williamr@2
|
498 |
{
|
williamr@2
|
499 |
BOOST_ASSERT( first <= last && "out of range unique()/erase_if()" );
|
williamr@2
|
500 |
BOOST_ASSERT( this->begin() <= first && "out of range unique()/erase_if()" );
|
williamr@2
|
501 |
BOOST_ASSERT( last <= this->end() && "out of range unique()/erase_if)(" );
|
williamr@2
|
502 |
}
|
williamr@2
|
503 |
|
williamr@2
|
504 |
void range_check( iterator first, iterator last )
|
williamr@2
|
505 |
{
|
williamr@2
|
506 |
range_check_impl( first, last,
|
williamr@2
|
507 |
BOOST_DEDUCED_TYPENAME iterator_category<iterator>::type() );
|
williamr@2
|
508 |
}
|
williamr@2
|
509 |
|
williamr@2
|
510 |
public:
|
williamr@2
|
511 |
|
williamr@2
|
512 |
template< class Compare >
|
williamr@2
|
513 |
void unique( iterator first, iterator last, Compare comp )
|
williamr@2
|
514 |
{
|
williamr@2
|
515 |
range_check(first,last);
|
williamr@2
|
516 |
|
williamr@2
|
517 |
iterator prev = first;
|
williamr@2
|
518 |
iterator next = first;
|
williamr@2
|
519 |
++next;
|
williamr@2
|
520 |
for( ; next != last; ++next )
|
williamr@2
|
521 |
{
|
williamr@2
|
522 |
BOOST_ASSERT( !::boost::is_null(prev) );
|
williamr@2
|
523 |
BOOST_ASSERT( !::boost::is_null(next) );
|
williamr@2
|
524 |
if( comp( *prev, *next ) )
|
williamr@2
|
525 |
{
|
williamr@2
|
526 |
this->remove( next ); // delete object
|
williamr@2
|
527 |
*next.base() = 0; // mark pointer as deleted
|
williamr@2
|
528 |
}
|
williamr@2
|
529 |
else
|
williamr@2
|
530 |
{
|
williamr@2
|
531 |
prev = next;
|
williamr@2
|
532 |
}
|
williamr@2
|
533 |
// ++next
|
williamr@2
|
534 |
}
|
williamr@2
|
535 |
|
williamr@2
|
536 |
compact_and_erase_nulls( first, last );
|
williamr@2
|
537 |
}
|
williamr@2
|
538 |
|
williamr@2
|
539 |
template< class Compare >
|
williamr@2
|
540 |
void unique( Compare comp )
|
williamr@2
|
541 |
{
|
williamr@2
|
542 |
unique( this->begin(), this->end(), comp );
|
williamr@2
|
543 |
}
|
williamr@2
|
544 |
|
williamr@2
|
545 |
template< class Pred >
|
williamr@2
|
546 |
void erase_if( iterator first, iterator last, Pred pred )
|
williamr@2
|
547 |
{
|
williamr@2
|
548 |
range_check(first,last);
|
williamr@2
|
549 |
|
williamr@2
|
550 |
iterator next = first;
|
williamr@2
|
551 |
for( ; next != last; ++next )
|
williamr@2
|
552 |
{
|
williamr@2
|
553 |
BOOST_ASSERT( !::boost::is_null(next) );
|
williamr@2
|
554 |
if( pred( *next ) )
|
williamr@2
|
555 |
{
|
williamr@2
|
556 |
this->remove( next ); // delete object
|
williamr@2
|
557 |
*next.base() = 0; // mark pointer as deleted
|
williamr@2
|
558 |
}
|
williamr@2
|
559 |
}
|
williamr@2
|
560 |
|
williamr@2
|
561 |
compact_and_erase_nulls( first, last );
|
williamr@2
|
562 |
}
|
williamr@2
|
563 |
|
williamr@2
|
564 |
template< class Pred >
|
williamr@2
|
565 |
void erase_if( Pred pred )
|
williamr@2
|
566 |
{
|
williamr@2
|
567 |
erase_if( this->begin(), this->end(), pred );
|
williamr@2
|
568 |
}
|
williamr@2
|
569 |
|
williamr@2
|
570 |
|
williamr@2
|
571 |
void merge( iterator first, iterator last,
|
williamr@2
|
572 |
ptr_sequence_adapter& from )
|
williamr@2
|
573 |
{
|
williamr@2
|
574 |
merge( first, last, from, std::less<T>() );
|
williamr@2
|
575 |
}
|
williamr@2
|
576 |
|
williamr@2
|
577 |
template< class BinPred >
|
williamr@2
|
578 |
void merge( iterator first, iterator last,
|
williamr@2
|
579 |
ptr_sequence_adapter& from, BinPred pred )
|
williamr@2
|
580 |
{
|
williamr@2
|
581 |
void_ptr_indirect_fun<BinPred,T> bin_pred(pred);
|
williamr@2
|
582 |
size_type current_size = this->size();
|
williamr@2
|
583 |
this->transfer( this->end(), first, last, from );
|
williamr@2
|
584 |
typename base_type::ptr_iterator middle = this->begin().base();
|
williamr@2
|
585 |
std::advance(middle,current_size);
|
williamr@2
|
586 |
std::inplace_merge( this->begin().base(),
|
williamr@2
|
587 |
middle,
|
williamr@2
|
588 |
this->end().base(),
|
williamr@2
|
589 |
bin_pred );
|
williamr@2
|
590 |
}
|
williamr@2
|
591 |
|
williamr@2
|
592 |
void merge( ptr_sequence_adapter& r )
|
williamr@2
|
593 |
{
|
williamr@2
|
594 |
merge( r, std::less<T>() );
|
williamr@2
|
595 |
BOOST_ASSERT( r.empty() );
|
williamr@2
|
596 |
}
|
williamr@2
|
597 |
|
williamr@2
|
598 |
template< class BinPred >
|
williamr@2
|
599 |
void merge( ptr_sequence_adapter& r, BinPred pred )
|
williamr@2
|
600 |
{
|
williamr@2
|
601 |
merge( r.begin(), r.end(), r, pred );
|
williamr@2
|
602 |
BOOST_ASSERT( r.empty() );
|
williamr@2
|
603 |
}
|
williamr@2
|
604 |
|
williamr@2
|
605 |
};
|
williamr@2
|
606 |
|
williamr@2
|
607 |
|
williamr@2
|
608 |
} // namespace 'boost'
|
williamr@2
|
609 |
|
williamr@2
|
610 |
#endif
|