comparison DEPENDENCIES/generic/include/boost/intrusive/hashtable.hpp @ 101:c530137014c0

Update Boost headers (1.58.0)
author Chris Cannam
date Mon, 07 Sep 2015 11:12:49 +0100
parents 2665513ce2d3
children
comparison
equal deleted inserted replaced
100:793467b5e61c 101:c530137014c0
11 ///////////////////////////////////////////////////////////////////////////// 11 /////////////////////////////////////////////////////////////////////////////
12 #ifndef BOOST_INTRUSIVE_HASHTABLE_HPP 12 #ifndef BOOST_INTRUSIVE_HASHTABLE_HPP
13 #define BOOST_INTRUSIVE_HASHTABLE_HPP 13 #define BOOST_INTRUSIVE_HASHTABLE_HPP
14 14
15 #include <boost/intrusive/detail/config_begin.hpp> 15 #include <boost/intrusive/detail/config_begin.hpp>
16 //std C++ 16 #include <boost/intrusive/intrusive_fwd.hpp>
17 #include <functional> //std::equal_to 17
18 #include <utility> //std::pair
19 #include <algorithm> //std::swap, std::lower_bound, std::upper_bound
20 #include <cstddef> //std::size_t
21 //boost
22 #include <boost/intrusive/detail/assert.hpp>
23 #include <boost/static_assert.hpp>
24 #include <boost/functional/hash.hpp>
25 #include <boost/pointer_cast.hpp>
26 //General intrusive utilities 18 //General intrusive utilities
27 #include <boost/intrusive/intrusive_fwd.hpp>
28 #include <boost/intrusive/detail/hashtable_node.hpp> 19 #include <boost/intrusive/detail/hashtable_node.hpp>
29 #include <boost/intrusive/detail/transform_iterator.hpp> 20 #include <boost/intrusive/detail/transform_iterator.hpp>
30 #include <boost/intrusive/link_mode.hpp> 21 #include <boost/intrusive/link_mode.hpp>
31 #include <boost/intrusive/detail/ebo_functor_holder.hpp> 22 #include <boost/intrusive/detail/ebo_functor_holder.hpp>
32 #include <boost/intrusive/detail/clear_on_destructor_base.hpp> 23 #include <boost/intrusive/detail/is_stateful_value_traits.hpp>
33 #include <boost/intrusive/detail/utilities.hpp> 24 #include <boost/intrusive/detail/node_to_value.hpp>
25 #include <boost/intrusive/detail/exception_disposer.hpp>
26 #include <boost/intrusive/detail/node_cloner_disposer.hpp>
27 #include <boost/intrusive/detail/simple_disposers.hpp>
28 #include <boost/intrusive/detail/size_holder.hpp>
29
34 //Implementation utilities 30 //Implementation utilities
35 #include <boost/intrusive/unordered_set_hook.hpp> 31 #include <boost/intrusive/unordered_set_hook.hpp>
36 #include <boost/intrusive/slist.hpp> 32 #include <boost/intrusive/slist.hpp>
37 #include <boost/intrusive/pointer_traits.hpp> 33 #include <boost/intrusive/pointer_traits.hpp>
38 #include <boost/intrusive/detail/mpl.hpp> 34 #include <boost/intrusive/detail/mpl.hpp>
39 #include <boost/move/move.hpp> 35
36 //boost
37 #include <boost/functional/hash.hpp>
38 #include <boost/intrusive/detail/assert.hpp>
39 #include <boost/static_assert.hpp>
40 #include <boost/move/utility_core.hpp>
41 #include <boost/move/adl_move_swap.hpp>
42
43 //std C++
44 #include <boost/intrusive/detail/minimal_less_equal_header.hpp> //std::equal_to
45 #include <boost/intrusive/detail/minimal_pair_header.hpp> //std::pair
46 #include <algorithm> //std::lower_bound, std::upper_bound
47 #include <cstddef> //std::size_t
48
49 #if defined(BOOST_HAS_PRAGMA_ONCE)
50 # pragma once
51 #endif
40 52
41 namespace boost { 53 namespace boost {
42 namespace intrusive { 54 namespace intrusive {
43 55
44 /// @cond 56 /// @cond
57
58 template<int Dummy = 0>
59 struct prime_list_holder
60 {
61 static const std::size_t prime_list[];
62 static const std::size_t prime_list_size;
63 };
64
65 //We only support LLP64(Win64) or LP64(most Unix) data models
66 #ifdef _WIN64 //In 64 bit windows sizeof(size_t) == sizeof(unsigned long long)
67 #define BOOST_INTRUSIVE_PRIME_C(NUMBER) NUMBER##ULL
68 #define BOOST_INTRUSIVE_64_BIT_SIZE_T 1
69 #else //In 32 bit windows and 32/64 bit unixes sizeof(size_t) == sizeof(unsigned long)
70 #define BOOST_INTRUSIVE_PRIME_C(NUMBER) NUMBER##UL
71 #define BOOST_INTRUSIVE_64_BIT_SIZE_T (((((ULONG_MAX>>16)>>16)>>16)>>15) != 0)
72 #endif
73
74 template<int Dummy>
75 const std::size_t prime_list_holder<Dummy>::prime_list[] = {
76 BOOST_INTRUSIVE_PRIME_C(3), BOOST_INTRUSIVE_PRIME_C(7),
77 BOOST_INTRUSIVE_PRIME_C(11), BOOST_INTRUSIVE_PRIME_C(17),
78 BOOST_INTRUSIVE_PRIME_C(29), BOOST_INTRUSIVE_PRIME_C(53),
79 BOOST_INTRUSIVE_PRIME_C(97), BOOST_INTRUSIVE_PRIME_C(193),
80 BOOST_INTRUSIVE_PRIME_C(389), BOOST_INTRUSIVE_PRIME_C(769),
81 BOOST_INTRUSIVE_PRIME_C(1543), BOOST_INTRUSIVE_PRIME_C(3079),
82 BOOST_INTRUSIVE_PRIME_C(6151), BOOST_INTRUSIVE_PRIME_C(12289),
83 BOOST_INTRUSIVE_PRIME_C(24593), BOOST_INTRUSIVE_PRIME_C(49157),
84 BOOST_INTRUSIVE_PRIME_C(98317), BOOST_INTRUSIVE_PRIME_C(196613),
85 BOOST_INTRUSIVE_PRIME_C(393241), BOOST_INTRUSIVE_PRIME_C(786433),
86 BOOST_INTRUSIVE_PRIME_C(1572869), BOOST_INTRUSIVE_PRIME_C(3145739),
87 BOOST_INTRUSIVE_PRIME_C(6291469), BOOST_INTRUSIVE_PRIME_C(12582917),
88 BOOST_INTRUSIVE_PRIME_C(25165843), BOOST_INTRUSIVE_PRIME_C(50331653),
89 BOOST_INTRUSIVE_PRIME_C(100663319), BOOST_INTRUSIVE_PRIME_C(201326611),
90 BOOST_INTRUSIVE_PRIME_C(402653189), BOOST_INTRUSIVE_PRIME_C(805306457),
91 BOOST_INTRUSIVE_PRIME_C(1610612741), BOOST_INTRUSIVE_PRIME_C(3221225473),
92 #if BOOST_INTRUSIVE_64_BIT_SIZE_T
93 //Taken from Boost.MultiIndex code, thanks to Joaquin M Lopez Munoz.
94 BOOST_INTRUSIVE_PRIME_C(6442450939), BOOST_INTRUSIVE_PRIME_C(12884901893),
95 BOOST_INTRUSIVE_PRIME_C(25769803751), BOOST_INTRUSIVE_PRIME_C(51539607551),
96 BOOST_INTRUSIVE_PRIME_C(103079215111), BOOST_INTRUSIVE_PRIME_C(206158430209),
97 BOOST_INTRUSIVE_PRIME_C(412316860441), BOOST_INTRUSIVE_PRIME_C(824633720831),
98 BOOST_INTRUSIVE_PRIME_C(1649267441651), BOOST_INTRUSIVE_PRIME_C(3298534883309),
99 BOOST_INTRUSIVE_PRIME_C(6597069766657), BOOST_INTRUSIVE_PRIME_C(13194139533299),
100 BOOST_INTRUSIVE_PRIME_C(26388279066623), BOOST_INTRUSIVE_PRIME_C(52776558133303),
101 BOOST_INTRUSIVE_PRIME_C(105553116266489), BOOST_INTRUSIVE_PRIME_C(211106232532969),
102 BOOST_INTRUSIVE_PRIME_C(422212465066001), BOOST_INTRUSIVE_PRIME_C(844424930131963),
103 BOOST_INTRUSIVE_PRIME_C(1688849860263953), BOOST_INTRUSIVE_PRIME_C(3377699720527861),
104 BOOST_INTRUSIVE_PRIME_C(6755399441055731), BOOST_INTRUSIVE_PRIME_C(13510798882111483),
105 BOOST_INTRUSIVE_PRIME_C(27021597764222939), BOOST_INTRUSIVE_PRIME_C(54043195528445957),
106 BOOST_INTRUSIVE_PRIME_C(108086391056891903), BOOST_INTRUSIVE_PRIME_C(216172782113783843),
107 BOOST_INTRUSIVE_PRIME_C(432345564227567621), BOOST_INTRUSIVE_PRIME_C(864691128455135207),
108 BOOST_INTRUSIVE_PRIME_C(1729382256910270481), BOOST_INTRUSIVE_PRIME_C(3458764513820540933),
109 BOOST_INTRUSIVE_PRIME_C(6917529027641081903), BOOST_INTRUSIVE_PRIME_C(13835058055282163729),
110 BOOST_INTRUSIVE_PRIME_C(18446744073709551557)
111 #else
112 BOOST_INTRUSIVE_PRIME_C(4294967291)
113 #endif
114 };
115
116 #undef BOOST_INTRUSIVE_PRIME_C
117 #undef BOOST_INTRUSIVE_64_BIT_SIZE_T
118
119 template<int Dummy>
120 const std::size_t prime_list_holder<Dummy>::prime_list_size
121 = sizeof(prime_list)/sizeof(std::size_t);
45 122
46 struct hash_bool_flags 123 struct hash_bool_flags
47 { 124 {
48 static const std::size_t unique_keys_pos = 1u; 125 static const std::size_t unique_keys_pos = 1u;
49 static const std::size_t constant_time_size_pos = 2u; 126 static const std::size_t constant_time_size_pos = 2u;
56 namespace detail { 133 namespace detail {
57 134
58 template<class SupposedValueTraits> 135 template<class SupposedValueTraits>
59 struct get_slist_impl_from_supposed_value_traits 136 struct get_slist_impl_from_supposed_value_traits
60 { 137 {
61 typedef typename detail::get_real_value_traits 138 typedef SupposedValueTraits value_traits;
62 <SupposedValueTraits>::type real_value_traits;
63 typedef typename detail::get_node_traits 139 typedef typename detail::get_node_traits
64 <real_value_traits>::type node_traits; 140 <value_traits>::type node_traits;
65 typedef typename get_slist_impl 141 typedef typename get_slist_impl
66 <typename reduced_slist_node_traits 142 <typename reduced_slist_node_traits
67 <node_traits>::type 143 <node_traits>::type
68 >::type type; 144 >::type type;
69 }; 145 };
254 { 330 {
255 if(first_in_group){ 331 if(first_in_group){
256 if(group_algorithms::unique(first_in_group)) 332 if(group_algorithms::unique(first_in_group))
257 group_algorithms::link_after(first_in_group, n); 333 group_algorithms::link_after(first_in_group, n);
258 else{ 334 else{
259 group_algorithms::link_after(group_algorithms::node_traits::get_next(first_in_group), n); 335 group_algorithms::link_after(node_traits::get_next(first_in_group), n);
260 } 336 }
261 } 337 }
262 else{ 338 else{
263 group_algorithms::init_header(n); 339 group_algorithms::init_header(n);
264 } 340 }
273 slist_node_ptr prev; 349 slist_node_ptr prev;
274 node_ptr elem(detail::dcast_bucket_ptr<node>(i)); 350 node_ptr elem(detail::dcast_bucket_ptr<node>(i));
275 351
276 //It's the last in group if the next_node is a bucket 352 //It's the last in group if the next_node is a bucket
277 slist_node_ptr nxt(node_traits::get_next(elem)); 353 slist_node_ptr nxt(node_traits::get_next(elem));
278 bool last_in_group = (first_end_ptr <= nxt && nxt <= last_end_ptr)/* || 354 bool last_in_group = (first_end_ptr <= nxt && nxt <= last_end_ptr) ||
279 (group_traits::get_next(nxt) != elem)*/; 355 (group_traits::get_next(detail::dcast_bucket_ptr<node>(nxt)) != elem);
280 //It's the first in group if group_previous's next_node is not 356 //It's the first in group if group_previous's next_node is not
281 //itself, as group list does not link bucket 357 //itself, as group list does not link bucket
282 node_ptr prev_in_group(group_traits::get_next(elem)); 358 node_ptr prev_in_group(group_traits::get_next(elem));
283 bool first_in_group = node_traits::get_next(prev_in_group) != elem; 359 bool first_in_group = node_traits::get_next(prev_in_group) != elem;
284 360
389 //!a hash container. 465 //!a hash container.
390 template<class ValueTraitsOrHookOption> 466 template<class ValueTraitsOrHookOption>
391 struct unordered_bucket 467 struct unordered_bucket
392 : public detail::unordered_bucket_impl 468 : public detail::unordered_bucket_impl
393 <typename ValueTraitsOrHookOption:: 469 <typename ValueTraitsOrHookOption::
394 template pack<none>::proto_value_traits 470 template pack<empty>::proto_value_traits
395 > 471 >
396 {}; 472 {};
397 473
398 //!This metafunction will obtain the type of a bucket pointer 474 //!This metafunction will obtain the type of a bucket pointer
399 //!from the value_traits or hook option to be used with 475 //!from the value_traits or hook option to be used with
400 //!a hash container. 476 //!a hash container.
401 template<class ValueTraitsOrHookOption> 477 template<class ValueTraitsOrHookOption>
402 struct unordered_bucket_ptr 478 struct unordered_bucket_ptr
403 : public detail::unordered_bucket_ptr_impl 479 : public detail::unordered_bucket_ptr_impl
404 <typename ValueTraitsOrHookOption:: 480 <typename ValueTraitsOrHookOption::
405 template pack<none>::proto_value_traits 481 template pack<empty>::proto_value_traits
406 > 482 >
407 {}; 483 {};
408 484
409 //!This metafunction will obtain the type of the default bucket traits 485 //!This metafunction will obtain the type of the default bucket traits
410 //!(when the user does not specify the bucket_traits<> option) from the 486 //!(when the user does not specify the bucket_traits<> option) from the
411 //!value_traits or hook option to be used with 487 //!value_traits or hook option to be used with
412 //!a hash container. 488 //!a hash container.
413 template<class ValueTraitsOrHookOption> 489 template<class ValueTraitsOrHookOption>
414 struct unordered_default_bucket_traits 490 struct unordered_default_bucket_traits
415 { 491 {
416 typedef typename ValueTraitsOrHookOption:: 492 typedef typename ValueTraitsOrHookOption::
417 template pack<none>::proto_value_traits supposed_value_traits; 493 template pack<empty>::proto_value_traits supposed_value_traits;
418 typedef typename detail:: 494 typedef typename detail::
419 get_slist_impl_from_supposed_value_traits 495 get_slist_impl_from_supposed_value_traits
420 <supposed_value_traits>::type slist_impl; 496 <supposed_value_traits>::type slist_impl;
421 typedef detail::bucket_traits_impl 497 typedef detail::bucket_traits_impl
422 <slist_impl> implementation_defined; 498 <slist_impl> implementation_defined;
423 typedef implementation_defined type; 499 typedef implementation_defined type;
424 }; 500 };
425 501
426 struct default_bucket_traits; 502 struct default_bucket_traits;
427 503
504 //hashtable default hook traits
505 struct default_hashtable_hook_applier
506 { template <class T> struct apply{ typedef typename T::default_hashtable_hook type; }; };
507
508 template<>
509 struct is_default_hook_tag<default_hashtable_hook_applier>
510 { static const bool value = true; };
511
428 struct hashtable_defaults 512 struct hashtable_defaults
429 { 513 {
430 typedef detail::default_hashtable_hook proto_value_traits; 514 typedef default_hashtable_hook_applier proto_value_traits;
431 typedef std::size_t size_type; 515 typedef std::size_t size_type;
432 typedef void equal; 516 typedef void equal;
433 typedef void hash; 517 typedef void hash;
434 typedef default_bucket_traits bucket_traits; 518 typedef default_bucket_traits bucket_traits;
435 static const bool constant_time_size = true; 519 static const bool constant_time_size = true;
437 static const bool cache_begin = false; 521 static const bool cache_begin = false;
438 static const bool compare_hash = false; 522 static const bool compare_hash = false;
439 static const bool incremental = false; 523 static const bool incremental = false;
440 }; 524 };
441 525
442 template<class RealValueTraits, bool IsConst> 526 template<class ValueTraits, bool IsConst>
443 struct downcast_node_to_value_t 527 struct downcast_node_to_value_t
444 : public detail::node_to_value<RealValueTraits, IsConst> 528 : public detail::node_to_value<ValueTraits, IsConst>
445 { 529 {
446 typedef detail::node_to_value<RealValueTraits, IsConst> base_t; 530 typedef detail::node_to_value<ValueTraits, IsConst> base_t;
447 typedef typename base_t::result_type result_type; 531 typedef typename base_t::result_type result_type;
448 typedef RealValueTraits real_value_traits; 532 typedef ValueTraits value_traits;
449 typedef typename detail::get_slist_impl 533 typedef typename detail::get_slist_impl
450 <typename detail::reduced_slist_node_traits 534 <typename detail::reduced_slist_node_traits
451 <typename real_value_traits::node_traits>::type 535 <typename value_traits::node_traits>::type
452 >::type slist_impl; 536 >::type slist_impl;
453 typedef typename detail::add_const_if_c 537 typedef typename detail::add_const_if_c
454 <typename slist_impl::node, IsConst>::type & first_argument_type; 538 <typename slist_impl::node, IsConst>::type & first_argument_type;
455 typedef typename detail::add_const_if_c 539 typedef typename detail::add_const_if_c
456 < typename RealValueTraits::node_traits::node 540 < typename ValueTraits::node_traits::node
457 , IsConst>::type & intermediate_argument_type; 541 , IsConst>::type & intermediate_argument_type;
458 typedef typename pointer_traits 542 typedef typename pointer_traits
459 <typename RealValueTraits::pointer>:: 543 <typename ValueTraits::pointer>::
460 template rebind_pointer 544 template rebind_pointer
461 <const RealValueTraits>::type const_real_value_traits_ptr; 545 <const ValueTraits>::type const_value_traits_ptr;
462 546
463 downcast_node_to_value_t(const const_real_value_traits_ptr &ptr) 547 downcast_node_to_value_t(const const_value_traits_ptr &ptr)
464 : base_t(ptr) 548 : base_t(ptr)
465 {} 549 {}
466 550
467 result_type operator()(first_argument_type arg) const 551 result_type operator()(first_argument_type arg) const
468 { return this->base_t::operator()(static_cast<intermediate_argument_type>(arg)); } 552 { return this->base_t::operator()(static_cast<intermediate_argument_type>(arg)); }
469 }; 553 };
470 554
471 template<class F, class SlistNodePtr, class NodePtr> 555 template<class F, class SlistNodePtr, class NodePtr>
472 struct node_cast_adaptor 556 struct node_cast_adaptor
473 : private detail::ebo_functor_holder<F> 557 //Use public inheritance to avoid MSVC bugs with closures
558 : public detail::ebo_functor_holder<F>
474 { 559 {
475 typedef detail::ebo_functor_holder<F> base_t; 560 typedef detail::ebo_functor_holder<F> base_t;
476 561
477 typedef typename pointer_traits<SlistNodePtr>::element_type slist_node; 562 typedef typename pointer_traits<SlistNodePtr>::element_type slist_node;
478 typedef typename pointer_traits<NodePtr>::element_type node; 563 typedef typename pointer_traits<NodePtr>::element_type node;
495 ( hash_bool_flags::cache_begin_pos 580 ( hash_bool_flags::cache_begin_pos
496 | hash_bool_flags::constant_time_size_pos 581 | hash_bool_flags::constant_time_size_pos
497 | hash_bool_flags::incremental_pos 582 | hash_bool_flags::incremental_pos
498 ); 583 );
499 584
585 //bucket_plus_vtraits stores ValueTraits + BucketTraits
586 //this data is needed by iterators to obtain the
587 //value from the iterator and detect the bucket
500 template<class ValueTraits, class BucketTraits> 588 template<class ValueTraits, class BucketTraits>
501 struct bucket_plus_vtraits : public ValueTraits 589 struct bucket_plus_vtraits : public ValueTraits
502 { 590 {
503 typedef BucketTraits bucket_traits; 591 typedef BucketTraits bucket_traits;
504 typedef ValueTraits value_traits; 592 typedef ValueTraits value_traits;
505 593
506 static const bool external_value_traits = 594 static const bool safemode_or_autounlink = is_safe_autounlink<value_traits::link_mode>::value;
507 detail::external_value_traits_bool_is_true<ValueTraits>::value; 595
508
509 static const bool external_bucket_traits =
510 detail::external_bucket_traits_bool_is_true<bucket_traits>::value;
511
512 typedef typename detail::get_real_value_traits<ValueTraits>::type real_value_traits;
513
514 static const bool safemode_or_autounlink = is_safe_autounlink<real_value_traits::link_mode>::value;
515
516 typedef typename detail::eval_if_c
517 < external_bucket_traits
518 , detail::eval_bucket_traits<bucket_traits>
519 , detail::identity<bucket_traits>
520 >::type real_bucket_traits;
521 typedef typename 596 typedef typename
522 detail::get_slist_impl_from_supposed_value_traits 597 detail::get_slist_impl_from_supposed_value_traits
523 <real_value_traits>::type slist_impl; 598 <value_traits>::type slist_impl;
599 typedef typename value_traits::node_traits node_traits;
600 typedef unordered_group_adapter<node_traits> group_traits;
601 typedef typename slist_impl::iterator siterator;
602 typedef typename slist_impl::size_type size_type;
603 typedef detail::bucket_impl<slist_impl> bucket_type;
604 typedef detail::group_functions<node_traits> group_functions_t;
605 typedef typename slist_impl::node_algorithms node_algorithms;
606 typedef typename slist_impl::node_ptr slist_node_ptr;
607 typedef typename node_traits::node_ptr node_ptr;
608 typedef typename node_traits::node node;
609 typedef typename value_traits::value_type value_type;
610 typedef circular_slist_algorithms<group_traits> group_algorithms;
611 typedef typename pointer_traits
612 <typename value_traits::pointer>::
613 template rebind_pointer
614 <const value_traits>::type const_value_traits_ptr;
615 typedef typename pointer_traits
616 <typename value_traits::pointer>::
617 template rebind_pointer
618 <const bucket_plus_vtraits>::type const_bucket_value_traits_ptr;
619 typedef typename detail::unordered_bucket_ptr_impl
620 <value_traits>::type bucket_ptr;
621 typedef detail::bool_<detail::optimize_multikey_is_true
622 <node_traits>::value> optimize_multikey_t;
524 623
525 template<class BucketTraitsType> 624 template<class BucketTraitsType>
526 bucket_plus_vtraits(const ValueTraits &val_traits, BOOST_FWD_REF(BucketTraitsType) b_traits) 625 bucket_plus_vtraits(const ValueTraits &val_traits, BOOST_FWD_REF(BucketTraitsType) b_traits)
527 : ValueTraits(val_traits), bucket_traits_(::boost::forward<BucketTraitsType>(b_traits)) 626 : ValueTraits(val_traits), bucket_traits_(::boost::forward<BucketTraitsType>(b_traits))
528 {} 627 {}
529 628
530 bucket_plus_vtraits & operator =(const bucket_plus_vtraits &x) 629 bucket_plus_vtraits & operator =(const bucket_plus_vtraits &x)
531 { 630 { bucket_traits_ = x.bucket_traits_; return *this; }
532 bucket_traits_ = x.bucket_traits_; 631
533 return *this; 632 const_value_traits_ptr priv_value_traits_ptr() const
534 } 633 { return pointer_traits<const_value_traits_ptr>::pointer_to(this->priv_value_traits()); }
535
536 //real_value_traits
537 //
538 const real_value_traits &priv_real_value_traits(detail::false_) const
539 { return *this; }
540
541 const real_value_traits &priv_real_value_traits(detail::true_) const
542 { return this->get_value_traits(*this); }
543
544 real_value_traits &priv_real_value_traits(detail::false_)
545 { return *this; }
546
547 real_value_traits &priv_real_value_traits(detail::true_)
548 { return this->get_value_traits(*this); }
549
550 const real_value_traits &priv_real_value_traits() const
551 { return this->priv_real_value_traits(detail::bool_<external_value_traits>()); }
552
553 real_value_traits &priv_real_value_traits()
554 { return this->priv_real_value_traits(detail::bool_<external_value_traits>()); }
555
556 typedef typename pointer_traits<typename real_value_traits::pointer>::
557 template rebind_pointer<const real_value_traits>::type const_real_value_traits_ptr;
558
559 const_real_value_traits_ptr real_value_traits_ptr() const
560 { return pointer_traits<const_real_value_traits_ptr>::pointer_to(this->priv_real_value_traits()); }
561
562 //real_bucket_traits
563 //
564 const real_bucket_traits &priv_real_bucket_traits(detail::false_) const
565 { return this->bucket_traits_; }
566
567 const real_bucket_traits &priv_real_bucket_traits(detail::true_) const
568 { return this->bucket_traits_.get_bucket_traits(*this); }
569
570 real_bucket_traits &priv_real_bucket_traits(detail::false_)
571 { return bucket_traits_; }
572
573 real_bucket_traits &priv_real_bucket_traits(detail::true_)
574 { return this->get_bucket_traits(*this); }
575
576 const real_bucket_traits &priv_real_bucket_traits() const
577 { return this->priv_real_bucket_traits(detail::bool_<external_bucket_traits>()); }
578
579 real_bucket_traits &priv_real_bucket_traits()
580 { return this->priv_real_bucket_traits(detail::bool_<external_bucket_traits>()); }
581 634
582 //bucket_value_traits 635 //bucket_value_traits
583 // 636 //
584 const bucket_plus_vtraits &get_bucket_value_traits() const 637 const bucket_plus_vtraits &get_bucket_value_traits() const
585 { return *this; } 638 { return *this; }
586 639
587 bucket_plus_vtraits &get_bucket_value_traits() 640 bucket_plus_vtraits &get_bucket_value_traits()
588 { return *this; } 641 { return *this; }
589 642
590 typedef typename pointer_traits<typename real_value_traits::pointer>::
591 template rebind_pointer<const bucket_plus_vtraits>::type const_bucket_value_traits_ptr;
592
593 const_bucket_value_traits_ptr bucket_value_traits_ptr() const 643 const_bucket_value_traits_ptr bucket_value_traits_ptr() const
594 { return pointer_traits<const_bucket_value_traits_ptr>::pointer_to(this->get_bucket_value_traits()); } 644 { return pointer_traits<const_bucket_value_traits_ptr>::pointer_to(this->get_bucket_value_traits()); }
595 645
596 //value traits 646 //value traits
597 // 647 //
607 { return this->bucket_traits_; } 657 { return this->bucket_traits_; }
608 658
609 bucket_traits &priv_bucket_traits() 659 bucket_traits &priv_bucket_traits()
610 { return this->bucket_traits_; } 660 { return this->bucket_traits_; }
611 661
612 //operations 662 //bucket operations
613 typedef typename detail::unordered_bucket_ptr_impl<real_value_traits>::type bucket_ptr;
614
615 bucket_ptr priv_bucket_pointer() const 663 bucket_ptr priv_bucket_pointer() const
616 { return this->priv_real_bucket_traits().bucket_begin(); } 664 { return this->priv_bucket_traits().bucket_begin(); }
617 665
618 typename slist_impl::size_type priv_bucket_count() const 666 typename slist_impl::size_type priv_bucket_count() const
619 { return this->priv_real_bucket_traits().bucket_count(); } 667 { return this->priv_bucket_traits().bucket_count(); }
620 668
621 bucket_ptr priv_invalid_bucket() const 669 bucket_ptr priv_invalid_bucket() const
622 { 670 {
623 const real_bucket_traits &rbt = this->priv_real_bucket_traits(); 671 const bucket_traits &rbt = this->priv_bucket_traits();
624 return rbt.bucket_begin() + rbt.bucket_count(); 672 return rbt.bucket_begin() + rbt.bucket_count();
625 } 673 }
626
627 typedef typename real_value_traits::node_traits node_traits;
628 typedef unordered_group_adapter<node_traits> group_traits;
629 typedef typename slist_impl::iterator siterator;
630 typedef typename slist_impl::size_type size_type;
631 typedef detail::bucket_impl<slist_impl> bucket_type;
632 typedef detail::group_functions<node_traits> group_functions_t;
633 typedef typename slist_impl::node_algorithms node_algorithms;
634 typedef typename slist_impl::node_ptr slist_node_ptr;
635 typedef typename node_traits::node_ptr node_ptr;
636 typedef typename node_traits::node node;
637 typedef typename real_value_traits::value_type value_type;
638 typedef circular_slist_algorithms<group_traits> group_algorithms;
639
640
641 /*
642 siterator priv_invalid_local_it() const 674 siterator priv_invalid_local_it() const
643 { return this->priv_invalid_bucket()->end(); } 675 { return this->priv_bucket_traits().bucket_begin()->before_begin(); }
644 */ 676
645 siterator priv_invalid_local_it() const
646 {
647 return this->priv_real_bucket_traits().bucket_begin()->before_begin();
648 }
649
650 ///
651 static siterator priv_get_last(bucket_type &b, detail::true_) //optimize multikey 677 static siterator priv_get_last(bucket_type &b, detail::true_) //optimize multikey
652 { 678 {
653 //First find the last node of p's group. 679 //First find the last node of p's group.
654 //This requires checking the first node of the next group or 680 //This requires checking the first node of the next group or
655 //the bucket node. 681 //the bucket node.
729 } 755 }
730 756
731 static std::size_t priv_stored_hash(slist_node_ptr n, detail::true_) //store_hash 757 static std::size_t priv_stored_hash(slist_node_ptr n, detail::true_) //store_hash
732 { return node_traits::get_hash(detail::dcast_bucket_ptr<node>(n)); } 758 { return node_traits::get_hash(detail::dcast_bucket_ptr<node>(n)); }
733 759
734 static std::size_t priv_stored_hash(slist_node_ptr, detail::false_) //NO store_hash 760 static std::size_t priv_stored_hash(slist_node_ptr, detail::false_) //NO store_hash (This should never be called)
735 { 761 { BOOST_INTRUSIVE_INVARIANT_ASSERT(0); return 0; }
736 //This code should never be reached!
737 BOOST_INTRUSIVE_INVARIANT_ASSERT(0);
738 return 0;
739 }
740 762
741 node &priv_value_to_node(value_type &v) 763 node &priv_value_to_node(value_type &v)
742 { return *this->priv_real_value_traits().to_node_ptr(v); } 764 { return *this->priv_value_traits().to_node_ptr(v); }
743 765
744 const node &priv_value_to_node(const value_type &v) const 766 const node &priv_value_to_node(const value_type &v) const
745 { return *this->priv_real_value_traits().to_node_ptr(v); } 767 { return *this->priv_value_traits().to_node_ptr(v); }
746 768
747 value_type &priv_value_from_slist_node(slist_node_ptr n) 769 value_type &priv_value_from_slist_node(slist_node_ptr n)
748 { return *this->priv_real_value_traits().to_value_ptr(detail::dcast_bucket_ptr<node>(n)); } 770 { return *this->priv_value_traits().to_value_ptr(detail::dcast_bucket_ptr<node>(n)); }
749 771
750 const value_type &priv_value_from_slist_node(slist_node_ptr n) const 772 const value_type &priv_value_from_slist_node(slist_node_ptr n) const
751 { return *this->priv_real_value_traits().to_value_ptr(detail::dcast_bucket_ptr<node>(n)); } 773 { return *this->priv_value_traits().to_value_ptr(detail::dcast_bucket_ptr<node>(n)); }
774
775 void priv_clear_buckets(const bucket_ptr buckets_ptr, const size_type bucket_cnt)
776 {
777 bucket_ptr buckets_it = buckets_ptr;
778 for(size_type bucket_i = 0; bucket_i != bucket_cnt; ++buckets_it, ++bucket_i){
779 if(safemode_or_autounlink){
780 bucket_plus_vtraits::priv_clear_group_nodes(*buckets_it, optimize_multikey_t());
781 buckets_it->clear_and_dispose(detail::init_disposer<node_algorithms>());
782 }
783 else{
784 buckets_it->clear();
785 }
786 }
787 }
752 788
753 bucket_traits bucket_traits_; 789 bucket_traits bucket_traits_;
754 }; 790 };
755 791
792 template<class Hash, class T>
793 struct get_hash
794 {
795 typedef Hash type;
796 };
797
798 template<class T>
799 struct get_hash<void, T>
800 {
801 typedef ::boost::hash<T> type;
802 };
803
804 //bucket_hash_t
805 //Stores bucket_plus_vtraits plust the hash function
756 template<class VoidOrKeyHash, class ValueTraits, class BucketTraits> 806 template<class VoidOrKeyHash, class ValueTraits, class BucketTraits>
757 struct bucket_hash_t 807 struct bucket_hash_t
808 //Use public inheritance to avoid MSVC bugs with closures
758 : public detail::ebo_functor_holder 809 : public detail::ebo_functor_holder
759 <typename get_hash< VoidOrKeyHash 810 <typename get_hash< VoidOrKeyHash
760 , typename bucket_plus_vtraits<ValueTraits,BucketTraits>::real_value_traits::value_type 811 , typename bucket_plus_vtraits<ValueTraits,BucketTraits>::value_traits::value_type
761 >::type 812 >::type
762 > 813 >
763 , bucket_plus_vtraits<ValueTraits, BucketTraits>
764 { 814 {
765 typedef typename bucket_plus_vtraits<ValueTraits,BucketTraits>::real_value_traits real_value_traits; 815 typedef typename bucket_plus_vtraits<ValueTraits,BucketTraits>::value_traits value_traits;
766 typedef typename real_value_traits::value_type value_type; 816 typedef typename value_traits::value_type value_type;
767 typedef typename real_value_traits::node_traits node_traits; 817 typedef typename value_traits::node_traits node_traits;
768 typedef typename get_hash< VoidOrKeyHash, value_type>::type hasher; 818 typedef typename get_hash< VoidOrKeyHash, value_type>::type hasher;
769 typedef BucketTraits bucket_traits; 819 typedef BucketTraits bucket_traits;
770 typedef bucket_plus_vtraits<ValueTraits, BucketTraits> bucket_plus_vtraits_t; 820 typedef bucket_plus_vtraits<ValueTraits, BucketTraits> bucket_plus_vtraits_t;
771 821
772 template<class BucketTraitsType> 822 template<class BucketTraitsType>
773 bucket_hash_t(const ValueTraits &val_traits, BOOST_FWD_REF(BucketTraitsType) b_traits, const hasher & h) 823 bucket_hash_t(const ValueTraits &val_traits, BOOST_FWD_REF(BucketTraitsType) b_traits, const hasher & h)
774 : detail::ebo_functor_holder<hasher>(h), bucket_plus_vtraits_t(val_traits, ::boost::forward<BucketTraitsType>(b_traits)) 824 : detail::ebo_functor_holder<hasher>(h), internal(val_traits, ::boost::forward<BucketTraitsType>(b_traits))
775 {} 825 {}
776 826
777 const hasher &priv_hasher() const 827 const hasher &priv_hasher() const
778 { return this->detail::ebo_functor_holder<hasher>::get(); } 828 { return this->detail::ebo_functor_holder<hasher>::get(); }
779 829
780 hasher &priv_hasher() 830 hasher &priv_hasher()
781 { return this->detail::ebo_functor_holder<hasher>::get(); } 831 { return this->detail::ebo_functor_holder<hasher>::get(); }
782 832
783 std::size_t priv_stored_or_compute_hash(const value_type &v, detail::true_) const //For store_hash == true 833 std::size_t priv_stored_or_compute_hash(const value_type &v, detail::true_) const //For store_hash == true
784 { return node_traits::get_hash(this->priv_real_value_traits().to_node_ptr(v)); } 834 { return node_traits::get_hash(this->internal.priv_value_traits().to_node_ptr(v)); }
785 835
786 std::size_t priv_stored_or_compute_hash(const value_type &v, detail::false_) const //For store_hash == false 836 std::size_t priv_stored_or_compute_hash(const value_type &v, detail::false_) const //For store_hash == false
787 { return this->priv_hasher()(v); } 837 { return this->priv_hasher()(v); }
838
839 bucket_plus_vtraits_t internal; //4
788 }; 840 };
789 841
842
843 template<class EqualTo, class T>
844 struct get_equal_to
845 {
846 typedef EqualTo type;
847 };
848
849 template<class T>
850 struct get_equal_to<void, T>
851 {
852 typedef ::std::equal_to<T> type;
853 };
854
855
856 //bucket_hash_equal_t
857 //Stores bucket_hash_t and the equality function when the first
858 //non-empty bucket shall not be cached.
790 template<class VoidOrKeyHash, class VoidOrKeyEqual, class ValueTraits, class BucketTraits, bool> 859 template<class VoidOrKeyHash, class VoidOrKeyEqual, class ValueTraits, class BucketTraits, bool>
791 struct bucket_hash_equal_t 860 struct bucket_hash_equal_t
861 //Use public inheritance to avoid MSVC bugs with closures
792 : public detail::ebo_functor_holder //equal 862 : public detail::ebo_functor_holder //equal
793 <typename get_equal_to< VoidOrKeyEqual 863 <typename get_equal_to< VoidOrKeyEqual
794 , typename bucket_plus_vtraits<ValueTraits,BucketTraits>::real_value_traits::value_type 864 , typename bucket_plus_vtraits<ValueTraits,BucketTraits>::value_traits::value_type
795 >::type 865 >::type
796 > 866 >
797 , bucket_hash_t<VoidOrKeyHash, ValueTraits, BucketTraits>
798 { 867 {
799 typedef bucket_hash_t<VoidOrKeyHash, ValueTraits, BucketTraits> bucket_hash_type; 868 typedef bucket_hash_t<VoidOrKeyHash, ValueTraits, BucketTraits> bucket_hash_type;
800 typedef typename bucket_plus_vtraits<ValueTraits,BucketTraits>::real_value_traits real_value_traits; 869 typedef bucket_plus_vtraits<ValueTraits,BucketTraits> bucket_plus_vtraits_t;
870 typedef typename bucket_plus_vtraits_t::value_traits value_traits;
801 typedef typename get_equal_to< VoidOrKeyEqual 871 typedef typename get_equal_to< VoidOrKeyEqual
802 , typename real_value_traits::value_type 872 , typename value_traits::value_type
803 >::type value_equal; 873 >::type value_equal;
804 typedef typename bucket_hash_type::hasher hasher; 874 typedef typename bucket_hash_type::hasher hasher;
805 typedef BucketTraits bucket_traits; 875 typedef BucketTraits bucket_traits;
806 typedef bucket_hash_t<VoidOrKeyHash, ValueTraits, BucketTraits> buckethash_t; 876 typedef typename bucket_plus_vtraits_t::slist_impl slist_impl;
807 typedef typename bucket_hash_type::real_bucket_traits real_bucket_traits; 877 typedef typename slist_impl::size_type size_type;
808 typedef typename bucket_hash_type::slist_impl slist_impl; 878 typedef typename slist_impl::iterator siterator;
809 typedef typename slist_impl::size_type size_type; 879 typedef detail::bucket_impl<slist_impl> bucket_type;
810 typedef typename slist_impl::iterator siterator; 880 typedef typename detail::unordered_bucket_ptr_impl<value_traits>::type bucket_ptr;
811 typedef detail::bucket_impl<slist_impl> bucket_type;
812 typedef typename detail::unordered_bucket_ptr_impl<real_value_traits>::type bucket_ptr;
813 881
814 template<class BucketTraitsType> 882 template<class BucketTraitsType>
815 bucket_hash_equal_t(const ValueTraits &val_traits, BOOST_FWD_REF(BucketTraitsType) b_traits, const hasher & h, const value_equal &e) 883 bucket_hash_equal_t(const ValueTraits &val_traits, BOOST_FWD_REF(BucketTraitsType) b_traits, const hasher & h, const value_equal &e)
816 : detail::ebo_functor_holder<value_equal>(e) 884 : detail::ebo_functor_holder<value_equal>(e)
817 , buckethash_t(val_traits, ::boost::forward<BucketTraitsType>(b_traits), h) 885 , internal(val_traits, ::boost::forward<BucketTraitsType>(b_traits), h)
818 {} 886 {}
819 887
820 bucket_ptr priv_get_cache() 888 bucket_ptr priv_get_cache()
821 { return this->priv_bucket_pointer(); } 889 { return this->internal.internal.priv_bucket_pointer(); }
822 890
823 void priv_set_cache(const bucket_ptr &) 891 void priv_set_cache(const bucket_ptr &)
824 {} 892 {}
825 893
826 size_type priv_get_cache_bucket_num() 894 size_type priv_get_cache_bucket_num()
833 {} 901 {}
834 902
835 siterator priv_begin() const 903 siterator priv_begin() const
836 { 904 {
837 size_type n = 0; 905 size_type n = 0;
838 size_type bucket_cnt = this->priv_bucket_count(); 906 size_type bucket_cnt = this->internal.internal.priv_bucket_count();
839 for (n = 0; n < bucket_cnt; ++n){ 907 for (n = 0; n < bucket_cnt; ++n){
840 bucket_type &b = this->priv_bucket_pointer()[n]; 908 bucket_type &b = this->internal.internal.priv_bucket_pointer()[n];
841 if(!b.empty()){ 909 if(!b.empty()){
842 return b.begin(); 910 return b.begin();
843 } 911 }
844 } 912 }
845 return this->priv_invalid_local_it(); 913 return this->internal.internal.priv_invalid_local_it();
846 } 914 }
847 915
848 void priv_insertion_update_cache(size_type) 916 void priv_insertion_update_cache(size_type)
849 {} 917 {}
850 918
857 const value_equal &priv_equal() const 925 const value_equal &priv_equal() const
858 { return this->detail::ebo_functor_holder<value_equal>::get(); } 926 { return this->detail::ebo_functor_holder<value_equal>::get(); }
859 927
860 value_equal &priv_equal() 928 value_equal &priv_equal()
861 { return this->detail::ebo_functor_holder<value_equal>::get(); } 929 { return this->detail::ebo_functor_holder<value_equal>::get(); }
930
931 bucket_hash_t<VoidOrKeyHash, ValueTraits, BucketTraits> internal; //3
862 }; 932 };
863 933
934 //bucket_hash_equal_t
935 //Stores bucket_hash_t and the equality function when the first
936 //non-empty bucket shall be cached.
864 template<class VoidOrKeyHash, class VoidOrKeyEqual, class ValueTraits, class BucketTraits> //cache_begin == true version 937 template<class VoidOrKeyHash, class VoidOrKeyEqual, class ValueTraits, class BucketTraits> //cache_begin == true version
865 struct bucket_hash_equal_t<VoidOrKeyHash, VoidOrKeyEqual, ValueTraits, BucketTraits, true> 938 struct bucket_hash_equal_t<VoidOrKeyHash, VoidOrKeyEqual, ValueTraits, BucketTraits, true>
939 //Use public inheritance to avoid MSVC bugs with closures
866 : public detail::ebo_functor_holder //equal 940 : public detail::ebo_functor_holder //equal
867 <typename get_equal_to< VoidOrKeyEqual 941 <typename get_equal_to< VoidOrKeyEqual
868 , typename bucket_plus_vtraits<ValueTraits,BucketTraits>::real_value_traits::value_type 942 , typename bucket_plus_vtraits<ValueTraits,BucketTraits>::value_traits::value_type
869 >::type 943 >::type
870 > 944 >
871 , public bucket_hash_t<VoidOrKeyHash, ValueTraits, BucketTraits>
872 { 945 {
873 typedef bucket_hash_t<VoidOrKeyHash, ValueTraits, BucketTraits> bucket_hash_type; 946 typedef bucket_plus_vtraits<ValueTraits, BucketTraits> bucket_plus_vtraits_t;
874 typedef typename get_equal_to< VoidOrKeyEqual 947 typedef bucket_hash_t<VoidOrKeyHash, ValueTraits, BucketTraits> bucket_hash_type;
875 , typename bucket_plus_vtraits<ValueTraits,BucketTraits>::real_value_traits::value_type 948 typedef typename bucket_plus_vtraits
876 >::type value_equal; 949 <ValueTraits,BucketTraits>::value_traits value_traits;
877 typedef typename bucket_hash_type::hasher hasher; 950 typedef typename get_equal_to
878 typedef BucketTraits bucket_traits; 951 < VoidOrKeyEqual
879 typedef typename bucket_hash_type::slist_impl::size_type size_type; 952 , typename value_traits::value_type>::type value_equal;
880 typedef typename bucket_hash_type::slist_impl::iterator siterator; 953 typedef typename bucket_hash_type::hasher hasher;
954 typedef BucketTraits bucket_traits;
955 typedef typename bucket_plus_vtraits_t::slist_impl::size_type size_type;
956 typedef typename bucket_plus_vtraits_t::slist_impl::iterator siterator;
881 957
882 template<class BucketTraitsType> 958 template<class BucketTraitsType>
883 bucket_hash_equal_t(const ValueTraits &val_traits, BOOST_FWD_REF(BucketTraitsType) b_traits, const hasher & h, const value_equal &e) 959 bucket_hash_equal_t(const ValueTraits &val_traits, BOOST_FWD_REF(BucketTraitsType) b_traits, const hasher & h, const value_equal &e)
884 : detail::ebo_functor_holder<value_equal>(e) 960 : detail::ebo_functor_holder<value_equal>(e)
885 , bucket_hash_type(val_traits, ::boost::forward<BucketTraitsType>(b_traits), h) 961 , internal(val_traits, ::boost::forward<BucketTraitsType>(b_traits), h)
886 {} 962 {}
887 963
888 typedef typename detail::unordered_bucket_ptr_impl 964 typedef typename detail::unordered_bucket_ptr_impl
889 <typename bucket_hash_type::real_value_traits>::type bucket_ptr; 965 <typename bucket_hash_type::value_traits>::type bucket_ptr;
890 966
891 bucket_ptr &priv_get_cache() 967 bucket_ptr &priv_get_cache()
892 { return cached_begin_; } 968 { return cached_begin_; }
893 969
894 const bucket_ptr &priv_get_cache() const 970 const bucket_ptr &priv_get_cache() const
896 972
897 void priv_set_cache(const bucket_ptr &p) 973 void priv_set_cache(const bucket_ptr &p)
898 { cached_begin_ = p; } 974 { cached_begin_ = p; }
899 975
900 std::size_t priv_get_cache_bucket_num() 976 std::size_t priv_get_cache_bucket_num()
901 { return this->cached_begin_ - this->priv_bucket_pointer(); } 977 { return this->cached_begin_ - this->internal.internal.priv_bucket_pointer(); }
902 978
903 void priv_initialize_cache() 979 void priv_initialize_cache()
904 { this->cached_begin_ = this->priv_invalid_bucket(); } 980 { this->cached_begin_ = this->internal.internal.priv_invalid_bucket(); }
905 981
906 void priv_swap_cache(bucket_hash_equal_t &other) 982 void priv_swap_cache(bucket_hash_equal_t &other)
907 { 983 {
908 std::swap(this->cached_begin_, other.cached_begin_); 984 ::boost::adl_move_swap(this->cached_begin_, other.cached_begin_);
909 } 985 }
910 986
911 siterator priv_begin() const 987 siterator priv_begin() const
912 { 988 {
913 if(this->cached_begin_ == this->priv_invalid_bucket()){ 989 if(this->cached_begin_ == this->internal.internal.priv_invalid_bucket()){
914 return this->priv_invalid_local_it(); 990 return this->internal.internal.priv_invalid_local_it();
915 } 991 }
916 else{ 992 else{
917 return this->cached_begin_->begin(); 993 return this->cached_begin_->begin();
918 } 994 }
919 } 995 }
920 996
921 void priv_insertion_update_cache(size_type insertion_bucket) 997 void priv_insertion_update_cache(size_type insertion_bucket)
922 { 998 {
923 bucket_ptr p = this->priv_bucket_pointer() + insertion_bucket; 999 bucket_ptr p = this->internal.internal.priv_bucket_pointer() + insertion_bucket;
924 if(p < this->cached_begin_){ 1000 if(p < this->cached_begin_){
925 this->cached_begin_ = p; 1001 this->cached_begin_ = p;
926 } 1002 }
927 } 1003 }
928 1004
935 void priv_erasure_update_cache_range(size_type first_bucket_num, size_type last_bucket_num) 1011 void priv_erasure_update_cache_range(size_type first_bucket_num, size_type last_bucket_num)
936 { 1012 {
937 //If the last bucket is the end, the cache must be updated 1013 //If the last bucket is the end, the cache must be updated
938 //to the last position if all 1014 //to the last position if all
939 if(this->priv_get_cache_bucket_num() == first_bucket_num && 1015 if(this->priv_get_cache_bucket_num() == first_bucket_num &&
940 this->priv_bucket_pointer()[first_bucket_num].empty() ){ 1016 this->internal.internal.priv_bucket_pointer()[first_bucket_num].empty() ){
941 this->priv_set_cache(this->priv_bucket_pointer() + last_bucket_num); 1017 this->priv_set_cache(this->internal.internal.priv_bucket_pointer() + last_bucket_num);
942 this->priv_erasure_update_cache(); 1018 this->priv_erasure_update_cache();
943 } 1019 }
944 } 1020 }
945 1021
946 void priv_erasure_update_cache() 1022 void priv_erasure_update_cache()
947 { 1023 {
948 if(this->cached_begin_ != this->priv_invalid_bucket()){ 1024 if(this->cached_begin_ != this->internal.internal.priv_invalid_bucket()){
949 size_type current_n = this->priv_get_cache() - this->priv_bucket_pointer(); 1025 size_type current_n = this->priv_get_cache() - this->internal.internal.priv_bucket_pointer();
950 for( const size_type num_buckets = this->priv_bucket_count() 1026 for( const size_type num_buckets = this->internal.internal.priv_bucket_count()
951 ; current_n < num_buckets 1027 ; current_n < num_buckets
952 ; ++current_n, ++this->priv_get_cache()){ 1028 ; ++current_n, ++this->priv_get_cache()){
953 if(!this->priv_get_cache()->empty()){ 1029 if(!this->priv_get_cache()->empty()){
954 return; 1030 return;
955 } 1031 }
956 } 1032 }
957 this->priv_initialize_cache(); 1033 this->priv_initialize_cache();
958 } 1034 }
959 } 1035 }
960 1036
961 private:
962 bucket_ptr cached_begin_; 1037 bucket_ptr cached_begin_;
1038 bucket_hash_t<VoidOrKeyHash, ValueTraits, BucketTraits> internal; //2
963 }; 1039 };
964 1040
1041 //hashdata_internal
1042 //Stores bucket_hash_equal_t and split_traits
965 template<class SizeType, std::size_t BoolFlags, class VoidOrKeyHash, class VoidOrKeyEqual, class ValueTraits, class BucketTraits> 1043 template<class SizeType, std::size_t BoolFlags, class VoidOrKeyHash, class VoidOrKeyEqual, class ValueTraits, class BucketTraits>
966 struct hashdata_internal 1044 struct hashdata_internal
967 : public detail::size_holder< 0 != (BoolFlags & hash_bool_flags::incremental_pos), SizeType, int> //split_traits 1045 : public detail::size_holder< 0 != (BoolFlags & hash_bool_flags::incremental_pos), SizeType, int> //split_traits
968 , public bucket_hash_equal_t
969 < VoidOrKeyHash, VoidOrKeyEqual, ValueTraits, BucketTraits
970 , 0 != (BoolFlags & hash_bool_flags::cache_begin_pos)
971 >
972 { 1046 {
973 typedef bucket_hash_equal_t 1047 typedef bucket_hash_equal_t
974 < VoidOrKeyHash, VoidOrKeyEqual, ValueTraits, BucketTraits 1048 < VoidOrKeyHash, VoidOrKeyEqual
1049 , ValueTraits, BucketTraits
975 , 0 != (BoolFlags & hash_bool_flags::cache_begin_pos) 1050 , 0 != (BoolFlags & hash_bool_flags::cache_begin_pos)
976 > bucket_hash_equal_type; 1051 > internal_type;
977 1052 typedef typename internal_type::value_equal value_equal;
978 typedef typename bucket_hash_equal_type::value_equal value_equal; 1053 typedef typename internal_type::hasher hasher;
979 typedef typename bucket_hash_equal_type::hasher hasher; 1054 typedef bucket_plus_vtraits<ValueTraits,BucketTraits> bucket_plus_vtraits_t;
980 typedef bucket_plus_vtraits<ValueTraits,BucketTraits> bucket_plus_vtraits_t; 1055 typedef typename bucket_plus_vtraits_t::size_type size_type;
981 typedef typename bucket_plus_vtraits_t::size_type size_type; 1056 typedef typename bucket_plus_vtraits_t::bucket_ptr bucket_ptr;
982 typedef typename bucket_plus_vtraits_t::bucket_ptr bucket_ptr; 1057 typedef detail::size_holder
983 static const bool optimize_multikey 1058 <0 != (BoolFlags & hash_bool_flags::incremental_pos)
984 = detail::optimize_multikey_is_true<typename bucket_plus_vtraits_t::real_value_traits::node_traits>::value; 1059 , SizeType, int> split_traits;
985 1060 typedef typename bucket_plus_vtraits_t::
986 typedef detail::bool_<optimize_multikey> optimize_multikey_t; 1061 value_traits::node_traits node_traits;
1062 typedef detail::bool_<detail::optimize_multikey_is_true
1063 <node_traits>::value> optimize_multikey_t;
987 1064
988 template<class BucketTraitsType> 1065 template<class BucketTraitsType>
989 hashdata_internal(const ValueTraits &val_traits, BOOST_FWD_REF(BucketTraitsType) b_traits, const hasher & h, const value_equal &e) 1066 hashdata_internal( const ValueTraits &val_traits, BOOST_FWD_REF(BucketTraitsType) b_traits
990 : bucket_hash_equal_type(val_traits, ::boost::forward<BucketTraitsType>(b_traits), h, e) 1067 , const hasher & h, const value_equal &e)
1068 : internal(val_traits, ::boost::forward<BucketTraitsType>(b_traits), h, e)
991 {} 1069 {}
992
993 typedef detail::size_holder
994 <0 != (BoolFlags & hash_bool_flags::incremental_pos), SizeType, int> split_traits;
995 1070
996 split_traits &priv_split_traits() 1071 split_traits &priv_split_traits()
997 { return *this; } 1072 { return *this; }
998 1073
999 const split_traits &priv_split_traits() const 1074 const split_traits &priv_split_traits() const
1000 { return *this; } 1075 { return *this; }
1076
1077 ~hashdata_internal()
1078 { this->priv_clear_buckets(); }
1079
1080 void priv_clear_buckets()
1081 {
1082 this->internal.internal.internal.priv_clear_buckets
1083 ( this->internal.priv_get_cache()
1084 , this->internal.internal.internal.priv_bucket_count()
1085 - (this->internal.priv_get_cache()
1086 - this->internal.internal.internal.priv_bucket_pointer()));
1087 }
1088
1089 void priv_clear_buckets_and_cache()
1090 {
1091 this->priv_clear_buckets();
1092 this->internal.priv_initialize_cache();
1093 }
1094
1095 void priv_initialize_buckets_and_cache()
1096 {
1097 this->internal.internal.internal.priv_clear_buckets
1098 ( this->internal.internal.internal.priv_bucket_pointer()
1099 , this->internal.internal.internal.priv_bucket_count());
1100 this->internal.priv_initialize_cache();
1101 }
1102
1103 internal_type internal; //2
1001 }; 1104 };
1002 1105
1106 //hashtable_data_t
1107 //Stores hashdata_internal and size_traits
1003 template<class SizeType, std::size_t BoolFlags, class VoidOrKeyHash, class VoidOrKeyEqual, class ValueTraits, class BucketTraits> 1108 template<class SizeType, std::size_t BoolFlags, class VoidOrKeyHash, class VoidOrKeyEqual, class ValueTraits, class BucketTraits>
1004 struct hashtable_data_t 1109 struct hashtable_data_t
1005 : public detail::size_holder< 0 != (BoolFlags & hash_bool_flags::constant_time_size_pos), SizeType> //size_traits 1110 : public detail::size_holder
1006 , public hashdata_internal 1111 < 0 != (BoolFlags & hash_bool_flags::constant_time_size_pos), SizeType> //size_traits
1007 < SizeType, BoolFlags & (hash_bool_flags::incremental_pos | hash_bool_flags::cache_begin_pos)
1008 , VoidOrKeyHash, VoidOrKeyEqual, ValueTraits, BucketTraits>
1009 { 1112 {
1010 static const std::size_t bool_flags = BoolFlags;
1011 typedef detail::size_holder 1113 typedef detail::size_holder
1012 < 0 != (BoolFlags & hash_bool_flags::constant_time_size_pos) 1114 < 0 != (BoolFlags & hash_bool_flags::constant_time_size_pos)
1013 , SizeType> size_traits; 1115 , SizeType> size_traits;
1014
1015 typedef hashdata_internal 1116 typedef hashdata_internal
1016 < SizeType, BoolFlags & (hash_bool_flags::incremental_pos | hash_bool_flags::cache_begin_pos) 1117 < SizeType
1017 , VoidOrKeyHash, VoidOrKeyEqual, ValueTraits, BucketTraits> internal_type; 1118 , BoolFlags & (hash_bool_flags::incremental_pos | hash_bool_flags::cache_begin_pos)
1018 1119 , VoidOrKeyHash, VoidOrKeyEqual
1019 typedef ValueTraits value_traits; 1120 , ValueTraits, BucketTraits> internal_type;
1020 typedef typename internal_type::value_equal value_equal; 1121 typedef ValueTraits value_traits;
1021 typedef typename internal_type::hasher hasher; 1122 typedef typename internal_type::value_equal value_equal;
1022 typedef BucketTraits bucket_traits; 1123 typedef typename internal_type::hasher hasher;
1124 typedef BucketTraits bucket_traits;
1023 typedef bucket_plus_vtraits 1125 typedef bucket_plus_vtraits
1024 <ValueTraits,BucketTraits> bucket_plus_vtraits_t; 1126 <ValueTraits,BucketTraits> bucket_plus_vtraits_t;
1025
1026 static const bool external_value_traits =
1027 detail::external_value_traits_bool_is_true<ValueTraits>::value;
1028 static const bool external_bucket_traits = bucket_plus_vtraits_t::external_bucket_traits;
1029
1030 typedef typename bucket_plus_vtraits_t::real_value_traits real_value_traits;
1031 typedef typename bucket_plus_vtraits_t::real_bucket_traits real_bucket_traits;
1032
1033 size_traits &priv_size_traits()
1034 { return *this; }
1035
1036 const size_traits &priv_size_traits() const
1037 { return *this; }
1038 1127
1039 template<class BucketTraitsType> 1128 template<class BucketTraitsType>
1040 hashtable_data_t( BOOST_FWD_REF(BucketTraitsType) b_traits, const hasher & h 1129 hashtable_data_t( BOOST_FWD_REF(BucketTraitsType) b_traits, const hasher & h
1041 , const value_equal &e, const value_traits &val_traits) 1130 , const value_equal &e, const value_traits &val_traits)
1042 : size_traits() 1131 : internal(val_traits, ::boost::forward<BucketTraitsType>(b_traits), h, e)
1043 , internal_type(val_traits, ::boost::forward<BucketTraitsType>(b_traits), h, e)
1044 {} 1132 {}
1133
1134 internal_type internal; //1
1045 }; 1135 };
1046 1136
1047 /// @endcond 1137 /// @endcond
1048 1138
1049 //! The class template hashtable is an intrusive hash table container, that 1139 //! The class template hashtable is an intrusive hash table container, that
1086 template<class T, class ...Options> 1176 template<class T, class ...Options>
1087 #else 1177 #else
1088 template<class ValueTraits, class VoidOrKeyHash, class VoidOrKeyEqual, class SizeType, class BucketTraits, std::size_t BoolFlags> 1178 template<class ValueTraits, class VoidOrKeyHash, class VoidOrKeyEqual, class SizeType, class BucketTraits, std::size_t BoolFlags>
1089 #endif 1179 #endif
1090 class hashtable_impl 1180 class hashtable_impl
1091 : public hashtable_data_t 1181 : private hashtable_data_t
1092 < SizeType 1182 < SizeType
1093 , BoolFlags & hashtable_data_bool_flags_mask 1183 , BoolFlags & hashtable_data_bool_flags_mask
1094 , VoidOrKeyHash, VoidOrKeyEqual, ValueTraits, BucketTraits> 1184 , VoidOrKeyHash, VoidOrKeyEqual, ValueTraits, BucketTraits>
1095 , private detail::clear_on_destructor_base
1096 < hashtable_impl<ValueTraits, VoidOrKeyHash, VoidOrKeyEqual, SizeType, BucketTraits, BoolFlags>
1097 , true //To always clear the bucket array
1098 //is_safe_autounlink<detail::get_real_value_traits<ValueTraits>::type::link_mode>::value
1099 >
1100 { 1185 {
1101 template<class C, bool> friend class detail::clear_on_destructor_base;
1102 public:
1103 typedef ValueTraits value_traits;
1104
1105 typedef hashtable_data_t 1186 typedef hashtable_data_t
1106 < SizeType 1187 < SizeType
1107 , BoolFlags & hashtable_data_bool_flags_mask 1188 , BoolFlags & hashtable_data_bool_flags_mask
1108 , VoidOrKeyHash, VoidOrKeyEqual, ValueTraits, BucketTraits> data_type; 1189 , VoidOrKeyHash, VoidOrKeyEqual, ValueTraits, BucketTraits> data_type;
1190
1191 public:
1192 typedef ValueTraits value_traits;
1109 1193
1110 /// @cond 1194 /// @cond
1111 static const bool external_value_traits = data_type::external_value_traits;
1112 static const bool external_bucket_traits = data_type::external_bucket_traits;
1113
1114 typedef BucketTraits bucket_traits; 1195 typedef BucketTraits bucket_traits;
1115 typedef typename data_type::real_bucket_traits real_bucket_traits;
1116 typedef typename data_type::real_value_traits real_value_traits;
1117
1118 1196
1119 typedef typename detail::get_slist_impl 1197 typedef typename detail::get_slist_impl
1120 <typename detail::reduced_slist_node_traits 1198 <typename detail::reduced_slist_node_traits
1121 <typename real_value_traits::node_traits>::type 1199 <typename value_traits::node_traits>::type
1122 >::type slist_impl; 1200 >::type slist_impl;
1123 typedef bucket_plus_vtraits<ValueTraits, BucketTraits> bucket_plus_vtraits_t; 1201 typedef bucket_plus_vtraits<ValueTraits, BucketTraits> bucket_plus_vtraits_t;
1124 typedef typename bucket_plus_vtraits_t::const_real_value_traits_ptr const_real_value_traits_ptr; 1202 typedef typename bucket_plus_vtraits_t::const_value_traits_ptr const_value_traits_ptr;
1125 1203
1126 1204
1127 /// @endcond 1205 /// @endcond
1128 1206
1129 typedef typename real_value_traits::pointer pointer; 1207 typedef typename value_traits::pointer pointer;
1130 typedef typename real_value_traits::const_pointer const_pointer; 1208 typedef typename value_traits::const_pointer const_pointer;
1131 typedef typename real_value_traits::value_type value_type; 1209 typedef typename value_traits::value_type value_type;
1132 typedef typename pointer_traits<pointer>::reference reference; 1210 typedef typename pointer_traits<pointer>::reference reference;
1133 typedef typename pointer_traits<const_pointer>::reference const_reference; 1211 typedef typename pointer_traits<const_pointer>::reference const_reference;
1134 typedef typename pointer_traits<pointer>::difference_type difference_type; 1212 typedef typename pointer_traits<pointer>::difference_type difference_type;
1135 typedef SizeType size_type; 1213 typedef SizeType size_type;
1136 typedef value_type key_type; 1214 typedef value_type key_type;
1137 typedef typename data_type::value_equal key_equal; 1215 typedef typename data_type::value_equal key_equal;
1216 typedef typename data_type::value_equal value_equal;
1138 typedef typename data_type::hasher hasher; 1217 typedef typename data_type::hasher hasher;
1139 typedef detail::bucket_impl<slist_impl> bucket_type; 1218 typedef detail::bucket_impl<slist_impl> bucket_type;
1140 typedef typename pointer_traits 1219 typedef typename pointer_traits
1141 <pointer>::template rebind_pointer 1220 <pointer>::template rebind_pointer
1142 < bucket_type >::type bucket_ptr; 1221 < bucket_type >::type bucket_ptr;
1222 typedef typename pointer_traits
1223 <pointer>::template rebind_pointer
1224 < const bucket_type >::type const_bucket_ptr;
1225 typedef typename pointer_traits
1226 <bucket_ptr>::reference bucket_reference;
1227 typedef typename pointer_traits
1228 <bucket_ptr>::reference const_bucket_reference;
1143 typedef typename slist_impl::iterator siterator; 1229 typedef typename slist_impl::iterator siterator;
1144 typedef typename slist_impl::const_iterator const_siterator; 1230 typedef typename slist_impl::const_iterator const_siterator;
1145 typedef hashtable_iterator<bucket_plus_vtraits_t, false> iterator; 1231 typedef hashtable_iterator<bucket_plus_vtraits_t, false> iterator;
1146 typedef hashtable_iterator<bucket_plus_vtraits_t, true> const_iterator; 1232 typedef hashtable_iterator<bucket_plus_vtraits_t, true> const_iterator;
1147 typedef typename real_value_traits::node_traits node_traits; 1233 typedef typename value_traits::node_traits node_traits;
1148 typedef typename node_traits::node node; 1234 typedef typename node_traits::node node;
1149 typedef typename pointer_traits 1235 typedef typename pointer_traits
1150 <pointer>::template rebind_pointer 1236 <pointer>::template rebind_pointer
1151 < node >::type node_ptr; 1237 < node >::type node_ptr;
1152 typedef typename pointer_traits 1238 typedef typename pointer_traits
1153 <pointer>::template rebind_pointer 1239 <pointer>::template rebind_pointer
1154 < const node >::type const_node_ptr; 1240 < const node >::type const_node_ptr;
1241 typedef typename pointer_traits
1242 <node_ptr>::reference node_reference;
1243 typedef typename pointer_traits
1244 <const_node_ptr>::reference const_node_reference;
1155 typedef typename slist_impl::node_algorithms node_algorithms; 1245 typedef typename slist_impl::node_algorithms node_algorithms;
1156 1246
1157 static const bool stateful_value_traits = detail::is_stateful_value_traits<real_value_traits>::value; 1247 static const bool stateful_value_traits = detail::is_stateful_value_traits<value_traits>::value;
1158 static const bool store_hash = detail::store_hash_is_true<node_traits>::value; 1248 static const bool store_hash = detail::store_hash_is_true<node_traits>::value;
1159 1249
1160 static const bool unique_keys = 0 != (BoolFlags & hash_bool_flags::unique_keys_pos); 1250 static const bool unique_keys = 0 != (BoolFlags & hash_bool_flags::unique_keys_pos);
1161 static const bool constant_time_size = 0 != (BoolFlags & hash_bool_flags::constant_time_size_pos); 1251 static const bool constant_time_size = 0 != (BoolFlags & hash_bool_flags::constant_time_size_pos);
1162 static const bool cache_begin = 0 != (BoolFlags & hash_bool_flags::cache_begin_pos); 1252 static const bool cache_begin = 0 != (BoolFlags & hash_bool_flags::cache_begin_pos);
1193 1283
1194 private: 1284 private:
1195 //noncopyable, movable 1285 //noncopyable, movable
1196 BOOST_MOVABLE_BUT_NOT_COPYABLE(hashtable_impl) 1286 BOOST_MOVABLE_BUT_NOT_COPYABLE(hashtable_impl)
1197 1287
1198 static const bool safemode_or_autounlink = is_safe_autounlink<real_value_traits::link_mode>::value; 1288 static const bool safemode_or_autounlink = is_safe_autounlink<value_traits::link_mode>::value;
1199 1289
1200 //Constant-time size is incompatible with auto-unlink hooks! 1290 //Constant-time size is incompatible with auto-unlink hooks!
1201 BOOST_STATIC_ASSERT(!(constant_time_size && ((int)real_value_traits::link_mode == (int)auto_unlink))); 1291 BOOST_STATIC_ASSERT(!(constant_time_size && ((int)value_traits::link_mode == (int)auto_unlink)));
1202 //Cache begin is incompatible with auto-unlink hooks! 1292 //Cache begin is incompatible with auto-unlink hooks!
1203 BOOST_STATIC_ASSERT(!(cache_begin && ((int)real_value_traits::link_mode == (int)auto_unlink))); 1293 BOOST_STATIC_ASSERT(!(cache_begin && ((int)value_traits::link_mode == (int)auto_unlink)));
1204 1294
1205 template<class Disposer> 1295 template<class Disposer>
1206 node_cast_adaptor< detail::node_disposer<Disposer, real_value_traits, CircularSListAlgorithms> 1296 node_cast_adaptor< detail::node_disposer<Disposer, value_traits, CircularSListAlgorithms>
1207 , slist_node_ptr, node_ptr > 1297 , slist_node_ptr, node_ptr >
1208 make_node_disposer(const Disposer &disposer) const 1298 make_node_disposer(const Disposer &disposer) const
1209 { 1299 {
1210 return node_cast_adaptor 1300 return node_cast_adaptor
1211 < detail::node_disposer<Disposer, real_value_traits, CircularSListAlgorithms> 1301 < detail::node_disposer<Disposer, value_traits, CircularSListAlgorithms>
1212 , slist_node_ptr, node_ptr > 1302 , slist_node_ptr, node_ptr >
1213 (disposer, &this->priv_real_value_traits()); 1303 (disposer, &this->priv_value_traits());
1214 } 1304 }
1215 1305
1216 /// @endcond 1306 /// @endcond
1217 1307
1218 public: 1308 public:
1219 typedef detail::insert_commit_data_impl insert_commit_data; 1309 typedef detail::insert_commit_data_impl insert_commit_data;
1220 1310
1221 typedef detail::transform_iterator 1311 typedef detail::transform_iterator
1222 < typename slist_impl::iterator 1312 < typename slist_impl::iterator
1223 , downcast_node_to_value_t 1313 , downcast_node_to_value_t
1224 < real_value_traits 1314 < value_traits
1225 , false> > local_iterator; 1315 , false> > local_iterator;
1226 1316
1227 typedef detail::transform_iterator 1317 typedef detail::transform_iterator
1228 < typename slist_impl::iterator 1318 < typename slist_impl::iterator
1229 , downcast_node_to_value_t 1319 , downcast_node_to_value_t
1230 < real_value_traits 1320 < value_traits
1231 , true> > const_local_iterator; 1321 , true> > const_local_iterator;
1232 1322
1233 public: 1323 public:
1234 1324
1235 //! <b>Requires</b>: buckets must not be being used by any other resource. 1325 //! <b>Requires</b>: buckets must not be being used by any other resource.
1249 , const hasher & hash_func = hasher() 1339 , const hasher & hash_func = hasher()
1250 , const key_equal &equal_func = key_equal() 1340 , const key_equal &equal_func = key_equal()
1251 , const value_traits &v_traits = value_traits()) 1341 , const value_traits &v_traits = value_traits())
1252 : data_type(b_traits, hash_func, equal_func, v_traits) 1342 : data_type(b_traits, hash_func, equal_func, v_traits)
1253 { 1343 {
1254 this->priv_initialize_buckets(); 1344 this->data_type::internal.priv_initialize_buckets_and_cache();
1255 this->priv_size_traits().set_size(size_type(0)); 1345 this->priv_size_traits().set_size(size_type(0));
1256 size_type bucket_sz = this->priv_bucket_count(); 1346 size_type bucket_sz = this->priv_bucket_count();
1257 BOOST_INTRUSIVE_INVARIANT_ASSERT(bucket_sz != 0); 1347 BOOST_INTRUSIVE_INVARIANT_ASSERT(bucket_sz != 0);
1258 //Check power of two bucket array if the option is activated 1348 //Check power of two bucket array if the option is activated
1259 BOOST_INTRUSIVE_INVARIANT_ASSERT 1349 BOOST_INTRUSIVE_INVARIANT_ASSERT
1294 //! 1384 //!
1295 //! <b>Complexity</b>: Linear to the number of elements in the unordered_set, if 1385 //! <b>Complexity</b>: Linear to the number of elements in the unordered_set, if
1296 //! it's a safe-mode or auto-unlink value. Otherwise constant. 1386 //! it's a safe-mode or auto-unlink value. Otherwise constant.
1297 //! 1387 //!
1298 //! <b>Throws</b>: Nothing. 1388 //! <b>Throws</b>: Nothing.
1299 ~hashtable_impl() 1389 ~hashtable_impl();
1300 {}
1301 #endif 1390 #endif
1302 1391
1303 //! <b>Effects</b>: Returns an iterator pointing to the beginning of the unordered_set. 1392 //! <b>Effects</b>: Returns an iterator pointing to the beginning of the unordered_set.
1304 //! 1393 //!
1305 //! <b>Complexity</b>: Amortized constant time. 1394 //! <b>Complexity</b>: Amortized constant time.
1427 //! 1516 //!
1428 //! <b>Throws</b>: If the swap() call for the comparison or hash functors 1517 //! <b>Throws</b>: If the swap() call for the comparison or hash functors
1429 //! found using ADL throw. Basic guarantee. 1518 //! found using ADL throw. Basic guarantee.
1430 void swap(hashtable_impl& other) 1519 void swap(hashtable_impl& other)
1431 { 1520 {
1432 using std::swap;
1433 //These can throw 1521 //These can throw
1434 swap(this->priv_equal(), other.priv_equal()); 1522 ::boost::adl_move_swap(this->priv_equal(), other.priv_equal());
1435 swap(this->priv_hasher(), other.priv_hasher()); 1523 ::boost::adl_move_swap(this->priv_hasher(), other.priv_hasher());
1436 //These can't throw 1524 //These can't throw
1437 swap(this->priv_bucket_traits(), other.priv_bucket_traits()); 1525 ::boost::adl_move_swap(this->priv_bucket_traits(), other.priv_bucket_traits());
1438 swap(this->priv_value_traits(), other.priv_value_traits()); 1526 ::boost::adl_move_swap(this->priv_value_traits(), other.priv_value_traits());
1439 this->priv_swap_cache(other); 1527 this->priv_swap_cache(other);
1440 if(constant_time_size){ 1528 if(constant_time_size){
1441 size_type backup = this->priv_size_traits().get_size(); 1529 size_type backup = this->priv_size_traits().get_size();
1442 this->priv_size_traits().set_size(other.priv_size_traits().get_size()); 1530 this->priv_size_traits().set_size(other.priv_size_traits().get_size());
1443 other.priv_size_traits().set_size(backup); 1531 other.priv_size_traits().set_size(backup);
1485 if(!incremental && (src_bucket_count >= dst_bucket_count)){ 1573 if(!incremental && (src_bucket_count >= dst_bucket_count)){
1486 //First clone the first ones 1574 //First clone the first ones
1487 const bucket_ptr src_buckets = src.priv_bucket_pointer(); 1575 const bucket_ptr src_buckets = src.priv_bucket_pointer();
1488 const bucket_ptr dst_buckets = this->priv_bucket_pointer(); 1576 const bucket_ptr dst_buckets = this->priv_bucket_pointer();
1489 size_type constructed; 1577 size_type constructed;
1490 1578
1491 typedef node_cast_adaptor< detail::node_disposer<Disposer, real_value_traits, CircularSListAlgorithms> 1579 typedef node_cast_adaptor< detail::node_disposer<Disposer, value_traits, CircularSListAlgorithms>
1492 , slist_node_ptr, node_ptr > NodeDisposer; 1580 , slist_node_ptr, node_ptr > NodeDisposer;
1493 typedef node_cast_adaptor< detail::node_cloner <Cloner, real_value_traits, CircularSListAlgorithms> 1581 typedef node_cast_adaptor< detail::node_cloner <Cloner, value_traits, CircularSListAlgorithms>
1494 , slist_node_ptr, node_ptr > NodeCloner; 1582 , slist_node_ptr, node_ptr > NodeCloner;
1495 NodeDisposer node_disp(disposer, &this->priv_real_value_traits()); 1583 NodeDisposer node_disp(disposer, &this->priv_value_traits());
1496 1584
1497 detail::exception_array_disposer<bucket_type, NodeDisposer, size_type> 1585 detail::exception_array_disposer<bucket_type, NodeDisposer, size_type>
1498 rollback(dst_buckets[0], node_disp, constructed); 1586 rollback(dst_buckets[0], node_disp, constructed);
1499 for( constructed = 0 1587 for( constructed = 0
1500 ; constructed < dst_bucket_count 1588 ; constructed < dst_bucket_count
1501 ; ++constructed){ 1589 ; ++constructed){
1502 dst_buckets[constructed].clone_from 1590 dst_buckets[constructed].clone_from
1503 ( src_buckets[constructed] 1591 ( src_buckets[constructed]
1504 , NodeCloner(cloner, &this->priv_real_value_traits()), node_disp); 1592 , NodeCloner(cloner, &this->priv_value_traits()), node_disp);
1505 } 1593 }
1506 if(src_bucket_count != dst_bucket_count){ 1594 if(src_bucket_count != dst_bucket_count){
1507 //Now insert the remaining ones using the modulo trick 1595 //Now insert the remaining ones using the modulo trick
1508 for(//"constructed" comes from the previous loop 1596 for(//"constructed" comes from the previous loop
1509 ; constructed < src_bucket_count 1597 ; constructed < src_bucket_count
1512 dst_buckets[detail::hash_to_bucket_split<power_2_buckets, incremental>(constructed, dst_bucket_count, dst_bucket_count)]; 1600 dst_buckets[detail::hash_to_bucket_split<power_2_buckets, incremental>(constructed, dst_bucket_count, dst_bucket_count)];
1513 bucket_type &src_b = src_buckets[constructed]; 1601 bucket_type &src_b = src_buckets[constructed];
1514 for( siterator b(src_b.begin()), e(src_b.end()) 1602 for( siterator b(src_b.begin()), e(src_b.end())
1515 ; b != e 1603 ; b != e
1516 ; ++b){ 1604 ; ++b){
1517 dst_b.push_front(*(NodeCloner(cloner, &this->priv_real_value_traits())(*b.pointed_node()))); 1605 dst_b.push_front(*(NodeCloner(cloner, &this->priv_value_traits())(*b.pointed_node())));
1518 } 1606 }
1519 } 1607 }
1520 } 1608 }
1521 this->priv_hasher() = src.priv_hasher(); 1609 this->priv_hasher() = src.priv_hasher();
1522 this->priv_equal() = src.priv_equal(); 1610 this->priv_equal() = src.priv_equal();
1527 this->priv_erasure_update_cache(); 1615 this->priv_erasure_update_cache();
1528 } 1616 }
1529 else if(store_hash){ 1617 else if(store_hash){
1530 //Unlike previous cloning algorithm, this can throw 1618 //Unlike previous cloning algorithm, this can throw
1531 //if cloner, hasher or comparison functor throw 1619 //if cloner, hasher or comparison functor throw
1532 const_iterator b(src.begin()), e(src.end()); 1620 const_iterator b(src.cbegin()), e(src.cend());
1533 detail::exception_disposer<hashtable_impl, Disposer> 1621 detail::exception_disposer<hashtable_impl, Disposer>
1534 rollback(*this, disposer); 1622 rollback(*this, disposer);
1535 for(; b != e; ++b){ 1623 for(; b != e; ++b){
1536 std::size_t hash_value = this->priv_stored_or_compute_hash(*b, store_hash_t());; 1624 std::size_t hash_value = this->priv_stored_or_compute_hash(*b, store_hash_t());;
1537 this->priv_insert_equal_with_hash(*cloner(*b), hash_value); 1625 this->priv_insert_equal_with_hash(*cloner(*b), hash_value);
1539 rollback.release(); 1627 rollback.release();
1540 } 1628 }
1541 else{ 1629 else{
1542 //Unlike previous cloning algorithm, this can throw 1630 //Unlike previous cloning algorithm, this can throw
1543 //if cloner, hasher or comparison functor throw 1631 //if cloner, hasher or comparison functor throw
1544 const_iterator b(src.begin()), e(src.end()); 1632 const_iterator b(src.cbegin()), e(src.cend());
1545 detail::exception_disposer<hashtable_impl, Disposer> 1633 detail::exception_disposer<hashtable_impl, Disposer>
1546 rollback(*this, disposer); 1634 rollback(*this, disposer);
1547 for(; b != e; ++b){ 1635 for(; b != e; ++b){
1548 this->insert_equal(*cloner(*b)); 1636 this->insert_equal(*cloner(*b));
1549 } 1637 }
1577 //! <b>Requires</b>: Dereferencing iterator must yield an lvalue 1665 //! <b>Requires</b>: Dereferencing iterator must yield an lvalue
1578 //! of type value_type. 1666 //! of type value_type.
1579 //! 1667 //!
1580 //! <b>Effects</b>: Equivalent to this->insert_equal(t) for each element in [b, e). 1668 //! <b>Effects</b>: Equivalent to this->insert_equal(t) for each element in [b, e).
1581 //! 1669 //!
1582 //! <b>Complexity</b>: Average case O(N), where N is std::distance(b, e). 1670 //! <b>Complexity</b>: Average case O(N), where N is distance(b, e).
1583 //! Worst case O(N*this->size()). 1671 //! Worst case O(N*this->size()).
1584 //! 1672 //!
1585 //! <b>Throws</b>: If the internal hasher or the equality functor throws. Basic guarantee. 1673 //! <b>Throws</b>: If the internal hasher or the equality functor throws. Basic guarantee.
1586 //! 1674 //!
1587 //! <b>Note</b>: Does not affect the validity of iterators and references. 1675 //! <b>Note</b>: Does not affect the validity of iterators and references.
1623 //! <b>Requires</b>: Dereferencing iterator must yield an lvalue 1711 //! <b>Requires</b>: Dereferencing iterator must yield an lvalue
1624 //! of type value_type. 1712 //! of type value_type.
1625 //! 1713 //!
1626 //! <b>Effects</b>: Equivalent to this->insert_unique(t) for each element in [b, e). 1714 //! <b>Effects</b>: Equivalent to this->insert_unique(t) for each element in [b, e).
1627 //! 1715 //!
1628 //! <b>Complexity</b>: Average case O(N), where N is std::distance(b, e). 1716 //! <b>Complexity</b>: Average case O(N), where N is distance(b, e).
1629 //! Worst case O(N*this->size()). 1717 //! Worst case O(N*this->size()).
1630 //! 1718 //!
1631 //! <b>Throws</b>: If the internal hasher or the equality functor throws. Basic guarantee. 1719 //! <b>Throws</b>: If the internal hasher or the equality functor throws. Basic guarantee.
1632 //! 1720 //!
1633 //! <b>Note</b>: Does not affect the validity of iterators and references. 1721 //! <b>Note</b>: Does not affect the validity of iterators and references.
1736 void erase(const_iterator i) 1824 void erase(const_iterator i)
1737 { this->erase_and_dispose(i, detail::null_disposer()); } 1825 { this->erase_and_dispose(i, detail::null_disposer()); }
1738 1826
1739 //! <b>Effects</b>: Erases the range pointed to by b end e. 1827 //! <b>Effects</b>: Erases the range pointed to by b end e.
1740 //! 1828 //!
1741 //! <b>Complexity</b>: Average case O(std::distance(b, e)), 1829 //! <b>Complexity</b>: Average case O(distance(b, e)),
1742 //! worst case O(this->size()). 1830 //! worst case O(this->size()).
1743 //! 1831 //!
1744 //! <b>Throws</b>: Nothing. 1832 //! <b>Throws</b>: Nothing.
1745 //! 1833 //!
1746 //! <b>Note</b>: Invalidates the iterators (but not the references) 1834 //! <b>Note</b>: Invalidates the iterators (but not the references)
1813 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw. 1901 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
1814 //! 1902 //!
1815 //! <b>Effects</b>: Erases the range pointed to by b end e. 1903 //! <b>Effects</b>: Erases the range pointed to by b end e.
1816 //! Disposer::operator()(pointer) is called for the removed elements. 1904 //! Disposer::operator()(pointer) is called for the removed elements.
1817 //! 1905 //!
1818 //! <b>Complexity</b>: Average case O(std::distance(b, e)), 1906 //! <b>Complexity</b>: Average case O(distance(b, e)),
1819 //! worst case O(this->size()). 1907 //! worst case O(this->size()).
1820 //! 1908 //!
1821 //! <b>Throws</b>: Nothing. 1909 //! <b>Throws</b>: Nothing.
1822 //! 1910 //!
1823 //! <b>Note</b>: Invalidates the iterators 1911 //! <b>Note</b>: Invalidates the iterators
1936 //! 2024 //!
1937 //! <b>Note</b>: Invalidates the iterators (but not the references) 2025 //! <b>Note</b>: Invalidates the iterators (but not the references)
1938 //! to the erased elements. No destructors are called. 2026 //! to the erased elements. No destructors are called.
1939 void clear() 2027 void clear()
1940 { 2028 {
1941 this->priv_clear_buckets(); 2029 this->data_type::internal.priv_clear_buckets_and_cache();
1942 this->priv_size_traits().set_size(size_type(0)); 2030 this->priv_size_traits().set_size(size_type(0));
1943 } 2031 }
1944 2032
1945 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw. 2033 //! <b>Requires</b>: Disposer::operator()(pointer) shouldn't throw.
1946 //! 2034 //!
2151 { 2239 {
2152 size_type bucket_n1, bucket_n2, cnt; 2240 size_type bucket_n1, bucket_n2, cnt;
2153 std::pair<siterator, siterator> ret = 2241 std::pair<siterator, siterator> ret =
2154 this->priv_equal_range(key, hash_func, equal_func, bucket_n1, bucket_n2, cnt); 2242 this->priv_equal_range(key, hash_func, equal_func, bucket_n1, bucket_n2, cnt);
2155 return std::pair<const_iterator, const_iterator> 2243 return std::pair<const_iterator, const_iterator>
2156 (const_iterator(ret.first, &this->get_bucket_value_traits()), const_iterator(ret.second, &this->get_bucket_value_traits())); 2244 ( const_iterator(ret.first, &this->get_bucket_value_traits())
2245 , const_iterator(ret.second, &this->get_bucket_value_traits()));
2157 } 2246 }
2158 2247
2159 //! <b>Requires</b>: value must be an lvalue and shall be in a unordered_set of 2248 //! <b>Requires</b>: value must be an lvalue and shall be in a unordered_set of
2160 //! appropriate type. Otherwise the behavior is undefined. 2249 //! appropriate type. Otherwise the behavior is undefined.
2161 //! 2250 //!
2165 //! <b>Complexity</b>: Constant. 2254 //! <b>Complexity</b>: Constant.
2166 //! 2255 //!
2167 //! <b>Throws</b>: If the internal hash function throws. 2256 //! <b>Throws</b>: If the internal hash function throws.
2168 iterator iterator_to(reference value) 2257 iterator iterator_to(reference value)
2169 { 2258 {
2170 return iterator(bucket_type::s_iterator_to(this->priv_value_to_node(value)), &this->get_bucket_value_traits()); 2259 return iterator(bucket_type::s_iterator_to
2260 (this->priv_value_to_node(value)), &this->get_bucket_value_traits());
2171 } 2261 }
2172 2262
2173 //! <b>Requires</b>: value must be an lvalue and shall be in a unordered_set of 2263 //! <b>Requires</b>: value must be an lvalue and shall be in a unordered_set of
2174 //! appropriate type. Otherwise the behavior is undefined. 2264 //! appropriate type. Otherwise the behavior is undefined.
2175 //! 2265 //!
2179 //! <b>Complexity</b>: Constant. 2269 //! <b>Complexity</b>: Constant.
2180 //! 2270 //!
2181 //! <b>Throws</b>: If the internal hash function throws. 2271 //! <b>Throws</b>: If the internal hash function throws.
2182 const_iterator iterator_to(const_reference value) const 2272 const_iterator iterator_to(const_reference value) const
2183 { 2273 {
2184 siterator sit = bucket_type::s_iterator_to(const_cast<node &>(this->priv_value_to_node(value))); 2274 node_reference r = *pointer_traits<node_ptr>::const_cast_from
2275 (pointer_traits<const_node_ptr>::pointer_to(this->priv_value_to_node(value)));
2276 siterator sit = bucket_type::s_iterator_to(r);
2185 return const_iterator(sit, &this->get_bucket_value_traits()); 2277 return const_iterator(sit, &this->get_bucket_value_traits());
2186 } 2278 }
2187 2279
2188 //! <b>Requires</b>: value must be an lvalue and shall be in a unordered_set of 2280 //! <b>Requires</b>: value must be an lvalue and shall be in a unordered_set of
2189 //! appropriate type. Otherwise the behavior is undefined. 2281 //! appropriate type. Otherwise the behavior is undefined.
2198 //! <b>Note</b>: This static function is available only if the <i>value traits</i> 2290 //! <b>Note</b>: This static function is available only if the <i>value traits</i>
2199 //! is stateless. 2291 //! is stateless.
2200 static local_iterator s_local_iterator_to(reference value) 2292 static local_iterator s_local_iterator_to(reference value)
2201 { 2293 {
2202 BOOST_STATIC_ASSERT((!stateful_value_traits)); 2294 BOOST_STATIC_ASSERT((!stateful_value_traits));
2203 siterator sit = bucket_type::s_iterator_to(((hashtable_impl*)0)->priv_value_to_node(value)); 2295 siterator sit = bucket_type::s_iterator_to(*value_traits::to_node_ptr(value));
2204 return local_iterator(sit, const_real_value_traits_ptr()); 2296 return local_iterator(sit, const_value_traits_ptr());
2205 } 2297 }
2206 2298
2207 //! <b>Requires</b>: value must be an lvalue and shall be in a unordered_set of 2299 //! <b>Requires</b>: value must be an lvalue and shall be in a unordered_set of
2208 //! appropriate type. Otherwise the behavior is undefined. 2300 //! appropriate type. Otherwise the behavior is undefined.
2209 //! 2301 //!
2217 //! <b>Note</b>: This static function is available only if the <i>value traits</i> 2309 //! <b>Note</b>: This static function is available only if the <i>value traits</i>
2218 //! is stateless. 2310 //! is stateless.
2219 static const_local_iterator s_local_iterator_to(const_reference value) 2311 static const_local_iterator s_local_iterator_to(const_reference value)
2220 { 2312 {
2221 BOOST_STATIC_ASSERT((!stateful_value_traits)); 2313 BOOST_STATIC_ASSERT((!stateful_value_traits));
2222 siterator sit = bucket_type::s_iterator_to(((hashtable_impl*)0)->priv_value_to_node(const_cast<value_type&>(value))); 2314 node_reference r = *pointer_traits<node_ptr>::const_cast_from
2223 return const_local_iterator(sit, const_real_value_traits_ptr()); 2315 (value_traits::to_node_ptr(value));
2316 siterator sit = bucket_type::s_iterator_to(r);
2317 return const_local_iterator(sit, const_value_traits_ptr());
2224 } 2318 }
2225 2319
2226 //! <b>Requires</b>: value must be an lvalue and shall be in a unordered_set of 2320 //! <b>Requires</b>: value must be an lvalue and shall be in a unordered_set of
2227 //! appropriate type. Otherwise the behavior is undefined. 2321 //! appropriate type. Otherwise the behavior is undefined.
2228 //! 2322 //!
2233 //! 2327 //!
2234 //! <b>Throws</b>: Nothing. 2328 //! <b>Throws</b>: Nothing.
2235 local_iterator local_iterator_to(reference value) 2329 local_iterator local_iterator_to(reference value)
2236 { 2330 {
2237 siterator sit = bucket_type::s_iterator_to(this->priv_value_to_node(value)); 2331 siterator sit = bucket_type::s_iterator_to(this->priv_value_to_node(value));
2238 return local_iterator(sit, this->real_value_traits_ptr()); 2332 return local_iterator(sit, this->priv_value_traits_ptr());
2239 } 2333 }
2240 2334
2241 //! <b>Requires</b>: value must be an lvalue and shall be in a unordered_set of 2335 //! <b>Requires</b>: value must be an lvalue and shall be in a unordered_set of
2242 //! appropriate type. Otherwise the behavior is undefined. 2336 //! appropriate type. Otherwise the behavior is undefined.
2243 //! 2337 //!
2247 //! <b>Complexity</b>: Constant. 2341 //! <b>Complexity</b>: Constant.
2248 //! 2342 //!
2249 //! <b>Throws</b>: Nothing. 2343 //! <b>Throws</b>: Nothing.
2250 const_local_iterator local_iterator_to(const_reference value) const 2344 const_local_iterator local_iterator_to(const_reference value) const
2251 { 2345 {
2252 siterator sit = bucket_type::s_iterator_to 2346 node_reference r = *pointer_traits<node_ptr>::const_cast_from
2253 (const_cast<node &>(this->priv_value_to_node(value))); 2347 (pointer_traits<const_node_ptr>::pointer_to(this->priv_value_to_node(value)));
2254 return const_local_iterator(sit, this->real_value_traits_ptr()); 2348 siterator sit = bucket_type::s_iterator_to(r);
2349 return const_local_iterator(sit, this->priv_value_traits_ptr());
2255 } 2350 }
2256 2351
2257 //! <b>Effects</b>: Returns the number of buckets passed in the constructor 2352 //! <b>Effects</b>: Returns the number of buckets passed in the constructor
2258 //! or the last rehash function. 2353 //! or the last rehash function.
2259 //! 2354 //!
2319 //! <b>Throws</b>: Nothing. 2414 //! <b>Throws</b>: Nothing.
2320 //! 2415 //!
2321 //! <b>Note</b>: [this->begin(n), this->end(n)) is a valid range 2416 //! <b>Note</b>: [this->begin(n), this->end(n)) is a valid range
2322 //! containing all of the elements in the nth bucket. 2417 //! containing all of the elements in the nth bucket.
2323 local_iterator begin(size_type n) 2418 local_iterator begin(size_type n)
2324 { return local_iterator(this->priv_bucket_pointer()[n].begin(), this->real_value_traits_ptr()); } 2419 { return local_iterator(this->priv_bucket_pointer()[n].begin(), this->priv_value_traits_ptr()); }
2325 2420
2326 //! <b>Requires</b>: n is in the range [0, this->bucket_count()). 2421 //! <b>Requires</b>: n is in the range [0, this->bucket_count()).
2327 //! 2422 //!
2328 //! <b>Effects</b>: Returns a const_local_iterator pointing to the beginning 2423 //! <b>Effects</b>: Returns a const_local_iterator pointing to the beginning
2329 //! of the sequence stored in the bucket n. 2424 //! of the sequence stored in the bucket n.
2348 //! 2443 //!
2349 //! <b>Note</b>: [this->begin(n), this->end(n)) is a valid range 2444 //! <b>Note</b>: [this->begin(n), this->end(n)) is a valid range
2350 //! containing all of the elements in the nth bucket. 2445 //! containing all of the elements in the nth bucket.
2351 const_local_iterator cbegin(size_type n) const 2446 const_local_iterator cbegin(size_type n) const
2352 { 2447 {
2353 siterator sit = const_cast<bucket_type&>(this->priv_bucket_pointer()[n]).begin(); 2448 bucket_reference br = pointer_traits<bucket_ptr>::const_cast_from(this->priv_bucket_pointer())[n];
2354 return const_local_iterator(sit, this->real_value_traits_ptr()); 2449 return const_local_iterator(br.begin(), this->priv_value_traits_ptr());
2355 } 2450 }
2356 2451
2357 //! <b>Requires</b>: n is in the range [0, this->bucket_count()). 2452 //! <b>Requires</b>: n is in the range [0, this->bucket_count()).
2358 //! 2453 //!
2359 //! <b>Effects</b>: Returns a local_iterator pointing to the end 2454 //! <b>Effects</b>: Returns a local_iterator pointing to the end
2364 //! <b>Throws</b>: Nothing. 2459 //! <b>Throws</b>: Nothing.
2365 //! 2460 //!
2366 //! <b>Note</b>: [this->begin(n), this->end(n)) is a valid range 2461 //! <b>Note</b>: [this->begin(n), this->end(n)) is a valid range
2367 //! containing all of the elements in the nth bucket. 2462 //! containing all of the elements in the nth bucket.
2368 local_iterator end(size_type n) 2463 local_iterator end(size_type n)
2369 { return local_iterator(this->priv_bucket_pointer()[n].end(), this->real_value_traits_ptr()); } 2464 { return local_iterator(this->priv_bucket_pointer()[n].end(), this->priv_value_traits_ptr()); }
2370 2465
2371 //! <b>Requires</b>: n is in the range [0, this->bucket_count()). 2466 //! <b>Requires</b>: n is in the range [0, this->bucket_count()).
2372 //! 2467 //!
2373 //! <b>Effects</b>: Returns a const_local_iterator pointing to the end 2468 //! <b>Effects</b>: Returns a const_local_iterator pointing to the end
2374 //! of the sequence stored in the bucket n. 2469 //! of the sequence stored in the bucket n.
2393 //! 2488 //!
2394 //! <b>Note</b>: [this->begin(n), this->end(n)) is a valid range 2489 //! <b>Note</b>: [this->begin(n), this->end(n)) is a valid range
2395 //! containing all of the elements in the nth bucket. 2490 //! containing all of the elements in the nth bucket.
2396 const_local_iterator cend(size_type n) const 2491 const_local_iterator cend(size_type n) const
2397 { 2492 {
2398 return const_local_iterator ( const_cast<bucket_type&>(this->priv_bucket_pointer()[n]).end() 2493 bucket_reference br = pointer_traits<bucket_ptr>::const_cast_from(this->priv_bucket_pointer())[n];
2399 , this->real_value_traits_ptr()); 2494 return const_local_iterator ( br.end(), this->priv_value_traits_ptr());
2400 } 2495 }
2401 2496
2402 //! <b>Requires</b>: new_bucket_traits can hold a pointer to a new bucket array 2497 //! <b>Requires</b>: new_bucket_traits can hold a pointer to a new bucket array
2403 //! or the same as the old bucket array with a different length. new_size is the length of the 2498 //! or the same as the old bucket array with a different length. new_size is the length of the
2404 //! the array pointed by new_buckets. If new_bucket_traits.bucket_begin() == this->bucket_pointer() 2499 //! the array pointed by new_buckets. If new_bucket_traits.bucket_begin() == this->bucket_pointer()
2501 } 2596 }
2502 } 2597 }
2503 2598
2504 this->priv_size_traits().set_size(size_backup); 2599 this->priv_size_traits().set_size(size_backup);
2505 this->priv_split_traits().set_size(new_bucket_count); 2600 this->priv_split_traits().set_size(new_bucket_count);
2506 this->priv_real_bucket_traits() = new_bucket_traits; 2601 this->priv_bucket_traits() = new_bucket_traits;
2507 this->priv_initialize_cache(); 2602 this->priv_initialize_cache();
2508 this->priv_insertion_update_cache(new_first_bucket_num); 2603 this->priv_insertion_update_cache(new_first_bucket_num);
2509 rollback1.release(); 2604 rollback1.release();
2510 rollback2.release(); 2605 rollback2.release();
2511 } 2606 }
2614 return false; 2709 return false;
2615 } 2710 }
2616 2711
2617 const size_type ini_n = this->priv_get_cache_bucket_num(); 2712 const size_type ini_n = this->priv_get_cache_bucket_num();
2618 const bucket_ptr old_buckets = this->priv_bucket_pointer(); 2713 const bucket_ptr old_buckets = this->priv_bucket_pointer();
2619 this->priv_real_bucket_traits() = new_bucket_traits; 2714 this->priv_bucket_traits() = new_bucket_traits;
2620 if(new_bucket_traits.bucket_begin() != old_buckets){ 2715 if(new_bucket_traits.bucket_begin() != old_buckets){
2621 for(size_type n = ini_n; n < split_idx; ++n){ 2716 for(size_type n = ini_n; n < split_idx; ++n){
2622 bucket_type &new_bucket = new_bucket_traits.bucket_begin()[n]; 2717 bucket_type &new_bucket = new_bucket_traits.bucket_begin()[n];
2623 bucket_type &old_bucket = old_buckets[n]; 2718 bucket_type &old_bucket = old_buckets[n];
2624 new_bucket.splice_after(new_bucket.cbefore_begin(), old_bucket); 2719 new_bucket.splice_after(new_bucket.cbefore_begin(), old_bucket);
2653 //! <b>Complexity</b>: Amortized constant time. 2748 //! <b>Complexity</b>: Amortized constant time.
2654 //! 2749 //!
2655 //! <b>Throws</b>: Nothing. 2750 //! <b>Throws</b>: Nothing.
2656 static size_type suggested_upper_bucket_count(size_type n) 2751 static size_type suggested_upper_bucket_count(size_type n)
2657 { 2752 {
2658 const std::size_t *primes = &detail::prime_list_holder<0>::prime_list[0]; 2753 const std::size_t *primes = &prime_list_holder<0>::prime_list[0];
2659 const std::size_t *primes_end = primes + detail::prime_list_holder<0>::prime_list_size; 2754 const std::size_t *primes_end = primes + prime_list_holder<0>::prime_list_size;
2660 std::size_t const* bound = std::lower_bound(primes, primes_end, n); 2755 std::size_t const* bound = std::lower_bound(primes, primes_end, n);
2661 if(bound == primes_end) 2756 bound -= (bound == primes_end);
2662 --bound;
2663 return size_type(*bound); 2757 return size_type(*bound);
2664 } 2758 }
2665 2759
2666 //! <b>Effects</b>: Returns the nearest new bucket count optimized for 2760 //! <b>Effects</b>: Returns the nearest new bucket count optimized for
2667 //! the container that is smaller or equal than n. This suggestion can be 2761 //! the container that is smaller or equal than n. This suggestion can be
2672 //! <b>Complexity</b>: Amortized constant time. 2766 //! <b>Complexity</b>: Amortized constant time.
2673 //! 2767 //!
2674 //! <b>Throws</b>: Nothing. 2768 //! <b>Throws</b>: Nothing.
2675 static size_type suggested_lower_bucket_count(size_type n) 2769 static size_type suggested_lower_bucket_count(size_type n)
2676 { 2770 {
2677 const std::size_t *primes = &detail::prime_list_holder<0>::prime_list[0]; 2771 const std::size_t *primes = &prime_list_holder<0>::prime_list[0];
2678 const std::size_t *primes_end = primes + detail::prime_list_holder<0>::prime_list_size; 2772 const std::size_t *primes_end = primes + prime_list_holder<0>::prime_list_size;
2679 size_type const* bound = std::upper_bound(primes, primes_end, n); 2773 size_type const* bound = std::upper_bound(primes, primes_end, n);
2680 if(bound != primes) 2774 bound -= (bound != primes);
2681 --bound;
2682 return size_type(*bound); 2775 return size_type(*bound);
2683 } 2776 }
2684
2685 /// @cond 2777 /// @cond
2778 void check() const {}
2686 private: 2779 private:
2687 2780 size_traits &priv_size_traits()
2688 void priv_clear_buckets(bucket_ptr buckets_ptr, size_type bucket_cnt) 2781 { return static_cast<size_traits&>(static_cast<data_type&>(*this)); }
2689 { 2782
2690 for(; bucket_cnt--; ++buckets_ptr){ 2783 const size_traits &priv_size_traits() const
2691 if(safemode_or_autounlink){ 2784 { return static_cast<const size_traits&>(static_cast<const data_type&>(*this)); }
2692 bucket_plus_vtraits_t::priv_clear_group_nodes(*buckets_ptr, optimize_multikey_t()); 2785
2693 buckets_ptr->clear_and_dispose(detail::init_disposer<node_algorithms>()); 2786 bucket_ptr priv_bucket_pointer() const
2694 } 2787 { return this->data_type::internal.internal.internal.internal.priv_bucket_pointer(); }
2695 else{ 2788
2696 buckets_ptr->clear(); 2789 SizeType priv_bucket_count() const
2697 } 2790 { return this->data_type::internal.internal.internal.internal.priv_bucket_count(); }
2698 } 2791
2699 this->priv_initialize_cache(); 2792 const bucket_plus_vtraits<ValueTraits, BucketTraits> &get_bucket_value_traits() const
2700 } 2793 { return this->data_type::internal.internal.internal.internal.get_bucket_value_traits(); }
2701 2794
2702 void priv_initialize_buckets() 2795 bucket_plus_vtraits<ValueTraits, BucketTraits> &get_bucket_value_traits()
2703 { this->priv_clear_buckets(this->priv_bucket_pointer(), this->priv_bucket_count()); } 2796 { return this->data_type::internal.internal.internal.internal.get_bucket_value_traits(); }
2704 2797
2705 void priv_clear_buckets() 2798 bucket_traits &priv_bucket_traits()
2706 { 2799 { return this->data_type::internal.internal.internal.internal.priv_bucket_traits(); }
2707 this->priv_clear_buckets 2800
2708 ( this->priv_get_cache() 2801 const bucket_traits &priv_bucket_traits() const
2709 , this->priv_bucket_count() - (this->priv_get_cache() - this->priv_bucket_pointer())); 2802 { return this->data_type::internal.internal.internal.internal.priv_bucket_traits(); }
2710 } 2803
2804 value_traits &priv_value_traits()
2805 { return this->data_type::internal.internal.internal.internal.priv_value_traits(); }
2806
2807 const value_traits &priv_value_traits() const
2808 { return this->data_type::internal.internal.internal.internal.priv_value_traits(); }
2809
2810 const_value_traits_ptr priv_value_traits_ptr() const
2811 { return this->data_type::internal.internal.internal.internal.priv_value_traits_ptr(); }
2812
2813 siterator priv_invalid_local_it() const
2814 { return this->data_type::internal.internal.internal.internal.priv_invalid_local_it(); }
2815
2816 split_traits &priv_split_traits()
2817 { return this->data_type::internal.priv_split_traits(); }
2818
2819 const split_traits &priv_split_traits() const
2820 { return this->data_type::internal.priv_split_traits(); }
2821
2822 bucket_ptr priv_get_cache()
2823 { return this->data_type::internal.internal.priv_get_cache(); }
2824
2825 void priv_initialize_cache()
2826 { return this->data_type::internal.internal.priv_initialize_cache(); }
2827
2828 siterator priv_begin() const
2829 { return this->data_type::internal.internal.priv_begin(); }
2830
2831 const value_equal &priv_equal() const
2832 { return this->data_type::internal.internal.priv_equal(); }
2833
2834 value_equal &priv_equal()
2835 { return this->data_type::internal.internal.priv_equal(); }
2836
2837 const hasher &priv_hasher() const
2838 { return this->data_type::internal.internal.internal.priv_hasher(); }
2839
2840 hasher &priv_hasher()
2841 { return this->data_type::internal.internal.internal.priv_hasher(); }
2842
2843 void priv_swap_cache(hashtable_impl &h)
2844 { this->data_type::internal.internal.priv_swap_cache(h.data_type::internal.internal); }
2845
2846 node &priv_value_to_node(value_type &v)
2847 { return this->data_type::internal.internal.internal.internal.priv_value_to_node(v); }
2848
2849 const node &priv_value_to_node(const value_type &v) const
2850 { return this->data_type::internal.internal.internal.internal.priv_value_to_node(v); }
2851
2852 SizeType priv_get_cache_bucket_num()
2853 { return this->data_type::internal.internal.priv_get_cache_bucket_num(); }
2854
2855 void priv_insertion_update_cache(SizeType n)
2856 { return this->data_type::internal.internal.priv_insertion_update_cache(n); }
2857
2858 template<bool Boolean>
2859 std::size_t priv_stored_or_compute_hash(const value_type &v, detail::bool_<Boolean> b) const
2860 { return this->data_type::internal.internal.internal.priv_stored_or_compute_hash(v, b); }
2861
2862 value_type &priv_value_from_slist_node(slist_node_ptr n)
2863 { return this->data_type::internal.internal.internal.internal.priv_value_from_slist_node(n); }
2864
2865 const value_type &priv_value_from_slist_node(slist_node_ptr n) const
2866 { return this->data_type::internal.internal.internal.internal.priv_value_from_slist_node(n); }
2867
2868 void priv_erasure_update_cache_range(SizeType first_bucket_num, SizeType last_bucket_num)
2869 { return this->data_type::internal.internal.priv_erasure_update_cache_range(first_bucket_num, last_bucket_num); }
2870
2871 void priv_erasure_update_cache()
2872 { return this->data_type::internal.internal.priv_erasure_update_cache(); }
2873
2874 static std::size_t priv_stored_hash(slist_node_ptr n, detail::true_ true_value)
2875 { return bucket_plus_vtraits<ValueTraits, BucketTraits>::priv_stored_hash(n, true_value); }
2876
2877 static std::size_t priv_stored_hash(slist_node_ptr n, detail::false_ false_value)
2878 { return bucket_plus_vtraits<ValueTraits, BucketTraits>::priv_stored_hash(n, false_value); }
2711 2879
2712 std::size_t priv_hash_to_bucket(std::size_t hash_value) const 2880 std::size_t priv_hash_to_bucket(std::size_t hash_value) const
2713 { 2881 {
2714 return detail::hash_to_bucket_split<power_2_buckets, incremental> 2882 return detail::hash_to_bucket_split<power_2_buckets, incremental>
2715 (hash_value, this->priv_real_bucket_traits().bucket_count(), this->priv_split_traits().get_size()); 2883 (hash_value, this->priv_bucket_traits().bucket_count(), this->priv_split_traits().get_size());
2716 } 2884 }
2717 2885
2718 template<class Disposer> 2886 template<class Disposer>
2719 void priv_erase_range_impl 2887 void priv_erase_range_impl
2720 (size_type bucket_num, siterator before_first_it, siterator end_sit, Disposer disposer, size_type &num_erased) 2888 (size_type bucket_num, siterator before_first_it, siterator end_sit, Disposer disposer, size_type &num_erased)
2788 return this->priv_hash_to_bucket 2956 return this->priv_hash_to_bucket
2789 (this->priv_stored_hash(it.pointed_node(), store_hash_t())); 2957 (this->priv_stored_hash(it.pointed_node(), store_hash_t()));
2790 } 2958 }
2791 2959
2792 std::size_t priv_get_bucket_num_hash_dispatch(siterator it, detail::false_) //NO store_hash 2960 std::size_t priv_get_bucket_num_hash_dispatch(siterator it, detail::false_) //NO store_hash
2793 { return this->priv_get_bucket_num_no_hash_store(it, optimize_multikey_t()); } 2961 { return this->data_type::internal.internal.internal.internal.priv_get_bucket_num_no_hash_store(it, optimize_multikey_t()); }
2794 2962
2795 static siterator priv_get_previous(bucket_type &b, siterator i) 2963 static siterator priv_get_previous(bucket_type &b, siterator i)
2796 { return bucket_plus_vtraits_t::priv_get_previous(b, i, optimize_multikey_t()); } 2964 { return bucket_plus_vtraits_t::priv_get_previous(b, i, optimize_multikey_t()); }
2797 2965
2798 static siterator priv_get_last(bucket_type &b) 2966 static siterator priv_get_last(bucket_type &b)
2946 siterator it = to_return.first; 3114 siterator it = to_return.first;
2947 if(optimize_multikey){ 3115 if(optimize_multikey){
2948 to_return.second = bucket_type::s_iterator_to 3116 to_return.second = bucket_type::s_iterator_to
2949 (*node_traits::get_next(group_functions_t::get_last_in_group 3117 (*node_traits::get_next(group_functions_t::get_last_in_group
2950 (detail::dcast_bucket_ptr<node>(it.pointed_node()), optimize_multikey_t()))); 3118 (detail::dcast_bucket_ptr<node>(it.pointed_node()), optimize_multikey_t())));
2951 cnt = std::distance(it, to_return.second); 3119
3120 cnt = 0;
3121 for(; it != to_return.second; ++it){ ++cnt; }
2952 if(to_return.second != b.end()){ 3122 if(to_return.second != b.end()){
2953 bucket_number_second = bucket_number_first; 3123 bucket_number_second = bucket_number_first;
2954 return to_return; 3124 return to_return;
2955 } 3125 }
2956 } 3126 }
3003 , class PackedOptions 3173 , class PackedOptions
3004 > 3174 >
3005 #else 3175 #else
3006 template <class T, bool UniqueKeys, class ...Options> 3176 template <class T, bool UniqueKeys, class ...Options>
3007 #endif 3177 #endif
3008 struct make_real_bucket_traits 3178 struct make_bucket_traits
3009 { 3179 {
3010 //Real value traits must be calculated from options 3180 //Real value traits must be calculated from options
3011 typedef typename detail::get_value_traits 3181 typedef typename detail::get_value_traits
3012 <T, typename PackedOptions::proto_value_traits>::type value_traits; 3182 <T, typename PackedOptions::proto_value_traits>::type value_traits;
3013 /* 3183
3014 static const bool resizable_bucket_traits =
3015 detail::resizable_bool_is_true<bucket_traits_traits>::value;*/
3016 typedef typename detail::get_real_value_traits<value_traits>::type real_value_traits;
3017 typedef typename PackedOptions::bucket_traits specified_bucket_traits; 3184 typedef typename PackedOptions::bucket_traits specified_bucket_traits;
3018 3185
3019 //Real bucket traits must be calculated from options and calculated value_traits 3186 //Real bucket traits must be calculated from options and calculated value_traits
3020 typedef typename detail::get_slist_impl 3187 typedef typename detail::get_slist_impl
3021 <typename detail::reduced_slist_node_traits 3188 <typename detail::reduced_slist_node_traits
3022 <typename real_value_traits::node_traits>::type 3189 <typename value_traits::node_traits>::type
3023 >::type slist_impl; 3190 >::type slist_impl;
3024 3191
3025 typedef typename 3192 typedef typename
3026 detail::if_c< detail::is_same 3193 detail::if_c< detail::is_same
3027 < specified_bucket_traits 3194 < specified_bucket_traits
3058 >::type packed_options; 3225 >::type packed_options;
3059 3226
3060 typedef typename detail::get_value_traits 3227 typedef typename detail::get_value_traits
3061 <T, typename packed_options::proto_value_traits>::type value_traits; 3228 <T, typename packed_options::proto_value_traits>::type value_traits;
3062 3229
3063 typedef typename make_real_bucket_traits 3230 typedef typename make_bucket_traits
3064 <T, false, packed_options>::type real_bucket_traits; 3231 <T, false, packed_options>::type bucket_traits;
3065 3232
3066 typedef hashtable_impl 3233 typedef hashtable_impl
3067 < value_traits 3234 < value_traits
3068 , typename packed_options::hash 3235 , typename packed_options::hash
3069 , typename packed_options::equal 3236 , typename packed_options::equal
3070 , typename packed_options::size_type 3237 , typename packed_options::size_type
3071 , real_bucket_traits 3238 , bucket_traits
3072 , (std::size_t(false)*hash_bool_flags::unique_keys_pos) 3239 , (std::size_t(false)*hash_bool_flags::unique_keys_pos)
3073 | (std::size_t(packed_options::constant_time_size)*hash_bool_flags::constant_time_size_pos) 3240 | (std::size_t(packed_options::constant_time_size)*hash_bool_flags::constant_time_size_pos)
3074 | (std::size_t(packed_options::power_2_buckets)*hash_bool_flags::power_2_buckets_pos) 3241 | (std::size_t(packed_options::power_2_buckets)*hash_bool_flags::power_2_buckets_pos)
3075 | (std::size_t(packed_options::cache_begin)*hash_bool_flags::cache_begin_pos) 3242 | (std::size_t(packed_options::cache_begin)*hash_bool_flags::cache_begin_pos)
3076 | (std::size_t(packed_options::compare_hash)*hash_bool_flags::compare_hash_pos) 3243 | (std::size_t(packed_options::compare_hash)*hash_bool_flags::compare_hash_pos)
3106 >::type Base; 3273 >::type Base;
3107 BOOST_MOVABLE_BUT_NOT_COPYABLE(hashtable) 3274 BOOST_MOVABLE_BUT_NOT_COPYABLE(hashtable)
3108 3275
3109 public: 3276 public:
3110 typedef typename Base::value_traits value_traits; 3277 typedef typename Base::value_traits value_traits;
3111 typedef typename Base::real_value_traits real_value_traits;
3112 typedef typename Base::iterator iterator; 3278 typedef typename Base::iterator iterator;
3113 typedef typename Base::const_iterator const_iterator; 3279 typedef typename Base::const_iterator const_iterator;
3114 typedef typename Base::bucket_ptr bucket_ptr; 3280 typedef typename Base::bucket_ptr bucket_ptr;
3115 typedef typename Base::size_type size_type; 3281 typedef typename Base::size_type size_type;
3116 typedef typename Base::hasher hasher; 3282 typedef typename Base::hasher hasher;
3117 typedef typename Base::bucket_traits bucket_traits; 3283 typedef typename Base::bucket_traits bucket_traits;
3118 typedef typename Base::key_equal key_equal; 3284 typedef typename Base::key_equal key_equal;
3119 3285
3120 //Assert if passed value traits are compatible with the type 3286 //Assert if passed value traits are compatible with the type
3121 BOOST_STATIC_ASSERT((detail::is_same<typename real_value_traits::value_type, T>::value)); 3287 BOOST_STATIC_ASSERT((detail::is_same<typename value_traits::value_type, T>::value));
3122 3288
3123 explicit hashtable ( const bucket_traits &b_traits 3289 explicit hashtable ( const bucket_traits &b_traits
3124 , const hasher & hash_func = hasher() 3290 , const hasher & hash_func = hasher()
3125 , const key_equal &equal_func = key_equal() 3291 , const key_equal &equal_func = key_equal()
3126 , const value_traits &v_traits = value_traits()) 3292 , const value_traits &v_traits = value_traits())
3127 : Base(b_traits, hash_func, equal_func, v_traits) 3293 : Base(b_traits, hash_func, equal_func, v_traits)
3128 {} 3294 {}
3129 3295
3130 hashtable(BOOST_RV_REF(hashtable) x) 3296 hashtable(BOOST_RV_REF(hashtable) x)
3131 : Base(::boost::move(static_cast<Base&>(x))) 3297 : Base(BOOST_MOVE_BASE(Base, x))
3132 {} 3298 {}
3133 3299
3134 hashtable& operator=(BOOST_RV_REF(hashtable) x) 3300 hashtable& operator=(BOOST_RV_REF(hashtable) x)
3135 { return static_cast<hashtable&>(this->Base::operator=(::boost::move(static_cast<Base&>(x)))); } 3301 { return static_cast<hashtable&>(this->Base::operator=(BOOST_MOVE_BASE(Base, x))); }
3136 }; 3302 };
3137 3303
3138 #endif 3304 #endif
3139 3305
3140 } //namespace intrusive 3306 } //namespace intrusive