annotate DEPENDENCIES/generic/include/boost/intrusive/slist.hpp @ 125:34e428693f5d vext

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