annotate DEPENDENCIES/generic/include/boost/intrusive/list.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +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_LIST_HPP
Chris@16 15 #define BOOST_INTRUSIVE_LIST_HPP
Chris@16 16
Chris@16 17 #include <boost/intrusive/detail/config_begin.hpp>
Chris@101 18 #include <boost/intrusive/intrusive_fwd.hpp>
Chris@16 19 #include <boost/intrusive/detail/assert.hpp>
Chris@16 20 #include <boost/intrusive/list_hook.hpp>
Chris@16 21 #include <boost/intrusive/circular_list_algorithms.hpp>
Chris@16 22 #include <boost/intrusive/pointer_traits.hpp>
Chris@16 23 #include <boost/intrusive/detail/mpl.hpp>
Chris@16 24 #include <boost/intrusive/link_mode.hpp>
Chris@101 25 #include <boost/intrusive/detail/get_value_traits.hpp>
Chris@101 26 #include <boost/intrusive/detail/is_stateful_value_traits.hpp>
Chris@101 27 #include <boost/intrusive/detail/default_header_holder.hpp>
Chris@101 28 #include <boost/intrusive/detail/reverse_iterator.hpp>
Chris@101 29 #include <boost/intrusive/detail/uncast.hpp>
Chris@101 30 #include <boost/intrusive/detail/list_iterator.hpp>
Chris@101 31 #include <boost/intrusive/detail/array_initializer.hpp>
Chris@101 32 #include <boost/intrusive/detail/exception_disposer.hpp>
Chris@101 33 #include <boost/intrusive/detail/equal_to_value.hpp>
Chris@101 34 #include <boost/intrusive/detail/key_nodeptr_comp.hpp>
Chris@101 35 #include <boost/intrusive/detail/simple_disposers.hpp>
Chris@101 36 #include <boost/intrusive/detail/size_holder.hpp>
Chris@101 37 #include <boost/intrusive/detail/algorithm.hpp>
Chris@101 38
Chris@101 39 #include <boost/move/utility_core.hpp>
Chris@16 40 #include <boost/static_assert.hpp>
Chris@101 41
Chris@101 42 #include <boost/intrusive/detail/minimal_less_equal_header.hpp>//std::less
Chris@101 43 #include <cstddef> //std::size_t, etc.
Chris@101 44
Chris@101 45 #if defined(BOOST_HAS_PRAGMA_ONCE)
Chris@101 46 # pragma once
Chris@101 47 #endif
Chris@16 48
Chris@16 49 namespace boost {
Chris@16 50 namespace intrusive {
Chris@16 51
Chris@16 52 /// @cond
Chris@16 53
Chris@101 54 struct default_list_hook_applier
Chris@101 55 { template <class T> struct apply{ typedef typename T::default_list_hook type; }; };
Chris@101 56
Chris@101 57 template<>
Chris@101 58 struct is_default_hook_tag<default_list_hook_applier>
Chris@101 59 { static const bool value = true; };
Chris@101 60
Chris@16 61 struct list_defaults
Chris@16 62 {
Chris@101 63 typedef default_list_hook_applier proto_value_traits;
Chris@16 64 static const bool constant_time_size = true;
Chris@16 65 typedef std::size_t size_type;
Chris@101 66 typedef void header_holder_type;
Chris@16 67 };
Chris@16 68
Chris@16 69 /// @endcond
Chris@16 70
Chris@16 71 //! The class template list is an intrusive container that mimics most of the
Chris@16 72 //! interface of std::list as described in the C++ standard.
Chris@16 73 //!
Chris@16 74 //! The template parameter \c T is the type to be managed by the container.
Chris@16 75 //! The user can specify additional options and if no options are provided
Chris@16 76 //! default options are used.
Chris@16 77 //!
Chris@16 78 //! The container supports the following options:
Chris@16 79 //! \c base_hook<>/member_hook<>/value_traits<>,
Chris@16 80 //! \c constant_time_size<> and \c size_type<>.
Chris@16 81 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
Chris@16 82 template<class T, class ...Options>
Chris@16 83 #else
Chris@101 84 template <class ValueTraits, class SizeType, bool ConstantTimeSize, typename HeaderHolder>
Chris@16 85 #endif
Chris@16 86 class list_impl
Chris@16 87 {
Chris@16 88 //Public typedefs
Chris@16 89 public:
Chris@101 90 typedef ValueTraits value_traits;
Chris@101 91 typedef typename value_traits::pointer pointer;
Chris@101 92 typedef typename value_traits::const_pointer const_pointer;
Chris@16 93 typedef typename pointer_traits<pointer>::element_type value_type;
Chris@16 94 typedef typename pointer_traits<pointer>::reference reference;
Chris@16 95 typedef typename pointer_traits<const_pointer>::reference const_reference;
Chris@16 96 typedef typename pointer_traits<pointer>::difference_type difference_type;
Chris@16 97 typedef SizeType size_type;
Chris@101 98 typedef list_iterator<value_traits, false> iterator;
Chris@101 99 typedef list_iterator<value_traits, true> const_iterator;
Chris@101 100 typedef boost::intrusive::reverse_iterator<iterator> reverse_iterator;
Chris@101 101 typedef boost::intrusive::reverse_iterator<const_iterator> const_reverse_iterator;
Chris@101 102 typedef typename value_traits::node_traits node_traits;
Chris@16 103 typedef typename node_traits::node node;
Chris@16 104 typedef typename node_traits::node_ptr node_ptr;
Chris@16 105 typedef typename node_traits::const_node_ptr const_node_ptr;
Chris@16 106 typedef circular_list_algorithms<node_traits> node_algorithms;
Chris@101 107 typedef typename detail::get_header_holder_type
Chris@101 108 < value_traits, HeaderHolder >::type header_holder_type;
Chris@16 109
Chris@16 110 static const bool constant_time_size = ConstantTimeSize;
Chris@101 111 static const bool stateful_value_traits = detail::is_stateful_value_traits<value_traits>::value;
Chris@101 112 static const bool has_container_from_iterator =
Chris@101 113 detail::is_same< header_holder_type, detail::default_header_holder< node_traits > >::value;
Chris@16 114
Chris@16 115 /// @cond
Chris@16 116
Chris@16 117 private:
Chris@16 118 typedef detail::size_holder<constant_time_size, size_type> size_traits;
Chris@16 119
Chris@16 120 //noncopyable
Chris@16 121 BOOST_MOVABLE_BUT_NOT_COPYABLE(list_impl)
Chris@16 122
Chris@101 123 static const bool safemode_or_autounlink = is_safe_autounlink<value_traits::link_mode>::value;
Chris@16 124
Chris@16 125 //Constant-time size is incompatible with auto-unlink hooks!
Chris@16 126 BOOST_STATIC_ASSERT(!(constant_time_size &&
Chris@101 127 ((int)value_traits::link_mode == (int)auto_unlink)
Chris@16 128 ));
Chris@16 129
Chris@16 130 node_ptr get_root_node()
Chris@101 131 { return data_.root_plus_size_.m_header.get_node(); }
Chris@16 132
Chris@16 133 const_node_ptr get_root_node() const
Chris@101 134 { return data_.root_plus_size_.m_header.get_node(); }
Chris@16 135
Chris@16 136 struct root_plus_size : public size_traits
Chris@16 137 {
Chris@101 138 header_holder_type m_header;
Chris@16 139 };
Chris@16 140
Chris@16 141 struct data_t : public value_traits
Chris@16 142 {
Chris@16 143 typedef typename list_impl::value_traits value_traits;
Chris@16 144 explicit data_t(const value_traits &val_traits)
Chris@16 145 : value_traits(val_traits)
Chris@16 146 {}
Chris@16 147
Chris@16 148 root_plus_size root_plus_size_;
Chris@16 149 } data_;
Chris@16 150
Chris@16 151 size_traits &priv_size_traits()
Chris@16 152 { return data_.root_plus_size_; }
Chris@16 153
Chris@16 154 const size_traits &priv_size_traits() const
Chris@16 155 { return data_.root_plus_size_; }
Chris@16 156
Chris@16 157 const value_traits &priv_value_traits() const
Chris@16 158 { return data_; }
Chris@16 159
Chris@16 160 value_traits &priv_value_traits()
Chris@16 161 { return data_; }
Chris@16 162
Chris@101 163 typedef typename boost::intrusive::value_traits_pointers
Chris@101 164 <ValueTraits>::const_value_traits_ptr const_value_traits_ptr;
Chris@16 165
Chris@101 166 const_value_traits_ptr priv_value_traits_ptr() const
Chris@101 167 { return pointer_traits<const_value_traits_ptr>::pointer_to(this->priv_value_traits()); }
Chris@16 168
Chris@16 169 /// @endcond
Chris@16 170
Chris@16 171 public:
Chris@16 172
Chris@16 173 //! <b>Effects</b>: constructs an empty list.
Chris@16 174 //!
Chris@16 175 //! <b>Complexity</b>: Constant
Chris@16 176 //!
Chris@101 177 //! <b>Throws</b>: If value_traits::node_traits::node
Chris@16 178 //! constructor throws (this does not happen with predefined Boost.Intrusive hooks).
Chris@16 179 explicit list_impl(const value_traits &v_traits = value_traits())
Chris@16 180 : data_(v_traits)
Chris@16 181 {
Chris@16 182 this->priv_size_traits().set_size(size_type(0));
Chris@16 183 node_algorithms::init_header(this->get_root_node());
Chris@16 184 }
Chris@16 185
Chris@16 186 //! <b>Requires</b>: Dereferencing iterator must yield an lvalue of type value_type.
Chris@16 187 //!
Chris@16 188 //! <b>Effects</b>: Constructs a list equal to the range [first,last).
Chris@16 189 //!
Chris@101 190 //! <b>Complexity</b>: Linear in distance(b, e). No copy constructors are called.
Chris@16 191 //!
Chris@101 192 //! <b>Throws</b>: If value_traits::node_traits::node
Chris@16 193 //! constructor throws (this does not happen with predefined Boost.Intrusive hooks).
Chris@16 194 template<class Iterator>
Chris@16 195 list_impl(Iterator b, Iterator e, const value_traits &v_traits = value_traits())
Chris@16 196 : data_(v_traits)
Chris@16 197 {
Chris@101 198 //nothrow, no need to rollback to release elements on exception
Chris@16 199 this->priv_size_traits().set_size(size_type(0));
Chris@16 200 node_algorithms::init_header(this->get_root_node());
Chris@101 201 //nothrow, no need to rollback to release elements on exception
Chris@16 202 this->insert(this->cend(), b, e);
Chris@16 203 }
Chris@16 204
Chris@16 205 //! <b>Effects</b>: to-do
Chris@16 206 //!
Chris@16 207 list_impl(BOOST_RV_REF(list_impl) x)
Chris@16 208 : data_(::boost::move(x.priv_value_traits()))
Chris@16 209 {
Chris@16 210 this->priv_size_traits().set_size(size_type(0));
Chris@16 211 node_algorithms::init_header(this->get_root_node());
Chris@101 212 //nothrow, no need to rollback to release elements on exception
Chris@16 213 this->swap(x);
Chris@16 214 }
Chris@16 215
Chris@16 216 //! <b>Effects</b>: to-do
Chris@16 217 //!
Chris@16 218 list_impl& operator=(BOOST_RV_REF(list_impl) x)
Chris@16 219 { this->swap(x); return *this; }
Chris@16 220
Chris@16 221 //! <b>Effects</b>: If it's not a safe-mode or an auto-unlink value_type
Chris@16 222 //! the destructor does nothing
Chris@16 223 //! (ie. no code is generated). Otherwise it detaches all elements from this.
Chris@16 224 //! In this case the objects in the list are not deleted (i.e. no destructors
Chris@16 225 //! are called), but the hooks according to the ValueTraits template parameter
Chris@16 226 //! are set to their default value.
Chris@16 227 //!
Chris@16 228 //! <b>Complexity</b>: Linear to the number of elements in the list, if
Chris@16 229 //! it's a safe-mode or auto-unlink value . Otherwise constant.
Chris@16 230 ~list_impl()
Chris@101 231 {
Chris@101 232 if(is_safe_autounlink<ValueTraits::link_mode>::value){
Chris@101 233 this->clear();
Chris@101 234 node_algorithms::init(this->get_root_node());
Chris@101 235 }
Chris@101 236 }
Chris@16 237
Chris@16 238 //! <b>Requires</b>: value must be an lvalue.
Chris@16 239 //!
Chris@16 240 //! <b>Effects</b>: Inserts the value in the back of the list.
Chris@16 241 //! No copy constructors are called.
Chris@16 242 //!
Chris@16 243 //! <b>Throws</b>: Nothing.
Chris@16 244 //!
Chris@16 245 //! <b>Complexity</b>: Constant.
Chris@16 246 //!
Chris@16 247 //! <b>Note</b>: Does not affect the validity of iterators and references.
Chris@16 248 void push_back(reference value)
Chris@16 249 {
Chris@101 250 node_ptr to_insert = priv_value_traits().to_node_ptr(value);
Chris@16 251 if(safemode_or_autounlink)
Chris@16 252 BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(to_insert));
Chris@16 253 node_algorithms::link_before(this->get_root_node(), to_insert);
Chris@16 254 this->priv_size_traits().increment();
Chris@16 255 }
Chris@16 256
Chris@16 257 //! <b>Requires</b>: value must be an lvalue.
Chris@16 258 //!
Chris@16 259 //! <b>Effects</b>: Inserts the value in the front of the list.
Chris@16 260 //! No copy constructors are called.
Chris@16 261 //!
Chris@16 262 //! <b>Throws</b>: Nothing.
Chris@16 263 //!
Chris@16 264 //! <b>Complexity</b>: Constant.
Chris@16 265 //!
Chris@16 266 //! <b>Note</b>: Does not affect the validity of iterators and references.
Chris@16 267 void push_front(reference value)
Chris@16 268 {
Chris@101 269 node_ptr to_insert = priv_value_traits().to_node_ptr(value);
Chris@16 270 if(safemode_or_autounlink)
Chris@16 271 BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT(node_algorithms::inited(to_insert));
Chris@16 272 node_algorithms::link_before(node_traits::get_next(this->get_root_node()), to_insert);
Chris@16 273 this->priv_size_traits().increment();
Chris@16 274 }
Chris@16 275
Chris@16 276 //! <b>Effects</b>: Erases the last element of the list.
Chris@16 277 //! No destructors are called.
Chris@16 278 //!
Chris@16 279 //! <b>Throws</b>: Nothing.
Chris@16 280 //!
Chris@16 281 //! <b>Complexity</b>: Constant.
Chris@16 282 //!
Chris@16 283 //! <b>Note</b>: Invalidates the iterators (but not the references) to the erased element.
Chris@16 284 void pop_back()
Chris@16 285 { return this->pop_back_and_dispose(detail::null_disposer()); }
Chris@16 286
Chris@16 287 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
Chris@16 288 //!
Chris@16 289 //! <b>Effects</b>: Erases the last element of the list.
Chris@16 290 //! No destructors are called.
Chris@16 291 //! Disposer::operator()(pointer) is called for the removed element.
Chris@16 292 //!
Chris@16 293 //! <b>Throws</b>: Nothing.
Chris@16 294 //!
Chris@16 295 //! <b>Complexity</b>: Constant.
Chris@16 296 //!
Chris@16 297 //! <b>Note</b>: Invalidates the iterators to the erased element.
Chris@16 298 template<class Disposer>
Chris@16 299 void pop_back_and_dispose(Disposer disposer)
Chris@16 300 {
Chris@16 301 node_ptr to_erase = node_traits::get_previous(this->get_root_node());
Chris@16 302 node_algorithms::unlink(to_erase);
Chris@16 303 this->priv_size_traits().decrement();
Chris@16 304 if(safemode_or_autounlink)
Chris@16 305 node_algorithms::init(to_erase);
Chris@101 306 disposer(priv_value_traits().to_value_ptr(to_erase));
Chris@16 307 }
Chris@16 308
Chris@16 309 //! <b>Effects</b>: Erases the first element of the list.
Chris@16 310 //! No destructors are called.
Chris@16 311 //!
Chris@16 312 //! <b>Throws</b>: Nothing.
Chris@16 313 //!
Chris@16 314 //! <b>Complexity</b>: Constant.
Chris@16 315 //!
Chris@16 316 //! <b>Note</b>: Invalidates the iterators (but not the references) to the erased element.
Chris@16 317 void pop_front()
Chris@16 318 { return this->pop_front_and_dispose(detail::null_disposer()); }
Chris@16 319
Chris@16 320 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
Chris@16 321 //!
Chris@16 322 //! <b>Effects</b>: Erases the first element of the list.
Chris@16 323 //! No destructors are called.
Chris@16 324 //! Disposer::operator()(pointer) is called for the removed element.
Chris@16 325 //!
Chris@16 326 //! <b>Throws</b>: Nothing.
Chris@16 327 //!
Chris@16 328 //! <b>Complexity</b>: Constant.
Chris@16 329 //!
Chris@16 330 //! <b>Note</b>: Invalidates the iterators to the erased element.
Chris@16 331 template<class Disposer>
Chris@16 332 void pop_front_and_dispose(Disposer disposer)
Chris@16 333 {
Chris@16 334 node_ptr to_erase = node_traits::get_next(this->get_root_node());
Chris@16 335 node_algorithms::unlink(to_erase);
Chris@16 336 this->priv_size_traits().decrement();
Chris@16 337 if(safemode_or_autounlink)
Chris@16 338 node_algorithms::init(to_erase);
Chris@101 339 disposer(priv_value_traits().to_value_ptr(to_erase));
Chris@16 340 }
Chris@16 341
Chris@16 342 //! <b>Effects</b>: Returns a reference to the first element of the list.
Chris@16 343 //!
Chris@16 344 //! <b>Throws</b>: Nothing.
Chris@16 345 //!
Chris@16 346 //! <b>Complexity</b>: Constant.
Chris@16 347 reference front()
Chris@101 348 { return *priv_value_traits().to_value_ptr(node_traits::get_next(this->get_root_node())); }
Chris@16 349
Chris@16 350 //! <b>Effects</b>: Returns a const_reference to the first element of the list.
Chris@16 351 //!
Chris@16 352 //! <b>Throws</b>: Nothing.
Chris@16 353 //!
Chris@16 354 //! <b>Complexity</b>: Constant.
Chris@16 355 const_reference front() const
Chris@101 356 { return *priv_value_traits().to_value_ptr(node_traits::get_next(this->get_root_node())); }
Chris@16 357
Chris@16 358 //! <b>Effects</b>: Returns a reference to the last element of the list.
Chris@16 359 //!
Chris@16 360 //! <b>Throws</b>: Nothing.
Chris@16 361 //!
Chris@16 362 //! <b>Complexity</b>: Constant.
Chris@16 363 reference back()
Chris@101 364 { return *priv_value_traits().to_value_ptr(node_traits::get_previous(this->get_root_node())); }
Chris@16 365
Chris@16 366 //! <b>Effects</b>: Returns a const_reference to the last element of the list.
Chris@16 367 //!
Chris@16 368 //! <b>Throws</b>: Nothing.
Chris@16 369 //!
Chris@16 370 //! <b>Complexity</b>: Constant.
Chris@16 371 const_reference back() const
Chris@101 372 { return *priv_value_traits().to_value_ptr(detail::uncast(node_traits::get_previous(this->get_root_node()))); }
Chris@16 373
Chris@16 374 //! <b>Effects</b>: Returns an iterator to the first element contained in the list.
Chris@16 375 //!
Chris@16 376 //! <b>Throws</b>: Nothing.
Chris@16 377 //!
Chris@16 378 //! <b>Complexity</b>: Constant.
Chris@16 379 iterator begin()
Chris@101 380 { return iterator(node_traits::get_next(this->get_root_node()), this->priv_value_traits_ptr()); }
Chris@16 381
Chris@16 382 //! <b>Effects</b>: Returns a const_iterator to the first element contained in the list.
Chris@16 383 //!
Chris@16 384 //! <b>Throws</b>: Nothing.
Chris@16 385 //!
Chris@16 386 //! <b>Complexity</b>: Constant.
Chris@16 387 const_iterator begin() const
Chris@16 388 { return this->cbegin(); }
Chris@16 389
Chris@16 390 //! <b>Effects</b>: Returns a const_iterator to the first element contained in the list.
Chris@16 391 //!
Chris@16 392 //! <b>Throws</b>: Nothing.
Chris@16 393 //!
Chris@16 394 //! <b>Complexity</b>: Constant.
Chris@16 395 const_iterator cbegin() const
Chris@101 396 { return const_iterator(node_traits::get_next(this->get_root_node()), this->priv_value_traits_ptr()); }
Chris@16 397
Chris@16 398 //! <b>Effects</b>: Returns an iterator to the end of the list.
Chris@16 399 //!
Chris@16 400 //! <b>Throws</b>: Nothing.
Chris@16 401 //!
Chris@16 402 //! <b>Complexity</b>: Constant.
Chris@16 403 iterator end()
Chris@101 404 { return iterator(this->get_root_node(), this->priv_value_traits_ptr()); }
Chris@16 405
Chris@16 406 //! <b>Effects</b>: Returns a const_iterator to the end of the list.
Chris@16 407 //!
Chris@16 408 //! <b>Throws</b>: Nothing.
Chris@16 409 //!
Chris@16 410 //! <b>Complexity</b>: Constant.
Chris@16 411 const_iterator end() const
Chris@16 412 { return this->cend(); }
Chris@16 413
Chris@16 414 //! <b>Effects</b>: Returns a constant iterator to the end of the list.
Chris@16 415 //!
Chris@16 416 //! <b>Throws</b>: Nothing.
Chris@16 417 //!
Chris@16 418 //! <b>Complexity</b>: Constant.
Chris@16 419 const_iterator cend() const
Chris@101 420 { return const_iterator(detail::uncast(this->get_root_node()), this->priv_value_traits_ptr()); }
Chris@16 421
Chris@16 422 //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
Chris@16 423 //! of the reversed list.
Chris@16 424 //!
Chris@16 425 //! <b>Throws</b>: Nothing.
Chris@16 426 //!
Chris@16 427 //! <b>Complexity</b>: Constant.
Chris@16 428 reverse_iterator rbegin()
Chris@16 429 { return reverse_iterator(this->end()); }
Chris@16 430
Chris@16 431 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
Chris@16 432 //! of the reversed list.
Chris@16 433 //!
Chris@16 434 //! <b>Throws</b>: Nothing.
Chris@16 435 //!
Chris@16 436 //! <b>Complexity</b>: Constant.
Chris@16 437 const_reverse_iterator rbegin() const
Chris@16 438 { return this->crbegin(); }
Chris@16 439
Chris@16 440 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
Chris@16 441 //! of the reversed list.
Chris@16 442 //!
Chris@16 443 //! <b>Throws</b>: Nothing.
Chris@16 444 //!
Chris@16 445 //! <b>Complexity</b>: Constant.
Chris@16 446 const_reverse_iterator crbegin() const
Chris@16 447 { return const_reverse_iterator(end()); }
Chris@16 448
Chris@16 449 //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
Chris@16 450 //! of the reversed list.
Chris@16 451 //!
Chris@16 452 //! <b>Throws</b>: Nothing.
Chris@16 453 //!
Chris@16 454 //! <b>Complexity</b>: Constant.
Chris@16 455 reverse_iterator rend()
Chris@16 456 { return reverse_iterator(begin()); }
Chris@16 457
Chris@16 458 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
Chris@16 459 //! of the reversed list.
Chris@16 460 //!
Chris@16 461 //! <b>Throws</b>: Nothing.
Chris@16 462 //!
Chris@16 463 //! <b>Complexity</b>: Constant.
Chris@16 464 const_reverse_iterator rend() const
Chris@16 465 { return this->crend(); }
Chris@16 466
Chris@16 467 //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
Chris@16 468 //! of the reversed list.
Chris@16 469 //!
Chris@16 470 //! <b>Throws</b>: Nothing.
Chris@16 471 //!
Chris@16 472 //! <b>Complexity</b>: Constant.
Chris@16 473 const_reverse_iterator crend() const
Chris@16 474 { return const_reverse_iterator(this->begin()); }
Chris@16 475
Chris@16 476 //! <b>Precondition</b>: end_iterator must be a valid end iterator
Chris@16 477 //! of list.
Chris@16 478 //!
Chris@16 479 //! <b>Effects</b>: Returns a const reference to the list associated to the end iterator
Chris@16 480 //!
Chris@16 481 //! <b>Throws</b>: Nothing.
Chris@16 482 //!
Chris@16 483 //! <b>Complexity</b>: Constant.
Chris@16 484 static list_impl &container_from_end_iterator(iterator end_iterator)
Chris@16 485 { return list_impl::priv_container_from_end_iterator(end_iterator); }
Chris@16 486
Chris@16 487 //! <b>Precondition</b>: end_iterator must be a valid end const_iterator
Chris@16 488 //! of list.
Chris@16 489 //!
Chris@16 490 //! <b>Effects</b>: Returns a const reference to the list associated to the end iterator
Chris@16 491 //!
Chris@16 492 //! <b>Throws</b>: Nothing.
Chris@16 493 //!
Chris@16 494 //! <b>Complexity</b>: Constant.
Chris@16 495 static const list_impl &container_from_end_iterator(const_iterator end_iterator)
Chris@16 496 { return list_impl::priv_container_from_end_iterator(end_iterator); }
Chris@16 497
Chris@16 498 //! <b>Effects</b>: Returns the number of the elements contained in the list.
Chris@16 499 //!
Chris@16 500 //! <b>Throws</b>: Nothing.
Chris@16 501 //!
Chris@16 502 //! <b>Complexity</b>: Linear to the number of elements contained in the list.
Chris@16 503 //! if constant-time size option is disabled. Constant time otherwise.
Chris@16 504 //!
Chris@16 505 //! <b>Note</b>: Does not affect the validity of iterators and references.
Chris@16 506 size_type size() const
Chris@16 507 {
Chris@16 508 if(constant_time_size)
Chris@16 509 return this->priv_size_traits().get_size();
Chris@16 510 else
Chris@16 511 return node_algorithms::count(this->get_root_node()) - 1;
Chris@16 512 }
Chris@16 513
Chris@16 514 //! <b>Effects</b>: Returns true if the list contains no elements.
Chris@16 515 //!
Chris@16 516 //! <b>Throws</b>: Nothing.
Chris@16 517 //!
Chris@16 518 //! <b>Complexity</b>: Constant.
Chris@16 519 //!
Chris@16 520 //! <b>Note</b>: Does not affect the validity of iterators and references.
Chris@16 521 bool empty() const
Chris@16 522 { return node_algorithms::unique(this->get_root_node()); }
Chris@16 523
Chris@16 524 //! <b>Effects</b>: Swaps the elements of x and *this.
Chris@16 525 //!
Chris@16 526 //! <b>Throws</b>: Nothing.
Chris@16 527 //!
Chris@16 528 //! <b>Complexity</b>: Constant.
Chris@16 529 //!
Chris@16 530 //! <b>Note</b>: Does not affect the validity of iterators and references.
Chris@16 531 void swap(list_impl& other)
Chris@16 532 {
Chris@16 533 node_algorithms::swap_nodes(this->get_root_node(), other.get_root_node());
Chris@16 534 if(constant_time_size){
Chris@16 535 size_type backup = this->priv_size_traits().get_size();
Chris@16 536 this->priv_size_traits().set_size(other.priv_size_traits().get_size());
Chris@16 537 other.priv_size_traits().set_size(backup);
Chris@16 538 }
Chris@16 539 }
Chris@16 540
Chris@16 541 //! <b>Effects</b>: Moves backwards all the elements, so that the first
Chris@16 542 //! element becomes the second, the second becomes the third...
Chris@16 543 //! the last element becomes the first one.
Chris@16 544 //!
Chris@16 545 //! <b>Throws</b>: Nothing.
Chris@16 546 //!
Chris@16 547 //! <b>Complexity</b>: Linear to the number of shifts.
Chris@16 548 //!
Chris@16 549 //! <b>Note</b>: Does not affect the validity of iterators and references.
Chris@16 550 void shift_backwards(size_type n = 1)
Chris@16 551 { node_algorithms::move_forward(this->get_root_node(), n); }
Chris@16 552
Chris@16 553 //! <b>Effects</b>: Moves forward all the elements, so that the second
Chris@16 554 //! element becomes the first, the third becomes the second...
Chris@16 555 //! the first element becomes the last one.
Chris@16 556 //!
Chris@16 557 //! <b>Throws</b>: Nothing.
Chris@16 558 //!
Chris@16 559 //! <b>Complexity</b>: Linear to the number of shifts.
Chris@16 560 //!
Chris@16 561 //! <b>Note</b>: Does not affect the validity of iterators and references.
Chris@16 562 void shift_forward(size_type n = 1)
Chris@16 563 { node_algorithms::move_backwards(this->get_root_node(), n); }
Chris@16 564
Chris@16 565 //! <b>Effects</b>: Erases the element pointed by i of the list.
Chris@16 566 //! No destructors are called.
Chris@16 567 //!
Chris@16 568 //! <b>Returns</b>: the first element remaining beyond the removed element,
Chris@16 569 //! or end() if no such element exists.
Chris@16 570 //!
Chris@16 571 //! <b>Throws</b>: Nothing.
Chris@16 572 //!
Chris@16 573 //! <b>Complexity</b>: Constant.
Chris@16 574 //!
Chris@16 575 //! <b>Note</b>: Invalidates the iterators (but not the references) to the
Chris@16 576 //! erased element.
Chris@16 577 iterator erase(const_iterator i)
Chris@16 578 { return this->erase_and_dispose(i, detail::null_disposer()); }
Chris@16 579
Chris@16 580 //! <b>Requires</b>: b and e must be valid iterators to elements in *this.
Chris@16 581 //!
Chris@16 582 //! <b>Effects</b>: Erases the element range pointed by b and e
Chris@16 583 //! No destructors are called.
Chris@16 584 //!
Chris@16 585 //! <b>Returns</b>: the first element remaining beyond the removed elements,
Chris@16 586 //! or end() if no such element exists.
Chris@16 587 //!
Chris@16 588 //! <b>Throws</b>: Nothing.
Chris@16 589 //!
Chris@16 590 //! <b>Complexity</b>: Linear to the number of erased elements if it's a safe-mode
Chris@16 591 //! or auto-unlink value, or constant-time size is enabled. Constant-time otherwise.
Chris@16 592 //!
Chris@16 593 //! <b>Note</b>: Invalidates the iterators (but not the references) to the
Chris@16 594 //! erased elements.
Chris@16 595 iterator erase(const_iterator b, const_iterator e)
Chris@16 596 {
Chris@16 597 if(safemode_or_autounlink || constant_time_size){
Chris@16 598 return this->erase_and_dispose(b, e, detail::null_disposer());
Chris@16 599 }
Chris@16 600 else{
Chris@16 601 node_algorithms::unlink(b.pointed_node(), e.pointed_node());
Chris@16 602 return e.unconst();
Chris@16 603 }
Chris@16 604 }
Chris@16 605
Chris@16 606 //! <b>Requires</b>: b and e must be valid iterators to elements in *this.
Chris@101 607 //! n must be distance(b, e).
Chris@16 608 //!
Chris@16 609 //! <b>Effects</b>: Erases the element range pointed by b and e
Chris@16 610 //! No destructors are called.
Chris@16 611 //!
Chris@16 612 //! <b>Returns</b>: the first element remaining beyond the removed elements,
Chris@16 613 //! or end() if no such element exists.
Chris@16 614 //!
Chris@16 615 //! <b>Throws</b>: Nothing.
Chris@16 616 //!
Chris@16 617 //! <b>Complexity</b>: Linear to the number of erased elements if it's a safe-mode
Chris@16 618 //! or auto-unlink value is enabled. Constant-time otherwise.
Chris@16 619 //!
Chris@16 620 //! <b>Note</b>: Invalidates the iterators (but not the references) to the
Chris@16 621 //! erased elements.
Chris@101 622 iterator erase(const_iterator b, const_iterator e, size_type n)
Chris@16 623 {
Chris@101 624 BOOST_INTRUSIVE_INVARIANT_ASSERT(node_algorithms::distance(b.pointed_node(), e.pointed_node()) == n);
Chris@16 625 if(safemode_or_autounlink || constant_time_size){
Chris@16 626 return this->erase_and_dispose(b, e, detail::null_disposer());
Chris@16 627 }
Chris@16 628 else{
Chris@16 629 if(constant_time_size){
Chris@16 630 this->priv_size_traits().decrease(n);
Chris@16 631 }
Chris@16 632 node_algorithms::unlink(b.pointed_node(), e.pointed_node());
Chris@16 633 return e.unconst();
Chris@16 634 }
Chris@16 635 }
Chris@16 636
Chris@16 637 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
Chris@16 638 //!
Chris@16 639 //! <b>Effects</b>: Erases the element pointed by i of the list.
Chris@16 640 //! No destructors are called.
Chris@16 641 //! Disposer::operator()(pointer) is called for the removed element.
Chris@16 642 //!
Chris@16 643 //! <b>Returns</b>: the first element remaining beyond the removed element,
Chris@16 644 //! or end() if no such element exists.
Chris@16 645 //!
Chris@16 646 //! <b>Throws</b>: Nothing.
Chris@16 647 //!
Chris@16 648 //! <b>Complexity</b>: Constant.
Chris@16 649 //!
Chris@16 650 //! <b>Note</b>: Invalidates the iterators to the erased element.
Chris@16 651 template <class Disposer>
Chris@16 652 iterator erase_and_dispose(const_iterator i, Disposer disposer)
Chris@16 653 {
Chris@16 654 node_ptr to_erase(i.pointed_node());
Chris@16 655 ++i;
Chris@16 656 node_algorithms::unlink(to_erase);
Chris@16 657 this->priv_size_traits().decrement();
Chris@16 658 if(safemode_or_autounlink)
Chris@16 659 node_algorithms::init(to_erase);
Chris@101 660 disposer(this->priv_value_traits().to_value_ptr(to_erase));
Chris@16 661 return i.unconst();
Chris@16 662 }
Chris@16 663
Chris@16 664 #if !defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
Chris@16 665 template<class Disposer>
Chris@16 666 iterator erase_and_dispose(iterator i, Disposer disposer)
Chris@16 667 { return this->erase_and_dispose(const_iterator(i), disposer); }
Chris@16 668 #endif
Chris@16 669
Chris@16 670 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
Chris@16 671 //!
Chris@16 672 //! <b>Effects</b>: Erases the element range pointed by b and e
Chris@16 673 //! No destructors are called.
Chris@16 674 //! Disposer::operator()(pointer) is called for the removed elements.
Chris@16 675 //!
Chris@16 676 //! <b>Returns</b>: the first element remaining beyond the removed elements,
Chris@16 677 //! or end() if no such element exists.
Chris@16 678 //!
Chris@16 679 //! <b>Throws</b>: Nothing.
Chris@16 680 //!
Chris@16 681 //! <b>Complexity</b>: Linear to the number of elements erased.
Chris@16 682 //!
Chris@16 683 //! <b>Note</b>: Invalidates the iterators to the erased elements.
Chris@16 684 template <class Disposer>
Chris@16 685 iterator erase_and_dispose(const_iterator b, const_iterator e, Disposer disposer)
Chris@16 686 {
Chris@16 687 node_ptr bp(b.pointed_node()), ep(e.pointed_node());
Chris@16 688 node_algorithms::unlink(bp, ep);
Chris@16 689 while(bp != ep){
Chris@16 690 node_ptr to_erase(bp);
Chris@16 691 bp = node_traits::get_next(bp);
Chris@16 692 if(safemode_or_autounlink)
Chris@16 693 node_algorithms::init(to_erase);
Chris@101 694 disposer(priv_value_traits().to_value_ptr(to_erase));
Chris@16 695 this->priv_size_traits().decrement();
Chris@16 696 }
Chris@16 697 return e.unconst();
Chris@16 698 }
Chris@16 699
Chris@16 700 //! <b>Effects</b>: Erases all the elements of the container.
Chris@16 701 //! No destructors are called.
Chris@16 702 //!
Chris@16 703 //! <b>Throws</b>: Nothing.
Chris@16 704 //!
Chris@16 705 //! <b>Complexity</b>: Linear to the number of elements of the list.
Chris@16 706 //! if it's a safe-mode or auto-unlink value_type. Constant time otherwise.
Chris@16 707 //!
Chris@16 708 //! <b>Note</b>: Invalidates the iterators (but not the references) to the erased elements.
Chris@16 709 void clear()
Chris@16 710 {
Chris@16 711 if(safemode_or_autounlink){
Chris@16 712 this->clear_and_dispose(detail::null_disposer());
Chris@16 713 }
Chris@16 714 else{
Chris@16 715 node_algorithms::init_header(this->get_root_node());
Chris@16 716 this->priv_size_traits().set_size(size_type(0));
Chris@16 717 }
Chris@16 718 }
Chris@16 719
Chris@16 720 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
Chris@16 721 //!
Chris@16 722 //! <b>Effects</b>: Erases all the elements of the container.
Chris@16 723 //! No destructors are called.
Chris@16 724 //! Disposer::operator()(pointer) is called for the removed elements.
Chris@16 725 //!
Chris@16 726 //! <b>Throws</b>: Nothing.
Chris@16 727 //!
Chris@16 728 //! <b>Complexity</b>: Linear to the number of elements of the list.
Chris@16 729 //!
Chris@16 730 //! <b>Note</b>: Invalidates the iterators to the erased elements.
Chris@16 731 template <class Disposer>
Chris@16 732 void clear_and_dispose(Disposer disposer)
Chris@16 733 {
Chris@16 734 const_iterator it(this->begin()), itend(this->end());
Chris@16 735 while(it != itend){
Chris@16 736 node_ptr to_erase(it.pointed_node());
Chris@16 737 ++it;
Chris@16 738 if(safemode_or_autounlink)
Chris@16 739 node_algorithms::init(to_erase);
Chris@101 740 disposer(priv_value_traits().to_value_ptr(to_erase));
Chris@16 741 }
Chris@16 742 node_algorithms::init_header(this->get_root_node());
Chris@16 743 this->priv_size_traits().set_size(0);
Chris@16 744 }
Chris@16 745
Chris@16 746 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
Chris@16 747 //! Cloner should yield to nodes equivalent to the original nodes.
Chris@16 748 //!
Chris@16 749 //! <b>Effects</b>: Erases all the elements from *this
Chris@16 750 //! calling Disposer::operator()(pointer), clones all the
Chris@16 751 //! elements from src calling Cloner::operator()(const_reference )
Chris@16 752 //! and inserts them on *this.
Chris@16 753 //!
Chris@16 754 //! If cloner throws, all cloned elements are unlinked and disposed
Chris@16 755 //! calling Disposer::operator()(pointer).
Chris@16 756 //!
Chris@16 757 //! <b>Complexity</b>: Linear to erased plus inserted elements.
Chris@16 758 //!
Chris@16 759 //! <b>Throws</b>: If cloner throws. Basic guarantee.
Chris@16 760 template <class Cloner, class Disposer>
Chris@16 761 void clone_from(const list_impl &src, Cloner cloner, Disposer disposer)
Chris@16 762 {
Chris@16 763 this->clear_and_dispose(disposer);
Chris@16 764 detail::exception_disposer<list_impl, Disposer>
Chris@16 765 rollback(*this, disposer);
Chris@16 766 const_iterator b(src.begin()), e(src.end());
Chris@16 767 for(; b != e; ++b){
Chris@16 768 this->push_back(*cloner(*b));
Chris@16 769 }
Chris@16 770 rollback.release();
Chris@16 771 }
Chris@16 772
Chris@16 773 //! <b>Requires</b>: value must be an lvalue and p must be a valid iterator of *this.
Chris@16 774 //!
Chris@16 775 //! <b>Effects</b>: Inserts the value before the position pointed by p.
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 time. No copy constructors are called.
Chris@16 782 //!
Chris@16 783 //! <b>Note</b>: Does not affect the validity of iterators and references.
Chris@16 784 iterator insert(const_iterator p, reference value)
Chris@16 785 {
Chris@101 786 node_ptr to_insert = this->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(to_insert));
Chris@16 789 node_algorithms::link_before(p.pointed_node(), to_insert);
Chris@16 790 this->priv_size_traits().increment();
Chris@101 791 return iterator(to_insert, this->priv_value_traits_ptr());
Chris@16 792 }
Chris@16 793
Chris@16 794 //! <b>Requires</b>: Dereferencing iterator must yield
Chris@16 795 //! an lvalue of type value_type and p must be a valid iterator of *this.
Chris@16 796 //!
Chris@16 797 //! <b>Effects</b>: Inserts the range pointed by b and e before the position p.
Chris@16 798 //! No copy constructors are called.
Chris@16 799 //!
Chris@16 800 //! <b>Throws</b>: Nothing.
Chris@16 801 //!
Chris@16 802 //! <b>Complexity</b>: Linear to the number of elements inserted.
Chris@16 803 //!
Chris@16 804 //! <b>Note</b>: Does not affect the validity of iterators and references.
Chris@16 805 template<class Iterator>
Chris@16 806 void insert(const_iterator p, Iterator b, Iterator e)
Chris@16 807 {
Chris@16 808 for (; b != e; ++b)
Chris@16 809 this->insert(p, *b);
Chris@16 810 }
Chris@16 811
Chris@16 812 //! <b>Requires</b>: Dereferencing iterator must yield
Chris@16 813 //! an lvalue of type value_type.
Chris@16 814 //!
Chris@16 815 //! <b>Effects</b>: Clears the list and inserts the range pointed by b and e.
Chris@16 816 //! No destructors or copy constructors are called.
Chris@16 817 //!
Chris@16 818 //! <b>Throws</b>: Nothing.
Chris@16 819 //!
Chris@16 820 //! <b>Complexity</b>: Linear to the number of elements inserted plus
Chris@16 821 //! linear to the elements contained in the list if it's a safe-mode
Chris@16 822 //! or auto-unlink value.
Chris@16 823 //! Linear to the number of elements inserted in the list otherwise.
Chris@16 824 //!
Chris@16 825 //! <b>Note</b>: Invalidates the iterators (but not the references)
Chris@16 826 //! to the erased elements.
Chris@16 827 template<class Iterator>
Chris@16 828 void assign(Iterator b, Iterator e)
Chris@16 829 {
Chris@16 830 this->clear();
Chris@16 831 this->insert(this->cend(), b, e);
Chris@16 832 }
Chris@16 833
Chris@16 834 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
Chris@16 835 //!
Chris@16 836 //! <b>Requires</b>: Dereferencing iterator must yield
Chris@16 837 //! an lvalue of type value_type.
Chris@16 838 //!
Chris@16 839 //! <b>Effects</b>: Clears the list and inserts the range pointed by b and e.
Chris@16 840 //! No destructors or copy constructors are called.
Chris@16 841 //! Disposer::operator()(pointer) is called for the removed elements.
Chris@16 842 //!
Chris@16 843 //! <b>Throws</b>: Nothing.
Chris@16 844 //!
Chris@16 845 //! <b>Complexity</b>: Linear to the number of elements inserted plus
Chris@16 846 //! linear to the elements contained in the list.
Chris@16 847 //!
Chris@16 848 //! <b>Note</b>: Invalidates the iterators (but not the references)
Chris@16 849 //! to the erased elements.
Chris@16 850 template<class Iterator, class Disposer>
Chris@16 851 void dispose_and_assign(Disposer disposer, Iterator b, Iterator e)
Chris@16 852 {
Chris@16 853 this->clear_and_dispose(disposer);
Chris@16 854 this->insert(this->cend(), b, e);
Chris@16 855 }
Chris@16 856
Chris@16 857 //! <b>Requires</b>: p must be a valid iterator of *this.
Chris@16 858 //!
Chris@16 859 //! <b>Effects</b>: Transfers all the elements of list x to this list, before the
Chris@16 860 //! the element pointed by p. No destructors or copy constructors are called.
Chris@16 861 //!
Chris@16 862 //! <b>Throws</b>: Nothing.
Chris@16 863 //!
Chris@16 864 //! <b>Complexity</b>: Constant.
Chris@16 865 //!
Chris@16 866 //! <b>Note</b>: Iterators of values obtained from list x now point to elements of
Chris@16 867 //! this list. Iterators of this list and all the references are not invalidated.
Chris@16 868 void splice(const_iterator p, list_impl& x)
Chris@16 869 {
Chris@16 870 if(!x.empty()){
Chris@16 871 node_algorithms::transfer
Chris@16 872 (p.pointed_node(), x.begin().pointed_node(), x.end().pointed_node());
Chris@16 873 size_traits &thist = this->priv_size_traits();
Chris@16 874 size_traits &xt = x.priv_size_traits();
Chris@16 875 thist.increase(xt.get_size());
Chris@16 876 xt.set_size(size_type(0));
Chris@16 877 }
Chris@16 878 }
Chris@16 879
Chris@16 880 //! <b>Requires</b>: p must be a valid iterator of *this.
Chris@16 881 //! new_ele must point to an element contained in list x.
Chris@16 882 //!
Chris@16 883 //! <b>Effects</b>: Transfers the value pointed by new_ele, from list x to this list,
Chris@101 884 //! before the element pointed by p. No destructors or copy constructors are called.
Chris@16 885 //! If p == new_ele or p == ++new_ele, this function is a null operation.
Chris@16 886 //!
Chris@16 887 //! <b>Throws</b>: Nothing.
Chris@16 888 //!
Chris@16 889 //! <b>Complexity</b>: Constant.
Chris@16 890 //!
Chris@16 891 //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
Chris@16 892 //! list. Iterators of this list and all the references are not invalidated.
Chris@16 893 void splice(const_iterator p, list_impl&x, const_iterator new_ele)
Chris@16 894 {
Chris@16 895 node_algorithms::transfer(p.pointed_node(), new_ele.pointed_node());
Chris@16 896 x.priv_size_traits().decrement();
Chris@16 897 this->priv_size_traits().increment();
Chris@16 898 }
Chris@16 899
Chris@16 900 //! <b>Requires</b>: p must be a valid iterator of *this.
Chris@16 901 //! f and e must point to elements contained in list x.
Chris@16 902 //!
Chris@16 903 //! <b>Effects</b>: Transfers the range pointed by f and e from list x to this list,
Chris@101 904 //! before the element pointed by p. No destructors or copy constructors are called.
Chris@16 905 //!
Chris@16 906 //! <b>Throws</b>: Nothing.
Chris@16 907 //!
Chris@16 908 //! <b>Complexity</b>: Linear to the number of elements transferred
Chris@16 909 //! if constant-time size option is enabled. Constant-time otherwise.
Chris@16 910 //!
Chris@16 911 //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
Chris@16 912 //! list. Iterators of this list and all the references are not invalidated.
Chris@16 913 void splice(const_iterator p, list_impl&x, const_iterator f, const_iterator e)
Chris@16 914 {
Chris@16 915 if(constant_time_size)
Chris@101 916 this->splice(p, x, f, e, node_algorithms::distance(f.pointed_node(), e.pointed_node()));
Chris@16 917 else
Chris@101 918 this->splice(p, x, f, e, 1);//intrusive::iterator_distance is a dummy value
Chris@16 919 }
Chris@16 920
Chris@16 921 //! <b>Requires</b>: p must be a valid iterator of *this.
Chris@16 922 //! f and e must point to elements contained in list x.
Chris@101 923 //! n == distance(f, e)
Chris@16 924 //!
Chris@16 925 //! <b>Effects</b>: Transfers the range pointed by f and e from list x to this list,
Chris@101 926 //! before the element pointed by p. No destructors or copy constructors are called.
Chris@16 927 //!
Chris@16 928 //! <b>Throws</b>: Nothing.
Chris@16 929 //!
Chris@16 930 //! <b>Complexity</b>: Constant.
Chris@16 931 //!
Chris@16 932 //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
Chris@16 933 //! list. Iterators of this list and all the references are not invalidated.
Chris@101 934 void splice(const_iterator p, list_impl&x, const_iterator f, const_iterator e, size_type n)
Chris@16 935 {
Chris@16 936 if(n){
Chris@16 937 if(constant_time_size){
Chris@101 938 BOOST_INTRUSIVE_INVARIANT_ASSERT(n == node_algorithms::distance(f.pointed_node(), e.pointed_node()));
Chris@16 939 node_algorithms::transfer(p.pointed_node(), f.pointed_node(), e.pointed_node());
Chris@16 940 size_traits &thist = this->priv_size_traits();
Chris@16 941 size_traits &xt = x.priv_size_traits();
Chris@16 942 thist.increase(n);
Chris@16 943 xt.decrease(n);
Chris@16 944 }
Chris@16 945 else{
Chris@16 946 node_algorithms::transfer(p.pointed_node(), f.pointed_node(), e.pointed_node());
Chris@16 947 }
Chris@16 948 }
Chris@16 949 }
Chris@16 950
Chris@16 951 //! <b>Effects</b>: This function sorts the list *this according to std::less<value_type>.
Chris@16 952 //! The sort is stable, that is, the relative order of equivalent elements is preserved.
Chris@16 953 //!
Chris@101 954 //! <b>Throws</b>: If value_traits::node_traits::node
Chris@16 955 //! constructor throws (this does not happen with predefined Boost.Intrusive hooks)
Chris@16 956 //! or std::less<value_type> throws. Basic guarantee.
Chris@16 957 //!
Chris@16 958 //! <b>Notes</b>: Iterators and references are not invalidated.
Chris@16 959 //!
Chris@16 960 //! <b>Complexity</b>: The number of comparisons is approximately N log N, where N
Chris@16 961 //! is the list's size.
Chris@16 962 void sort()
Chris@16 963 { this->sort(std::less<value_type>()); }
Chris@16 964
Chris@16 965 //! <b>Requires</b>: p must be a comparison function that induces a strict weak ordering
Chris@16 966 //!
Chris@16 967 //! <b>Effects</b>: This function sorts the list *this according to p. The sort is
Chris@16 968 //! stable, that is, the relative order of equivalent elements is preserved.
Chris@16 969 //!
Chris@101 970 //! <b>Throws</b>: If value_traits::node_traits::node
Chris@16 971 //! constructor throws (this does not happen with predefined Boost.Intrusive hooks)
Chris@16 972 //! or the predicate throws. Basic guarantee.
Chris@16 973 //!
Chris@16 974 //! <b>Notes</b>: This won't throw if list_base_hook<> or
Chris@16 975 //! list_member_hook are used.
Chris@16 976 //! Iterators and references are not invalidated.
Chris@16 977 //!
Chris@16 978 //! <b>Complexity</b>: The number of comparisons is approximately N log N, where N
Chris@16 979 //! is the list's size.
Chris@16 980 template<class Predicate>
Chris@16 981 void sort(Predicate p)
Chris@16 982 {
Chris@16 983 if(node_traits::get_next(this->get_root_node())
Chris@16 984 != node_traits::get_previous(this->get_root_node())){
Chris@16 985 list_impl carry(this->priv_value_traits());
Chris@16 986 detail::array_initializer<list_impl, 64> counter(this->priv_value_traits());
Chris@16 987 int fill = 0;
Chris@16 988 while(!this->empty()){
Chris@16 989 carry.splice(carry.cbegin(), *this, this->cbegin());
Chris@16 990 int i = 0;
Chris@16 991 while(i < fill && !counter[i].empty()) {
Chris@16 992 counter[i].merge(carry, p);
Chris@16 993 carry.swap(counter[i++]);
Chris@16 994 }
Chris@16 995 carry.swap(counter[i]);
Chris@16 996 if(i == fill)
Chris@16 997 ++fill;
Chris@16 998 }
Chris@16 999 for (int i = 1; i < fill; ++i)
Chris@16 1000 counter[i].merge(counter[i-1], p);
Chris@16 1001 this->swap(counter[fill-1]);
Chris@16 1002 }
Chris@16 1003 }
Chris@16 1004
Chris@16 1005 //! <b>Effects</b>: This function removes all of x's elements and inserts them
Chris@16 1006 //! in order into *this according to std::less<value_type>. The merge is stable;
Chris@16 1007 //! that is, if an element from *this is equivalent to one from x, then the element
Chris@16 1008 //! from *this will precede the one from x.
Chris@16 1009 //!
Chris@16 1010 //! <b>Throws</b>: If std::less<value_type> throws. Basic guarantee.
Chris@16 1011 //!
Chris@16 1012 //! <b>Complexity</b>: This function is linear time: it performs at most
Chris@16 1013 //! size() + x.size() - 1 comparisons.
Chris@16 1014 //!
Chris@16 1015 //! <b>Note</b>: Iterators and references are not invalidated
Chris@16 1016 void merge(list_impl& x)
Chris@16 1017 { this->merge(x, std::less<value_type>()); }
Chris@16 1018
Chris@16 1019 //! <b>Requires</b>: p must be a comparison function that induces a strict weak
Chris@16 1020 //! ordering and both *this and x must be sorted according to that ordering
Chris@16 1021 //! The lists x and *this must be distinct.
Chris@16 1022 //!
Chris@16 1023 //! <b>Effects</b>: This function removes all of x's elements and inserts them
Chris@16 1024 //! in order into *this. The merge is stable; that is, if an element from *this is
Chris@16 1025 //! equivalent to one from x, then the element from *this will precede the one from x.
Chris@16 1026 //!
Chris@16 1027 //! <b>Throws</b>: If the predicate throws. Basic guarantee.
Chris@16 1028 //!
Chris@16 1029 //! <b>Complexity</b>: This function is linear time: it performs at most
Chris@16 1030 //! size() + x.size() - 1 comparisons.
Chris@16 1031 //!
Chris@16 1032 //! <b>Note</b>: Iterators and references are not invalidated.
Chris@16 1033 template<class Predicate>
Chris@16 1034 void merge(list_impl& x, Predicate p)
Chris@16 1035 {
Chris@16 1036 const_iterator e(this->cend()), ex(x.cend());
Chris@16 1037 const_iterator b(this->cbegin());
Chris@16 1038 while(!x.empty()){
Chris@16 1039 const_iterator ix(x.cbegin());
Chris@16 1040 while (b != e && !p(*ix, *b)){
Chris@16 1041 ++b;
Chris@16 1042 }
Chris@16 1043 if(b == e){
Chris@16 1044 //Now transfer the rest to the end of the container
Chris@16 1045 this->splice(e, x);
Chris@16 1046 break;
Chris@16 1047 }
Chris@16 1048 else{
Chris@16 1049 size_type n(0);
Chris@16 1050 do{
Chris@16 1051 ++ix; ++n;
Chris@16 1052 } while(ix != ex && p(*ix, *b));
Chris@16 1053 this->splice(b, x, x.begin(), ix, n);
Chris@16 1054 }
Chris@16 1055 }
Chris@16 1056 }
Chris@16 1057
Chris@16 1058 //! <b>Effects</b>: Reverses the order of elements in the list.
Chris@16 1059 //!
Chris@16 1060 //! <b>Throws</b>: Nothing.
Chris@16 1061 //!
Chris@16 1062 //! <b>Complexity</b>: This function is linear time.
Chris@16 1063 //!
Chris@16 1064 //! <b>Note</b>: Iterators and references are not invalidated
Chris@16 1065 void reverse()
Chris@16 1066 { node_algorithms::reverse(this->get_root_node()); }
Chris@16 1067
Chris@16 1068 //! <b>Effects</b>: Removes all the elements that compare equal to value.
Chris@16 1069 //! No destructors are called.
Chris@16 1070 //!
Chris@16 1071 //! <b>Throws</b>: If std::equal_to<value_type> throws. Basic guarantee.
Chris@16 1072 //!
Chris@16 1073 //! <b>Complexity</b>: Linear time. It performs exactly size() comparisons for equality.
Chris@16 1074 //!
Chris@16 1075 //! <b>Note</b>: The relative order of elements that are not removed is unchanged,
Chris@16 1076 //! and iterators to elements that are not removed remain valid.
Chris@16 1077 void remove(const_reference value)
Chris@16 1078 { this->remove_if(detail::equal_to_value<const_reference>(value)); }
Chris@16 1079
Chris@16 1080 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
Chris@16 1081 //!
Chris@16 1082 //! <b>Effects</b>: Removes all the elements that compare equal to value.
Chris@16 1083 //! Disposer::operator()(pointer) is called for every removed element.
Chris@16 1084 //!
Chris@16 1085 //! <b>Throws</b>: If std::equal_to<value_type> throws. Basic guarantee.
Chris@16 1086 //!
Chris@16 1087 //! <b>Complexity</b>: Linear time. It performs exactly size() comparisons for equality.
Chris@16 1088 //!
Chris@16 1089 //! <b>Note</b>: The relative order of elements that are not removed is unchanged,
Chris@16 1090 //! and iterators to elements that are not removed remain valid.
Chris@16 1091 template<class Disposer>
Chris@16 1092 void remove_and_dispose(const_reference value, Disposer disposer)
Chris@16 1093 { this->remove_and_dispose_if(detail::equal_to_value<const_reference>(value), disposer); }
Chris@16 1094
Chris@16 1095 //! <b>Effects</b>: Removes all the elements for which a specified
Chris@16 1096 //! predicate is satisfied. No destructors are called.
Chris@16 1097 //!
Chris@16 1098 //! <b>Throws</b>: If pred throws. Basic guarantee.
Chris@16 1099 //!
Chris@16 1100 //! <b>Complexity</b>: Linear time. It performs exactly size() calls to the predicate.
Chris@16 1101 //!
Chris@16 1102 //! <b>Note</b>: The relative order of elements that are not removed is unchanged,
Chris@16 1103 //! and iterators to elements that are not removed remain valid.
Chris@16 1104 template<class Pred>
Chris@16 1105 void remove_if(Pred pred)
Chris@101 1106 {
Chris@101 1107 const node_ptr root_node = this->get_root_node();
Chris@101 1108 typename node_algorithms::stable_partition_info info;
Chris@101 1109 node_algorithms::stable_partition
Chris@101 1110 (node_traits::get_next(root_node), root_node, detail::key_nodeptr_comp<Pred, value_traits>(pred, &this->priv_value_traits()), info);
Chris@101 1111 //Invariants preserved by stable_partition so erase can be safely called
Chris@101 1112 //The first element might have changed so calculate it again
Chris@101 1113 this->erase( const_iterator(node_traits::get_next(root_node), this->priv_value_traits_ptr())
Chris@101 1114 , const_iterator(info.beg_2st_partition, this->priv_value_traits_ptr())
Chris@101 1115 , info.num_1st_partition);
Chris@101 1116 }
Chris@16 1117
Chris@16 1118 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
Chris@16 1119 //!
Chris@16 1120 //! <b>Effects</b>: Removes all the elements for which a specified
Chris@16 1121 //! predicate is satisfied.
Chris@16 1122 //! Disposer::operator()(pointer) is called for every removed element.
Chris@16 1123 //!
Chris@16 1124 //! <b>Throws</b>: If pred throws. Basic guarantee.
Chris@16 1125 //!
Chris@16 1126 //! <b>Complexity</b>: Linear time. It performs exactly size() comparisons for equality.
Chris@16 1127 //!
Chris@16 1128 //! <b>Note</b>: The relative order of elements that are not removed is unchanged,
Chris@16 1129 //! and iterators to elements that are not removed remain valid.
Chris@16 1130 template<class Pred, class Disposer>
Chris@16 1131 void remove_and_dispose_if(Pred pred, Disposer disposer)
Chris@16 1132 {
Chris@101 1133 const node_ptr root_node = this->get_root_node();
Chris@101 1134 typename node_algorithms::stable_partition_info info;
Chris@101 1135 node_algorithms::stable_partition
Chris@101 1136 (node_traits::get_next(root_node), root_node, detail::key_nodeptr_comp<Pred, value_traits>(pred, &this->priv_value_traits()), info);
Chris@101 1137 //Invariants preserved by stable_partition so erase can be safely called
Chris@101 1138 //The first element might have changed so calculate it again
Chris@101 1139 this->erase_and_dispose( const_iterator(node_traits::get_next(root_node), this->priv_value_traits_ptr())
Chris@101 1140 , const_iterator(info.beg_2st_partition, this->priv_value_traits_ptr())
Chris@101 1141 , disposer);
Chris@16 1142 }
Chris@16 1143
Chris@16 1144 //! <b>Effects</b>: Removes adjacent duplicate elements or adjacent
Chris@16 1145 //! elements that are equal from the list. No destructors are called.
Chris@16 1146 //!
Chris@16 1147 //! <b>Throws</b>: If std::equal_to<value_type throws. Basic guarantee.
Chris@16 1148 //!
Chris@16 1149 //! <b>Complexity</b>: Linear time (size()-1 comparisons calls to pred()).
Chris@16 1150 //!
Chris@16 1151 //! <b>Note</b>: The relative order of elements that are not removed is unchanged,
Chris@16 1152 //! and iterators to elements that are not removed remain valid.
Chris@16 1153 void unique()
Chris@16 1154 { this->unique_and_dispose(std::equal_to<value_type>(), detail::null_disposer()); }
Chris@16 1155
Chris@16 1156 //! <b>Effects</b>: Removes adjacent duplicate elements or adjacent
Chris@16 1157 //! elements that satisfy some binary predicate from the list.
Chris@16 1158 //! No destructors are called.
Chris@16 1159 //!
Chris@16 1160 //! <b>Throws</b>: If pred throws. Basic guarantee.
Chris@16 1161 //!
Chris@16 1162 //! <b>Complexity</b>: Linear time (size()-1 comparisons equality comparisons).
Chris@16 1163 //!
Chris@16 1164 //! <b>Note</b>: The relative order of elements that are not removed is unchanged,
Chris@16 1165 //! and iterators to elements that are not removed remain valid.
Chris@16 1166 template<class BinaryPredicate>
Chris@16 1167 void unique(BinaryPredicate pred)
Chris@16 1168 { this->unique_and_dispose(pred, detail::null_disposer()); }
Chris@16 1169
Chris@16 1170 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
Chris@16 1171 //!
Chris@16 1172 //! <b>Effects</b>: Removes adjacent duplicate elements or adjacent
Chris@16 1173 //! elements that are equal from the list.
Chris@16 1174 //! Disposer::operator()(pointer) is called for every removed element.
Chris@16 1175 //!
Chris@16 1176 //! <b>Throws</b>: If std::equal_to<value_type throws. Basic guarantee.
Chris@16 1177 //!
Chris@16 1178 //! <b>Complexity</b>: Linear time (size()-1) comparisons equality comparisons.
Chris@16 1179 //!
Chris@16 1180 //! <b>Note</b>: The relative order of elements that are not removed is unchanged,
Chris@16 1181 //! and iterators to elements that are not removed remain valid.
Chris@16 1182 template<class Disposer>
Chris@16 1183 void unique_and_dispose(Disposer disposer)
Chris@16 1184 { this->unique_and_dispose(std::equal_to<value_type>(), disposer); }
Chris@16 1185
Chris@16 1186 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
Chris@16 1187 //!
Chris@16 1188 //! <b>Effects</b>: Removes adjacent duplicate elements or adjacent
Chris@16 1189 //! elements that satisfy some binary predicate from the list.
Chris@16 1190 //! Disposer::operator()(pointer) is called for every removed element.
Chris@16 1191 //!
Chris@16 1192 //! <b>Throws</b>: If pred throws. Basic guarantee.
Chris@16 1193 //!
Chris@16 1194 //! <b>Complexity</b>: Linear time (size()-1) comparisons equality comparisons.
Chris@16 1195 //!
Chris@16 1196 //! <b>Note</b>: The relative order of elements that are not removed is unchanged,
Chris@16 1197 //! and iterators to elements that are not removed remain valid.
Chris@16 1198 template<class BinaryPredicate, class Disposer>
Chris@16 1199 void unique_and_dispose(BinaryPredicate pred, Disposer disposer)
Chris@16 1200 {
Chris@16 1201 const_iterator itend(this->cend());
Chris@16 1202 const_iterator cur(this->cbegin());
Chris@16 1203
Chris@16 1204 if(cur != itend){
Chris@16 1205 const_iterator after(cur);
Chris@16 1206 ++after;
Chris@16 1207 while(after != itend){
Chris@16 1208 if(pred(*cur, *after)){
Chris@16 1209 after = this->erase_and_dispose(after, disposer);
Chris@16 1210 }
Chris@16 1211 else{
Chris@16 1212 cur = after;
Chris@16 1213 ++after;
Chris@16 1214 }
Chris@16 1215 }
Chris@16 1216 }
Chris@16 1217 }
Chris@16 1218
Chris@16 1219 //! <b>Requires</b>: value must be a reference to a value inserted in a list.
Chris@16 1220 //!
Chris@16 1221 //! <b>Effects</b>: This function returns a const_iterator pointing to the element
Chris@16 1222 //!
Chris@16 1223 //! <b>Throws</b>: Nothing.
Chris@16 1224 //!
Chris@16 1225 //! <b>Complexity</b>: Constant time.
Chris@16 1226 //!
Chris@16 1227 //! <b>Note</b>: Iterators and references are not invalidated.
Chris@16 1228 //! This static function is available only if the <i>value traits</i>
Chris@16 1229 //! is stateless.
Chris@16 1230 static iterator s_iterator_to(reference value)
Chris@16 1231 {
Chris@16 1232 BOOST_STATIC_ASSERT((!stateful_value_traits));
Chris@101 1233 BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(value_traits::to_node_ptr(value)));
Chris@101 1234 return iterator(value_traits::to_node_ptr(value), const_value_traits_ptr());
Chris@16 1235 }
Chris@16 1236
Chris@16 1237 //! <b>Requires</b>: value must be a const reference to a value inserted in a list.
Chris@16 1238 //!
Chris@16 1239 //! <b>Effects</b>: This function returns an iterator pointing to the element.
Chris@16 1240 //!
Chris@16 1241 //! <b>Throws</b>: Nothing.
Chris@16 1242 //!
Chris@16 1243 //! <b>Complexity</b>: Constant time.
Chris@16 1244 //!
Chris@16 1245 //! <b>Note</b>: Iterators and references are not invalidated.
Chris@16 1246 //! This static function is available only if the <i>value traits</i>
Chris@16 1247 //! is stateless.
Chris@16 1248 static const_iterator s_iterator_to(const_reference value)
Chris@16 1249 {
Chris@16 1250 BOOST_STATIC_ASSERT((!stateful_value_traits));
Chris@101 1251 reference r =*detail::uncast(pointer_traits<const_pointer>::pointer_to(value));
Chris@101 1252 BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(value_traits::to_node_ptr(r)));
Chris@101 1253 return const_iterator(value_traits::to_node_ptr(r), const_value_traits_ptr());
Chris@16 1254 }
Chris@16 1255
Chris@16 1256 //! <b>Requires</b>: value must be a reference to a value inserted in a list.
Chris@16 1257 //!
Chris@16 1258 //! <b>Effects</b>: This function returns a const_iterator pointing to the element
Chris@16 1259 //!
Chris@16 1260 //! <b>Throws</b>: Nothing.
Chris@16 1261 //!
Chris@16 1262 //! <b>Complexity</b>: Constant time.
Chris@16 1263 //!
Chris@16 1264 //! <b>Note</b>: Iterators and references are not invalidated.
Chris@16 1265 iterator iterator_to(reference value)
Chris@16 1266 {
Chris@101 1267 BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(this->priv_value_traits().to_node_ptr(value)));
Chris@101 1268 return iterator(this->priv_value_traits().to_node_ptr(value), this->priv_value_traits_ptr());
Chris@16 1269 }
Chris@16 1270
Chris@16 1271 //! <b>Requires</b>: value must be a const reference to a value inserted in a list.
Chris@16 1272 //!
Chris@16 1273 //! <b>Effects</b>: This function returns an iterator pointing to the element.
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 and references are not invalidated.
Chris@16 1280 const_iterator iterator_to(const_reference value) const
Chris@16 1281 {
Chris@101 1282 reference r = *detail::uncast(pointer_traits<const_pointer>::pointer_to(value));
Chris@101 1283 BOOST_INTRUSIVE_INVARIANT_ASSERT(!node_algorithms::inited(this->priv_value_traits().to_node_ptr(r)));
Chris@101 1284 return const_iterator(this->priv_value_traits().to_node_ptr(r), this->priv_value_traits_ptr());
Chris@101 1285 }
Chris@101 1286
Chris@101 1287 //! <b>Effects</b>: Asserts the integrity of the container.
Chris@101 1288 //!
Chris@101 1289 //! <b>Complexity</b>: Linear time.
Chris@101 1290 //!
Chris@101 1291 //! <b>Note</b>: The method has no effect when asserts are turned off (e.g., with NDEBUG).
Chris@101 1292 //! Experimental function, interface might change in future versions.
Chris@101 1293 void check() const
Chris@101 1294 {
Chris@101 1295 const_node_ptr header_ptr = get_root_node();
Chris@101 1296 // header's next and prev are never null
Chris@101 1297 BOOST_INTRUSIVE_INVARIANT_ASSERT(node_traits::get_next(header_ptr));
Chris@101 1298 BOOST_INTRUSIVE_INVARIANT_ASSERT(node_traits::get_previous(header_ptr));
Chris@101 1299 // header's next and prev either both point to header (empty list) or neither does
Chris@101 1300 BOOST_INTRUSIVE_INVARIANT_ASSERT((node_traits::get_next(header_ptr) == header_ptr)
Chris@101 1301 == (node_traits::get_previous(header_ptr) == header_ptr));
Chris@101 1302 if (node_traits::get_next(header_ptr) == header_ptr)
Chris@101 1303 {
Chris@101 1304 if (constant_time_size)
Chris@101 1305 BOOST_INTRUSIVE_INVARIANT_ASSERT(this->priv_size_traits().get_size() == 0);
Chris@101 1306 return;
Chris@101 1307 }
Chris@101 1308 size_t node_count = 0;
Chris@101 1309 const_node_ptr p = header_ptr;
Chris@101 1310 while (true)
Chris@101 1311 {
Chris@101 1312 const_node_ptr next_p = node_traits::get_next(p);
Chris@101 1313 BOOST_INTRUSIVE_INVARIANT_ASSERT(next_p);
Chris@101 1314 BOOST_INTRUSIVE_INVARIANT_ASSERT(node_traits::get_previous(next_p) == p);
Chris@101 1315 p = next_p;
Chris@101 1316 if (p == header_ptr) break;
Chris@101 1317 ++node_count;
Chris@101 1318 }
Chris@101 1319 if (constant_time_size)
Chris@101 1320 BOOST_INTRUSIVE_INVARIANT_ASSERT(this->priv_size_traits().get_size() == node_count);
Chris@16 1321 }
Chris@16 1322
Chris@16 1323 /// @cond
Chris@16 1324
Chris@16 1325 private:
Chris@16 1326 static list_impl &priv_container_from_end_iterator(const const_iterator &end_iterator)
Chris@16 1327 {
Chris@101 1328 BOOST_STATIC_ASSERT((has_container_from_iterator));
Chris@101 1329 node_ptr p = end_iterator.pointed_node();
Chris@101 1330 header_holder_type* h = header_holder_type::get_holder(p);
Chris@101 1331 root_plus_size* r = detail::parent_from_member
Chris@101 1332 < root_plus_size, header_holder_type>(h, &root_plus_size::m_header);
Chris@16 1333 data_t *d = detail::parent_from_member<data_t, root_plus_size>
Chris@16 1334 ( r, &data_t::root_plus_size_);
Chris@16 1335 list_impl *s = detail::parent_from_member<list_impl, data_t>(d, &list_impl::data_);
Chris@16 1336 return *s;
Chris@16 1337 }
Chris@16 1338 /// @endcond
Chris@16 1339 };
Chris@16 1340
Chris@16 1341 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
Chris@16 1342 template<class T, class ...Options>
Chris@16 1343 #else
Chris@101 1344 template <class ValueTraits, class SizeType, bool ConstantTimeSize, typename HeaderHolder>
Chris@16 1345 #endif
Chris@16 1346 inline bool operator<
Chris@16 1347 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
Chris@16 1348 (const list_impl<T, Options...> &x, const list_impl<T, Options...> &y)
Chris@16 1349 #else
Chris@101 1350 (const list_impl<ValueTraits, SizeType, ConstantTimeSize, HeaderHolder> &x, const list_impl<ValueTraits, SizeType, ConstantTimeSize, HeaderHolder> &y)
Chris@16 1351 #endif
Chris@101 1352 { return ::boost::intrusive::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
Chris@16 1353
Chris@16 1354 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
Chris@16 1355 template<class T, class ...Options>
Chris@16 1356 #else
Chris@101 1357 template <class ValueTraits, class SizeType, bool ConstantTimeSize, typename HeaderHolder>
Chris@16 1358 #endif
Chris@16 1359 bool operator==
Chris@16 1360 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
Chris@16 1361 (const list_impl<T, Options...> &x, const list_impl<T, Options...> &y)
Chris@16 1362 #else
Chris@101 1363 (const list_impl<ValueTraits, SizeType, ConstantTimeSize, HeaderHolder> &x, const list_impl<ValueTraits, SizeType, ConstantTimeSize, HeaderHolder> &y)
Chris@16 1364 #endif
Chris@16 1365 {
Chris@101 1366 typedef list_impl<ValueTraits, SizeType, ConstantTimeSize, HeaderHolder> list_type;
Chris@16 1367 const bool C = list_type::constant_time_size;
Chris@16 1368 if(C && x.size() != y.size()){
Chris@16 1369 return false;
Chris@16 1370 }
Chris@101 1371 return ::boost::intrusive::algo_equal(x.cbegin(), x.cend(), y.cbegin(), y.cend());
Chris@16 1372 }
Chris@16 1373
Chris@16 1374 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
Chris@16 1375 template<class T, class ...Options>
Chris@16 1376 #else
Chris@101 1377 template <class ValueTraits, class SizeType, bool ConstantTimeSize, typename HeaderHolder>
Chris@16 1378 #endif
Chris@16 1379 inline bool operator!=
Chris@16 1380 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
Chris@16 1381 (const list_impl<T, Options...> &x, const list_impl<T, Options...> &y)
Chris@16 1382 #else
Chris@101 1383 (const list_impl<ValueTraits, SizeType, ConstantTimeSize, HeaderHolder> &x, const list_impl<ValueTraits, SizeType, ConstantTimeSize, HeaderHolder> &y)
Chris@16 1384 #endif
Chris@16 1385 { return !(x == y); }
Chris@16 1386
Chris@16 1387 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
Chris@16 1388 template<class T, class ...Options>
Chris@16 1389 #else
Chris@101 1390 template <class ValueTraits, class SizeType, bool ConstantTimeSize, typename HeaderHolder>
Chris@16 1391 #endif
Chris@16 1392 inline bool operator>
Chris@16 1393 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
Chris@16 1394 (const list_impl<T, Options...> &x, const list_impl<T, Options...> &y)
Chris@16 1395 #else
Chris@101 1396 (const list_impl<ValueTraits, SizeType, ConstantTimeSize, HeaderHolder> &x, const list_impl<ValueTraits, SizeType, ConstantTimeSize, HeaderHolder> &y)
Chris@16 1397 #endif
Chris@16 1398 { return y < x; }
Chris@16 1399
Chris@16 1400 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
Chris@16 1401 template<class T, class ...Options>
Chris@16 1402 #else
Chris@101 1403 template <class ValueTraits, class SizeType, bool ConstantTimeSize, typename HeaderHolder>
Chris@16 1404 #endif
Chris@16 1405 inline bool operator<=
Chris@16 1406 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
Chris@16 1407 (const list_impl<T, Options...> &x, const list_impl<T, Options...> &y)
Chris@16 1408 #else
Chris@101 1409 (const list_impl<ValueTraits, SizeType, ConstantTimeSize, HeaderHolder> &x, const list_impl<ValueTraits, SizeType, ConstantTimeSize, HeaderHolder> &y)
Chris@16 1410 #endif
Chris@16 1411 { return !(y < x); }
Chris@16 1412
Chris@16 1413 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
Chris@16 1414 template<class T, class ...Options>
Chris@16 1415 #else
Chris@101 1416 template <class ValueTraits, class SizeType, bool ConstantTimeSize, typename HeaderHolder>
Chris@16 1417 #endif
Chris@16 1418 inline bool operator>=
Chris@16 1419 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
Chris@16 1420 (const list_impl<T, Options...> &x, const list_impl<T, Options...> &y)
Chris@16 1421 #else
Chris@101 1422 (const list_impl<ValueTraits, SizeType, ConstantTimeSize, HeaderHolder> &x, const list_impl<ValueTraits, SizeType, ConstantTimeSize, HeaderHolder> &y)
Chris@16 1423 #endif
Chris@16 1424 { return !(x < y); }
Chris@16 1425
Chris@16 1426 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
Chris@16 1427 template<class T, class ...Options>
Chris@16 1428 #else
Chris@101 1429 template <class ValueTraits, class SizeType, bool ConstantTimeSize, typename HeaderHolder>
Chris@16 1430 #endif
Chris@16 1431 inline void swap
Chris@16 1432 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED)
Chris@16 1433 (list_impl<T, Options...> &x, list_impl<T, Options...> &y)
Chris@16 1434 #else
Chris@101 1435 (list_impl<ValueTraits, SizeType, ConstantTimeSize, HeaderHolder> &x, list_impl<ValueTraits, SizeType, ConstantTimeSize, HeaderHolder> &y)
Chris@16 1436 #endif
Chris@16 1437 { x.swap(y); }
Chris@16 1438
Chris@16 1439 //! Helper metafunction to define a \c list that yields to the same type when the
Chris@16 1440 //! same options (either explicitly or implicitly) are used.
Chris@16 1441 #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
Chris@16 1442 template<class T, class ...Options>
Chris@16 1443 #else
Chris@101 1444 template<class T, class O1 = void, class O2 = void, class O3 = void, class O4 = void>
Chris@16 1445 #endif
Chris@16 1446 struct make_list
Chris@16 1447 {
Chris@16 1448 /// @cond
Chris@16 1449 typedef typename pack_options
Chris@16 1450 < list_defaults,
Chris@16 1451 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
Chris@101 1452 O1, O2, O3, O4
Chris@16 1453 #else
Chris@16 1454 Options...
Chris@16 1455 #endif
Chris@16 1456 >::type packed_options;
Chris@16 1457
Chris@16 1458 typedef typename detail::get_value_traits
Chris@16 1459 <T, typename packed_options::proto_value_traits>::type value_traits;
Chris@16 1460 typedef list_impl
Chris@16 1461 <
Chris@16 1462 value_traits,
Chris@16 1463 typename packed_options::size_type,
Chris@101 1464 packed_options::constant_time_size,
Chris@101 1465 typename packed_options::header_holder_type
Chris@16 1466 > implementation_defined;
Chris@16 1467 /// @endcond
Chris@16 1468 typedef implementation_defined type;
Chris@16 1469 };
Chris@16 1470
Chris@16 1471
Chris@16 1472 #ifndef BOOST_INTRUSIVE_DOXYGEN_INVOKED
Chris@16 1473
Chris@16 1474 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
Chris@101 1475 template<class T, class O1, class O2, class O3, class O4>
Chris@16 1476 #else
Chris@16 1477 template<class T, class ...Options>
Chris@16 1478 #endif
Chris@16 1479 class list
Chris@16 1480 : public make_list<T,
Chris@16 1481 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
Chris@101 1482 O1, O2, O3, O4
Chris@16 1483 #else
Chris@16 1484 Options...
Chris@16 1485 #endif
Chris@16 1486 >::type
Chris@16 1487 {
Chris@16 1488 typedef typename make_list
Chris@16 1489 <T,
Chris@16 1490 #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES)
Chris@101 1491 O1, O2, O3, O4
Chris@16 1492 #else
Chris@16 1493 Options...
Chris@16 1494 #endif
Chris@16 1495 >::type Base;
Chris@16 1496 //Assert if passed value traits are compatible with the type
Chris@101 1497 BOOST_STATIC_ASSERT((detail::is_same<typename Base::value_traits::value_type, T>::value));
Chris@16 1498 BOOST_MOVABLE_BUT_NOT_COPYABLE(list)
Chris@16 1499
Chris@16 1500 public:
Chris@16 1501 typedef typename Base::value_traits value_traits;
Chris@16 1502 typedef typename Base::iterator iterator;
Chris@16 1503 typedef typename Base::const_iterator const_iterator;
Chris@16 1504
Chris@16 1505 explicit list(const value_traits &v_traits = value_traits())
Chris@16 1506 : Base(v_traits)
Chris@16 1507 {}
Chris@16 1508
Chris@16 1509 template<class Iterator>
Chris@16 1510 list(Iterator b, Iterator e, const value_traits &v_traits = value_traits())
Chris@16 1511 : Base(b, e, v_traits)
Chris@16 1512 {}
Chris@16 1513
Chris@16 1514 list(BOOST_RV_REF(list) x)
Chris@101 1515 : Base(BOOST_MOVE_BASE(Base, x))
Chris@16 1516 {}
Chris@16 1517
Chris@16 1518 list& operator=(BOOST_RV_REF(list) x)
Chris@101 1519 { return static_cast<list &>(this->Base::operator=(BOOST_MOVE_BASE(Base, x))); }
Chris@16 1520
Chris@16 1521 static list &container_from_end_iterator(iterator end_iterator)
Chris@16 1522 { return static_cast<list &>(Base::container_from_end_iterator(end_iterator)); }
Chris@16 1523
Chris@16 1524 static const list &container_from_end_iterator(const_iterator end_iterator)
Chris@16 1525 { return static_cast<const list &>(Base::container_from_end_iterator(end_iterator)); }
Chris@16 1526 };
Chris@16 1527
Chris@16 1528 #endif
Chris@16 1529
Chris@16 1530 } //namespace intrusive
Chris@16 1531 } //namespace boost
Chris@16 1532
Chris@16 1533 #include <boost/intrusive/detail/config_end.hpp>
Chris@16 1534
Chris@16 1535 #endif //BOOST_INTRUSIVE_LIST_HPP