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