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