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