Chris@16
|
1 /////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
2 //
|
Chris@16
|
3 // (C) Copyright Olaf Krzikalla 2004-2006.
|
Chris@16
|
4 // (C) Copyright Ion Gaztanaga 2006-2013
|
Chris@16
|
5 //
|
Chris@16
|
6 // Distributed under the Boost Software License, Version 1.0.
|
Chris@16
|
7 // (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
8 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
9 //
|
Chris@16
|
10 // See http://www.boost.org/libs/intrusive for documentation.
|
Chris@16
|
11 //
|
Chris@16
|
12 /////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
13
|
Chris@16
|
14 #ifndef BOOST_INTRUSIVE_SLIST_HPP
|
Chris@16
|
15 #define BOOST_INTRUSIVE_SLIST_HPP
|
Chris@16
|
16
|
Chris@16
|
17 #include <boost/intrusive/detail/config_begin.hpp>
|
Chris@16
|
18 #include <boost/static_assert.hpp>
|
Chris@16
|
19 #include <boost/intrusive/detail/assert.hpp>
|
Chris@16
|
20 #include <boost/intrusive/intrusive_fwd.hpp>
|
Chris@16
|
21 #include <boost/intrusive/slist_hook.hpp>
|
Chris@16
|
22 #include <boost/intrusive/circular_slist_algorithms.hpp>
|
Chris@16
|
23 #include <boost/intrusive/linear_slist_algorithms.hpp>
|
Chris@16
|
24 #include <boost/intrusive/pointer_traits.hpp>
|
Chris@16
|
25 #include <boost/intrusive/detail/clear_on_destructor_base.hpp>
|
Chris@16
|
26 #include <boost/intrusive/link_mode.hpp>
|
Chris@16
|
27 #include <boost/intrusive/options.hpp>
|
Chris@16
|
28 #include <boost/intrusive/detail/utilities.hpp>
|
Chris@16
|
29 #include <iterator>
|
Chris@16
|
30 #include <functional>
|
Chris@16
|
31 #include <algorithm>
|
Chris@16
|
32 #include <cstddef> //std::size_t
|
Chris@16
|
33 #include <utility> //std::pair
|
Chris@16
|
34 #include <boost/move/move.hpp>
|
Chris@16
|
35
|
Chris@16
|
36 namespace boost {
|
Chris@16
|
37 namespace intrusive {
|
Chris@16
|
38
|
Chris@16
|
39 /// @cond
|
Chris@16
|
40
|
Chris@16
|
41 template<class Node, class NodePtr, bool>
|
Chris@16
|
42 struct root_plus_last
|
Chris@16
|
43 {
|
Chris@16
|
44 Node root_;
|
Chris@16
|
45 NodePtr last_;
|
Chris@16
|
46 };
|
Chris@16
|
47
|
Chris@16
|
48 template<class Node, class NodePtr>
|
Chris@16
|
49 struct root_plus_last<Node, NodePtr, false>
|
Chris@16
|
50 {
|
Chris@16
|
51 Node root_;
|
Chris@16
|
52 };
|
Chris@16
|
53
|
Chris@16
|
54 struct slist_defaults
|
Chris@16
|
55 {
|
Chris@16
|
56 typedef detail::default_slist_hook proto_value_traits;
|
Chris@16
|
57 static const bool constant_time_size = true;
|
Chris@16
|
58 static const bool linear = false;
|
Chris@16
|
59 typedef std::size_t size_type;
|
Chris@16
|
60 static const bool cache_last = false;
|
Chris@16
|
61 };
|
Chris@16
|
62
|
Chris@16
|
63 struct slist_bool_flags
|
Chris@16
|
64 {
|
Chris@16
|
65 static const std::size_t linear_pos = 1u;
|
Chris@16
|
66 static const std::size_t constant_time_size_pos = 2u;
|
Chris@16
|
67 static const std::size_t cache_last_pos = 4u;
|
Chris@16
|
68 };
|
Chris@16
|
69
|
Chris@16
|
70
|
Chris@16
|
71 /// @endcond
|
Chris@16
|
72
|
Chris@16
|
73 //! The class template slist is an intrusive container, that encapsulates
|
Chris@16
|
74 //! a singly-linked list. You can use such a list to squeeze the last bit
|
Chris@16
|
75 //! of performance from your application. Unfortunately, the little gains
|
Chris@16
|
76 //! come with some huge drawbacks. A lot of member functions can't be
|
Chris@16
|
77 //! implemented as efficiently as for standard containers. To overcome
|
Chris@16
|
78 //! this limitation some other member functions with rather unusual semantics
|
Chris@16
|
79 //! have to be introduced.
|
Chris@16
|
80 //!
|
Chris@16
|
81 //! The template parameter \c T is the type to be managed by the container.
|
Chris@16
|
82 //! The user can specify additional options and if no options are provided
|
Chris@16
|
83 //! default options are used.
|
Chris@16
|
84 //!
|
Chris@16
|
85 //! The container supports the following options:
|
Chris@16
|
86 //! \c base_hook<>/member_hook<>/value_traits<>,
|
Chris@16
|
87 //! \c constant_time_size<>, \c size_type<>,
|
Chris@16
|
88 //! \c linear<> and \c cache_last<>.
|
Chris@16
|
89 //!
|
Chris@16
|
90 //! The iterators of slist are forward iterators. slist provides a static
|
Chris@16
|
91 //! function called "previous" to compute the previous iterator of a given iterator.
|
Chris@16
|
92 //! This function has linear complexity. To improve the usability esp. with
|
Chris@16
|
93 //! the '*_after' functions, ++end() == begin() and previous(begin()) == end()
|
Chris@16
|
94 //! are defined. An new special function "before_begin()" is defined, which returns
|
Chris@16
|
95 //! an iterator that points one less the beginning of the list: ++before_begin() == begin()
|
Chris@16
|
96 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
|
Chris@16
|
97 template<class T, class ...Options>
|
Chris@16
|
98 #else
|
Chris@16
|
99 template<class ValueTraits, class SizeType, std::size_t BoolFlags>
|
Chris@16
|
100 #endif
|
Chris@16
|
101 class slist_impl
|
Chris@16
|
102 : private detail::clear_on_destructor_base
|
Chris@16
|
103 < slist_impl<ValueTraits, SizeType, BoolFlags>
|
Chris@16
|
104 , is_safe_autounlink<detail::get_real_value_traits<ValueTraits>::type::link_mode>::value
|
Chris@16
|
105 >
|
Chris@16
|
106 {
|
Chris@16
|
107 template<class C, bool> friend class detail::clear_on_destructor_base;
|
Chris@16
|
108 //Public typedefs
|
Chris@16
|
109 public:
|
Chris@16
|
110 typedef ValueTraits value_traits;
|
Chris@16
|
111 /// @cond
|
Chris@16
|
112 static const bool external_value_traits =
|
Chris@16
|
113 detail::external_value_traits_bool_is_true<value_traits>::value;
|
Chris@16
|
114 typedef typename detail::get_real_value_traits<ValueTraits>::type real_value_traits;
|
Chris@16
|
115 /// @endcond
|
Chris@16
|
116 typedef typename real_value_traits::pointer pointer;
|
Chris@16
|
117 typedef typename real_value_traits::const_pointer const_pointer;
|
Chris@16
|
118 typedef typename pointer_traits<pointer>::element_type value_type;
|
Chris@16
|
119 typedef typename pointer_traits<pointer>::reference reference;
|
Chris@16
|
120 typedef typename pointer_traits<const_pointer>::reference const_reference;
|
Chris@16
|
121 typedef typename pointer_traits<pointer>::difference_type difference_type;
|
Chris@16
|
122 typedef SizeType size_type;
|
Chris@16
|
123 typedef slist_iterator<real_value_traits, false> iterator;
|
Chris@16
|
124 typedef slist_iterator<real_value_traits, true> const_iterator;
|
Chris@16
|
125 typedef typename real_value_traits::node_traits node_traits;
|
Chris@16
|
126 typedef typename node_traits::node node;
|
Chris@16
|
127 typedef typename node_traits::node_ptr node_ptr;
|
Chris@16
|
128 typedef typename node_traits::const_node_ptr const_node_ptr;
|
Chris@16
|
129
|
Chris@16
|
130 static const bool constant_time_size = 0 != (BoolFlags & slist_bool_flags::constant_time_size_pos);
|
Chris@16
|
131 static const bool stateful_value_traits = detail::is_stateful_value_traits<real_value_traits>::value;
|
Chris@16
|
132 static const bool linear = 0 != (BoolFlags & slist_bool_flags::linear_pos);
|
Chris@16
|
133 static const bool cache_last = 0 != (BoolFlags & slist_bool_flags::cache_last_pos);
|
Chris@16
|
134
|
Chris@16
|
135 typedef typename detail::if_c
|
Chris@16
|
136 < linear
|
Chris@16
|
137 , linear_slist_algorithms<node_traits>
|
Chris@16
|
138 , circular_slist_algorithms<node_traits>
|
Chris@16
|
139 >::type node_algorithms;
|
Chris@16
|
140
|
Chris@16
|
141 /// @cond
|
Chris@16
|
142 private:
|
Chris@16
|
143 typedef detail::size_holder<constant_time_size, size_type> size_traits;
|
Chris@16
|
144
|
Chris@16
|
145 //noncopyable
|
Chris@16
|
146 BOOST_MOVABLE_BUT_NOT_COPYABLE(slist_impl)
|
Chris@16
|
147
|
Chris@16
|
148 static const bool safemode_or_autounlink = is_safe_autounlink<real_value_traits::link_mode>::value;
|
Chris@16
|
149
|
Chris@16
|
150 //Constant-time size is incompatible with auto-unlink hooks!
|
Chris@16
|
151 BOOST_STATIC_ASSERT(!(constant_time_size && ((int)real_value_traits::link_mode == (int)auto_unlink)));
|
Chris@16
|
152 //Linear singly linked lists are incompatible with auto-unlink hooks!
|
Chris@16
|
153 BOOST_STATIC_ASSERT(!(linear && ((int)real_value_traits::link_mode == (int)auto_unlink)));
|
Chris@16
|
154 //A list with cached last node is incompatible with auto-unlink hooks!
|
Chris@16
|
155 BOOST_STATIC_ASSERT(!(cache_last && ((int)real_value_traits::link_mode == (int)auto_unlink)));
|
Chris@16
|
156
|
Chris@16
|
157 node_ptr get_end_node()
|
Chris@16
|
158 { return node_ptr(linear ? node_ptr() : this->get_root_node()); }
|
Chris@16
|
159
|
Chris@16
|
160 const_node_ptr get_end_node() const
|
Chris@16
|
161 {
|
Chris@16
|
162 return const_node_ptr
|
Chris@16
|
163 (linear ? const_node_ptr() : this->get_root_node()); }
|
Chris@16
|
164
|
Chris@16
|
165 node_ptr get_root_node()
|
Chris@16
|
166 { return pointer_traits<node_ptr>::pointer_to(data_.root_plus_size_.root_); }
|
Chris@16
|
167
|
Chris@16
|
168 const_node_ptr get_root_node() const
|
Chris@16
|
169 { return pointer_traits<const_node_ptr>::pointer_to(data_.root_plus_size_.root_); }
|
Chris@16
|
170
|
Chris@16
|
171 node_ptr get_last_node()
|
Chris@16
|
172 { return this->get_last_node(detail::bool_<cache_last>()); }
|
Chris@16
|
173
|
Chris@16
|
174 const_node_ptr get_last_node() const
|
Chris@16
|
175 { return this->get_last_node(detail::bool_<cache_last>()); }
|
Chris@16
|
176
|
Chris@16
|
177 void set_last_node(const node_ptr &n)
|
Chris@16
|
178 { return this->set_last_node(n, detail::bool_<cache_last>()); }
|
Chris@16
|
179
|
Chris@16
|
180 static node_ptr get_last_node(detail::bool_<false>)
|
Chris@16
|
181 {
|
Chris@16
|
182 //This function shall not be used if cache_last is not true
|
Chris@16
|
183 BOOST_INTRUSIVE_INVARIANT_ASSERT(cache_last);
|
Chris@16
|
184 return node_ptr();
|
Chris@16
|
185 }
|
Chris@16
|
186
|
Chris@16
|
187 static void set_last_node(const node_ptr &, detail::bool_<false>)
|
Chris@16
|
188 {
|
Chris@16
|
189 //This function shall not be used if cache_last is not true
|
Chris@16
|
190 BOOST_INTRUSIVE_INVARIANT_ASSERT(cache_last);
|
Chris@16
|
191 }
|
Chris@16
|
192
|
Chris@16
|
193 node_ptr get_last_node(detail::bool_<true>)
|
Chris@16
|
194 { return node_ptr(data_.root_plus_size_.last_); }
|
Chris@16
|
195
|
Chris@16
|
196 const_node_ptr get_last_node(detail::bool_<true>) const
|
Chris@16
|
197 { return const_node_ptr(data_.root_plus_size_.last_); }
|
Chris@16
|
198
|
Chris@16
|
199 void set_last_node(const node_ptr & n, detail::bool_<true>)
|
Chris@16
|
200 { data_.root_plus_size_.last_ = n; }
|
Chris@16
|
201
|
Chris@16
|
202 void set_default_constructed_state()
|
Chris@16
|
203 {
|
Chris@16
|
204 node_algorithms::init_header(this->get_root_node());
|
Chris@16
|
205 this->priv_size_traits().set_size(size_type(0));
|
Chris@16
|
206 if(cache_last){
|
Chris@16
|
207 this->set_last_node(this->get_root_node());
|
Chris@16
|
208 }
|
Chris@16
|
209 }
|
Chris@16
|
210
|
Chris@16
|
211 struct root_plus_size
|
Chris@16
|
212 : public size_traits
|
Chris@16
|
213 , public root_plus_last<node, node_ptr, cache_last>
|
Chris@16
|
214 {};
|
Chris@16
|
215
|
Chris@16
|
216 struct data_t
|
Chris@16
|
217 : public slist_impl::value_traits
|
Chris@16
|
218 {
|
Chris@16
|
219 typedef typename slist_impl::value_traits value_traits;
|
Chris@16
|
220 explicit data_t(const value_traits &val_traits)
|
Chris@16
|
221 : value_traits(val_traits)
|
Chris@16
|
222 {}
|
Chris@16
|
223
|
Chris@16
|
224 root_plus_size root_plus_size_;
|
Chris@16
|
225 } data_;
|
Chris@16
|
226
|
Chris@16
|
227 size_traits &priv_size_traits()
|
Chris@16
|
228 { return data_.root_plus_size_; }
|
Chris@16
|
229
|
Chris@16
|
230 const size_traits &priv_size_traits() const
|
Chris@16
|
231 { return data_.root_plus_size_; }
|
Chris@16
|
232
|
Chris@16
|
233 const real_value_traits &get_real_value_traits(detail::bool_<false>) const
|
Chris@16
|
234 { return data_; }
|
Chris@16
|
235
|
Chris@16
|
236 const real_value_traits &get_real_value_traits(detail::bool_<true>) const
|
Chris@16
|
237 { return data_.get_value_traits(*this); }
|
Chris@16
|
238
|
Chris@16
|
239 real_value_traits &get_real_value_traits(detail::bool_<false>)
|
Chris@16
|
240 { return data_; }
|
Chris@16
|
241
|
Chris@16
|
242 real_value_traits &get_real_value_traits(detail::bool_<true>)
|
Chris@16
|
243 { return data_.get_value_traits(*this); }
|
Chris@16
|
244
|
Chris@16
|
245 const value_traits &priv_value_traits() const
|
Chris@16
|
246 { return data_; }
|
Chris@16
|
247
|
Chris@16
|
248 value_traits &priv_value_traits()
|
Chris@16
|
249 { return data_; }
|
Chris@16
|
250
|
Chris@16
|
251 protected:
|
Chris@16
|
252 node &prot_root_node()
|
Chris@16
|
253 { return data_.root_plus_size_.root_; }
|
Chris@16
|
254
|
Chris@16
|
255 node const &prot_root_node() const
|
Chris@16
|
256 { return data_.root_plus_size_.root_; }
|
Chris@16
|
257
|
Chris@16
|
258 void prot_set_size(size_type s)
|
Chris@16
|
259 { data_.root_plus_size_.set_size(s); }
|
Chris@16
|
260
|
Chris@16
|
261 /// @endcond
|
Chris@16
|
262
|
Chris@16
|
263 public:
|
Chris@16
|
264
|
Chris@16
|
265 const real_value_traits &get_real_value_traits() const
|
Chris@16
|
266 { return this->get_real_value_traits(detail::bool_<external_value_traits>()); }
|
Chris@16
|
267
|
Chris@16
|
268 real_value_traits &get_real_value_traits()
|
Chris@16
|
269 { return this->get_real_value_traits(detail::bool_<external_value_traits>()); }
|
Chris@16
|
270
|
Chris@16
|
271 typedef typename pointer_traits<node_ptr>::template rebind_pointer<const real_value_traits>::type const_real_value_traits_ptr;
|
Chris@16
|
272
|
Chris@16
|
273 const_real_value_traits_ptr real_value_traits_ptr() const
|
Chris@16
|
274 { return pointer_traits<const_real_value_traits_ptr>::pointer_to(this->get_real_value_traits()); }
|
Chris@16
|
275
|
Chris@16
|
276 public:
|
Chris@16
|
277
|
Chris@16
|
278 ///@cond
|
Chris@16
|
279
|
Chris@16
|
280 //! <b>Requires</b>: f and before_l belong to another slist.
|
Chris@16
|
281 //!
|
Chris@16
|
282 //! <b>Effects</b>: Transfers the range [f, before_l] to this
|
Chris@16
|
283 //! list, after the element pointed by prev_pos.
|
Chris@16
|
284 //! No destructors or copy constructors are called.
|
Chris@16
|
285 //!
|
Chris@16
|
286 //! <b>Throws</b>: Nothing.
|
Chris@16
|
287 //!
|
Chris@16
|
288 //! <b>Complexity</b>: Linear to the number of elements transferred
|
Chris@16
|
289 //! if constant_time_size is true. Constant-time otherwise.
|
Chris@16
|
290 //!
|
Chris@16
|
291 //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
|
Chris@16
|
292 //! list. Iterators of this list and all the references are not invalidated.
|
Chris@16
|
293 //!
|
Chris@16
|
294 //! <b>Warning</b>: Experimental function, don't use it!
|
Chris@16
|
295 slist_impl( const node_ptr & f, const node_ptr & before_l
|
Chris@16
|
296 , size_type n, const value_traits &v_traits = value_traits())
|
Chris@16
|
297 : data_(v_traits)
|
Chris@16
|
298 {
|
Chris@16
|
299 if(n){
|
Chris@16
|
300 this->priv_size_traits().set_size(n);
|
Chris@16
|
301 if(cache_last){
|
Chris@16
|
302 this->set_last_node(before_l);
|
Chris@16
|
303 }
|
Chris@16
|
304 node_traits::set_next(this->get_root_node(), f);
|
Chris@16
|
305 node_traits::set_next(before_l, this->get_end_node());
|
Chris@16
|
306 }
|
Chris@16
|
307 else{
|
Chris@16
|
308 this->set_default_constructed_state();
|
Chris@16
|
309 }
|
Chris@16
|
310 }
|
Chris@16
|
311
|
Chris@16
|
312 ///@endcond
|
Chris@16
|
313
|
Chris@16
|
314 //! <b>Effects</b>: constructs an empty list.
|
Chris@16
|
315 //!
|
Chris@16
|
316 //! <b>Complexity</b>: Constant
|
Chris@16
|
317 //!
|
Chris@16
|
318 //! <b>Throws</b>: If value_traits::node_traits::node
|
Chris@16
|
319 //! constructor throws (this does not happen with predefined Boost.Intrusive hooks).
|
Chris@16
|
320 explicit slist_impl(const value_traits &v_traits = value_traits())
|
Chris@16
|
321 : data_(v_traits)
|
Chris@16
|
322 { this->set_default_constructed_state(); }
|
Chris@16
|
323
|
Chris@16
|
324 //! <b>Requires</b>: Dereferencing iterator must yield an lvalue of type value_type.
|
Chris@16
|
325 //!
|
Chris@16
|
326 //! <b>Effects</b>: Constructs a list equal to [b ,e).
|
Chris@16
|
327 //!
|
Chris@16
|
328 //! <b>Complexity</b>: Linear in std::distance(b, e). No copy constructors are called.
|
Chris@16
|
329 //!
|
Chris@16
|
330 //! <b>Throws</b>: If value_traits::node_traits::node
|
Chris@16
|
331 //! constructor throws (this does not happen with predefined Boost.Intrusive hooks).
|
Chris@16
|
332 template<class Iterator>
|
Chris@16
|
333 slist_impl(Iterator b, Iterator e, const value_traits &v_traits = value_traits())
|
Chris@16
|
334 : data_(v_traits)
|
Chris@16
|
335 {
|
Chris@16
|
336 this->set_default_constructed_state();
|
Chris@16
|
337 this->insert_after(this->cbefore_begin(), b, e);
|
Chris@16
|
338 }
|
Chris@16
|
339
|
Chris@16
|
340 //! <b>Effects</b>: to-do
|
Chris@16
|
341 //!
|
Chris@16
|
342 slist_impl(BOOST_RV_REF(slist_impl) x)
|
Chris@16
|
343 : data_(::boost::move(x.priv_value_traits()))
|
Chris@16
|
344 {
|
Chris@16
|
345 this->priv_size_traits().set_size(size_type(0));
|
Chris@16
|
346 node_algorithms::init_header(this->get_root_node());
|
Chris@16
|
347 this->swap(x);
|
Chris@16
|
348 }
|
Chris@16
|
349
|
Chris@16
|
350 //! <b>Effects</b>: to-do
|
Chris@16
|
351 //!
|
Chris@16
|
352 slist_impl& operator=(BOOST_RV_REF(slist_impl) x)
|
Chris@16
|
353 { this->swap(x); return *this; }
|
Chris@16
|
354
|
Chris@16
|
355 #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
Chris@16
|
356 //! <b>Effects</b>: If it's a safe-mode
|
Chris@16
|
357 //! or auto-unlink value, the destructor does nothing
|
Chris@16
|
358 //! (ie. no code is generated). Otherwise it detaches all elements from this.
|
Chris@16
|
359 //! In this case the objects in the list are not deleted (i.e. no destructors
|
Chris@16
|
360 //! are called), but the hooks according to the value_traits template parameter
|
Chris@16
|
361 //! are set to their default value.
|
Chris@16
|
362 //!
|
Chris@16
|
363 //! <b>Complexity</b>: Linear to the number of elements in the list, if
|
Chris@16
|
364 //! it's a safe-mode or auto-unlink value. Otherwise constant.
|
Chris@16
|
365 ~slist_impl()
|
Chris@16
|
366 {}
|
Chris@16
|
367 #endif
|
Chris@16
|
368
|
Chris@16
|
369 //! <b>Effects</b>: Erases all the elements of the container.
|
Chris@16
|
370 //!
|
Chris@16
|
371 //! <b>Throws</b>: Nothing.
|
Chris@16
|
372 //!
|
Chris@16
|
373 //! <b>Complexity</b>: Linear to the number of elements of the list.
|
Chris@16
|
374 //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise.
|
Chris@16
|
375 //!
|
Chris@16
|
376 //! <b>Note</b>: Invalidates the iterators (but not the references) to the erased elements.
|
Chris@16
|
377 void clear()
|
Chris@16
|
378 {
|
Chris@16
|
379 if(safemode_or_autounlink){
|
Chris@16
|
380 this->clear_and_dispose(detail::null_disposer());
|
Chris@16
|
381 }
|
Chris@16
|
382 else{
|
Chris@16
|
383 this->set_default_constructed_state();
|
Chris@16
|
384 }
|
Chris@16
|
385 }
|
Chris@16
|
386
|
Chris@16
|
387 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
|
Chris@16
|
388 //!
|
Chris@16
|
389 //! <b>Effects</b>: Erases all the elements of the container
|
Chris@16
|
390 //! Disposer::operator()(pointer) is called for the removed elements.
|
Chris@16
|
391 //!
|
Chris@16
|
392 //! <b>Throws</b>: Nothing.
|
Chris@16
|
393 //!
|
Chris@16
|
394 //! <b>Complexity</b>: Linear to the number of elements of the list.
|
Chris@16
|
395 //!
|
Chris@16
|
396 //! <b>Note</b>: Invalidates the iterators to the erased elements.
|
Chris@16
|
397 template <class Disposer>
|
Chris@16
|
398 void clear_and_dispose(Disposer disposer)
|
Chris@16
|
399 {
|
Chris@16
|
400 const_iterator it(this->begin()), itend(this->end());
|
Chris@16
|
401 while(it != itend){
|
Chris@16
|
402 node_ptr to_erase(it.pointed_node());
|
Chris@16
|
403 ++it;
|
Chris@16
|
404 if(safemode_or_autounlink)
|
Chris@16
|
405 node_algorithms::init(to_erase);
|
Chris@16
|
406 disposer(get_real_value_traits().to_value_ptr(to_erase));
|
Chris@16
|
407 }
|
Chris@16
|
408 this->set_default_constructed_state();
|
Chris@16
|
409 }
|
Chris@16
|
410
|
Chris@16
|
411 //! <b>Requires</b>: value must be an lvalue.
|
Chris@16
|
412 //!
|
Chris@16
|
413 //! <b>Effects</b>: Inserts the value in the front of the list.
|
Chris@16
|
414 //! No copy constructors are called.
|
Chris@16
|
415 //!
|
Chris@16
|
416 //! <b>Throws</b>: Nothing.
|
Chris@16
|
417 //!
|
Chris@16
|
418 //! <b>Complexity</b>: Constant.
|
Chris@16
|
419 //!
|
Chris@16
|
420 //! <b>Note</b>: Does not affect the validity of iterators and references.
|
Chris@16
|
421 void push_front(reference value)
|
Chris@16
|
422 {
|
Chris@16
|
423 node_ptr to_insert = get_real_value_traits().to_node_ptr(value);
|
Chris@16
|
424 if(safemode_or_autounlink)
|
Chris@16
|
425 BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(to_insert));
|
Chris@16
|
426 if(cache_last){
|
Chris@16
|
427 if(this->empty()){
|
Chris@16
|
428 this->set_last_node(to_insert);
|
Chris@16
|
429 }
|
Chris@16
|
430 }
|
Chris@16
|
431 node_algorithms::link_after(this->get_root_node(), to_insert);
|
Chris@16
|
432 this->priv_size_traits().increment();
|
Chris@16
|
433 }
|
Chris@16
|
434
|
Chris@16
|
435 //! <b>Requires</b>: value must be an lvalue.
|
Chris@16
|
436 //!
|
Chris@16
|
437 //! <b>Effects</b>: Inserts the value in the back of the list.
|
Chris@16
|
438 //! No copy constructors are called.
|
Chris@16
|
439 //!
|
Chris@16
|
440 //! <b>Throws</b>: Nothing.
|
Chris@16
|
441 //!
|
Chris@16
|
442 //! <b>Complexity</b>: Constant.
|
Chris@16
|
443 //!
|
Chris@16
|
444 //! <b>Note</b>: Does not affect the validity of iterators and references.
|
Chris@16
|
445 //! This function is only available is cache_last<> is true.
|
Chris@16
|
446 void push_back(reference value)
|
Chris@16
|
447 {
|
Chris@16
|
448 BOOST_STATIC_ASSERT((cache_last));
|
Chris@16
|
449 node_ptr n = get_real_value_traits().to_node_ptr(value);
|
Chris@16
|
450 if(safemode_or_autounlink)
|
Chris@16
|
451 BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(n));
|
Chris@16
|
452 node_algorithms::link_after(this->get_last_node(), n);
|
Chris@16
|
453 if(cache_last){
|
Chris@16
|
454 this->set_last_node(n);
|
Chris@16
|
455 }
|
Chris@16
|
456 this->priv_size_traits().increment();
|
Chris@16
|
457 }
|
Chris@16
|
458
|
Chris@16
|
459 //! <b>Effects</b>: Erases the first element of the list.
|
Chris@16
|
460 //! No destructors are called.
|
Chris@16
|
461 //!
|
Chris@16
|
462 //! <b>Throws</b>: Nothing.
|
Chris@16
|
463 //!
|
Chris@16
|
464 //! <b>Complexity</b>: Constant.
|
Chris@16
|
465 //!
|
Chris@16
|
466 //! <b>Note</b>: Invalidates the iterators (but not the references) to the erased element.
|
Chris@16
|
467 void pop_front()
|
Chris@16
|
468 { return this->pop_front_and_dispose(detail::null_disposer()); }
|
Chris@16
|
469
|
Chris@16
|
470 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
|
Chris@16
|
471 //!
|
Chris@16
|
472 //! <b>Effects</b>: Erases the first element of the list.
|
Chris@16
|
473 //! Disposer::operator()(pointer) is called for the removed element.
|
Chris@16
|
474 //!
|
Chris@16
|
475 //! <b>Throws</b>: Nothing.
|
Chris@16
|
476 //!
|
Chris@16
|
477 //! <b>Complexity</b>: Constant.
|
Chris@16
|
478 //!
|
Chris@16
|
479 //! <b>Note</b>: Invalidates the iterators to the erased element.
|
Chris@16
|
480 template<class Disposer>
|
Chris@16
|
481 void pop_front_and_dispose(Disposer disposer)
|
Chris@16
|
482 {
|
Chris@16
|
483 node_ptr to_erase = node_traits::get_next(this->get_root_node());
|
Chris@16
|
484 node_algorithms::unlink_after(this->get_root_node());
|
Chris@16
|
485 this->priv_size_traits().decrement();
|
Chris@16
|
486 if(safemode_or_autounlink)
|
Chris@16
|
487 node_algorithms::init(to_erase);
|
Chris@16
|
488 disposer(get_real_value_traits().to_value_ptr(to_erase));
|
Chris@16
|
489 if(cache_last){
|
Chris@16
|
490 if(this->empty()){
|
Chris@16
|
491 this->set_last_node(this->get_root_node());
|
Chris@16
|
492 }
|
Chris@16
|
493 }
|
Chris@16
|
494 }
|
Chris@16
|
495
|
Chris@16
|
496 //! <b>Effects</b>: Returns a reference to the first element of the list.
|
Chris@16
|
497 //!
|
Chris@16
|
498 //! <b>Throws</b>: Nothing.
|
Chris@16
|
499 //!
|
Chris@16
|
500 //! <b>Complexity</b>: Constant.
|
Chris@16
|
501 reference front()
|
Chris@16
|
502 { return *this->get_real_value_traits().to_value_ptr(node_traits::get_next(this->get_root_node())); }
|
Chris@16
|
503
|
Chris@16
|
504 //! <b>Effects</b>: Returns a const_reference to the first element of the list.
|
Chris@16
|
505 //!
|
Chris@16
|
506 //! <b>Throws</b>: Nothing.
|
Chris@16
|
507 //!
|
Chris@16
|
508 //! <b>Complexity</b>: Constant.
|
Chris@16
|
509 const_reference front() const
|
Chris@16
|
510 { return *this->get_real_value_traits().to_value_ptr(detail::uncast(node_traits::get_next(this->get_root_node()))); }
|
Chris@16
|
511
|
Chris@16
|
512 //! <b>Effects</b>: Returns a reference to the last element of the list.
|
Chris@16
|
513 //!
|
Chris@16
|
514 //! <b>Throws</b>: Nothing.
|
Chris@16
|
515 //!
|
Chris@16
|
516 //! <b>Complexity</b>: Constant.
|
Chris@16
|
517 //!
|
Chris@16
|
518 //! <b>Note</b>: Does not affect the validity of iterators and references.
|
Chris@16
|
519 //! This function is only available is cache_last<> is true.
|
Chris@16
|
520 reference back()
|
Chris@16
|
521 {
|
Chris@16
|
522 BOOST_STATIC_ASSERT((cache_last));
|
Chris@16
|
523 return *this->get_real_value_traits().to_value_ptr(this->get_last_node());
|
Chris@16
|
524 }
|
Chris@16
|
525
|
Chris@16
|
526 //! <b>Effects</b>: Returns a const_reference to the last element of the list.
|
Chris@16
|
527 //!
|
Chris@16
|
528 //! <b>Throws</b>: Nothing.
|
Chris@16
|
529 //!
|
Chris@16
|
530 //! <b>Complexity</b>: Constant.
|
Chris@16
|
531 //!
|
Chris@16
|
532 //! <b>Note</b>: Does not affect the validity of iterators and references.
|
Chris@16
|
533 //! This function is only available is cache_last<> is true.
|
Chris@16
|
534 const_reference back() const
|
Chris@16
|
535 {
|
Chris@16
|
536 BOOST_STATIC_ASSERT((cache_last));
|
Chris@16
|
537 return *this->get_real_value_traits().to_value_ptr(this->get_last_node());
|
Chris@16
|
538 }
|
Chris@16
|
539
|
Chris@16
|
540 //! <b>Effects</b>: Returns an iterator to the first element contained in the list.
|
Chris@16
|
541 //!
|
Chris@16
|
542 //! <b>Throws</b>: Nothing.
|
Chris@16
|
543 //!
|
Chris@16
|
544 //! <b>Complexity</b>: Constant.
|
Chris@16
|
545 iterator begin()
|
Chris@16
|
546 { return iterator (node_traits::get_next(this->get_root_node()), this->real_value_traits_ptr()); }
|
Chris@16
|
547
|
Chris@16
|
548 //! <b>Effects</b>: Returns a const_iterator to the first element contained in the list.
|
Chris@16
|
549 //!
|
Chris@16
|
550 //! <b>Throws</b>: Nothing.
|
Chris@16
|
551 //!
|
Chris@16
|
552 //! <b>Complexity</b>: Constant.
|
Chris@16
|
553 const_iterator begin() const
|
Chris@16
|
554 { return const_iterator (node_traits::get_next(this->get_root_node()), this->real_value_traits_ptr()); }
|
Chris@16
|
555
|
Chris@16
|
556 //! <b>Effects</b>: Returns a const_iterator to the first element contained in the list.
|
Chris@16
|
557 //!
|
Chris@16
|
558 //! <b>Throws</b>: Nothing.
|
Chris@16
|
559 //!
|
Chris@16
|
560 //! <b>Complexity</b>: Constant.
|
Chris@16
|
561 const_iterator cbegin() const
|
Chris@16
|
562 { return const_iterator(node_traits::get_next(this->get_root_node()), this->real_value_traits_ptr()); }
|
Chris@16
|
563
|
Chris@16
|
564 //! <b>Effects</b>: Returns an iterator to the end of the list.
|
Chris@16
|
565 //!
|
Chris@16
|
566 //! <b>Throws</b>: Nothing.
|
Chris@16
|
567 //!
|
Chris@16
|
568 //! <b>Complexity</b>: Constant.
|
Chris@16
|
569 iterator end()
|
Chris@16
|
570 { return iterator(this->get_end_node(), this->real_value_traits_ptr()); }
|
Chris@16
|
571
|
Chris@16
|
572 //! <b>Effects</b>: Returns a const_iterator to the end of the list.
|
Chris@16
|
573 //!
|
Chris@16
|
574 //! <b>Throws</b>: Nothing.
|
Chris@16
|
575 //!
|
Chris@16
|
576 //! <b>Complexity</b>: Constant.
|
Chris@16
|
577 const_iterator end() const
|
Chris@16
|
578 { return const_iterator(detail::uncast(this->get_end_node()), this->real_value_traits_ptr()); }
|
Chris@16
|
579
|
Chris@16
|
580 //! <b>Effects</b>: Returns a const_iterator to the end of the list.
|
Chris@16
|
581 //!
|
Chris@16
|
582 //! <b>Throws</b>: Nothing.
|
Chris@16
|
583 //!
|
Chris@16
|
584 //! <b>Complexity</b>: Constant.
|
Chris@16
|
585 const_iterator cend() const
|
Chris@16
|
586 { return this->end(); }
|
Chris@16
|
587
|
Chris@16
|
588 //! <b>Effects</b>: Returns an iterator that points to a position
|
Chris@16
|
589 //! before the first element. Equivalent to "end()"
|
Chris@16
|
590 //!
|
Chris@16
|
591 //! <b>Throws</b>: Nothing.
|
Chris@16
|
592 //!
|
Chris@16
|
593 //! <b>Complexity</b>: Constant.
|
Chris@16
|
594 iterator before_begin()
|
Chris@16
|
595 { return iterator(this->get_root_node(), this->real_value_traits_ptr()); }
|
Chris@16
|
596
|
Chris@16
|
597 //! <b>Effects</b>: Returns an iterator that points to a position
|
Chris@16
|
598 //! before the first element. Equivalent to "end()"
|
Chris@16
|
599 //!
|
Chris@16
|
600 //! <b>Throws</b>: Nothing.
|
Chris@16
|
601 //!
|
Chris@16
|
602 //! <b>Complexity</b>: Constant.
|
Chris@16
|
603 const_iterator before_begin() const
|
Chris@16
|
604 { return const_iterator(detail::uncast(this->get_root_node()), this->real_value_traits_ptr()); }
|
Chris@16
|
605
|
Chris@16
|
606 //! <b>Effects</b>: Returns an iterator that points to a position
|
Chris@16
|
607 //! before the first element. Equivalent to "end()"
|
Chris@16
|
608 //!
|
Chris@16
|
609 //! <b>Throws</b>: Nothing.
|
Chris@16
|
610 //!
|
Chris@16
|
611 //! <b>Complexity</b>: Constant.
|
Chris@16
|
612 const_iterator cbefore_begin() const
|
Chris@16
|
613 { return this->before_begin(); }
|
Chris@16
|
614
|
Chris@16
|
615 //! <b>Effects</b>: Returns an iterator to the last element contained in the list.
|
Chris@16
|
616 //!
|
Chris@16
|
617 //! <b>Throws</b>: Nothing.
|
Chris@16
|
618 //!
|
Chris@16
|
619 //! <b>Complexity</b>: Constant.
|
Chris@16
|
620 //!
|
Chris@16
|
621 //! <b>Note</b>: This function is present only if cached_last<> option is true.
|
Chris@16
|
622 iterator last()
|
Chris@16
|
623 {
|
Chris@16
|
624 //This function shall not be used if cache_last is not true
|
Chris@16
|
625 BOOST_INTRUSIVE_INVARIANT_ASSERT(cache_last);
|
Chris@16
|
626 return iterator (this->get_last_node(), this->real_value_traits_ptr());
|
Chris@16
|
627 }
|
Chris@16
|
628
|
Chris@16
|
629 //! <b>Effects</b>: Returns a const_iterator to the last element contained in the list.
|
Chris@16
|
630 //!
|
Chris@16
|
631 //! <b>Throws</b>: Nothing.
|
Chris@16
|
632 //!
|
Chris@16
|
633 //! <b>Complexity</b>: Constant.
|
Chris@16
|
634 //!
|
Chris@16
|
635 //! <b>Note</b>: This function is present only if cached_last<> option is true.
|
Chris@16
|
636 const_iterator last() const
|
Chris@16
|
637 {
|
Chris@16
|
638 //This function shall not be used if cache_last is not true
|
Chris@16
|
639 BOOST_INTRUSIVE_INVARIANT_ASSERT(cache_last);
|
Chris@16
|
640 return const_iterator (this->get_last_node(), this->real_value_traits_ptr());
|
Chris@16
|
641 }
|
Chris@16
|
642
|
Chris@16
|
643 //! <b>Effects</b>: Returns a const_iterator to the last element contained in the list.
|
Chris@16
|
644 //!
|
Chris@16
|
645 //! <b>Throws</b>: Nothing.
|
Chris@16
|
646 //!
|
Chris@16
|
647 //! <b>Complexity</b>: Constant.
|
Chris@16
|
648 //!
|
Chris@16
|
649 //! <b>Note</b>: This function is present only if cached_last<> option is true.
|
Chris@16
|
650 const_iterator clast() const
|
Chris@16
|
651 { return const_iterator(this->get_last_node(), this->real_value_traits_ptr()); }
|
Chris@16
|
652
|
Chris@16
|
653 //! <b>Precondition</b>: end_iterator must be a valid end iterator
|
Chris@16
|
654 //! of slist.
|
Chris@16
|
655 //!
|
Chris@16
|
656 //! <b>Effects</b>: Returns a const reference to the slist associated to the end iterator
|
Chris@16
|
657 //!
|
Chris@16
|
658 //! <b>Throws</b>: Nothing.
|
Chris@16
|
659 //!
|
Chris@16
|
660 //! <b>Complexity</b>: Constant.
|
Chris@16
|
661 static slist_impl &container_from_end_iterator(iterator end_iterator)
|
Chris@16
|
662 { return slist_impl::priv_container_from_end_iterator(end_iterator); }
|
Chris@16
|
663
|
Chris@16
|
664 //! <b>Precondition</b>: end_iterator must be a valid end const_iterator
|
Chris@16
|
665 //! of slist.
|
Chris@16
|
666 //!
|
Chris@16
|
667 //! <b>Effects</b>: Returns a const reference to the slist associated to the end iterator
|
Chris@16
|
668 //!
|
Chris@16
|
669 //! <b>Throws</b>: Nothing.
|
Chris@16
|
670 //!
|
Chris@16
|
671 //! <b>Complexity</b>: Constant.
|
Chris@16
|
672 static const slist_impl &container_from_end_iterator(const_iterator end_iterator)
|
Chris@16
|
673 { return slist_impl::priv_container_from_end_iterator(end_iterator); }
|
Chris@16
|
674
|
Chris@16
|
675 //! <b>Effects</b>: Returns the number of the elements contained in the list.
|
Chris@16
|
676 //!
|
Chris@16
|
677 //! <b>Throws</b>: Nothing.
|
Chris@16
|
678 //!
|
Chris@16
|
679 //! <b>Complexity</b>: Linear to the number of elements contained in the list.
|
Chris@16
|
680 //! if constant_time_size is false. Constant time otherwise.
|
Chris@16
|
681 //!
|
Chris@16
|
682 //! <b>Note</b>: Does not affect the validity of iterators and references.
|
Chris@16
|
683 size_type size() const
|
Chris@16
|
684 {
|
Chris@16
|
685 if(constant_time_size)
|
Chris@16
|
686 return this->priv_size_traits().get_size();
|
Chris@16
|
687 else
|
Chris@16
|
688 return node_algorithms::count(this->get_root_node()) - 1;
|
Chris@16
|
689 }
|
Chris@16
|
690
|
Chris@16
|
691 //! <b>Effects</b>: Returns true if the list contains no elements.
|
Chris@16
|
692 //!
|
Chris@16
|
693 //! <b>Throws</b>: Nothing.
|
Chris@16
|
694 //!
|
Chris@16
|
695 //! <b>Complexity</b>: Constant.
|
Chris@16
|
696 //!
|
Chris@16
|
697 //! <b>Note</b>: Does not affect the validity of iterators and references.
|
Chris@16
|
698 bool empty() const
|
Chris@16
|
699 { return node_algorithms::unique(this->get_root_node()); }
|
Chris@16
|
700
|
Chris@16
|
701 //! <b>Effects</b>: Swaps the elements of x and *this.
|
Chris@16
|
702 //!
|
Chris@16
|
703 //! <b>Throws</b>: Nothing.
|
Chris@16
|
704 //!
|
Chris@16
|
705 //! <b>Complexity</b>: Linear to the number of elements of both lists.
|
Chris@16
|
706 //! Constant-time if linear<> and/or cache_last<> options are used.
|
Chris@16
|
707 //!
|
Chris@16
|
708 //! <b>Note</b>: Does not affect the validity of iterators and references.
|
Chris@16
|
709 void swap(slist_impl& other)
|
Chris@16
|
710 {
|
Chris@16
|
711 if(cache_last){
|
Chris@16
|
712 priv_swap_cache_last(this, &other);
|
Chris@16
|
713 }
|
Chris@16
|
714 else{
|
Chris@16
|
715 this->priv_swap_lists(this->get_root_node(), other.get_root_node(), detail::bool_<linear>());
|
Chris@16
|
716 }
|
Chris@16
|
717 if(constant_time_size){
|
Chris@16
|
718 size_type backup = this->priv_size_traits().get_size();
|
Chris@16
|
719 this->priv_size_traits().set_size(other.priv_size_traits().get_size());
|
Chris@16
|
720 other.priv_size_traits().set_size(backup);
|
Chris@16
|
721 }
|
Chris@16
|
722 }
|
Chris@16
|
723
|
Chris@16
|
724 //! <b>Effects</b>: Moves backwards all the elements, so that the first
|
Chris@16
|
725 //! element becomes the second, the second becomes the third...
|
Chris@16
|
726 //! the last element becomes the first one.
|
Chris@16
|
727 //!
|
Chris@16
|
728 //! <b>Throws</b>: Nothing.
|
Chris@16
|
729 //!
|
Chris@16
|
730 //! <b>Complexity</b>: Linear to the number of elements plus the number shifts.
|
Chris@16
|
731 //!
|
Chris@16
|
732 //! <b>Note</b>: Iterators Does not affect the validity of iterators and references.
|
Chris@16
|
733 void shift_backwards(size_type n = 1)
|
Chris@16
|
734 { this->priv_shift_backwards(n, detail::bool_<linear>()); }
|
Chris@16
|
735
|
Chris@16
|
736 //! <b>Effects</b>: Moves forward all the elements, so that the second
|
Chris@16
|
737 //! element becomes the first, the third becomes the second...
|
Chris@16
|
738 //! the first element becomes the last one.
|
Chris@16
|
739 //!
|
Chris@16
|
740 //! <b>Throws</b>: Nothing.
|
Chris@16
|
741 //!
|
Chris@16
|
742 //! <b>Complexity</b>: Linear to the number of elements plus the number shifts.
|
Chris@16
|
743 //!
|
Chris@16
|
744 //! <b>Note</b>: Does not affect the validity of iterators and references.
|
Chris@16
|
745 void shift_forward(size_type n = 1)
|
Chris@16
|
746 { this->priv_shift_forward(n, detail::bool_<linear>()); }
|
Chris@16
|
747
|
Chris@16
|
748 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
|
Chris@16
|
749 //! Cloner should yield to nodes equivalent to the original nodes.
|
Chris@16
|
750 //!
|
Chris@16
|
751 //! <b>Effects</b>: Erases all the elements from *this
|
Chris@16
|
752 //! calling Disposer::operator()(pointer), clones all the
|
Chris@16
|
753 //! elements from src calling Cloner::operator()(const_reference )
|
Chris@16
|
754 //! and inserts them on *this.
|
Chris@16
|
755 //!
|
Chris@16
|
756 //! If cloner throws, all cloned elements are unlinked and disposed
|
Chris@16
|
757 //! calling Disposer::operator()(pointer).
|
Chris@16
|
758 //!
|
Chris@16
|
759 //! <b>Complexity</b>: Linear to erased plus inserted elements.
|
Chris@16
|
760 //!
|
Chris@16
|
761 //! <b>Throws</b>: If cloner throws.
|
Chris@16
|
762 template <class Cloner, class Disposer>
|
Chris@16
|
763 void clone_from(const slist_impl &src, Cloner cloner, Disposer disposer)
|
Chris@16
|
764 {
|
Chris@16
|
765 this->clear_and_dispose(disposer);
|
Chris@16
|
766 detail::exception_disposer<slist_impl, Disposer>
|
Chris@16
|
767 rollback(*this, disposer);
|
Chris@16
|
768 const_iterator prev(this->cbefore_begin());
|
Chris@16
|
769 const_iterator b(src.begin()), e(src.end());
|
Chris@16
|
770 for(; b != e; ++b){
|
Chris@16
|
771 prev = this->insert_after(prev, *cloner(*b));
|
Chris@16
|
772 }
|
Chris@16
|
773 rollback.release();
|
Chris@16
|
774 }
|
Chris@16
|
775
|
Chris@16
|
776 //! <b>Requires</b>: value must be an lvalue and prev_p must point to an element
|
Chris@16
|
777 //! contained by the list or to end().
|
Chris@16
|
778 //!
|
Chris@16
|
779 //! <b>Effects</b>: Inserts the value after the position pointed by prev_p.
|
Chris@16
|
780 //! No copy constructor is called.
|
Chris@16
|
781 //!
|
Chris@16
|
782 //! <b>Returns</b>: An iterator to the inserted element.
|
Chris@16
|
783 //!
|
Chris@16
|
784 //! <b>Throws</b>: Nothing.
|
Chris@16
|
785 //!
|
Chris@16
|
786 //! <b>Complexity</b>: Constant.
|
Chris@16
|
787 //!
|
Chris@16
|
788 //! <b>Note</b>: Does not affect the validity of iterators and references.
|
Chris@16
|
789 iterator insert_after(const_iterator prev_p, reference value)
|
Chris@16
|
790 {
|
Chris@16
|
791 node_ptr n = get_real_value_traits().to_node_ptr(value);
|
Chris@16
|
792 if(safemode_or_autounlink)
|
Chris@16
|
793 BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(n));
|
Chris@16
|
794 node_ptr prev_n(prev_p.pointed_node());
|
Chris@16
|
795 node_algorithms::link_after(prev_n, n);
|
Chris@16
|
796 if(cache_last && (this->get_last_node() == prev_n)){
|
Chris@16
|
797 this->set_last_node(n);
|
Chris@16
|
798 }
|
Chris@16
|
799 this->priv_size_traits().increment();
|
Chris@16
|
800 return iterator (n, this->real_value_traits_ptr());
|
Chris@16
|
801 }
|
Chris@16
|
802
|
Chris@16
|
803 //! <b>Requires</b>: Dereferencing iterator must yield
|
Chris@16
|
804 //! an lvalue of type value_type and prev_p must point to an element
|
Chris@16
|
805 //! contained by the list or to the end node.
|
Chris@16
|
806 //!
|
Chris@16
|
807 //! <b>Effects</b>: Inserts the [f, l)
|
Chris@16
|
808 //! after the position prev_p.
|
Chris@16
|
809 //!
|
Chris@16
|
810 //! <b>Throws</b>: Nothing.
|
Chris@16
|
811 //!
|
Chris@16
|
812 //! <b>Complexity</b>: Linear to the number of elements inserted.
|
Chris@16
|
813 //!
|
Chris@16
|
814 //! <b>Note</b>: Does not affect the validity of iterators and references.
|
Chris@16
|
815 template<class Iterator>
|
Chris@16
|
816 void insert_after(const_iterator prev_p, Iterator f, Iterator l)
|
Chris@16
|
817 {
|
Chris@16
|
818 //Insert first nodes avoiding cache and size checks
|
Chris@16
|
819 size_type count = 0;
|
Chris@16
|
820 node_ptr prev_n(prev_p.pointed_node());
|
Chris@16
|
821 for (; f != l; ++f, ++count){
|
Chris@16
|
822 const node_ptr n = get_real_value_traits().to_node_ptr(*f);
|
Chris@16
|
823 if(safemode_or_autounlink)
|
Chris@16
|
824 BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(n));
|
Chris@16
|
825 node_algorithms::link_after(prev_n, n);
|
Chris@16
|
826 prev_n = n;
|
Chris@16
|
827 }
|
Chris@16
|
828 //Now fix special cases if needed
|
Chris@16
|
829 if(cache_last && (this->get_last_node() == prev_p.pointed_node())){
|
Chris@16
|
830 this->set_last_node(prev_n);
|
Chris@16
|
831 }
|
Chris@16
|
832 if(constant_time_size){
|
Chris@16
|
833 this->priv_size_traits().increase(count);
|
Chris@16
|
834 }
|
Chris@16
|
835 }
|
Chris@16
|
836
|
Chris@16
|
837 //! <b>Requires</b>: value must be an lvalue and p must point to an element
|
Chris@16
|
838 //! contained by the list or to end().
|
Chris@16
|
839 //!
|
Chris@16
|
840 //! <b>Effects</b>: Inserts the value before the position pointed by p.
|
Chris@16
|
841 //! No copy constructor is called.
|
Chris@16
|
842 //!
|
Chris@16
|
843 //! <b>Throws</b>: Nothing.
|
Chris@16
|
844 //!
|
Chris@16
|
845 //! <b>Complexity</b>: Linear to the number of elements before p.
|
Chris@16
|
846 //! Constant-time if cache_last<> is true and p == end().
|
Chris@16
|
847 //!
|
Chris@16
|
848 //! <b>Note</b>: Does not affect the validity of iterators and references.
|
Chris@16
|
849 iterator insert(const_iterator p, reference value)
|
Chris@16
|
850 { return this->insert_after(this->previous(p), value); }
|
Chris@16
|
851
|
Chris@16
|
852 //! <b>Requires</b>: Dereferencing iterator must yield
|
Chris@16
|
853 //! an lvalue of type value_type and p must point to an element
|
Chris@16
|
854 //! contained by the list or to the end node.
|
Chris@16
|
855 //!
|
Chris@16
|
856 //! <b>Effects</b>: Inserts the pointed by b and e
|
Chris@16
|
857 //! before the position p. No copy constructors are called.
|
Chris@16
|
858 //!
|
Chris@16
|
859 //! <b>Throws</b>: Nothing.
|
Chris@16
|
860 //!
|
Chris@16
|
861 //! <b>Complexity</b>: Linear to the number of elements inserted plus linear
|
Chris@16
|
862 //! to the elements before b.
|
Chris@16
|
863 //! Linear to the number of elements to insert if cache_last<> option is true and p == end().
|
Chris@16
|
864 //!
|
Chris@16
|
865 //! <b>Note</b>: Does not affect the validity of iterators and references.
|
Chris@16
|
866 template<class Iterator>
|
Chris@16
|
867 void insert(const_iterator p, Iterator b, Iterator e)
|
Chris@16
|
868 { return this->insert_after(this->previous(p), b, e); }
|
Chris@16
|
869
|
Chris@16
|
870 //! <b>Effects</b>: Erases the element after the element pointed by prev of
|
Chris@16
|
871 //! the list. No destructors are called.
|
Chris@16
|
872 //!
|
Chris@16
|
873 //! <b>Returns</b>: the first element remaining beyond the removed elements,
|
Chris@16
|
874 //! or end() if no such element exists.
|
Chris@16
|
875 //!
|
Chris@16
|
876 //! <b>Throws</b>: Nothing.
|
Chris@16
|
877 //!
|
Chris@16
|
878 //! <b>Complexity</b>: Constant.
|
Chris@16
|
879 //!
|
Chris@16
|
880 //! <b>Note</b>: Invalidates the iterators (but not the references) to the
|
Chris@16
|
881 //! erased element.
|
Chris@16
|
882 iterator erase_after(const_iterator prev)
|
Chris@16
|
883 { return this->erase_after_and_dispose(prev, detail::null_disposer()); }
|
Chris@16
|
884
|
Chris@16
|
885 //! <b>Effects</b>: Erases the range (before_f, l) from
|
Chris@16
|
886 //! the list. No destructors are called.
|
Chris@16
|
887 //!
|
Chris@16
|
888 //! <b>Returns</b>: the first element remaining beyond the removed elements,
|
Chris@16
|
889 //! or end() if no such element exists.
|
Chris@16
|
890 //!
|
Chris@16
|
891 //! <b>Throws</b>: Nothing.
|
Chris@16
|
892 //!
|
Chris@16
|
893 //! <b>Complexity</b>: Linear to the number of erased elements if it's a safe-mode
|
Chris@16
|
894 //! , auto-unlink value or constant-time size is activated. Constant time otherwise.
|
Chris@16
|
895 //!
|
Chris@16
|
896 //! <b>Note</b>: Invalidates the iterators (but not the references) to the
|
Chris@16
|
897 //! erased element.
|
Chris@16
|
898 iterator erase_after(const_iterator before_f, const_iterator l)
|
Chris@16
|
899 {
|
Chris@16
|
900 if(safemode_or_autounlink || constant_time_size){
|
Chris@16
|
901 return this->erase_after_and_dispose(before_f, l, detail::null_disposer());
|
Chris@16
|
902 }
|
Chris@16
|
903 else{
|
Chris@16
|
904 const node_ptr bfp = before_f.pointed_node();
|
Chris@16
|
905 const node_ptr lp = l.pointed_node();
|
Chris@16
|
906 if(cache_last){
|
Chris@16
|
907 if(lp == this->get_end_node()){
|
Chris@16
|
908 this->set_last_node(bfp);
|
Chris@16
|
909 }
|
Chris@16
|
910 }
|
Chris@16
|
911 node_algorithms::unlink_after(bfp, lp);
|
Chris@16
|
912 return l.unconst();
|
Chris@16
|
913 }
|
Chris@16
|
914 }
|
Chris@16
|
915
|
Chris@16
|
916 //! <b>Effects</b>: Erases the range (before_f, l) from
|
Chris@16
|
917 //! the list. n must be std::distance(before_f, l) - 1.
|
Chris@16
|
918 //! No destructors are called.
|
Chris@16
|
919 //!
|
Chris@16
|
920 //! <b>Returns</b>: the first element remaining beyond the removed elements,
|
Chris@16
|
921 //! or end() if no such element exists.
|
Chris@16
|
922 //!
|
Chris@16
|
923 //! <b>Throws</b>: Nothing.
|
Chris@16
|
924 //!
|
Chris@16
|
925 //! <b>Complexity</b>: constant-time if link_mode is normal_link.
|
Chris@16
|
926 //! Linear to the elements (l - before_f) otherwise.
|
Chris@16
|
927 //!
|
Chris@16
|
928 //! <b>Note</b>: Invalidates the iterators (but not the references) to the
|
Chris@16
|
929 //! erased element.
|
Chris@16
|
930 iterator erase_after(const_iterator before_f, const_iterator l, size_type n)
|
Chris@16
|
931 {
|
Chris@16
|
932 BOOST_INTRUSIVE_INVARIANT_ASSERT(std::distance(++const_iterator(before_f), l) == difference_type(n));
|
Chris@16
|
933 if(safemode_or_autounlink){
|
Chris@16
|
934 return this->erase_after(before_f, l);
|
Chris@16
|
935 }
|
Chris@16
|
936 else{
|
Chris@16
|
937 const node_ptr bfp = before_f.pointed_node();
|
Chris@16
|
938 const node_ptr lp = l.pointed_node();
|
Chris@16
|
939 if(cache_last){
|
Chris@16
|
940 if((lp == this->get_end_node())){
|
Chris@16
|
941 this->set_last_node(bfp);
|
Chris@16
|
942 }
|
Chris@16
|
943 }
|
Chris@16
|
944 node_algorithms::unlink_after(bfp, lp);
|
Chris@16
|
945 if(constant_time_size){
|
Chris@16
|
946 this->priv_size_traits().decrease(n);
|
Chris@16
|
947 }
|
Chris@16
|
948 return l.unconst();
|
Chris@16
|
949 }
|
Chris@16
|
950 }
|
Chris@16
|
951
|
Chris@16
|
952 //! <b>Effects</b>: Erases the element pointed by i of the list.
|
Chris@16
|
953 //! No destructors are called.
|
Chris@16
|
954 //!
|
Chris@16
|
955 //! <b>Returns</b>: the first element remaining beyond the removed element,
|
Chris@16
|
956 //! or end() if no such element exists.
|
Chris@16
|
957 //!
|
Chris@16
|
958 //! <b>Throws</b>: Nothing.
|
Chris@16
|
959 //!
|
Chris@16
|
960 //! <b>Complexity</b>: Linear to the elements before i.
|
Chris@16
|
961 //!
|
Chris@16
|
962 //! <b>Note</b>: Invalidates the iterators (but not the references) to the
|
Chris@16
|
963 //! erased element.
|
Chris@16
|
964 iterator erase(const_iterator i)
|
Chris@16
|
965 { return this->erase_after(this->previous(i)); }
|
Chris@16
|
966
|
Chris@16
|
967 //! <b>Requires</b>: f and l must be valid iterator to elements in *this.
|
Chris@16
|
968 //!
|
Chris@16
|
969 //! <b>Effects</b>: Erases the range pointed by b and e.
|
Chris@16
|
970 //! No destructors are called.
|
Chris@16
|
971 //!
|
Chris@16
|
972 //! <b>Returns</b>: the first element remaining beyond the removed elements,
|
Chris@16
|
973 //! or end() if no such element exists.
|
Chris@16
|
974 //!
|
Chris@16
|
975 //! <b>Throws</b>: Nothing.
|
Chris@16
|
976 //!
|
Chris@16
|
977 //! <b>Complexity</b>: Linear to the elements before l.
|
Chris@16
|
978 //!
|
Chris@16
|
979 //! <b>Note</b>: Invalidates the iterators (but not the references) to the
|
Chris@16
|
980 //! erased elements.
|
Chris@16
|
981 iterator erase(const_iterator f, const_iterator l)
|
Chris@16
|
982 { return this->erase_after(this->previous(f), l); }
|
Chris@16
|
983
|
Chris@16
|
984 //! <b>Effects</b>: Erases the range [f, l) from
|
Chris@16
|
985 //! the list. n must be std::distance(f, l).
|
Chris@16
|
986 //! No destructors are called.
|
Chris@16
|
987 //!
|
Chris@16
|
988 //! <b>Returns</b>: the first element remaining beyond the removed elements,
|
Chris@16
|
989 //! or end() if no such element exists.
|
Chris@16
|
990 //!
|
Chris@16
|
991 //! <b>Throws</b>: Nothing.
|
Chris@16
|
992 //!
|
Chris@16
|
993 //! <b>Complexity</b>: linear to the elements before f if link_mode is normal_link
|
Chris@16
|
994 //! and constant_time_size is activated. Linear to the elements before l otherwise.
|
Chris@16
|
995 //!
|
Chris@16
|
996 //! <b>Note</b>: Invalidates the iterators (but not the references) to the
|
Chris@16
|
997 //! erased element.
|
Chris@16
|
998 iterator erase(const_iterator f, const_iterator l, size_type n)
|
Chris@16
|
999 { return this->erase_after(this->previous(f), l, n); }
|
Chris@16
|
1000
|
Chris@16
|
1001 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
|
Chris@16
|
1002 //!
|
Chris@16
|
1003 //! <b>Effects</b>: Erases the element after the element pointed by prev of
|
Chris@16
|
1004 //! the list.
|
Chris@16
|
1005 //! Disposer::operator()(pointer) is called for the removed element.
|
Chris@16
|
1006 //!
|
Chris@16
|
1007 //! <b>Returns</b>: the first element remaining beyond the removed elements,
|
Chris@16
|
1008 //! or end() if no such element exists.
|
Chris@16
|
1009 //!
|
Chris@16
|
1010 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1011 //!
|
Chris@16
|
1012 //! <b>Complexity</b>: Constant.
|
Chris@16
|
1013 //!
|
Chris@16
|
1014 //! <b>Note</b>: Invalidates the iterators to the erased element.
|
Chris@16
|
1015 template<class Disposer>
|
Chris@16
|
1016 iterator erase_after_and_dispose(const_iterator prev, Disposer disposer)
|
Chris@16
|
1017 {
|
Chris@16
|
1018 const_iterator it(prev);
|
Chris@16
|
1019 ++it;
|
Chris@16
|
1020 node_ptr to_erase(it.pointed_node());
|
Chris@16
|
1021 ++it;
|
Chris@16
|
1022 node_ptr prev_n(prev.pointed_node());
|
Chris@16
|
1023 node_algorithms::unlink_after(prev_n);
|
Chris@16
|
1024 if(cache_last && (to_erase == this->get_last_node())){
|
Chris@16
|
1025 this->set_last_node(prev_n);
|
Chris@16
|
1026 }
|
Chris@16
|
1027 if(safemode_or_autounlink)
|
Chris@16
|
1028 node_algorithms::init(to_erase);
|
Chris@16
|
1029 disposer(get_real_value_traits().to_value_ptr(to_erase));
|
Chris@16
|
1030 this->priv_size_traits().decrement();
|
Chris@16
|
1031 return it.unconst();
|
Chris@16
|
1032 }
|
Chris@16
|
1033
|
Chris@16
|
1034 /// @cond
|
Chris@16
|
1035
|
Chris@16
|
1036 template<class Disposer>
|
Chris@16
|
1037 static iterator s_erase_after_and_dispose(const_iterator prev, Disposer disposer)
|
Chris@16
|
1038 {
|
Chris@16
|
1039 BOOST_STATIC_ASSERT(((!cache_last)&&(!constant_time_size)&&(!stateful_value_traits)));
|
Chris@16
|
1040 const_iterator it(prev);
|
Chris@16
|
1041 ++it;
|
Chris@16
|
1042 node_ptr to_erase(it.pointed_node());
|
Chris@16
|
1043 ++it;
|
Chris@16
|
1044 node_ptr prev_n(prev.pointed_node());
|
Chris@16
|
1045 node_algorithms::unlink_after(prev_n);
|
Chris@16
|
1046 if(safemode_or_autounlink)
|
Chris@16
|
1047 node_algorithms::init(to_erase);
|
Chris@16
|
1048 disposer(real_value_traits::to_value_ptr(to_erase));
|
Chris@16
|
1049 return it.unconst();
|
Chris@16
|
1050 }
|
Chris@16
|
1051
|
Chris@16
|
1052 static iterator s_erase_after(const_iterator prev)
|
Chris@16
|
1053 { return s_erase_after_and_dispose(prev, detail::null_disposer()); }
|
Chris@16
|
1054
|
Chris@16
|
1055 /// @endcond
|
Chris@16
|
1056
|
Chris@16
|
1057 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
|
Chris@16
|
1058 //!
|
Chris@16
|
1059 //! <b>Effects</b>: Erases the range (before_f, l) from
|
Chris@16
|
1060 //! the list.
|
Chris@16
|
1061 //! Disposer::operator()(pointer) is called for the removed elements.
|
Chris@16
|
1062 //!
|
Chris@16
|
1063 //! <b>Returns</b>: the first element remaining beyond the removed elements,
|
Chris@16
|
1064 //! or end() if no such element exists.
|
Chris@16
|
1065 //!
|
Chris@16
|
1066 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1067 //!
|
Chris@16
|
1068 //! <b>Complexity</b>: Lineal to the elements (l - before_f + 1).
|
Chris@16
|
1069 //!
|
Chris@16
|
1070 //! <b>Note</b>: Invalidates the iterators to the erased element.
|
Chris@16
|
1071 template<class Disposer>
|
Chris@16
|
1072 iterator erase_after_and_dispose(const_iterator before_f, const_iterator l, Disposer disposer)
|
Chris@16
|
1073 {
|
Chris@16
|
1074 node_ptr bfp(before_f.pointed_node()), lp(l.pointed_node());
|
Chris@16
|
1075 node_ptr fp(node_traits::get_next(bfp));
|
Chris@16
|
1076 node_algorithms::unlink_after(bfp, lp);
|
Chris@16
|
1077 while(fp != lp){
|
Chris@16
|
1078 node_ptr to_erase(fp);
|
Chris@16
|
1079 fp = node_traits::get_next(fp);
|
Chris@16
|
1080 if(safemode_or_autounlink)
|
Chris@16
|
1081 node_algorithms::init(to_erase);
|
Chris@16
|
1082 disposer(get_real_value_traits().to_value_ptr(to_erase));
|
Chris@16
|
1083 this->priv_size_traits().decrement();
|
Chris@16
|
1084 }
|
Chris@16
|
1085 if(cache_last && (node_traits::get_next(bfp) == this->get_end_node())){
|
Chris@16
|
1086 this->set_last_node(bfp);
|
Chris@16
|
1087 }
|
Chris@16
|
1088 return l.unconst();
|
Chris@16
|
1089 }
|
Chris@16
|
1090
|
Chris@16
|
1091 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
|
Chris@16
|
1092 //!
|
Chris@16
|
1093 //! <b>Effects</b>: Erases the element pointed by i of the list.
|
Chris@16
|
1094 //! No destructors are called.
|
Chris@16
|
1095 //! Disposer::operator()(pointer) is called for the removed element.
|
Chris@16
|
1096 //!
|
Chris@16
|
1097 //! <b>Returns</b>: the first element remaining beyond the removed element,
|
Chris@16
|
1098 //! or end() if no such element exists.
|
Chris@16
|
1099 //!
|
Chris@16
|
1100 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1101 //!
|
Chris@16
|
1102 //! <b>Complexity</b>: Linear to the elements before i.
|
Chris@16
|
1103 //!
|
Chris@16
|
1104 //! <b>Note</b>: Invalidates the iterators (but not the references) to the
|
Chris@16
|
1105 //! erased element.
|
Chris@16
|
1106 template<class Disposer>
|
Chris@16
|
1107 iterator erase_and_dispose(const_iterator i, Disposer disposer)
|
Chris@16
|
1108 { return this->erase_after_and_dispose(this->previous(i), disposer); }
|
Chris@16
|
1109
|
Chris@16
|
1110 #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
|
Chris@16
|
1111 template<class Disposer>
|
Chris@16
|
1112 iterator erase_and_dispose(iterator i, Disposer disposer)
|
Chris@16
|
1113 { return this->erase_and_dispose(const_iterator(i), disposer); }
|
Chris@16
|
1114 #endif
|
Chris@16
|
1115
|
Chris@16
|
1116 //! <b>Requires</b>: f and l must be valid iterator to elements in *this.
|
Chris@16
|
1117 //! Disposer::operator()(pointer) shouldn't throw.
|
Chris@16
|
1118 //!
|
Chris@16
|
1119 //! <b>Effects</b>: Erases the range pointed by b and e.
|
Chris@16
|
1120 //! No destructors are called.
|
Chris@16
|
1121 //! Disposer::operator()(pointer) is called for the removed elements.
|
Chris@16
|
1122 //!
|
Chris@16
|
1123 //! <b>Returns</b>: the first element remaining beyond the removed elements,
|
Chris@16
|
1124 //! or end() if no such element exists.
|
Chris@16
|
1125 //!
|
Chris@16
|
1126 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1127 //!
|
Chris@16
|
1128 //! <b>Complexity</b>: Linear to the number of erased elements plus linear
|
Chris@16
|
1129 //! to the elements before f.
|
Chris@16
|
1130 //!
|
Chris@16
|
1131 //! <b>Note</b>: Invalidates the iterators (but not the references) to the
|
Chris@16
|
1132 //! erased elements.
|
Chris@16
|
1133 template<class Disposer>
|
Chris@16
|
1134 iterator erase_and_dispose(const_iterator f, const_iterator l, Disposer disposer)
|
Chris@16
|
1135 { return this->erase_after_and_dispose(this->previous(f), l, disposer); }
|
Chris@16
|
1136
|
Chris@16
|
1137 //! <b>Requires</b>: Dereferencing iterator must yield
|
Chris@16
|
1138 //! an lvalue of type value_type.
|
Chris@16
|
1139 //!
|
Chris@16
|
1140 //! <b>Effects</b>: Clears the list and inserts the range pointed by b and e.
|
Chris@16
|
1141 //! No destructors or copy constructors are called.
|
Chris@16
|
1142 //!
|
Chris@16
|
1143 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1144 //!
|
Chris@16
|
1145 //! <b>Complexity</b>: Linear to the number of elements inserted plus
|
Chris@16
|
1146 //! linear to the elements contained in the list if it's a safe-mode
|
Chris@16
|
1147 //! or auto-unlink value.
|
Chris@16
|
1148 //! Linear to the number of elements inserted in the list otherwise.
|
Chris@16
|
1149 //!
|
Chris@16
|
1150 //! <b>Note</b>: Invalidates the iterators (but not the references)
|
Chris@16
|
1151 //! to the erased elements.
|
Chris@16
|
1152 template<class Iterator>
|
Chris@16
|
1153 void assign(Iterator b, Iterator e)
|
Chris@16
|
1154 {
|
Chris@16
|
1155 this->clear();
|
Chris@16
|
1156 this->insert_after(this->cbefore_begin(), b, e);
|
Chris@16
|
1157 }
|
Chris@16
|
1158
|
Chris@16
|
1159 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
|
Chris@16
|
1160 //!
|
Chris@16
|
1161 //! <b>Requires</b>: Dereferencing iterator must yield
|
Chris@16
|
1162 //! an lvalue of type value_type.
|
Chris@16
|
1163 //!
|
Chris@16
|
1164 //! <b>Effects</b>: Clears the list and inserts the range pointed by b and e.
|
Chris@16
|
1165 //! No destructors or copy constructors are called.
|
Chris@16
|
1166 //! Disposer::operator()(pointer) is called for the removed elements.
|
Chris@16
|
1167 //!
|
Chris@16
|
1168 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1169 //!
|
Chris@16
|
1170 //! <b>Complexity</b>: Linear to the number of elements inserted plus
|
Chris@16
|
1171 //! linear to the elements contained in the list.
|
Chris@16
|
1172 //!
|
Chris@16
|
1173 //! <b>Note</b>: Invalidates the iterators (but not the references)
|
Chris@16
|
1174 //! to the erased elements.
|
Chris@16
|
1175 template<class Iterator, class Disposer>
|
Chris@16
|
1176 void dispose_and_assign(Disposer disposer, Iterator b, Iterator e)
|
Chris@16
|
1177 {
|
Chris@16
|
1178 this->clear_and_dispose(disposer);
|
Chris@16
|
1179 this->insert_after(this->cbefore_begin(), b, e, disposer);
|
Chris@16
|
1180 }
|
Chris@16
|
1181
|
Chris@16
|
1182 //! <b>Requires</b>: prev must point to an element contained by this list or
|
Chris@16
|
1183 //! to the before_begin() element
|
Chris@16
|
1184 //!
|
Chris@16
|
1185 //! <b>Effects</b>: Transfers all the elements of list x to this list, after the
|
Chris@16
|
1186 //! the element pointed by prev. No destructors or copy constructors are called.
|
Chris@16
|
1187 //!
|
Chris@16
|
1188 //! <b>Returns</b>: Nothing.
|
Chris@16
|
1189 //!
|
Chris@16
|
1190 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1191 //!
|
Chris@16
|
1192 //! <b>Complexity</b>: In general, linear to the elements contained in x.
|
Chris@16
|
1193 //! Constant-time if cache_last<> option is true and also constant-time if
|
Chris@16
|
1194 //! linear<> option is true "this" is empty and "l" is not used.
|
Chris@16
|
1195 //!
|
Chris@16
|
1196 //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
|
Chris@16
|
1197 //! list. Iterators of this list and all the references are not invalidated.
|
Chris@16
|
1198 //!
|
Chris@16
|
1199 //! <b>Additional note</b>: If the optional parameter "l" is provided, it will be
|
Chris@16
|
1200 //! assigned to the last spliced element or prev if x is empty.
|
Chris@16
|
1201 //! This iterator can be used as new "prev" iterator for a new splice_after call.
|
Chris@16
|
1202 //! that will splice new values after the previously spliced values.
|
Chris@16
|
1203 void splice_after(const_iterator prev, slist_impl &x, const_iterator *l = 0)
|
Chris@16
|
1204 {
|
Chris@16
|
1205 if(x.empty()){
|
Chris@16
|
1206 if(l) *l = prev;
|
Chris@16
|
1207 }
|
Chris@16
|
1208 else if(linear && this->empty()){
|
Chris@16
|
1209 this->swap(x);
|
Chris@16
|
1210 if(l) *l = this->previous(this->cend());
|
Chris@16
|
1211 }
|
Chris@16
|
1212 else{
|
Chris@16
|
1213 const_iterator last_x(x.previous(x.end())); //<- constant time if cache_last is active
|
Chris@16
|
1214 node_ptr prev_n(prev.pointed_node());
|
Chris@16
|
1215 node_ptr last_x_n(last_x.pointed_node());
|
Chris@16
|
1216 if(cache_last){
|
Chris@16
|
1217 x.set_last_node(x.get_root_node());
|
Chris@16
|
1218 if(node_traits::get_next(prev_n) == this->get_end_node()){
|
Chris@16
|
1219 this->set_last_node(last_x_n);
|
Chris@16
|
1220 }
|
Chris@16
|
1221 }
|
Chris@16
|
1222 node_algorithms::transfer_after( prev_n, x.before_begin().pointed_node(), last_x_n);
|
Chris@16
|
1223 this->priv_size_traits().increase(x.priv_size_traits().get_size());
|
Chris@16
|
1224 x.priv_size_traits().set_size(size_type(0));
|
Chris@16
|
1225 if(l) *l = last_x;
|
Chris@16
|
1226 }
|
Chris@16
|
1227 }
|
Chris@16
|
1228
|
Chris@16
|
1229 //! <b>Requires</b>: prev must point to an element contained by this list or
|
Chris@16
|
1230 //! to the before_begin() element. prev_ele must point to an element contained in list
|
Chris@16
|
1231 //! x or must be x.before_begin().
|
Chris@16
|
1232 //!
|
Chris@16
|
1233 //! <b>Effects</b>: Transfers the element after prev_ele, from list x to this list,
|
Chris@16
|
1234 //! after the element pointed by prev. No destructors or copy constructors are called.
|
Chris@16
|
1235 //!
|
Chris@16
|
1236 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1237 //!
|
Chris@16
|
1238 //! <b>Complexity</b>: Constant.
|
Chris@16
|
1239 //!
|
Chris@16
|
1240 //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
|
Chris@16
|
1241 //! list. Iterators of this list and all the references are not invalidated.
|
Chris@16
|
1242 void splice_after(const_iterator prev_pos, slist_impl &x, const_iterator prev_ele)
|
Chris@16
|
1243 {
|
Chris@16
|
1244 const_iterator elem = prev_ele;
|
Chris@16
|
1245 this->splice_after(prev_pos, x, prev_ele, ++elem, 1);
|
Chris@16
|
1246 }
|
Chris@16
|
1247
|
Chris@16
|
1248 //! <b>Requires</b>: prev_pos must be a dereferenceable iterator in *this or be
|
Chris@16
|
1249 //! before_begin(), and before_f and before_l belong to x and
|
Chris@16
|
1250 //! ++before_f != x.end() && before_l != x.end().
|
Chris@16
|
1251 //!
|
Chris@16
|
1252 //! <b>Effects</b>: Transfers the range (before_f, before_l] from list x to this
|
Chris@16
|
1253 //! list, after the element pointed by prev_pos.
|
Chris@16
|
1254 //! No destructors or copy constructors are called.
|
Chris@16
|
1255 //!
|
Chris@16
|
1256 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1257 //!
|
Chris@16
|
1258 //! <b>Complexity</b>: Linear to the number of elements transferred
|
Chris@16
|
1259 //! if constant_time_size is true. Constant-time otherwise.
|
Chris@16
|
1260 //!
|
Chris@16
|
1261 //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
|
Chris@16
|
1262 //! list. Iterators of this list and all the references are not invalidated.
|
Chris@16
|
1263 void splice_after(const_iterator prev_pos, slist_impl &x, const_iterator before_f, const_iterator before_l)
|
Chris@16
|
1264 {
|
Chris@16
|
1265 if(constant_time_size)
|
Chris@16
|
1266 this->splice_after(prev_pos, x, before_f, before_l, std::distance(before_f, before_l));
|
Chris@16
|
1267 else
|
Chris@16
|
1268 this->priv_splice_after
|
Chris@16
|
1269 (prev_pos.pointed_node(), x, before_f.pointed_node(), before_l.pointed_node());
|
Chris@16
|
1270 }
|
Chris@16
|
1271
|
Chris@16
|
1272 //! <b>Requires</b>: prev_pos must be a dereferenceable iterator in *this or be
|
Chris@16
|
1273 //! before_begin(), and before_f and before_l belong to x and
|
Chris@16
|
1274 //! ++before_f != x.end() && before_l != x.end() and
|
Chris@16
|
1275 //! n == std::distance(before_f, before_l).
|
Chris@16
|
1276 //!
|
Chris@16
|
1277 //! <b>Effects</b>: Transfers the range (before_f, before_l] from list x to this
|
Chris@16
|
1278 //! list, after the element pointed by p. No destructors or copy constructors are called.
|
Chris@16
|
1279 //!
|
Chris@16
|
1280 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1281 //!
|
Chris@16
|
1282 //! <b>Complexity</b>: Constant time.
|
Chris@16
|
1283 //!
|
Chris@16
|
1284 //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
|
Chris@16
|
1285 //! list. Iterators of this list and all the references are not invalidated.
|
Chris@16
|
1286 void splice_after(const_iterator prev_pos, slist_impl &x, const_iterator before_f, const_iterator before_l, size_type n)
|
Chris@16
|
1287 {
|
Chris@16
|
1288 BOOST_INTRUSIVE_INVARIANT_ASSERT(std::distance(before_f, before_l) == difference_type(n));
|
Chris@16
|
1289 this->priv_splice_after
|
Chris@16
|
1290 (prev_pos.pointed_node(), x, before_f.pointed_node(), before_l.pointed_node());
|
Chris@16
|
1291 if(constant_time_size){
|
Chris@16
|
1292 this->priv_size_traits().increase(n);
|
Chris@16
|
1293 x.priv_size_traits().decrease(n);
|
Chris@16
|
1294 }
|
Chris@16
|
1295 }
|
Chris@16
|
1296
|
Chris@16
|
1297 //! <b>Requires</b>: it is an iterator to an element in *this.
|
Chris@16
|
1298 //!
|
Chris@16
|
1299 //! <b>Effects</b>: Transfers all the elements of list x to this list, before the
|
Chris@16
|
1300 //! the element pointed by it. No destructors or copy constructors are called.
|
Chris@16
|
1301 //!
|
Chris@16
|
1302 //! <b>Returns</b>: Nothing.
|
Chris@16
|
1303 //!
|
Chris@16
|
1304 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1305 //!
|
Chris@16
|
1306 //! <b>Complexity</b>: Linear to the elements contained in x plus linear to
|
Chris@16
|
1307 //! the elements before it.
|
Chris@16
|
1308 //! Linear to the elements before it if cache_last<> option is true.
|
Chris@16
|
1309 //! Constant-time if cache_last<> option is true and it == end().
|
Chris@16
|
1310 //!
|
Chris@16
|
1311 //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
|
Chris@16
|
1312 //! list. Iterators of this list and all the references are not invalidated.
|
Chris@16
|
1313 //!
|
Chris@16
|
1314 //! <b>Additional note</b>: If the optional parameter "l" is provided, it will be
|
Chris@16
|
1315 //! assigned to the last spliced element or prev if x is empty.
|
Chris@16
|
1316 //! This iterator can be used as new "prev" iterator for a new splice_after call.
|
Chris@16
|
1317 //! that will splice new values after the previously spliced values.
|
Chris@16
|
1318 void splice(const_iterator it, slist_impl &x, const_iterator *l = 0)
|
Chris@16
|
1319 { this->splice_after(this->previous(it), x, l); }
|
Chris@16
|
1320
|
Chris@16
|
1321 //! <b>Requires</b>: it p must be a valid iterator of *this.
|
Chris@16
|
1322 //! elem must point to an element contained in list
|
Chris@16
|
1323 //! x.
|
Chris@16
|
1324 //!
|
Chris@16
|
1325 //! <b>Effects</b>: Transfers the element elem, from list x to this list,
|
Chris@16
|
1326 //! before the element pointed by pos. No destructors or copy constructors are called.
|
Chris@16
|
1327 //!
|
Chris@16
|
1328 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1329 //!
|
Chris@16
|
1330 //! <b>Complexity</b>: Linear to the elements before pos and before elem.
|
Chris@16
|
1331 //! Linear to the elements before elem if cache_last<> option is true and pos == end().
|
Chris@16
|
1332 //!
|
Chris@16
|
1333 //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
|
Chris@16
|
1334 //! list. Iterators of this list and all the references are not invalidated.
|
Chris@16
|
1335 void splice(const_iterator pos, slist_impl &x, const_iterator elem)
|
Chris@16
|
1336 { return this->splice_after(this->previous(pos), x, x.previous(elem)); }
|
Chris@16
|
1337
|
Chris@16
|
1338 //! <b>Requires</b>: pos must be a dereferenceable iterator in *this
|
Chris@16
|
1339 //! and f and f belong to x and f and f a valid range on x.
|
Chris@16
|
1340 //!
|
Chris@16
|
1341 //! <b>Effects</b>: Transfers the range [f, l) from list x to this
|
Chris@16
|
1342 //! list, before the element pointed by pos.
|
Chris@16
|
1343 //! No destructors or copy constructors are called.
|
Chris@16
|
1344 //!
|
Chris@16
|
1345 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1346 //!
|
Chris@16
|
1347 //! <b>Complexity</b>: Linear to the sum of elements before pos, f, and l
|
Chris@16
|
1348 //! plus linear to the number of elements transferred if constant_time_size is true.
|
Chris@16
|
1349 //! Linear to the sum of elements before f, and l
|
Chris@16
|
1350 //! plus linear to the number of elements transferred if constant_time_size is true
|
Chris@16
|
1351 //! if cache_last<> is true and pos == end()
|
Chris@16
|
1352 //!
|
Chris@16
|
1353 //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
|
Chris@16
|
1354 //! list. Iterators of this list and all the references are not invalidated.
|
Chris@16
|
1355 void splice(const_iterator pos, slist_impl &x, const_iterator f, const_iterator l)
|
Chris@16
|
1356 { return this->splice_after(this->previous(pos), x, x.previous(f), x.previous(l)); }
|
Chris@16
|
1357
|
Chris@16
|
1358 //! <b>Requires</b>: pos must be a dereferenceable iterator in *this
|
Chris@16
|
1359 //! and f and l belong to x and f and l a valid range on x.
|
Chris@16
|
1360 //! n == std::distance(f, l).
|
Chris@16
|
1361 //!
|
Chris@16
|
1362 //! <b>Effects</b>: Transfers the range [f, l) from list x to this
|
Chris@16
|
1363 //! list, before the element pointed by pos.
|
Chris@16
|
1364 //! No destructors or copy constructors are called.
|
Chris@16
|
1365 //!
|
Chris@16
|
1366 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1367 //!
|
Chris@16
|
1368 //! <b>Complexity</b>: Linear to the sum of elements before pos, f, and l.
|
Chris@16
|
1369 //! Linear to the sum of elements before f and l
|
Chris@16
|
1370 //! if cache_last<> is true and pos == end().
|
Chris@16
|
1371 //!
|
Chris@16
|
1372 //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
|
Chris@16
|
1373 //! list. Iterators of this list and all the references are not invalidated.
|
Chris@16
|
1374 void splice(const_iterator pos, slist_impl &x, const_iterator f, const_iterator l, size_type n)
|
Chris@16
|
1375 { return this->splice_after(this->previous(pos), x, x.previous(f), x.previous(l), n); }
|
Chris@16
|
1376
|
Chris@16
|
1377 //! <b>Effects</b>: This function sorts the list *this according to std::less<value_type>.
|
Chris@16
|
1378 //! The sort is stable, that is, the relative order of equivalent elements is preserved.
|
Chris@16
|
1379 //!
|
Chris@16
|
1380 //! <b>Throws</b>: If value_traits::node_traits::node
|
Chris@16
|
1381 //! constructor throws (this does not happen with predefined Boost.Intrusive hooks)
|
Chris@16
|
1382 //! or the predicate throws. Basic guarantee.
|
Chris@16
|
1383 //!
|
Chris@16
|
1384 //! <b>Complexity</b>: The number of comparisons is approximately N log N, where N
|
Chris@16
|
1385 //! is the list's size.
|
Chris@16
|
1386 //!
|
Chris@16
|
1387 //! <b>Note</b>: Iterators and references are not invalidated
|
Chris@16
|
1388 template<class Predicate>
|
Chris@16
|
1389 void sort(Predicate p)
|
Chris@16
|
1390 {
|
Chris@16
|
1391 if (node_traits::get_next(node_traits::get_next(this->get_root_node()))
|
Chris@16
|
1392 != this->get_root_node()) {
|
Chris@16
|
1393
|
Chris@16
|
1394 slist_impl carry(this->priv_value_traits());
|
Chris@16
|
1395 detail::array_initializer<slist_impl, 64> counter(this->priv_value_traits());
|
Chris@16
|
1396 int fill = 0;
|
Chris@16
|
1397 const_iterator last_inserted;
|
Chris@16
|
1398 while(!this->empty()){
|
Chris@16
|
1399 last_inserted = this->cbegin();
|
Chris@16
|
1400 carry.splice_after(carry.cbefore_begin(), *this, this->cbefore_begin());
|
Chris@16
|
1401 int i = 0;
|
Chris@16
|
1402 while(i < fill && !counter[i].empty()) {
|
Chris@16
|
1403 carry.swap(counter[i]);
|
Chris@16
|
1404 carry.merge(counter[i++], p, &last_inserted);
|
Chris@16
|
1405 }
|
Chris@16
|
1406 BOOST_INTRUSIVE_INVARIANT_ASSERT(counter[i].empty());
|
Chris@16
|
1407 const_iterator last_element(carry.previous(last_inserted, carry.end()));
|
Chris@16
|
1408
|
Chris@16
|
1409 if(constant_time_size){
|
Chris@16
|
1410 counter[i].splice_after( counter[i].cbefore_begin(), carry
|
Chris@16
|
1411 , carry.cbefore_begin(), last_element
|
Chris@16
|
1412 , carry.size());
|
Chris@16
|
1413 }
|
Chris@16
|
1414 else{
|
Chris@16
|
1415 counter[i].splice_after( counter[i].cbefore_begin(), carry
|
Chris@16
|
1416 , carry.cbefore_begin(), last_element);
|
Chris@16
|
1417 }
|
Chris@16
|
1418 if(i == fill)
|
Chris@16
|
1419 ++fill;
|
Chris@16
|
1420 }
|
Chris@16
|
1421
|
Chris@16
|
1422 for (int i = 1; i < fill; ++i)
|
Chris@16
|
1423 counter[i].merge(counter[i-1], p, &last_inserted);
|
Chris@16
|
1424 --fill;
|
Chris@16
|
1425 const_iterator last_element(counter[fill].previous(last_inserted, counter[fill].end()));
|
Chris@16
|
1426 if(constant_time_size){
|
Chris@16
|
1427 this->splice_after( cbefore_begin(), counter[fill], counter[fill].cbefore_begin()
|
Chris@16
|
1428 , last_element, counter[fill].size());
|
Chris@16
|
1429 }
|
Chris@16
|
1430 else{
|
Chris@16
|
1431 this->splice_after( cbefore_begin(), counter[fill], counter[fill].cbefore_begin()
|
Chris@16
|
1432 , last_element);
|
Chris@16
|
1433 }
|
Chris@16
|
1434 }
|
Chris@16
|
1435 }
|
Chris@16
|
1436
|
Chris@16
|
1437 //! <b>Requires</b>: p must be a comparison function that induces a strict weak
|
Chris@16
|
1438 //! ordering and both *this and x must be sorted according to that ordering
|
Chris@16
|
1439 //! The lists x and *this must be distinct.
|
Chris@16
|
1440 //!
|
Chris@16
|
1441 //! <b>Effects</b>: This function removes all of x's elements and inserts them
|
Chris@16
|
1442 //! in order into *this. The merge is stable; that is, if an element from *this is
|
Chris@16
|
1443 //! equivalent to one from x, then the element from *this will precede the one from x.
|
Chris@16
|
1444 //!
|
Chris@16
|
1445 //! <b>Throws</b>: If value_traits::node_traits::node
|
Chris@16
|
1446 //! constructor throws (this does not happen with predefined Boost.Intrusive hooks)
|
Chris@16
|
1447 //! or std::less<value_type> throws. Basic guarantee.
|
Chris@16
|
1448 //!
|
Chris@16
|
1449 //! <b>Complexity</b>: This function is linear time: it performs at most
|
Chris@16
|
1450 //! size() + x.size() - 1 comparisons.
|
Chris@16
|
1451 //!
|
Chris@16
|
1452 //! <b>Note</b>: Iterators and references are not invalidated.
|
Chris@16
|
1453 void sort()
|
Chris@16
|
1454 { this->sort(std::less<value_type>()); }
|
Chris@16
|
1455
|
Chris@16
|
1456 //! <b>Requires</b>: p must be a comparison function that induces a strict weak
|
Chris@16
|
1457 //! ordering and both *this and x must be sorted according to that ordering
|
Chris@16
|
1458 //! The lists x and *this must be distinct.
|
Chris@16
|
1459 //!
|
Chris@16
|
1460 //! <b>Effects</b>: This function removes all of x's elements and inserts them
|
Chris@16
|
1461 //! in order into *this. The merge is stable; that is, if an element from *this is
|
Chris@16
|
1462 //! equivalent to one from x, then the element from *this will precede the one from x.
|
Chris@16
|
1463 //!
|
Chris@16
|
1464 //! <b>Returns</b>: Nothing.
|
Chris@16
|
1465 //!
|
Chris@16
|
1466 //! <b>Throws</b>: If the predicate throws. Basic guarantee.
|
Chris@16
|
1467 //!
|
Chris@16
|
1468 //! <b>Complexity</b>: This function is linear time: it performs at most
|
Chris@16
|
1469 //! size() + x.size() - 1 comparisons.
|
Chris@16
|
1470 //!
|
Chris@16
|
1471 //! <b>Note</b>: Iterators and references are not invalidated.
|
Chris@16
|
1472 //!
|
Chris@16
|
1473 //! <b>Additional note</b>: If optional "l" argument is passed, it is assigned
|
Chris@16
|
1474 //! to an iterator to the last transferred value or end() is x is empty.
|
Chris@16
|
1475 template<class Predicate>
|
Chris@16
|
1476 void merge(slist_impl& x, Predicate p, const_iterator *l = 0)
|
Chris@16
|
1477 {
|
Chris@16
|
1478 const_iterator e(this->cend()), ex(x.cend()), bb(this->cbefore_begin()),
|
Chris@16
|
1479 bb_next;
|
Chris@16
|
1480 if(l) *l = e.unconst();
|
Chris@16
|
1481 while(!x.empty()){
|
Chris@16
|
1482 const_iterator ibx_next(x.cbefore_begin()), ibx(ibx_next++);
|
Chris@16
|
1483 while (++(bb_next = bb) != e && !p(*ibx_next, *bb_next)){
|
Chris@16
|
1484 bb = bb_next;
|
Chris@16
|
1485 }
|
Chris@16
|
1486 if(bb_next == e){
|
Chris@16
|
1487 //Now transfer the rest to the end of the container
|
Chris@16
|
1488 this->splice_after(bb, x, l);
|
Chris@16
|
1489 break;
|
Chris@16
|
1490 }
|
Chris@16
|
1491 else{
|
Chris@16
|
1492 size_type n(0);
|
Chris@16
|
1493 do{
|
Chris@16
|
1494 ibx = ibx_next; ++n;
|
Chris@16
|
1495 } while(++(ibx_next = ibx) != ex && p(*ibx_next, *bb_next));
|
Chris@16
|
1496 this->splice_after(bb, x, x.before_begin(), ibx, n);
|
Chris@16
|
1497 if(l) *l = ibx;
|
Chris@16
|
1498 }
|
Chris@16
|
1499 }
|
Chris@16
|
1500 }
|
Chris@16
|
1501
|
Chris@16
|
1502 //! <b>Effects</b>: This function removes all of x's elements and inserts them
|
Chris@16
|
1503 //! in order into *this according to std::less<value_type>. The merge is stable;
|
Chris@16
|
1504 //! that is, if an element from *this is equivalent to one from x, then the element
|
Chris@16
|
1505 //! from *this will precede the one from x.
|
Chris@16
|
1506 //!
|
Chris@16
|
1507 //! <b>Throws</b>: if std::less<value_type> throws. Basic guarantee.
|
Chris@16
|
1508 //!
|
Chris@16
|
1509 //! <b>Complexity</b>: This function is linear time: it performs at most
|
Chris@16
|
1510 //! size() + x.size() - 1 comparisons.
|
Chris@16
|
1511 //!
|
Chris@16
|
1512 //! <b>Note</b>: Iterators and references are not invalidated
|
Chris@16
|
1513 void merge(slist_impl& x)
|
Chris@16
|
1514 { this->merge(x, std::less<value_type>()); }
|
Chris@16
|
1515
|
Chris@16
|
1516 //! <b>Effects</b>: Reverses the order of elements in the list.
|
Chris@16
|
1517 //!
|
Chris@16
|
1518 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1519 //!
|
Chris@16
|
1520 //! <b>Complexity</b>: This function is linear to the contained elements.
|
Chris@16
|
1521 //!
|
Chris@16
|
1522 //! <b>Note</b>: Iterators and references are not invalidated
|
Chris@16
|
1523 void reverse()
|
Chris@16
|
1524 {
|
Chris@16
|
1525 if(cache_last && !this->empty()){
|
Chris@16
|
1526 this->set_last_node(node_traits::get_next(this->get_root_node()));
|
Chris@16
|
1527 }
|
Chris@16
|
1528 this->priv_reverse(detail::bool_<linear>());
|
Chris@16
|
1529 }
|
Chris@16
|
1530
|
Chris@16
|
1531 //! <b>Effects</b>: Removes all the elements that compare equal to value.
|
Chris@16
|
1532 //! No destructors are called.
|
Chris@16
|
1533 //!
|
Chris@16
|
1534 //! <b>Throws</b>: If std::equal_to<value_type> throws. Basic guarantee.
|
Chris@16
|
1535 //!
|
Chris@16
|
1536 //! <b>Complexity</b>: Linear time. It performs exactly size() comparisons for equality.
|
Chris@16
|
1537 //!
|
Chris@16
|
1538 //! <b>Note</b>: The relative order of elements that are not removed is unchanged,
|
Chris@16
|
1539 //! and iterators to elements that are not removed remain valid. This function is
|
Chris@16
|
1540 //! linear time: it performs exactly size() comparisons for equality.
|
Chris@16
|
1541 void remove(const_reference value)
|
Chris@16
|
1542 { this->remove_if(detail::equal_to_value<const_reference>(value)); }
|
Chris@16
|
1543
|
Chris@16
|
1544 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
|
Chris@16
|
1545 //!
|
Chris@16
|
1546 //! <b>Effects</b>: Removes all the elements that compare equal to value.
|
Chris@16
|
1547 //! Disposer::operator()(pointer) is called for every removed element.
|
Chris@16
|
1548 //!
|
Chris@16
|
1549 //! <b>Throws</b>: If std::equal_to<value_type> throws. Basic guarantee.
|
Chris@16
|
1550 //!
|
Chris@16
|
1551 //! <b>Complexity</b>: Linear time. It performs exactly size() comparisons for equality.
|
Chris@16
|
1552 //!
|
Chris@16
|
1553 //! <b>Note</b>: The relative order of elements that are not removed is unchanged,
|
Chris@16
|
1554 //! and iterators to elements that are not removed remain valid.
|
Chris@16
|
1555 template<class Disposer>
|
Chris@16
|
1556 void remove_and_dispose(const_reference value, Disposer disposer)
|
Chris@16
|
1557 { this->remove_and_dispose_if(detail::equal_to_value<const_reference>(value), disposer); }
|
Chris@16
|
1558
|
Chris@16
|
1559 //! <b>Effects</b>: Removes all the elements for which a specified
|
Chris@16
|
1560 //! predicate is satisfied. No destructors are called.
|
Chris@16
|
1561 //!
|
Chris@16
|
1562 //! <b>Throws</b>: If pred throws. Basic guarantee.
|
Chris@16
|
1563 //!
|
Chris@16
|
1564 //! <b>Complexity</b>: Linear time. It performs exactly size() calls to the predicate.
|
Chris@16
|
1565 //!
|
Chris@16
|
1566 //! <b>Note</b>: The relative order of elements that are not removed is unchanged,
|
Chris@16
|
1567 //! and iterators to elements that are not removed remain valid.
|
Chris@16
|
1568 template<class Pred>
|
Chris@16
|
1569 void remove_if(Pred pred)
|
Chris@16
|
1570 { this->remove_and_dispose_if(pred, detail::null_disposer()); }
|
Chris@16
|
1571
|
Chris@16
|
1572 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
|
Chris@16
|
1573 //!
|
Chris@16
|
1574 //! <b>Effects</b>: Removes all the elements for which a specified
|
Chris@16
|
1575 //! predicate is satisfied.
|
Chris@16
|
1576 //! Disposer::operator()(pointer) is called for every removed element.
|
Chris@16
|
1577 //!
|
Chris@16
|
1578 //! <b>Throws</b>: If pred throws. Basic guarantee.
|
Chris@16
|
1579 //!
|
Chris@16
|
1580 //! <b>Complexity</b>: Linear time. It performs exactly size() comparisons for equality.
|
Chris@16
|
1581 //!
|
Chris@16
|
1582 //! <b>Note</b>: The relative order of elements that are not removed is unchanged,
|
Chris@16
|
1583 //! and iterators to elements that are not removed remain valid.
|
Chris@16
|
1584 template<class Pred, class Disposer>
|
Chris@16
|
1585 void remove_and_dispose_if(Pred pred, Disposer disposer)
|
Chris@16
|
1586 {
|
Chris@16
|
1587 const_iterator bcur(this->before_begin()), cur(this->begin()), e(this->end());
|
Chris@16
|
1588
|
Chris@16
|
1589 while(cur != e){
|
Chris@16
|
1590 if (pred(*cur)){
|
Chris@16
|
1591 cur = this->erase_after_and_dispose(bcur, disposer);
|
Chris@16
|
1592 }
|
Chris@16
|
1593 else{
|
Chris@16
|
1594 bcur = cur;
|
Chris@16
|
1595 ++cur;
|
Chris@16
|
1596 }
|
Chris@16
|
1597 }
|
Chris@16
|
1598 if(cache_last){
|
Chris@16
|
1599 this->set_last_node(bcur.pointed_node());
|
Chris@16
|
1600 }
|
Chris@16
|
1601 }
|
Chris@16
|
1602
|
Chris@16
|
1603 //! <b>Effects</b>: Removes adjacent duplicate elements or adjacent
|
Chris@16
|
1604 //! elements that are equal from the list. No destructors are called.
|
Chris@16
|
1605 //!
|
Chris@16
|
1606 //! <b>Throws</b>: If std::equal_to<value_type> throws. Basic guarantee.
|
Chris@16
|
1607 //!
|
Chris@16
|
1608 //! <b>Complexity</b>: Linear time (size()-1) comparisons calls to pred()).
|
Chris@16
|
1609 //!
|
Chris@16
|
1610 //! <b>Note</b>: The relative order of elements that are not removed is unchanged,
|
Chris@16
|
1611 //! and iterators to elements that are not removed remain valid.
|
Chris@16
|
1612 void unique()
|
Chris@16
|
1613 { this->unique_and_dispose(std::equal_to<value_type>(), detail::null_disposer()); }
|
Chris@16
|
1614
|
Chris@16
|
1615 //! <b>Effects</b>: Removes adjacent duplicate elements or adjacent
|
Chris@16
|
1616 //! elements that satisfy some binary predicate from the list.
|
Chris@16
|
1617 //! No destructors are called.
|
Chris@16
|
1618 //!
|
Chris@16
|
1619 //! <b>Throws</b>: If the predicate throws. Basic guarantee.
|
Chris@16
|
1620 //!
|
Chris@16
|
1621 //! <b>Complexity</b>: Linear time (size()-1) comparisons equality comparisons.
|
Chris@16
|
1622 //!
|
Chris@16
|
1623 //! <b>Note</b>: The relative order of elements that are not removed is unchanged,
|
Chris@16
|
1624 //! and iterators to elements that are not removed remain valid.
|
Chris@16
|
1625 template<class BinaryPredicate>
|
Chris@16
|
1626 void unique(BinaryPredicate pred)
|
Chris@16
|
1627 { this->unique_and_dispose(pred, detail::null_disposer()); }
|
Chris@16
|
1628
|
Chris@16
|
1629 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
|
Chris@16
|
1630 //!
|
Chris@16
|
1631 //! <b>Effects</b>: Removes adjacent duplicate elements or adjacent
|
Chris@16
|
1632 //! elements that satisfy some binary predicate from the list.
|
Chris@16
|
1633 //! Disposer::operator()(pointer) is called for every removed element.
|
Chris@16
|
1634 //!
|
Chris@16
|
1635 //! <b>Throws</b>: If std::equal_to<value_type> throws. Basic guarantee.
|
Chris@16
|
1636 //!
|
Chris@16
|
1637 //! <b>Complexity</b>: Linear time (size()-1) comparisons equality comparisons.
|
Chris@16
|
1638 //!
|
Chris@16
|
1639 //! <b>Note</b>: The relative order of elements that are not removed is unchanged,
|
Chris@16
|
1640 //! and iterators to elements that are not removed remain valid.
|
Chris@16
|
1641 template<class Disposer>
|
Chris@16
|
1642 void unique_and_dispose(Disposer disposer)
|
Chris@16
|
1643 { this->unique(std::equal_to<value_type>(), disposer); }
|
Chris@16
|
1644
|
Chris@16
|
1645 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
|
Chris@16
|
1646 //!
|
Chris@16
|
1647 //! <b>Effects</b>: Removes adjacent duplicate elements or adjacent
|
Chris@16
|
1648 //! elements that satisfy some binary predicate from the list.
|
Chris@16
|
1649 //! Disposer::operator()(pointer) is called for every removed element.
|
Chris@16
|
1650 //!
|
Chris@16
|
1651 //! <b>Throws</b>: If the predicate throws. Basic guarantee.
|
Chris@16
|
1652 //!
|
Chris@16
|
1653 //! <b>Complexity</b>: Linear time (size()-1) comparisons equality comparisons.
|
Chris@16
|
1654 //!
|
Chris@16
|
1655 //! <b>Note</b>: The relative order of elements that are not removed is unchanged,
|
Chris@16
|
1656 //! and iterators to elements that are not removed remain valid.
|
Chris@16
|
1657 template<class BinaryPredicate, class Disposer>
|
Chris@16
|
1658 void unique_and_dispose(BinaryPredicate pred, Disposer disposer)
|
Chris@16
|
1659 {
|
Chris@16
|
1660 const_iterator end_n(this->cend());
|
Chris@16
|
1661 const_iterator bcur(this->cbegin());
|
Chris@16
|
1662 if(bcur != end_n){
|
Chris@16
|
1663 const_iterator cur(bcur);
|
Chris@16
|
1664 ++cur;
|
Chris@16
|
1665 while(cur != end_n) {
|
Chris@16
|
1666 if (pred(*bcur, *cur)){
|
Chris@16
|
1667 cur = this->erase_after_and_dispose(bcur, disposer);
|
Chris@16
|
1668 }
|
Chris@16
|
1669 else{
|
Chris@16
|
1670 bcur = cur;
|
Chris@16
|
1671 ++cur;
|
Chris@16
|
1672 }
|
Chris@16
|
1673 }
|
Chris@16
|
1674 if(cache_last){
|
Chris@16
|
1675 this->set_last_node(bcur.pointed_node());
|
Chris@16
|
1676 }
|
Chris@16
|
1677 }
|
Chris@16
|
1678 }
|
Chris@16
|
1679
|
Chris@16
|
1680 //! <b>Requires</b>: value must be a reference to a value inserted in a list.
|
Chris@16
|
1681 //!
|
Chris@16
|
1682 //! <b>Effects</b>: This function returns a const_iterator pointing to the element
|
Chris@16
|
1683 //!
|
Chris@16
|
1684 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1685 //!
|
Chris@16
|
1686 //! <b>Complexity</b>: Constant time.
|
Chris@16
|
1687 //!
|
Chris@16
|
1688 //! <b>Note</b>: Iterators and references are not invalidated.
|
Chris@16
|
1689 //! This static function is available only if the <i>value traits</i>
|
Chris@16
|
1690 //! is stateless.
|
Chris@16
|
1691 static iterator s_iterator_to(reference value)
|
Chris@16
|
1692 {
|
Chris@16
|
1693 BOOST_STATIC_ASSERT((!stateful_value_traits));
|
Chris@16
|
1694 //BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::inited(value_traits::to_node_ptr(value)));
|
Chris@16
|
1695 return iterator (value_traits::to_node_ptr(value), const_real_value_traits_ptr());
|
Chris@16
|
1696 }
|
Chris@16
|
1697
|
Chris@16
|
1698 //! <b>Requires</b>: value must be a const reference to a value inserted in a list.
|
Chris@16
|
1699 //!
|
Chris@16
|
1700 //! <b>Effects</b>: This function returns an iterator pointing to the element.
|
Chris@16
|
1701 //!
|
Chris@16
|
1702 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1703 //!
|
Chris@16
|
1704 //! <b>Complexity</b>: Constant time.
|
Chris@16
|
1705 //!
|
Chris@16
|
1706 //! <b>Note</b>: Iterators and references are not invalidated.
|
Chris@16
|
1707 //! This static function is available only if the <i>value traits</i>
|
Chris@16
|
1708 //! is stateless.
|
Chris@16
|
1709 static const_iterator s_iterator_to(const_reference value)
|
Chris@16
|
1710 {
|
Chris@16
|
1711 BOOST_STATIC_ASSERT((!stateful_value_traits));
|
Chris@16
|
1712 //BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::inited(value_traits::to_node_ptr(const_cast<reference> (value))));
|
Chris@16
|
1713 return const_iterator (value_traits::to_node_ptr(const_cast<reference> (value)), const_real_value_traits_ptr());
|
Chris@16
|
1714 }
|
Chris@16
|
1715
|
Chris@16
|
1716 //! <b>Requires</b>: value must be a reference to a value inserted in a list.
|
Chris@16
|
1717 //!
|
Chris@16
|
1718 //! <b>Effects</b>: This function returns a const_iterator pointing to the element
|
Chris@16
|
1719 //!
|
Chris@16
|
1720 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1721 //!
|
Chris@16
|
1722 //! <b>Complexity</b>: Constant time.
|
Chris@16
|
1723 //!
|
Chris@16
|
1724 //! <b>Note</b>: Iterators and references are not invalidated.
|
Chris@16
|
1725 iterator iterator_to(reference value)
|
Chris@16
|
1726 {
|
Chris@16
|
1727 //BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::inited(value_traits::to_node_ptr(value)));
|
Chris@16
|
1728 return iterator (value_traits::to_node_ptr(value), this->real_value_traits_ptr());
|
Chris@16
|
1729 }
|
Chris@16
|
1730
|
Chris@16
|
1731 //! <b>Requires</b>: value must be a const reference to a value inserted in a list.
|
Chris@16
|
1732 //!
|
Chris@16
|
1733 //! <b>Effects</b>: This function returns an iterator pointing to the element.
|
Chris@16
|
1734 //!
|
Chris@16
|
1735 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1736 //!
|
Chris@16
|
1737 //! <b>Complexity</b>: Constant time.
|
Chris@16
|
1738 //!
|
Chris@16
|
1739 //! <b>Note</b>: Iterators and references are not invalidated.
|
Chris@16
|
1740 const_iterator iterator_to(const_reference value) const
|
Chris@16
|
1741 {
|
Chris@16
|
1742 //BOOST_INTRUSIVE_INVARIANT_ASSERT (!node_algorithms::inited(value_traits::to_node_ptr(const_cast<reference> (value))));
|
Chris@16
|
1743 return const_iterator (value_traits::to_node_ptr(const_cast<reference> (value)), this->real_value_traits_ptr());
|
Chris@16
|
1744 }
|
Chris@16
|
1745
|
Chris@16
|
1746 //! <b>Returns</b>: The iterator to the element before i in the list.
|
Chris@16
|
1747 //! Returns the end-iterator, if either i is the begin-iterator or the
|
Chris@16
|
1748 //! list is empty.
|
Chris@16
|
1749 //!
|
Chris@16
|
1750 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1751 //!
|
Chris@16
|
1752 //! <b>Complexity</b>: Linear to the number of elements before i.
|
Chris@16
|
1753 //! Constant if cache_last<> is true and i == end().
|
Chris@16
|
1754 iterator previous(iterator i)
|
Chris@16
|
1755 { return this->previous(this->cbefore_begin(), i); }
|
Chris@16
|
1756
|
Chris@16
|
1757 //! <b>Returns</b>: The const_iterator to the element before i in the list.
|
Chris@16
|
1758 //! Returns the end-const_iterator, if either i is the begin-const_iterator or
|
Chris@16
|
1759 //! the list is empty.
|
Chris@16
|
1760 //!
|
Chris@16
|
1761 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1762 //!
|
Chris@16
|
1763 //! <b>Complexity</b>: Linear to the number of elements before i.
|
Chris@16
|
1764 //! Constant if cache_last<> is true and i == end().
|
Chris@16
|
1765 const_iterator previous(const_iterator i) const
|
Chris@16
|
1766 { return this->previous(this->cbefore_begin(), i); }
|
Chris@16
|
1767
|
Chris@16
|
1768 //! <b>Returns</b>: The iterator to the element before i in the list,
|
Chris@16
|
1769 //! starting the search on element after prev_from.
|
Chris@16
|
1770 //! Returns the end-iterator, if either i is the begin-iterator or the
|
Chris@16
|
1771 //! list is empty.
|
Chris@16
|
1772 //!
|
Chris@16
|
1773 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1774 //!
|
Chris@16
|
1775 //! <b>Complexity</b>: Linear to the number of elements before i.
|
Chris@16
|
1776 //! Constant if cache_last<> is true and i == end().
|
Chris@16
|
1777 iterator previous(const_iterator prev_from, iterator i)
|
Chris@16
|
1778 { return this->previous(prev_from, const_iterator(i)).unconst(); }
|
Chris@16
|
1779
|
Chris@16
|
1780 //! <b>Returns</b>: The const_iterator to the element before i in the list,
|
Chris@16
|
1781 //! starting the search on element after prev_from.
|
Chris@16
|
1782 //! Returns the end-const_iterator, if either i is the begin-const_iterator or
|
Chris@16
|
1783 //! the list is empty.
|
Chris@16
|
1784 //!
|
Chris@16
|
1785 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1786 //!
|
Chris@16
|
1787 //! <b>Complexity</b>: Linear to the number of elements before i.
|
Chris@16
|
1788 //! Constant if cache_last<> is true and i == end().
|
Chris@16
|
1789 const_iterator previous(const_iterator prev_from, const_iterator i) const
|
Chris@16
|
1790 {
|
Chris@16
|
1791 if(cache_last && (i.pointed_node() == this->get_end_node())){
|
Chris@16
|
1792 return const_iterator(detail::uncast(this->get_last_node()), this->real_value_traits_ptr());
|
Chris@16
|
1793 }
|
Chris@16
|
1794 return const_iterator
|
Chris@16
|
1795 (node_algorithms::get_previous_node
|
Chris@16
|
1796 (prev_from.pointed_node(), i.pointed_node()), this->real_value_traits_ptr());
|
Chris@16
|
1797 }
|
Chris@16
|
1798
|
Chris@16
|
1799 ///@cond
|
Chris@16
|
1800
|
Chris@16
|
1801 //! <b>Requires</b>: prev_pos must be a dereferenceable iterator in *this or be
|
Chris@16
|
1802 //! before_begin(), and f and before_l belong to another slist.
|
Chris@16
|
1803 //!
|
Chris@16
|
1804 //! <b>Effects</b>: Transfers the range [f, before_l] to this
|
Chris@16
|
1805 //! list, after the element pointed by prev_pos.
|
Chris@16
|
1806 //! No destructors or copy constructors are called.
|
Chris@16
|
1807 //!
|
Chris@16
|
1808 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1809 //!
|
Chris@16
|
1810 //! <b>Complexity</b>: Linear to the number of elements transferred
|
Chris@16
|
1811 //! if constant_time_size is true. Constant-time otherwise.
|
Chris@16
|
1812 //!
|
Chris@16
|
1813 //! <b>Note</b>: Iterators of values obtained from the list that owned f and before_l now
|
Chris@16
|
1814 //! point to elements of this list. Iterators of this list and all the references are not invalidated.
|
Chris@16
|
1815 //!
|
Chris@16
|
1816 //! <b>Warning</b>: Experimental function, don't use it!
|
Chris@16
|
1817 void incorporate_after(const_iterator prev_pos, const node_ptr & f, const node_ptr & before_l)
|
Chris@16
|
1818 {
|
Chris@16
|
1819 if(constant_time_size)
|
Chris@16
|
1820 this->incorporate_after(prev_pos, f, before_l, std::distance(f, before_l)+1);
|
Chris@16
|
1821 else
|
Chris@16
|
1822 this->priv_incorporate_after(prev_pos.pointed_node(), f, before_l);
|
Chris@16
|
1823 }
|
Chris@16
|
1824
|
Chris@16
|
1825 //! <b>Requires</b>: prev_pos must be a dereferenceable iterator in *this or be
|
Chris@16
|
1826 //! before_begin(), and f and before_l belong to another slist.
|
Chris@16
|
1827 //! n == std::distance(f, before_l) + 1.
|
Chris@16
|
1828 //!
|
Chris@16
|
1829 //! <b>Effects</b>: Transfers the range [f, before_l] to this
|
Chris@16
|
1830 //! list, after the element pointed by prev_pos.
|
Chris@16
|
1831 //! No destructors or copy constructors are called.
|
Chris@16
|
1832 //!
|
Chris@16
|
1833 //! <b>Throws</b>: Nothing.
|
Chris@16
|
1834 //!
|
Chris@16
|
1835 //! <b>Complexity</b>: Constant time.
|
Chris@16
|
1836 //!
|
Chris@16
|
1837 //! <b>Note</b>: Iterators of values obtained from the list that owned f and before_l now
|
Chris@16
|
1838 //! point to elements of this list. Iterators of this list and all the references are not invalidated.
|
Chris@16
|
1839 //!
|
Chris@16
|
1840 //! <b>Warning</b>: Experimental function, don't use it!
|
Chris@16
|
1841 void incorporate_after(const_iterator prev_pos, const node_ptr & f, const node_ptr & before_l, size_type n)
|
Chris@16
|
1842 {
|
Chris@16
|
1843 if(n){
|
Chris@16
|
1844 BOOST_INTRUSIVE_INVARIANT_ASSERT(n > 0);
|
Chris@16
|
1845 BOOST_INTRUSIVE_INVARIANT_ASSERT
|
Chris@16
|
1846 (size_type(std::distance
|
Chris@16
|
1847 ( iterator(f, this->real_value_traits_ptr())
|
Chris@16
|
1848 , iterator(before_l, this->real_value_traits_ptr())))
|
Chris@16
|
1849 +1 == n);
|
Chris@16
|
1850 this->priv_incorporate_after(prev_pos.pointed_node(), f, before_l);
|
Chris@16
|
1851 if(constant_time_size){
|
Chris@16
|
1852 this->priv_size_traits().increase(n);
|
Chris@16
|
1853 }
|
Chris@16
|
1854 }
|
Chris@16
|
1855 }
|
Chris@16
|
1856
|
Chris@16
|
1857 ///@endcond
|
Chris@16
|
1858
|
Chris@16
|
1859 private:
|
Chris@16
|
1860 void priv_splice_after(const node_ptr & prev_pos_n, slist_impl &x, const node_ptr & before_f_n, const node_ptr & before_l_n)
|
Chris@16
|
1861 {
|
Chris@16
|
1862 if (cache_last && (before_f_n != before_l_n)){
|
Chris@16
|
1863 if(prev_pos_n == this->get_last_node()){
|
Chris@16
|
1864 this->set_last_node(before_l_n);
|
Chris@16
|
1865 }
|
Chris@16
|
1866 if(&x != this && node_traits::get_next(before_l_n) == x.get_end_node()){
|
Chris@16
|
1867 x.set_last_node(before_f_n);
|
Chris@16
|
1868 }
|
Chris@16
|
1869 }
|
Chris@16
|
1870 node_algorithms::transfer_after(prev_pos_n, before_f_n, before_l_n);
|
Chris@16
|
1871 }
|
Chris@16
|
1872
|
Chris@16
|
1873 void priv_incorporate_after(const node_ptr & prev_pos_n, const node_ptr & first_n, const node_ptr & before_l_n)
|
Chris@16
|
1874 {
|
Chris@16
|
1875 if(cache_last){
|
Chris@16
|
1876 if(prev_pos_n == this->get_last_node()){
|
Chris@16
|
1877 this->set_last_node(before_l_n);
|
Chris@16
|
1878 }
|
Chris@16
|
1879 }
|
Chris@16
|
1880 node_algorithms::incorporate_after(prev_pos_n, first_n, before_l_n);
|
Chris@16
|
1881 }
|
Chris@16
|
1882
|
Chris@16
|
1883 void priv_reverse(detail::bool_<false>)
|
Chris@16
|
1884 { node_algorithms::reverse(this->get_root_node()); }
|
Chris@16
|
1885
|
Chris@16
|
1886 void priv_reverse(detail::bool_<true>)
|
Chris@16
|
1887 {
|
Chris@16
|
1888 node_ptr new_first = node_algorithms::reverse
|
Chris@16
|
1889 (node_traits::get_next(this->get_root_node()));
|
Chris@16
|
1890 node_traits::set_next(this->get_root_node(), new_first);
|
Chris@16
|
1891 }
|
Chris@16
|
1892
|
Chris@16
|
1893 void priv_shift_backwards(size_type n, detail::bool_<false>)
|
Chris@16
|
1894 {
|
Chris@16
|
1895 node_ptr l = node_algorithms::move_forward(this->get_root_node(), (std::size_t)n);
|
Chris@16
|
1896 if(cache_last && l){
|
Chris@16
|
1897 this->set_last_node(l);
|
Chris@16
|
1898 }
|
Chris@16
|
1899 }
|
Chris@16
|
1900
|
Chris@16
|
1901 void priv_shift_backwards(size_type n, detail::bool_<true>)
|
Chris@16
|
1902 {
|
Chris@16
|
1903 std::pair<node_ptr, node_ptr> ret(
|
Chris@16
|
1904 node_algorithms::move_first_n_forward
|
Chris@16
|
1905 (node_traits::get_next(this->get_root_node()), (std::size_t)n));
|
Chris@16
|
1906 if(ret.first){
|
Chris@16
|
1907 node_traits::set_next(this->get_root_node(), ret.first);
|
Chris@16
|
1908 if(cache_last){
|
Chris@16
|
1909 this->set_last_node(ret.second);
|
Chris@16
|
1910 }
|
Chris@16
|
1911 }
|
Chris@16
|
1912 }
|
Chris@16
|
1913
|
Chris@16
|
1914 void priv_shift_forward(size_type n, detail::bool_<false>)
|
Chris@16
|
1915 {
|
Chris@16
|
1916 node_ptr l = node_algorithms::move_backwards(this->get_root_node(), (std::size_t)n);
|
Chris@16
|
1917 if(cache_last && l){
|
Chris@16
|
1918 this->set_last_node(l);
|
Chris@16
|
1919 }
|
Chris@16
|
1920 }
|
Chris@16
|
1921
|
Chris@16
|
1922 void priv_shift_forward(size_type n, detail::bool_<true>)
|
Chris@16
|
1923 {
|
Chris@16
|
1924 std::pair<node_ptr, node_ptr> ret(
|
Chris@16
|
1925 node_algorithms::move_first_n_backwards
|
Chris@16
|
1926 (node_traits::get_next(this->get_root_node()), (std::size_t)n));
|
Chris@16
|
1927 if(ret.first){
|
Chris@16
|
1928 node_traits::set_next(this->get_root_node(), ret.first);
|
Chris@16
|
1929 if(cache_last){
|
Chris@16
|
1930 this->set_last_node(ret.second);
|
Chris@16
|
1931 }
|
Chris@16
|
1932 }
|
Chris@16
|
1933 }
|
Chris@16
|
1934
|
Chris@16
|
1935 static void priv_swap_cache_last(slist_impl *this_impl, slist_impl *other_impl)
|
Chris@16
|
1936 {
|
Chris@16
|
1937 bool other_was_empty = false;
|
Chris@16
|
1938 if(this_impl->empty()){
|
Chris@16
|
1939 //Check if both are empty or
|
Chris@16
|
1940 if(other_impl->empty())
|
Chris@16
|
1941 return;
|
Chris@16
|
1942 //If this is empty swap pointers
|
Chris@16
|
1943 slist_impl *tmp = this_impl;
|
Chris@16
|
1944 this_impl = other_impl;
|
Chris@16
|
1945 other_impl = tmp;
|
Chris@16
|
1946 other_was_empty = true;
|
Chris@16
|
1947 }
|
Chris@16
|
1948 else{
|
Chris@16
|
1949 other_was_empty = other_impl->empty();
|
Chris@16
|
1950 }
|
Chris@16
|
1951
|
Chris@16
|
1952 //Precondition: this is not empty
|
Chris@16
|
1953 node_ptr other_old_last(other_impl->get_last_node());
|
Chris@16
|
1954 node_ptr other_bfirst(other_impl->get_root_node());
|
Chris@16
|
1955 node_ptr this_bfirst(this_impl->get_root_node());
|
Chris@16
|
1956 node_ptr this_old_last(this_impl->get_last_node());
|
Chris@16
|
1957
|
Chris@16
|
1958 //Move all nodes from this to other's beginning
|
Chris@16
|
1959 node_algorithms::transfer_after(other_bfirst, this_bfirst, this_old_last);
|
Chris@16
|
1960 other_impl->set_last_node(this_old_last);
|
Chris@16
|
1961
|
Chris@16
|
1962 if(other_was_empty){
|
Chris@16
|
1963 this_impl->set_last_node(this_bfirst);
|
Chris@16
|
1964 }
|
Chris@16
|
1965 else{
|
Chris@16
|
1966 //Move trailing nodes from other to this
|
Chris@16
|
1967 node_algorithms::transfer_after(this_bfirst, this_old_last, other_old_last);
|
Chris@16
|
1968 this_impl->set_last_node(other_old_last);
|
Chris@16
|
1969 }
|
Chris@16
|
1970 }
|
Chris@16
|
1971
|
Chris@16
|
1972 //circular version
|
Chris@16
|
1973 static void priv_swap_lists(const node_ptr & this_node, const node_ptr & other_node, detail::bool_<false>)
|
Chris@16
|
1974 { node_algorithms::swap_nodes(this_node, other_node); }
|
Chris@16
|
1975
|
Chris@16
|
1976 //linear version
|
Chris@16
|
1977 static void priv_swap_lists(const node_ptr & this_node, const node_ptr & other_node, detail::bool_<true>)
|
Chris@16
|
1978 { node_algorithms::swap_trailing_nodes(this_node, other_node); }
|
Chris@16
|
1979
|
Chris@16
|
1980 static slist_impl &priv_container_from_end_iterator(const const_iterator &end_iterator)
|
Chris@16
|
1981 {
|
Chris@16
|
1982 //Obtaining the container from the end iterator is not possible with linear
|
Chris@16
|
1983 //singly linked lists (because "end" is represented by the null pointer)
|
Chris@16
|
1984 BOOST_STATIC_ASSERT(!linear);
|
Chris@16
|
1985 root_plus_size *r = detail::parent_from_member<root_plus_size, node>
|
Chris@16
|
1986 ( boost::intrusive::detail::to_raw_pointer(end_iterator.pointed_node()), (&root_plus_size::root_));
|
Chris@16
|
1987 data_t *d = detail::parent_from_member<data_t, root_plus_size>
|
Chris@16
|
1988 ( r, &data_t::root_plus_size_);
|
Chris@16
|
1989 slist_impl *s = detail::parent_from_member<slist_impl, data_t>(d, &slist_impl::data_);
|
Chris@16
|
1990 return *s;
|
Chris@16
|
1991 }
|
Chris@16
|
1992 };
|
Chris@16
|
1993
|
Chris@16
|
1994 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
|
Chris@16
|
1995 template<class T, class ...Options>
|
Chris@16
|
1996 #else
|
Chris@16
|
1997 template<class ValueTraits, class SizeType, std::size_t BoolFlags>
|
Chris@16
|
1998 #endif
|
Chris@16
|
1999 inline bool operator<
|
Chris@16
|
2000 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
|
Chris@16
|
2001 (const slist_impl<T, Options...> &x, const slist_impl<T, Options...> &y)
|
Chris@16
|
2002 #else
|
Chris@16
|
2003 ( const slist_impl<ValueTraits, SizeType, BoolFlags> &x
|
Chris@16
|
2004 , const slist_impl<ValueTraits, SizeType, BoolFlags> &y)
|
Chris@16
|
2005 #endif
|
Chris@16
|
2006 { return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
|
Chris@16
|
2007
|
Chris@16
|
2008 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
|
Chris@16
|
2009 template<class T, class ...Options>
|
Chris@16
|
2010 #else
|
Chris@16
|
2011 template<class ValueTraits, class SizeType, std::size_t BoolFlags>
|
Chris@16
|
2012 #endif
|
Chris@16
|
2013 bool operator==
|
Chris@16
|
2014 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
|
Chris@16
|
2015 (const slist_impl<T, Options...> &x, const slist_impl<T, Options...> &y)
|
Chris@16
|
2016 #else
|
Chris@16
|
2017 ( const slist_impl<ValueTraits, SizeType, BoolFlags> &x
|
Chris@16
|
2018 , const slist_impl<ValueTraits, SizeType, BoolFlags> &y)
|
Chris@16
|
2019 #endif
|
Chris@16
|
2020 {
|
Chris@16
|
2021 typedef slist_impl<ValueTraits, SizeType, BoolFlags> slist_type;
|
Chris@16
|
2022 typedef typename slist_type::const_iterator const_iterator;
|
Chris@16
|
2023 const bool C = slist_type::constant_time_size;
|
Chris@16
|
2024 if(C && x.size() != y.size()){
|
Chris@16
|
2025 return false;
|
Chris@16
|
2026 }
|
Chris@16
|
2027 const_iterator end1 = x.end();
|
Chris@16
|
2028
|
Chris@16
|
2029 const_iterator i1 = x.begin();
|
Chris@16
|
2030 const_iterator i2 = y.begin();
|
Chris@16
|
2031 if(C){
|
Chris@16
|
2032 while (i1 != end1 && *i1 == *i2) {
|
Chris@16
|
2033 ++i1;
|
Chris@16
|
2034 ++i2;
|
Chris@16
|
2035 }
|
Chris@16
|
2036 return i1 == end1;
|
Chris@16
|
2037 }
|
Chris@16
|
2038 else{
|
Chris@16
|
2039 const_iterator end2 = y.end();
|
Chris@16
|
2040 while (i1 != end1 && i2 != end2 && *i1 == *i2) {
|
Chris@16
|
2041 ++i1;
|
Chris@16
|
2042 ++i2;
|
Chris@16
|
2043 }
|
Chris@16
|
2044 return i1 == end1 && i2 == end2;
|
Chris@16
|
2045 }
|
Chris@16
|
2046 }
|
Chris@16
|
2047
|
Chris@16
|
2048 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
|
Chris@16
|
2049 template<class T, class ...Options>
|
Chris@16
|
2050 #else
|
Chris@16
|
2051 template<class ValueTraits, class SizeType, std::size_t BoolFlags>
|
Chris@16
|
2052 #endif
|
Chris@16
|
2053 inline bool operator!=
|
Chris@16
|
2054 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
|
Chris@16
|
2055 (const slist_impl<T, Options...> &x, const slist_impl<T, Options...> &y)
|
Chris@16
|
2056 #else
|
Chris@16
|
2057 ( const slist_impl<ValueTraits, SizeType, BoolFlags> &x
|
Chris@16
|
2058 , const slist_impl<ValueTraits, SizeType, BoolFlags> &y)
|
Chris@16
|
2059 #endif
|
Chris@16
|
2060 { return !(x == y); }
|
Chris@16
|
2061
|
Chris@16
|
2062 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
|
Chris@16
|
2063 template<class T, class ...Options>
|
Chris@16
|
2064 #else
|
Chris@16
|
2065 template<class ValueTraits, class SizeType, std::size_t BoolFlags>
|
Chris@16
|
2066 #endif
|
Chris@16
|
2067 inline bool operator>
|
Chris@16
|
2068 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
|
Chris@16
|
2069 (const slist_impl<T, Options...> &x, const slist_impl<T, Options...> &y)
|
Chris@16
|
2070 #else
|
Chris@16
|
2071 ( const slist_impl<ValueTraits, SizeType, BoolFlags> &x
|
Chris@16
|
2072 , const slist_impl<ValueTraits, SizeType, BoolFlags> &y)
|
Chris@16
|
2073 #endif
|
Chris@16
|
2074 { return y < x; }
|
Chris@16
|
2075
|
Chris@16
|
2076 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
|
Chris@16
|
2077 template<class T, class ...Options>
|
Chris@16
|
2078 #else
|
Chris@16
|
2079 template<class ValueTraits, class SizeType, std::size_t BoolFlags>
|
Chris@16
|
2080 #endif
|
Chris@16
|
2081 inline bool operator<=
|
Chris@16
|
2082 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
|
Chris@16
|
2083 (const slist_impl<T, Options...> &x, const slist_impl<T, Options...> &y)
|
Chris@16
|
2084 #else
|
Chris@16
|
2085 ( const slist_impl<ValueTraits, SizeType, BoolFlags> &x
|
Chris@16
|
2086 , const slist_impl<ValueTraits, SizeType, BoolFlags> &y)
|
Chris@16
|
2087 #endif
|
Chris@16
|
2088 { return !(y < x); }
|
Chris@16
|
2089
|
Chris@16
|
2090 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
|
Chris@16
|
2091 template<class T, class ...Options>
|
Chris@16
|
2092 #else
|
Chris@16
|
2093 template<class ValueTraits, class SizeType, std::size_t BoolFlags>
|
Chris@16
|
2094 #endif
|
Chris@16
|
2095 inline bool operator>=
|
Chris@16
|
2096 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
|
Chris@16
|
2097 (const slist_impl<T, Options...> &x, const slist_impl<T, Options...> &y)
|
Chris@16
|
2098 #else
|
Chris@16
|
2099 ( const slist_impl<ValueTraits, SizeType, BoolFlags> &x
|
Chris@16
|
2100 , const slist_impl<ValueTraits, SizeType, BoolFlags> &y)
|
Chris@16
|
2101 #endif
|
Chris@16
|
2102 { return !(x < y); }
|
Chris@16
|
2103
|
Chris@16
|
2104 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
|
Chris@16
|
2105 template<class T, class ...Options>
|
Chris@16
|
2106 #else
|
Chris@16
|
2107 template<class ValueTraits, class SizeType, std::size_t BoolFlags>
|
Chris@16
|
2108 #endif
|
Chris@16
|
2109 inline void swap
|
Chris@16
|
2110 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
|
Chris@16
|
2111 (slist_impl<T, Options...> &x, slist_impl<T, Options...> &y)
|
Chris@16
|
2112 #else
|
Chris@16
|
2113 ( slist_impl<ValueTraits, SizeType, BoolFlags> &x
|
Chris@16
|
2114 , slist_impl<ValueTraits, SizeType, BoolFlags> &y)
|
Chris@16
|
2115 #endif
|
Chris@16
|
2116 { x.swap(y); }
|
Chris@16
|
2117
|
Chris@16
|
2118 //! Helper metafunction to define a \c slist that yields to the same type when the
|
Chris@16
|
2119 //! same options (either explicitly or implicitly) are used.
|
Chris@16
|
2120 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
Chris@16
|
2121 template<class T, class ...Options>
|
Chris@16
|
2122 #else
|
Chris@16
|
2123 template<class T, class O1 = void, class O2 = void, class O3 = void, class O4 = void, class O5 = void>
|
Chris@16
|
2124 #endif
|
Chris@16
|
2125 struct make_slist
|
Chris@16
|
2126 {
|
Chris@16
|
2127 /// @cond
|
Chris@16
|
2128 typedef typename pack_options
|
Chris@16
|
2129 < slist_defaults,
|
Chris@16
|
2130 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
Chris@16
|
2131 O1, O2, O3, O4, O5
|
Chris@16
|
2132 #else
|
Chris@16
|
2133 Options...
|
Chris@16
|
2134 #endif
|
Chris@16
|
2135 >::type packed_options;
|
Chris@16
|
2136 typedef typename detail::get_value_traits
|
Chris@16
|
2137 <T, typename packed_options::proto_value_traits>::type value_traits;
|
Chris@16
|
2138 typedef slist_impl
|
Chris@16
|
2139 < value_traits
|
Chris@16
|
2140 , typename packed_options::size_type
|
Chris@16
|
2141 , (std::size_t(packed_options::linear)*slist_bool_flags::linear_pos)
|
Chris@16
|
2142 |(std::size_t(packed_options::constant_time_size)*slist_bool_flags::constant_time_size_pos)
|
Chris@16
|
2143 |(std::size_t(packed_options::cache_last)*slist_bool_flags::cache_last_pos)
|
Chris@16
|
2144 > implementation_defined;
|
Chris@16
|
2145 /// @endcond
|
Chris@16
|
2146 typedef implementation_defined type;
|
Chris@16
|
2147 };
|
Chris@16
|
2148
|
Chris@16
|
2149
|
Chris@16
|
2150 #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
|
Chris@16
|
2151
|
Chris@16
|
2152 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
Chris@16
|
2153 template<class T, class O1, class O2, class O3, class O4, class O5>
|
Chris@16
|
2154 #else
|
Chris@16
|
2155 template<class T, class ...Options>
|
Chris@16
|
2156 #endif
|
Chris@16
|
2157 class slist
|
Chris@16
|
2158 : public make_slist<T,
|
Chris@16
|
2159 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
Chris@16
|
2160 O1, O2, O3, O4, O5
|
Chris@16
|
2161 #else
|
Chris@16
|
2162 Options...
|
Chris@16
|
2163 #endif
|
Chris@16
|
2164 >::type
|
Chris@16
|
2165 {
|
Chris@16
|
2166 typedef typename make_slist
|
Chris@16
|
2167 <T,
|
Chris@16
|
2168 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
|
Chris@16
|
2169 O1, O2, O3, O4, O5
|
Chris@16
|
2170 #else
|
Chris@16
|
2171 Options...
|
Chris@16
|
2172 #endif
|
Chris@16
|
2173 >::type Base;
|
Chris@16
|
2174 typedef typename Base::real_value_traits real_value_traits;
|
Chris@16
|
2175 //Assert if passed value traits are compatible with the type
|
Chris@16
|
2176 BOOST_STATIC_ASSERT((detail::is_same<typename real_value_traits::value_type, T>::value));
|
Chris@16
|
2177 BOOST_MOVABLE_BUT_NOT_COPYABLE(slist)
|
Chris@16
|
2178
|
Chris@16
|
2179 public:
|
Chris@16
|
2180 typedef typename Base::value_traits value_traits;
|
Chris@16
|
2181 typedef typename Base::iterator iterator;
|
Chris@16
|
2182 typedef typename Base::const_iterator const_iterator;
|
Chris@16
|
2183 typedef typename Base::size_type size_type;
|
Chris@16
|
2184 typedef typename Base::node_ptr node_ptr;
|
Chris@16
|
2185
|
Chris@16
|
2186 explicit slist(const value_traits &v_traits = value_traits())
|
Chris@16
|
2187 : Base(v_traits)
|
Chris@16
|
2188 {}
|
Chris@16
|
2189
|
Chris@16
|
2190 struct incorporate_t{};
|
Chris@16
|
2191
|
Chris@16
|
2192 slist( const node_ptr & f, const node_ptr & before_l
|
Chris@16
|
2193 , size_type n, const value_traits &v_traits = value_traits())
|
Chris@16
|
2194 : Base(f, before_l, n, v_traits)
|
Chris@16
|
2195 {}
|
Chris@16
|
2196
|
Chris@16
|
2197 template<class Iterator>
|
Chris@16
|
2198 slist(Iterator b, Iterator e, const value_traits &v_traits = value_traits())
|
Chris@16
|
2199 : Base(b, e, v_traits)
|
Chris@16
|
2200 {}
|
Chris@16
|
2201
|
Chris@16
|
2202 slist(BOOST_RV_REF(slist) x)
|
Chris@16
|
2203 : Base(::boost::move(static_cast<Base&>(x)))
|
Chris@16
|
2204 {}
|
Chris@16
|
2205
|
Chris@16
|
2206 slist& operator=(BOOST_RV_REF(slist) x)
|
Chris@16
|
2207 { return static_cast<slist &>(this->Base::operator=(::boost::move(static_cast<Base&>(x)))); }
|
Chris@16
|
2208
|
Chris@16
|
2209 static slist &container_from_end_iterator(iterator end_iterator)
|
Chris@16
|
2210 { return static_cast<slist &>(Base::container_from_end_iterator(end_iterator)); }
|
Chris@16
|
2211
|
Chris@16
|
2212 static const slist &container_from_end_iterator(const_iterator end_iterator)
|
Chris@16
|
2213 { return static_cast<const slist &>(Base::container_from_end_iterator(end_iterator)); }
|
Chris@16
|
2214 };
|
Chris@16
|
2215
|
Chris@16
|
2216 #endif
|
Chris@16
|
2217
|
Chris@16
|
2218 } //namespace intrusive
|
Chris@16
|
2219 } //namespace boost
|
Chris@16
|
2220
|
Chris@16
|
2221 #include <boost/intrusive/detail/config_end.hpp>
|
Chris@16
|
2222
|
Chris@16
|
2223 #endif //BOOST_INTRUSIVE_SLIST_HPP
|