comparison DEPENDENCIES/generic/include/boost/intrusive/slist.hpp @ 16:2665513ce2d3

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