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