LCOV - code coverage report
Current view: top level - usr/include/boost/unordered/detail - implementation.hpp (source / functions) Hit Total Coverage
Test: ROSE Lines: 341 583 58.5 %
Date: 2022-12-08 13:48:47 Functions: 38 597 6.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
       2             : // Copyright (C) 2005-2016 Daniel James
       3             : //
       4             : // Distributed under the Boost Software License, Version 1.0. (See accompanying
       5             : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
       6             : 
       7             : #ifndef BOOST_UNORDERED_DETAIL_IMPLEMENTATION_HPP
       8             : #define BOOST_UNORDERED_DETAIL_IMPLEMENTATION_HPP
       9             : 
      10             : #include <boost/config.hpp>
      11             : #if defined(BOOST_HAS_PRAGMA_ONCE)
      12             : #pragma once
      13             : #endif
      14             : 
      15             : #include <boost/assert.hpp>
      16             : #include <boost/core/no_exceptions_support.hpp>
      17             : #include <boost/core/pointer_traits.hpp>
      18             : #include <boost/detail/select_type.hpp>
      19             : #include <boost/limits.hpp>
      20             : #include <boost/move/move.hpp>
      21             : #include <boost/preprocessor/arithmetic/inc.hpp>
      22             : #include <boost/preprocessor/cat.hpp>
      23             : #include <boost/preprocessor/repetition/enum.hpp>
      24             : #include <boost/preprocessor/repetition/enum_binary_params.hpp>
      25             : #include <boost/preprocessor/repetition/enum_params.hpp>
      26             : #include <boost/preprocessor/repetition/repeat_from_to.hpp>
      27             : #include <boost/preprocessor/seq/enum.hpp>
      28             : #include <boost/preprocessor/seq/size.hpp>
      29             : #include <boost/swap.hpp>
      30             : #include <boost/throw_exception.hpp>
      31             : #include <boost/tuple/tuple.hpp>
      32             : #include <boost/type_traits/add_lvalue_reference.hpp>
      33             : #include <boost/type_traits/aligned_storage.hpp>
      34             : #include <boost/type_traits/alignment_of.hpp>
      35             : #include <boost/type_traits/integral_constant.hpp>
      36             : #include <boost/type_traits/is_base_of.hpp>
      37             : #include <boost/type_traits/is_class.hpp>
      38             : #include <boost/type_traits/is_empty.hpp>
      39             : #include <boost/type_traits/is_nothrow_move_assignable.hpp>
      40             : #include <boost/type_traits/is_nothrow_move_constructible.hpp>
      41             : #include <boost/type_traits/is_nothrow_swappable.hpp>
      42             : #include <boost/type_traits/is_same.hpp>
      43             : #include <boost/type_traits/remove_const.hpp>
      44             : #include <boost/unordered/detail/fwd.hpp>
      45             : #include <boost/utility/addressof.hpp>
      46             : #include <boost/utility/enable_if.hpp>
      47             : #include <cmath>
      48             : #include <iterator>
      49             : #include <stdexcept>
      50             : #include <utility>
      51             : 
      52             : #if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
      53             : #include <type_traits>
      54             : #endif
      55             : 
      56             : ////////////////////////////////////////////////////////////////////////////////
      57             : // Configuration
      58             : //
      59             : // Unless documented elsewhere these configuration macros should be considered
      60             : // an implementation detail, I'll try not to break them, but you never know.
      61             : 
      62             : // Use Sun C++ workarounds
      63             : // I'm not sure which versions of the compiler require these workarounds, so
      64             : // I'm just using them of everything older than the current test compilers
      65             : // (as of May 2017).
      66             : 
      67             : #if !defined(BOOST_UNORDERED_SUN_WORKAROUNDS1)
      68             : #if BOOST_COMP_SUNPRO && BOOST_COMP_SUNPRO < BOOST_VERSION_NUMBER(5, 20, 0)
      69             : #define BOOST_UNORDERED_SUN_WORKAROUNDS1 1
      70             : #else
      71             : #define BOOST_UNORDERED_SUN_WORKAROUNDS1 0
      72             : #endif
      73             : #endif
      74             : 
      75             : // BOOST_UNORDERED_EMPLACE_LIMIT = The maximum number of parameters in
      76             : // emplace (not including things like hints). Don't set it to a lower value, as
      77             : // that might break something.
      78             : 
      79             : #if !defined BOOST_UNORDERED_EMPLACE_LIMIT
      80             : #define BOOST_UNORDERED_EMPLACE_LIMIT 10
      81             : #endif
      82             : 
      83             : // BOOST_UNORDERED_USE_ALLOCATOR_TRAITS - Pick which version of
      84             : // allocator_traits to use.
      85             : //
      86             : // 0 = Own partial implementation
      87             : // 1 = std::allocator_traits
      88             : // 2 = boost::container::allocator_traits
      89             : 
      90             : #if !defined(BOOST_UNORDERED_USE_ALLOCATOR_TRAITS)
      91             : #if !defined(BOOST_NO_CXX11_ALLOCATOR)
      92             : #define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 1
      93             : #elif defined(BOOST_MSVC)
      94             : #if BOOST_MSVC < 1400
      95             : // Use container's allocator_traits for older versions of Visual
      96             : // C++ as I don't test with them.
      97             : #define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 2
      98             : #endif
      99             : #endif
     100             : #endif
     101             : 
     102             : #if !defined(BOOST_UNORDERED_USE_ALLOCATOR_TRAITS)
     103             : #define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 0
     104             : #endif
     105             : 
     106             : // BOOST_UNORDERED_TUPLE_ARGS
     107             : //
     108             : // Maximum number of std::tuple members to support, or 0 if std::tuple
     109             : // isn't avaiable. More are supported when full C++11 is used.
     110             : 
     111             : // Already defined, so do nothing
     112             : #if defined(BOOST_UNORDERED_TUPLE_ARGS)
     113             : 
     114             : // Assume if we have C++11 tuple it's properly variadic,
     115             : // and just use a max number of 10 arguments.
     116             : #elif !defined(BOOST_NO_CXX11_HDR_TUPLE)
     117             : #define BOOST_UNORDERED_TUPLE_ARGS 10
     118             : 
     119             : // Visual C++ has a decent enough tuple for piecewise construction,
     120             : // so use that if available, using _VARIADIC_MAX for the maximum
     121             : // number of parameters. Note that this comes after the check
     122             : // for a full C++11 tuple.
     123             : #elif defined(BOOST_MSVC)
     124             : #if !BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT
     125             : #define BOOST_UNORDERED_TUPLE_ARGS 0
     126             : #elif defined(_VARIADIC_MAX)
     127             : #define BOOST_UNORDERED_TUPLE_ARGS _VARIADIC_MAX
     128             : #else
     129             : #define BOOST_UNORDERED_TUPLE_ARGS 5
     130             : #endif
     131             : 
     132             : // Assume that we don't have std::tuple
     133             : #else
     134             : #define BOOST_UNORDERED_TUPLE_ARGS 0
     135             : #endif
     136             : 
     137             : #if BOOST_UNORDERED_TUPLE_ARGS
     138             : #include <tuple>
     139             : #endif
     140             : 
     141             : // BOOST_UNORDERED_CXX11_CONSTRUCTION
     142             : //
     143             : // Use C++11 construction, requires variadic arguments, good construct support
     144             : // in allocator_traits and piecewise construction of std::pair
     145             : // Otherwise allocators aren't used for construction/destruction
     146             : 
     147             : #if BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT &&                                \
     148             :   !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && BOOST_UNORDERED_TUPLE_ARGS
     149             : #if BOOST_COMP_SUNPRO && BOOST_LIB_STD_GNU
     150             : // Sun C++ std::pair piecewise construction doesn't seem to be exception safe.
     151             : // (At least for Sun C++ 12.5 using libstdc++).
     152             : #define BOOST_UNORDERED_CXX11_CONSTRUCTION 0
     153             : #elif BOOST_COMP_GNUC && BOOST_COMP_GNUC < BOOST_VERSION_NUMBER(4, 7, 0)
     154             : // Piecewise construction in GCC 4.6 doesn't work for uncopyable types.
     155             : #define BOOST_UNORDERED_CXX11_CONSTRUCTION 0
     156             : #elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 0 &&                             \
     157             :   !defined(BOOST_NO_SFINAE_EXPR)
     158             : #define BOOST_UNORDERED_CXX11_CONSTRUCTION 1
     159             : #elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
     160             : #define BOOST_UNORDERED_CXX11_CONSTRUCTION 1
     161             : #endif
     162             : #endif
     163             : 
     164             : #if !defined(BOOST_UNORDERED_CXX11_CONSTRUCTION)
     165             : #define BOOST_UNORDERED_CXX11_CONSTRUCTION 0
     166             : #endif
     167             : 
     168             : // BOOST_UNORDERED_SUPPRESS_DEPRECATED
     169             : //
     170             : // Define to stop deprecation attributes
     171             : 
     172             : #if defined(BOOST_UNORDERED_SUPPRESS_DEPRECATED)
     173             : #define BOOST_UNORDERED_DEPRECATED(msg)
     174             : #endif
     175             : 
     176             : // BOOST_UNORDERED_DEPRECATED
     177             : //
     178             : // Wrapper around various depreaction attributes.
     179             : 
     180             : #if defined(__has_cpp_attribute) &&                                            \
     181             :   (!defined(__cplusplus) || __cplusplus >= 201402)
     182             : #if __has_cpp_attribute(deprecated) && !defined(BOOST_UNORDERED_DEPRECATED)
     183             : #define BOOST_UNORDERED_DEPRECATED(msg) [[deprecated(msg)]]
     184             : #endif
     185             : #endif
     186             : 
     187             : #if !defined(BOOST_UNORDERED_DEPRECATED)
     188             : #if defined(__GNUC__) && __GNUC__ >= 4
     189             : #define BOOST_UNORDERED_DEPRECATED(msg) __attribute__((deprecated))
     190             : #elif defined(_MSC_VER) && _MSC_VER >= 1400
     191             : #define BOOST_UNORDERED_DEPRECATED(msg) __declspec(deprecated(msg))
     192             : #elif defined(_MSC_VER) && _MSC_VER >= 1310
     193             : #define BOOST_UNORDERED_DEPRECATED(msg) __declspec(deprecated)
     194             : #else
     195             : #define BOOST_UNORDERED_DEPRECATED(msg)
     196             : #endif
     197             : #endif
     198             : 
     199             : // BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES
     200             : 
     201             : #if !defined(BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES)
     202             : #if BOOST_COMP_CLANG && __cplusplus >= 201703
     203             : #define BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES 1
     204             : #endif
     205             : #endif
     206             : 
     207             : #if !defined(BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES)
     208             : #define BOOST_UNORDERED_TEMPLATE_DEDUCTION_GUIDES 0
     209             : #endif
     210             : 
     211             : namespace boost {
     212             :   namespace unordered {
     213             :     namespace iterator_detail {
     214             :       template <typename Node> struct iterator;
     215             :       template <typename Node> struct c_iterator;
     216             :       template <typename Node> struct l_iterator;
     217             :       template <typename Node> struct cl_iterator;
     218             :     }
     219             :   }
     220             : }
     221             : 
     222             : namespace boost {
     223             :   namespace unordered {
     224             :     namespace detail {
     225             : 
     226             :       template <typename Types> struct table;
     227             :       template <typename NodePointer> struct bucket;
     228             :       struct ptr_bucket;
     229             : 
     230             :       template <typename A, typename T> struct node;
     231             :       template <typename T> struct ptr_node;
     232             : 
     233             :       static const float minimum_max_load_factor = 1e-3f;
     234             :       static const std::size_t default_bucket_count = 11;
     235             : 
     236             :       struct move_tag
     237             :       {
     238             :       };
     239             : 
     240             :       struct empty_emplace
     241             :       {
     242             :       };
     243             : 
     244             :       struct no_key
     245             :       {
     246             :         no_key() {}
     247             :         template <class T> no_key(T const&) {}
     248             :       };
     249             : 
     250             :       namespace func {
     251             :         template <class T> inline void ignore_unused_variable_warning(T const&)
     252             :         {
     253             :         }
     254             :       }
     255             : 
     256             :       //////////////////////////////////////////////////////////////////////////
     257             :       // iterator SFINAE
     258             : 
     259             :       template <typename I>
     260             :       struct is_forward : boost::is_base_of<std::forward_iterator_tag,
     261             :                             typename std::iterator_traits<I>::iterator_category>
     262             :       {
     263             :       };
     264             : 
     265             :       template <typename I, typename ReturnType>
     266             :       struct enable_if_forward
     267             :         : boost::enable_if_c<boost::unordered::detail::is_forward<I>::value,
     268             :             ReturnType>
     269             :       {
     270             :       };
     271             : 
     272             :       template <typename I, typename ReturnType>
     273             :       struct disable_if_forward
     274             :         : boost::disable_if_c<boost::unordered::detail::is_forward<I>::value,
     275             :             ReturnType>
     276             :       {
     277             :       };
     278             :     }
     279             :   }
     280             : }
     281             : 
     282             : ////////////////////////////////////////////////////////////////////////////////
     283             : // primes
     284             : 
     285             : // clang-format off
     286             : #define BOOST_UNORDERED_PRIMES \
     287             :     (17ul)(29ul)(37ul)(53ul)(67ul)(79ul) \
     288             :     (97ul)(131ul)(193ul)(257ul)(389ul)(521ul)(769ul) \
     289             :     (1031ul)(1543ul)(2053ul)(3079ul)(6151ul)(12289ul)(24593ul) \
     290             :     (49157ul)(98317ul)(196613ul)(393241ul)(786433ul) \
     291             :     (1572869ul)(3145739ul)(6291469ul)(12582917ul)(25165843ul) \
     292             :     (50331653ul)(100663319ul)(201326611ul)(402653189ul)(805306457ul) \
     293             :     (1610612741ul)(3221225473ul)(4294967291ul)
     294             : // clang-format on
     295             : 
     296             : namespace boost {
     297             :   namespace unordered {
     298             :     namespace detail {
     299             :       template <class T> struct prime_list_template
     300             :       {
     301             :         static std::size_t const value[];
     302             : 
     303             : #if !BOOST_UNORDERED_SUN_WORKAROUNDS1
     304             :         static std::ptrdiff_t const length;
     305             : #else
     306             :         static std::ptrdiff_t const length =
     307             :           BOOST_PP_SEQ_SIZE(BOOST_UNORDERED_PRIMES);
     308             : #endif
     309             :       };
     310             : 
     311             :       template <class T>
     312             :       std::size_t const prime_list_template<T>::value[] = {
     313             :         BOOST_PP_SEQ_ENUM(BOOST_UNORDERED_PRIMES)};
     314             : 
     315             : #if !BOOST_UNORDERED_SUN_WORKAROUNDS1
     316             :       template <class T>
     317             :       std::ptrdiff_t const prime_list_template<T>::length = BOOST_PP_SEQ_SIZE(
     318             :         BOOST_UNORDERED_PRIMES);
     319             : #endif
     320             : 
     321             : #undef BOOST_UNORDERED_PRIMES
     322             : 
     323             :       typedef prime_list_template<std::size_t> prime_list;
     324             : 
     325             :       // no throw
     326           0 :       inline std::size_t next_prime(std::size_t num)
     327             :       {
     328           0 :         std::size_t const* const prime_list_begin = prime_list::value;
     329           0 :         std::size_t const* const prime_list_end =
     330             :           prime_list_begin + prime_list::length;
     331           0 :         std::size_t const* bound =
     332           0 :           std::lower_bound(prime_list_begin, prime_list_end, num);
     333           0 :         if (bound == prime_list_end)
     334           0 :           bound--;
     335           0 :         return *bound;
     336             :       }
     337             : 
     338             :       // no throw
     339             :       inline std::size_t prev_prime(std::size_t num)
     340             :       {
     341             :         std::size_t const* const prime_list_begin = prime_list::value;
     342             :         std::size_t const* const prime_list_end =
     343             :           prime_list_begin + prime_list::length;
     344             :         std::size_t const* bound =
     345             :           std::upper_bound(prime_list_begin, prime_list_end, num);
     346             :         if (bound != prime_list_begin)
     347             :           bound--;
     348             :         return *bound;
     349             :       }
     350             : 
     351             :       //////////////////////////////////////////////////////////////////////////
     352             :       // insert_size/initial_size
     353             : 
     354             :       template <class I>
     355           0 :       inline std::size_t insert_size(I i, I j,
     356             :         typename boost::unordered::detail::enable_if_forward<I, void*>::type =
     357             :           0)
     358             :       {
     359           0 :         return static_cast<std::size_t>(std::distance(i, j));
     360             :       }
     361             : 
     362             :       template <class I>
     363             :       inline std::size_t insert_size(I, I,
     364             :         typename boost::unordered::detail::disable_if_forward<I, void*>::type =
     365             :           0)
     366             :       {
     367             :         return 1;
     368             :       }
     369             : 
     370             :       template <class I>
     371             :       inline std::size_t initial_size(I i, I j,
     372             :         std::size_t num_buckets =
     373             :           boost::unordered::detail::default_bucket_count)
     374             :       {
     375             :         return (std::max)(
     376             :           boost::unordered::detail::insert_size(i, j), num_buckets);
     377             :       }
     378             : 
     379             :       //////////////////////////////////////////////////////////////////////////
     380             :       // compressed
     381             : 
     382       55170 :       template <typename T, int Index> struct compressed_base : private T
     383             :       {
     384      304103 :         compressed_base(T const& x) : T(x) {}
     385           0 :         compressed_base(T& x, move_tag) : T(boost::move(x)) {}
     386             : 
     387     5257417 :         T& get() { return *this; }
     388         671 :         T const& get() const { return *this; }
     389             :       };
     390             : 
     391             :       template <typename T, int Index> struct uncompressed_base
     392             :       {
     393      304102 :         uncompressed_base(T const& x) : value_(x) {}
     394             :         uncompressed_base(T& x, move_tag) : value_(boost::move(x)) {}
     395             : 
     396             :         T& get() { return value_; }
     397    61990022 :         T const& get() const { return value_; }
     398             : 
     399             :       private:
     400             :         T value_;
     401             :       };
     402             : 
     403             :       template <typename T, int Index>
     404             :       struct generate_base
     405             :         : boost::detail::if_true<
     406             :             boost::is_empty<T>::value>::BOOST_NESTED_TEMPLATE
     407             :             then<boost::unordered::detail::compressed_base<T, Index>,
     408             :               boost::unordered::detail::uncompressed_base<T, Index> >
     409             :       {
     410             :       };
     411             : 
     412             :       template <typename T1, typename T2>
     413       55170 :       struct compressed
     414             :         : private boost::unordered::detail::generate_base<T1, 1>::type,
     415             :           private boost::unordered::detail::generate_base<T2, 2>::type
     416             :       {
     417             :         typedef typename generate_base<T1, 1>::type base1;
     418             :         typedef typename generate_base<T2, 2>::type base2;
     419             : 
     420             :         typedef T1 first_type;
     421             :         typedef T2 second_type;
     422             : 
     423      102604 :         first_type& first() { return static_cast<base1*>(this)->get(); }
     424             : 
     425    40859693 :         first_type const& first() const
     426             :         {
     427    16211551 :           return static_cast<base1 const*>(this)->get();
     428             :         }
     429             : 
     430     5154820 :         second_type& second() { return static_cast<base2*>(this)->get(); }
     431             : 
     432    56394981 :         second_type const& second() const
     433             :         {
     434    13064809 :           return static_cast<base2 const*>(this)->get();
     435             :         }
     436             : 
     437             :         template <typename First, typename Second>
     438      304103 :         compressed(First const& x1, Second const& x2) : base1(x1), base2(x2)
     439             :         {
     440             :         }
     441             : 
     442           0 :         compressed(compressed const& x) : base1(x.first()), base2(x.second()) {}
     443             : 
     444           0 :         compressed(compressed& x, move_tag m)
     445           0 :             : base1(x.first(), m), base2(x.second(), m)
     446             :         {
     447             :         }
     448             : 
     449             :         void assign(compressed const& x)
     450             :         {
     451             :           first() = x.first();
     452             :           second() = x.second();
     453             :         }
     454             : 
     455             :         void move_assign(compressed& x)
     456             :         {
     457             :           first() = boost::move(x.first());
     458             :           second() = boost::move(x.second());
     459             :         }
     460             : 
     461             :         void swap(compressed& x)
     462             :         {
     463             :           boost::swap(first(), x.first());
     464             :           boost::swap(second(), x.second());
     465             :         }
     466             : 
     467             :       private:
     468             :         // Prevent assignment just to make use of assign or
     469             :         // move_assign explicit.
     470             :         compressed& operator=(compressed const&);
     471             :       };
     472             : 
     473             :       //////////////////////////////////////////////////////////////////////////
     474             :       // pair_traits
     475             :       //
     476             :       // Used to get the types from a pair without instantiating it.
     477             : 
     478             :       template <typename Pair> struct pair_traits
     479             :       {
     480             :         typedef typename Pair::first_type first_type;
     481             :         typedef typename Pair::second_type second_type;
     482             :       };
     483             : 
     484             :       template <typename T1, typename T2> struct pair_traits<std::pair<T1, T2> >
     485             :       {
     486             :         typedef T1 first_type;
     487             :         typedef T2 second_type;
     488             :       };
     489             : 
     490             : #if defined(BOOST_MSVC)
     491             : #pragma warning(push)
     492             : #pragma warning(disable : 4512) // assignment operator could not be generated.
     493             : #pragma warning(disable : 4345) // behavior change: an object of POD type
     494             : // constructed with an initializer of the form ()
     495             : // will be default-initialized.
     496             : #endif
     497             : 
     498             :       //////////////////////////////////////////////////////////////////////////
     499             :       // Bits and pieces for implementing traits
     500             : 
     501             :       template <typename T>
     502             :       typename boost::add_lvalue_reference<T>::type make();
     503             :       struct choice9
     504             :       {
     505             :         typedef char (&type)[9];
     506             :       };
     507             :       struct choice8 : choice9
     508             :       {
     509             :         typedef char (&type)[8];
     510             :       };
     511             :       struct choice7 : choice8
     512             :       {
     513             :         typedef char (&type)[7];
     514             :       };
     515             :       struct choice6 : choice7
     516             :       {
     517             :         typedef char (&type)[6];
     518             :       };
     519             :       struct choice5 : choice6
     520             :       {
     521             :         typedef char (&type)[5];
     522             :       };
     523             :       struct choice4 : choice5
     524             :       {
     525             :         typedef char (&type)[4];
     526             :       };
     527             :       struct choice3 : choice4
     528             :       {
     529             :         typedef char (&type)[3];
     530             :       };
     531             :       struct choice2 : choice3
     532             :       {
     533             :         typedef char (&type)[2];
     534             :       };
     535             :       struct choice1 : choice2
     536             :       {
     537             :         typedef char (&type)[1];
     538             :       };
     539             :       choice1 choose();
     540             : 
     541             :       typedef choice1::type yes_type;
     542             :       typedef choice2::type no_type;
     543             : 
     544             :       struct private_type
     545             :       {
     546             :         private_type const& operator,(int) const;
     547             :       };
     548             : 
     549             :       template <typename T> no_type is_private_type(T const&);
     550             :       yes_type is_private_type(private_type const&);
     551             : 
     552             :       struct convert_from_anything
     553             :       {
     554             :         template <typename T> convert_from_anything(T const&);
     555             :       };
     556             :     }
     557             :   }
     558             : }
     559             : 
     560             : ////////////////////////////////////////////////////////////////////////////
     561             : // emplace_args
     562             : //
     563             : // Either forwarding variadic arguments, or storing the arguments in
     564             : // emplace_args##n
     565             : 
     566             : #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
     567             : 
     568             : #define BOOST_UNORDERED_EMPLACE_TEMPLATE typename... Args
     569             : #define BOOST_UNORDERED_EMPLACE_ARGS BOOST_FWD_REF(Args)... args
     570             : #define BOOST_UNORDERED_EMPLACE_FORWARD boost::forward<Args>(args)...
     571             : 
     572             : #else
     573             : 
     574             : #define BOOST_UNORDERED_EMPLACE_TEMPLATE typename Args
     575             : #define BOOST_UNORDERED_EMPLACE_ARGS Args const& args
     576             : #define BOOST_UNORDERED_EMPLACE_FORWARD args
     577             : 
     578             : #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
     579             : 
     580             : #define BOOST_UNORDERED_EARGS_MEMBER(z, n, _)                                  \
     581             :   typedef BOOST_FWD_REF(BOOST_PP_CAT(A, n)) BOOST_PP_CAT(Arg, n);              \
     582             :   BOOST_PP_CAT(Arg, n) BOOST_PP_CAT(a, n);
     583             : 
     584             : #else
     585             : 
     586             : #define BOOST_UNORDERED_EARGS_MEMBER(z, n, _)                                  \
     587             :   typedef typename boost::add_lvalue_reference<BOOST_PP_CAT(A, n)>::type       \
     588             :     BOOST_PP_CAT(Arg, n);                                                      \
     589             :   BOOST_PP_CAT(Arg, n) BOOST_PP_CAT(a, n);
     590             : 
     591             : #endif
     592             : 
     593             : #define BOOST_UNORDERED_FWD_PARAM(z, n, a)                                     \
     594             :   BOOST_FWD_REF(BOOST_PP_CAT(A, n)) BOOST_PP_CAT(a, n)
     595             : 
     596             : #define BOOST_UNORDERED_CALL_FORWARD(z, i, a)                                  \
     597             :   boost::forward<BOOST_PP_CAT(A, i)>(BOOST_PP_CAT(a, i))
     598             : 
     599             : #define BOOST_UNORDERED_EARGS_INIT(z, n, _)                                    \
     600             :   BOOST_PP_CAT(a, n)(BOOST_PP_CAT(b, n))
     601             : 
     602             : #define BOOST_UNORDERED_EARGS(z, n, _)                                         \
     603             :   template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)>                          \
     604             :   struct BOOST_PP_CAT(emplace_args, n)                                         \
     605             :   {                                                                            \
     606             :     BOOST_PP_REPEAT_##z(n, BOOST_UNORDERED_EARGS_MEMBER, _) BOOST_PP_CAT(      \
     607             :       emplace_args, n)(BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, Arg, b))            \
     608             :         : BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_EARGS_INIT, _)                  \
     609             :     {                                                                          \
     610             :     }                                                                          \
     611             :   };                                                                           \
     612             :                                                                                \
     613             :   template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)>                          \
     614             :   inline BOOST_PP_CAT(emplace_args, n)<BOOST_PP_ENUM_PARAMS_Z(z, n, A)>        \
     615             :     create_emplace_args(BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, b))    \
     616             :   {                                                                            \
     617             :     BOOST_PP_CAT(emplace_args, n)<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> e(          \
     618             :       BOOST_PP_ENUM_PARAMS_Z(z, n, b));                                        \
     619             :     return e;                                                                  \
     620             :   }
     621             : 
     622             : namespace boost {
     623             :   namespace unordered {
     624             :     namespace detail {
     625             :       template <typename A0> struct emplace_args1
     626             :       {
     627             :         BOOST_UNORDERED_EARGS_MEMBER(1, 0, _)
     628             : 
     629             :         explicit emplace_args1(Arg0 b0) : a0(b0) {}
     630             :       };
     631             : 
     632             :       template <typename A0>
     633             :       inline emplace_args1<A0> create_emplace_args(BOOST_FWD_REF(A0) b0)
     634             :       {
     635             :         emplace_args1<A0> e(b0);
     636             :         return e;
     637             :       }
     638             : 
     639             :       template <typename A0, typename A1> struct emplace_args2
     640             :       {
     641             :         BOOST_UNORDERED_EARGS_MEMBER(1, 0, _)
     642             :         BOOST_UNORDERED_EARGS_MEMBER(1, 1, _)
     643             : 
     644             :         emplace_args2(Arg0 b0, Arg1 b1) : a0(b0), a1(b1) {}
     645             :       };
     646             : 
     647             :       template <typename A0, typename A1>
     648             :       inline emplace_args2<A0, A1> create_emplace_args(
     649             :         BOOST_FWD_REF(A0) b0, BOOST_FWD_REF(A1) b1)
     650             :       {
     651             :         emplace_args2<A0, A1> e(b0, b1);
     652             :         return e;
     653             :       }
     654             : 
     655             :       template <typename A0, typename A1, typename A2> struct emplace_args3
     656             :       {
     657             :         BOOST_UNORDERED_EARGS_MEMBER(1, 0, _)
     658             :         BOOST_UNORDERED_EARGS_MEMBER(1, 1, _)
     659             :         BOOST_UNORDERED_EARGS_MEMBER(1, 2, _)
     660             : 
     661             :         emplace_args3(Arg0 b0, Arg1 b1, Arg2 b2) : a0(b0), a1(b1), a2(b2) {}
     662             :       };
     663             : 
     664             :       template <typename A0, typename A1, typename A2>
     665             :       inline emplace_args3<A0, A1, A2> create_emplace_args(
     666             :         BOOST_FWD_REF(A0) b0, BOOST_FWD_REF(A1) b1, BOOST_FWD_REF(A2) b2)
     667             :       {
     668             :         emplace_args3<A0, A1, A2> e(b0, b1, b2);
     669             :         return e;
     670             :       }
     671             : 
     672             :       BOOST_UNORDERED_EARGS(1, 4, _)
     673             :       BOOST_UNORDERED_EARGS(1, 5, _)
     674             :       BOOST_UNORDERED_EARGS(1, 6, _)
     675             :       BOOST_UNORDERED_EARGS(1, 7, _)
     676             :       BOOST_UNORDERED_EARGS(1, 8, _)
     677             :       BOOST_UNORDERED_EARGS(1, 9, _)
     678             :       BOOST_PP_REPEAT_FROM_TO(10, BOOST_PP_INC(BOOST_UNORDERED_EMPLACE_LIMIT),
     679             :         BOOST_UNORDERED_EARGS, _)
     680             :     }
     681             :   }
     682             : }
     683             : 
     684             : #undef BOOST_UNORDERED_DEFINE_EMPLACE_ARGS
     685             : #undef BOOST_UNORDERED_EARGS_MEMBER
     686             : #undef BOOST_UNORDERED_EARGS_INIT
     687             : 
     688             : #endif
     689             : 
     690             : ////////////////////////////////////////////////////////////////////////////////
     691             : //
     692             : // Some utilities for implementing allocator_traits, but useful elsewhere so
     693             : // they're always defined.
     694             : 
     695             : namespace boost {
     696             :   namespace unordered {
     697             :     namespace detail {
     698             : 
     699             : ////////////////////////////////////////////////////////////////////////////
     700             : // Integral_constrant, true_type, false_type
     701             : //
     702             : // Uses the standard versions if available.
     703             : 
     704             : #if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
     705             : 
     706             :       using std::integral_constant;
     707             :       using std::true_type;
     708             :       using std::false_type;
     709             : 
     710             : #else
     711             : 
     712             :       template <typename T, T Value> struct integral_constant
     713             :       {
     714             :         enum
     715             :         {
     716             :           value = Value
     717             :         };
     718             :       };
     719             : 
     720             :       typedef boost::unordered::detail::integral_constant<bool, true> true_type;
     721             :       typedef boost::unordered::detail::integral_constant<bool, false>
     722             :         false_type;
     723             : 
     724             : #endif
     725             : 
     726             : ////////////////////////////////////////////////////////////////////////////
     727             : // Explicitly call a destructor
     728             : 
     729             : #if defined(BOOST_MSVC)
     730             : #pragma warning(push)
     731             : #pragma warning(disable : 4100) // unreferenced formal parameter
     732             : #endif
     733             : 
     734             :       namespace func {
     735      183546 :         template <class T> inline void destroy(T* x) { x->~T(); }
     736             :       }
     737             : 
     738             : #if defined(BOOST_MSVC)
     739             : #pragma warning(pop)
     740             : #endif
     741             : 
     742             :       //////////////////////////////////////////////////////////////////////////
     743             :       // value_base
     744             :       //
     745             :       // Space used to store values.
     746             : 
     747             :       template <typename ValueType> struct value_base
     748             :       {
     749             :         typedef ValueType value_type;
     750             : 
     751             :         typename boost::aligned_storage<sizeof(value_type),
     752             :           boost::alignment_of<value_type>::value>::type data_;
     753             : 
     754             :         value_base() : data_() {}
     755             : 
     756             :         void* address() { return this; }
     757             : 
     758    70494441 :         value_type& value() { return *(ValueType*)this; }
     759             : 
     760             :         value_type const& value() const { return *(ValueType const*)this; }
     761             : 
     762    73826092 :         value_type* value_ptr() { return (ValueType*)this; }
     763             : 
     764             :         value_type const* value_ptr() const { return (ValueType const*)this; }
     765             : 
     766             :       private:
     767             :         value_base& operator=(value_base const&);
     768             :       };
     769             : 
     770             :       //////////////////////////////////////////////////////////////////////////
     771             :       // optional
     772             :       // TODO: Use std::optional when available.
     773             : 
     774             :       template <typename T> class optional
     775             :       {
     776             :         BOOST_MOVABLE_BUT_NOT_COPYABLE(optional)
     777             : 
     778             :         boost::unordered::detail::value_base<T> value_;
     779             :         bool has_value_;
     780             : 
     781             :         void destroy()
     782             :         {
     783             :           if (has_value_) {
     784             :             boost::unordered::detail::func::destroy(value_.value_ptr());
     785             :             has_value_ = false;
     786             :           }
     787             :         }
     788             : 
     789             :         void move(optional<T>& x)
     790             :         {
     791             :           BOOST_ASSERT(!has_value_ && x.has_value_);
     792             :           new (value_.value_ptr()) T(boost::move(x.value_.value()));
     793             :           boost::unordered::detail::func::destroy(x.value_.value_ptr());
     794             :           has_value_ = true;
     795             :           x.has_value_ = false;
     796             :         }
     797             : 
     798             :       public:
     799             :         optional() BOOST_NOEXCEPT : has_value_(false) {}
     800             : 
     801             :         optional(BOOST_RV_REF(optional<T>) x) : has_value_(false)
     802             :         {
     803             :           if (x.has_value_) {
     804             :             move(x);
     805             :           }
     806             :         }
     807             : 
     808             :         explicit optional(T const& x) : has_value_(true)
     809             :         {
     810             :           new (value_.value_ptr()) T(x);
     811             :         }
     812             : 
     813             :         optional& operator=(BOOST_RV_REF(optional<T>) x)
     814             :         {
     815             :           destroy();
     816             :           if (x.has_value_) {
     817             :             move(x);
     818             :           }
     819             :           return *this;
     820             :         }
     821             : 
     822             :         ~optional() { destroy(); }
     823             : 
     824             :         bool has_value() const { return has_value_; }
     825             :         T& operator*() { return value_.value(); }
     826             :         T const& operator*() const { return value_.value(); }
     827             :         T* operator->() { return value_.value_ptr(); }
     828             :         T const* operator->() const { return value_.value_ptr(); }
     829             : 
     830             :         bool operator==(optional<T> const& x)
     831             :         {
     832             :           return has_value_ ? x.has_value_ && value_.value() == x.value_.value()
     833             :                             : !x.has_value_;
     834             :         }
     835             : 
     836             :         bool operator!=(optional<T> const& x) { return !((*this) == x); }
     837             : 
     838             :         void swap(optional<T>& x)
     839             :         {
     840             :           if (has_value_ != x.has_value_) {
     841             :             if (has_value_) {
     842             :               x.move(*this);
     843             :             } else {
     844             :               move(x);
     845             :             }
     846             :           } else if (has_value_) {
     847             :             boost::swap(value_.value(), x.value_.value());
     848             :           }
     849             :         }
     850             : 
     851             :         friend void swap(optional<T>& x, optional<T>& y) { x.swap(y); }
     852             :       };
     853             :     }
     854             :   }
     855             : }
     856             : 
     857             : ////////////////////////////////////////////////////////////////////////////
     858             : // Expression test mechanism
     859             : //
     860             : // When SFINAE expressions are available, define
     861             : // BOOST_UNORDERED_HAS_FUNCTION which can check if a function call is
     862             : // supported by a class, otherwise define BOOST_UNORDERED_HAS_MEMBER which
     863             : // can detect if a class has the specified member, but not that it has the
     864             : // correct type, this is good enough for a passable impression of
     865             : // allocator_traits.
     866             : 
     867             : #if !defined(BOOST_NO_SFINAE_EXPR)
     868             : 
     869             : namespace boost {
     870             :   namespace unordered {
     871             :     namespace detail {
     872             :       template <typename T, long unsigned int> struct expr_test;
     873             :       template <typename T> struct expr_test<T, sizeof(char)> : T
     874             :       {
     875             :       };
     876             :     }
     877             :   }
     878             : }
     879             : 
     880             : #define BOOST_UNORDERED_CHECK_EXPRESSION(count, result, expression)            \
     881             :   template <typename U>                                                        \
     882             :   static                                                                       \
     883             :     typename boost::unordered::detail::expr_test<BOOST_PP_CAT(choice, result), \
     884             :       sizeof(for_expr_test(((expression), 0)))>::type                          \
     885             :       test(BOOST_PP_CAT(choice, count))
     886             : 
     887             : #define BOOST_UNORDERED_DEFAULT_EXPRESSION(count, result)                      \
     888             :   template <typename U>                                                        \
     889             :   static BOOST_PP_CAT(choice, result)::type test(BOOST_PP_CAT(choice, count))
     890             : 
     891             : #define BOOST_UNORDERED_HAS_FUNCTION(name, thing, args, _)                     \
     892             :   struct BOOST_PP_CAT(has_, name)                                              \
     893             :   {                                                                            \
     894             :     template <typename U> static char for_expr_test(U const&);                 \
     895             :     BOOST_UNORDERED_CHECK_EXPRESSION(                                          \
     896             :       1, 1, boost::unordered::detail::make<thing>().name args);                \
     897             :     BOOST_UNORDERED_DEFAULT_EXPRESSION(2, 2);                                  \
     898             :                                                                                \
     899             :     enum                                                                       \
     900             :     {                                                                          \
     901             :       value = sizeof(test<T>(choose())) == sizeof(choice1::type)               \
     902             :     };                                                                         \
     903             :   }
     904             : 
     905             : #else
     906             : 
     907             : namespace boost {
     908             :   namespace unordered {
     909             :     namespace detail {
     910             :       template <typename T> struct identity
     911             :       {
     912             :         typedef T type;
     913             :       };
     914             :     }
     915             :   }
     916             : }
     917             : 
     918             : #define BOOST_UNORDERED_CHECK_MEMBER(count, result, name, member)              \
     919             :                                                                                \
     920             :   typedef                                                                      \
     921             :     typename boost::unordered::detail::identity<member>::type BOOST_PP_CAT(    \
     922             :       check, count);                                                           \
     923             :                                                                                \
     924             :   template <BOOST_PP_CAT(check, count) e> struct BOOST_PP_CAT(test, count)     \
     925             :   {                                                                            \
     926             :     typedef BOOST_PP_CAT(choice, result) type;                                 \
     927             :   };                                                                           \
     928             :                                                                                \
     929             :   template <class U>                                                           \
     930             :   static typename BOOST_PP_CAT(test, count)<&U::name>::type test(              \
     931             :     BOOST_PP_CAT(choice, count))
     932             : 
     933             : #define BOOST_UNORDERED_DEFAULT_MEMBER(count, result)                          \
     934             :   template <class U>                                                           \
     935             :   static BOOST_PP_CAT(choice, result)::type test(BOOST_PP_CAT(choice, count))
     936             : 
     937             : #define BOOST_UNORDERED_HAS_MEMBER(name)                                       \
     938             :   struct BOOST_PP_CAT(has_, name)                                              \
     939             :   {                                                                            \
     940             :     struct impl                                                                \
     941             :     {                                                                          \
     942             :       struct base_mixin                                                        \
     943             :       {                                                                        \
     944             :         int name;                                                              \
     945             :       };                                                                       \
     946             :       struct base : public T, public base_mixin                                \
     947             :       {                                                                        \
     948             :       };                                                                       \
     949             :                                                                                \
     950             :       BOOST_UNORDERED_CHECK_MEMBER(1, 1, name, int base_mixin::*);             \
     951             :       BOOST_UNORDERED_DEFAULT_MEMBER(2, 2);                                    \
     952             :                                                                                \
     953             :       enum                                                                     \
     954             :       {                                                                        \
     955             :         value = sizeof(choice2::type) == sizeof(test<base>(choose()))          \
     956             :       };                                                                       \
     957             :     };                                                                         \
     958             :                                                                                \
     959             :     enum                                                                       \
     960             :     {                                                                          \
     961             :       value = impl::value                                                      \
     962             :     };                                                                         \
     963             :   }
     964             : 
     965             : #endif
     966             : 
     967             : ////////////////////////////////////////////////////////////////////////////
     968             : // TRAITS TYPE DETECTION MECHANISM
     969             : //
     970             : // Used to implement traits that use a type if present, or a
     971             : // default otherwise.
     972             : 
     973             : #if defined(BOOST_MSVC) && BOOST_MSVC <= 1400
     974             : 
     975             : #define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname)                              \
     976             :   template <typename Tp, typename Default> struct default_type_##tname         \
     977             :   {                                                                            \
     978             :                                                                                \
     979             :     template <typename X>                                                      \
     980             :     static choice1::type test(choice1, typename X::tname* = 0);                \
     981             :                                                                                \
     982             :     template <typename X> static choice2::type test(choice2, void* = 0);       \
     983             :                                                                                \
     984             :     struct DefaultWrap                                                         \
     985             :     {                                                                          \
     986             :       typedef Default tname;                                                   \
     987             :     };                                                                         \
     988             :                                                                                \
     989             :     enum                                                                       \
     990             :     {                                                                          \
     991             :       value = (1 == sizeof(test<Tp>(choose())))                                \
     992             :     };                                                                         \
     993             :                                                                                \
     994             :     typedef typename boost::detail::if_true<value>::BOOST_NESTED_TEMPLATE      \
     995             :       then<Tp, DefaultWrap>::type::tname type;                                 \
     996             :   }
     997             : 
     998             : #else
     999             : 
    1000             : namespace boost {
    1001             :   namespace unordered {
    1002             :     namespace detail {
    1003             :       template <typename T, typename T2> struct sfinae : T2
    1004             :       {
    1005             :       };
    1006             :     }
    1007             :   }
    1008             : }
    1009             : 
    1010             : #define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname)                              \
    1011             :   template <typename Tp, typename Default> struct default_type_##tname         \
    1012             :   {                                                                            \
    1013             :                                                                                \
    1014             :     template <typename X>                                                      \
    1015             :     static typename boost::unordered::detail::sfinae<typename X::tname,        \
    1016             :       choice1>::type test(choice1);                                            \
    1017             :                                                                                \
    1018             :     template <typename X> static choice2::type test(choice2);                  \
    1019             :                                                                                \
    1020             :     struct DefaultWrap                                                         \
    1021             :     {                                                                          \
    1022             :       typedef Default tname;                                                   \
    1023             :     };                                                                         \
    1024             :                                                                                \
    1025             :     enum                                                                       \
    1026             :     {                                                                          \
    1027             :       value = (1 == sizeof(test<Tp>(choose())))                                \
    1028             :     };                                                                         \
    1029             :                                                                                \
    1030             :     typedef typename boost::detail::if_true<value>::BOOST_NESTED_TEMPLATE      \
    1031             :       then<Tp, DefaultWrap>::type::tname type;                                 \
    1032             :   }
    1033             : 
    1034             : #endif
    1035             : 
    1036             : #define BOOST_UNORDERED_DEFAULT_TYPE(T, tname, arg)                            \
    1037             :   typename default_type_##tname<T, arg>::type
    1038             : 
    1039             : ////////////////////////////////////////////////////////////////////////////////
    1040             : //
    1041             : // Allocator traits
    1042             : //
    1043             : // First our implementation, then later light wrappers around the alternatives
    1044             : 
    1045             : #if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 0
    1046             : 
    1047             : #include <boost/limits.hpp>
    1048             : #include <boost/pointer_to_other.hpp>
    1049             : #include <boost/utility/enable_if.hpp>
    1050             : 
    1051             : namespace boost {
    1052             :   namespace unordered {
    1053             :     namespace detail {
    1054             : 
    1055             :       template <typename Alloc, typename T> struct rebind_alloc;
    1056             : 
    1057             : #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
    1058             : 
    1059             :       template <template <typename, typename...> class Alloc, typename U,
    1060             :         typename T, typename... Args>
    1061             :       struct rebind_alloc<Alloc<U, Args...>, T>
    1062             :       {
    1063             :         typedef Alloc<T, Args...> type;
    1064             :       };
    1065             : 
    1066             : #else
    1067             : 
    1068             :       template <template <typename> class Alloc, typename U, typename T>
    1069             :       struct rebind_alloc<Alloc<U>, T>
    1070             :       {
    1071             :         typedef Alloc<T> type;
    1072             :       };
    1073             : 
    1074             :       template <template <typename, typename> class Alloc, typename U,
    1075             :         typename T, typename A0>
    1076             :       struct rebind_alloc<Alloc<U, A0>, T>
    1077             :       {
    1078             :         typedef Alloc<T, A0> type;
    1079             :       };
    1080             : 
    1081             :       template <template <typename, typename, typename> class Alloc, typename U,
    1082             :         typename T, typename A0, typename A1>
    1083             :       struct rebind_alloc<Alloc<U, A0, A1>, T>
    1084             :       {
    1085             :         typedef Alloc<T, A0, A1> type;
    1086             :       };
    1087             : 
    1088             : #endif
    1089             : 
    1090             :       template <typename Alloc, typename T> struct rebind_wrap
    1091             :       {
    1092             :         template <typename X>
    1093             :         static choice1::type test(
    1094             :           choice1, typename X::BOOST_NESTED_TEMPLATE rebind<T>::other* = 0);
    1095             :         template <typename X> static choice2::type test(choice2, void* = 0);
    1096             : 
    1097             :         enum
    1098             :         {
    1099             :           value = (1 == sizeof(test<Alloc>(choose())))
    1100             :         };
    1101             : 
    1102             :         struct fallback
    1103             :         {
    1104             :           template <typename U> struct rebind
    1105             :           {
    1106             :             typedef typename rebind_alloc<Alloc, T>::type other;
    1107             :           };
    1108             :         };
    1109             : 
    1110             :         typedef
    1111             :           typename boost::detail::if_true<value>::BOOST_NESTED_TEMPLATE then<
    1112             :             Alloc, fallback>::type::BOOST_NESTED_TEMPLATE rebind<T>::other type;
    1113             :       };
    1114             :     }
    1115             :   }
    1116             : }
    1117             : 
    1118             : namespace boost {
    1119             :   namespace unordered {
    1120             :     namespace detail {
    1121             :       BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(pointer);
    1122             :       BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(const_pointer);
    1123             :       BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(void_pointer);
    1124             :       BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(const_void_pointer);
    1125             :       BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(difference_type);
    1126             :       BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(size_type);
    1127             :       BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(
    1128             :         propagate_on_container_copy_assignment);
    1129             :       BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(
    1130             :         propagate_on_container_move_assignment);
    1131             :       BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_swap);
    1132             :       BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(is_always_equal);
    1133             : 
    1134             : #if !defined(BOOST_NO_SFINAE_EXPR)
    1135             : 
    1136             :       template <typename T>
    1137             :       BOOST_UNORDERED_HAS_FUNCTION(
    1138             :         select_on_container_copy_construction, U const, (), 0);
    1139             : 
    1140             :       template <typename T>
    1141             :       BOOST_UNORDERED_HAS_FUNCTION(max_size, U const, (), 0);
    1142             : 
    1143             : #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
    1144             : 
    1145             :       template <typename T, typename ValueType, typename... Args>
    1146             :       BOOST_UNORDERED_HAS_FUNCTION(construct, U,
    1147             :         (boost::unordered::detail::make<ValueType*>(),
    1148             :           boost::unordered::detail::make<Args const>()...),
    1149             :         2);
    1150             : 
    1151             : #else
    1152             : 
    1153             :       template <typename T, typename ValueType>
    1154             :       BOOST_UNORDERED_HAS_FUNCTION(construct, U,
    1155             :         (boost::unordered::detail::make<ValueType*>(),
    1156             :           boost::unordered::detail::make<ValueType const>()),
    1157             :         2);
    1158             : 
    1159             : #endif
    1160             : 
    1161             :       template <typename T, typename ValueType>
    1162             :       BOOST_UNORDERED_HAS_FUNCTION(
    1163             :         destroy, U, (boost::unordered::detail::make<ValueType*>()), 1);
    1164             : 
    1165             : #else
    1166             : 
    1167             :       template <typename T>
    1168             :       BOOST_UNORDERED_HAS_MEMBER(select_on_container_copy_construction);
    1169             : 
    1170             :       template <typename T> BOOST_UNORDERED_HAS_MEMBER(max_size);
    1171             : 
    1172             :       template <typename T, typename ValueType>
    1173             :       BOOST_UNORDERED_HAS_MEMBER(construct);
    1174             : 
    1175             :       template <typename T, typename ValueType>
    1176             :       BOOST_UNORDERED_HAS_MEMBER(destroy);
    1177             : 
    1178             : #endif
    1179             :     }
    1180             :   }
    1181             : }
    1182             : 
    1183             : namespace boost {
    1184             :   namespace unordered {
    1185             :     namespace detail {
    1186             :       namespace func {
    1187             : 
    1188             :         template <typename Alloc>
    1189             :         inline Alloc call_select_on_container_copy_construction(
    1190             :           const Alloc& rhs,
    1191             :           typename boost::enable_if_c<
    1192             :             boost::unordered::detail::has_select_on_container_copy_construction<
    1193             :               Alloc>::value,
    1194             :             void*>::type = 0)
    1195             :         {
    1196             :           return rhs.select_on_container_copy_construction();
    1197             :         }
    1198             : 
    1199             :         template <typename Alloc>
    1200             :         inline Alloc call_select_on_container_copy_construction(
    1201             :           const Alloc& rhs,
    1202             :           typename boost::disable_if_c<
    1203             :             boost::unordered::detail::has_select_on_container_copy_construction<
    1204             :               Alloc>::value,
    1205             :             void*>::type = 0)
    1206             :         {
    1207             :           return rhs;
    1208             :         }
    1209             : 
    1210             :         template <typename SizeType, typename Alloc>
    1211             :         inline SizeType call_max_size(const Alloc& a,
    1212             :           typename boost::enable_if_c<
    1213             :             boost::unordered::detail::has_max_size<Alloc>::value, void*>::type =
    1214             :             0)
    1215             :         {
    1216             :           return a.max_size();
    1217             :         }
    1218             : 
    1219             :         template <typename SizeType, typename Alloc>
    1220             :         inline SizeType call_max_size(const Alloc&,
    1221             :           typename boost::disable_if_c<
    1222             :             boost::unordered::detail::has_max_size<Alloc>::value, void*>::type =
    1223             :             0)
    1224             :         {
    1225             :           return (std::numeric_limits<SizeType>::max)();
    1226             :         }
    1227             :       } // namespace func.
    1228             :     }
    1229             :   }
    1230             : }
    1231             : 
    1232             : namespace boost {
    1233             :   namespace unordered {
    1234             :     namespace detail {
    1235             :       template <typename Alloc> struct allocator_traits
    1236             :       {
    1237             :         typedef Alloc allocator_type;
    1238             :         typedef typename Alloc::value_type value_type;
    1239             : 
    1240             :         typedef BOOST_UNORDERED_DEFAULT_TYPE(
    1241             :           Alloc, pointer, value_type*) pointer;
    1242             : 
    1243             :         template <typename T>
    1244             :         struct pointer_to_other : boost::pointer_to_other<pointer, T>
    1245             :         {
    1246             :         };
    1247             : 
    1248             :         typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_pointer,
    1249             :           typename pointer_to_other<const value_type>::type) const_pointer;
    1250             : 
    1251             :         // typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, void_pointer,
    1252             :         //    typename pointer_to_other<void>::type)
    1253             :         //    void_pointer;
    1254             :         //
    1255             :         // typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_void_pointer,
    1256             :         //    typename pointer_to_other<const void>::type)
    1257             :         //    const_void_pointer;
    1258             : 
    1259             :         typedef BOOST_UNORDERED_DEFAULT_TYPE(
    1260             :           Alloc, difference_type, std::ptrdiff_t) difference_type;
    1261             : 
    1262             :         typedef BOOST_UNORDERED_DEFAULT_TYPE(
    1263             :           Alloc, size_type, std::size_t) size_type;
    1264             : 
    1265             : #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
    1266             :         template <typename T>
    1267             :         using rebind_alloc = typename rebind_wrap<Alloc, T>::type;
    1268             : 
    1269             :         template <typename T>
    1270             :         using rebind_traits =
    1271             :           boost::unordered::detail::allocator_traits<rebind_alloc<T> >;
    1272             : #endif
    1273             : 
    1274             :         static pointer allocate(Alloc& a, size_type n) { return a.allocate(n); }
    1275             : 
    1276             :         // I never use this, so I'll just comment it out for now.
    1277             :         //
    1278             :         // static pointer allocate(Alloc& a, size_type n,
    1279             :         //        const_void_pointer hint)
    1280             :         //    { return DEFAULT_FUNC(allocate, pointer)(a, n, hint); }
    1281             : 
    1282             :         static void deallocate(Alloc& a, pointer p, size_type n)
    1283             :         {
    1284             :           a.deallocate(p, n);
    1285             :         }
    1286             : 
    1287             :       public:
    1288             : #if BOOST_UNORDERED_CXX11_CONSTRUCTION
    1289             : 
    1290             :         template <typename T, typename... Args>
    1291             :         static
    1292             :           typename boost::enable_if_c<boost::unordered::detail::has_construct<
    1293             :             Alloc, T, Args...>::value>::type
    1294             :           construct(Alloc& a, T* p, BOOST_FWD_REF(Args)... x)
    1295             :         {
    1296             :           a.construct(p, boost::forward<Args>(x)...);
    1297             :         }
    1298             : 
    1299             :         template <typename T, typename... Args>
    1300             :         static
    1301             :           typename boost::disable_if_c<boost::unordered::detail::has_construct<
    1302             :             Alloc, T, Args...>::value>::type
    1303             :           construct(Alloc&, T* p, BOOST_FWD_REF(Args)... x)
    1304             :         {
    1305             :           new (static_cast<void*>(p)) T(boost::forward<Args>(x)...);
    1306             :         }
    1307             : 
    1308             :         template <typename T>
    1309             :         static typename boost::enable_if_c<
    1310             :           boost::unordered::detail::has_destroy<Alloc, T>::value>::type
    1311             :         destroy(Alloc& a, T* p)
    1312             :         {
    1313             :           a.destroy(p);
    1314             :         }
    1315             : 
    1316             :         template <typename T>
    1317             :         static typename boost::disable_if_c<
    1318             :           boost::unordered::detail::has_destroy<Alloc, T>::value>::type
    1319             :         destroy(Alloc&, T* p)
    1320             :         {
    1321             :           boost::unordered::detail::func::destroy(p);
    1322             :         }
    1323             : 
    1324             : #elif !defined(BOOST_NO_SFINAE_EXPR)
    1325             : 
    1326             :         template <typename T>
    1327             :         static typename boost::enable_if_c<
    1328             :           boost::unordered::detail::has_construct<Alloc, T>::value>::type
    1329             :         construct(Alloc& a, T* p, T const& x)
    1330             :         {
    1331             :           a.construct(p, x);
    1332             :         }
    1333             : 
    1334             :         template <typename T>
    1335             :         static typename boost::disable_if_c<
    1336             :           boost::unordered::detail::has_construct<Alloc, T>::value>::type
    1337             :         construct(Alloc&, T* p, T const& x)
    1338             :         {
    1339             :           new (static_cast<void*>(p)) T(x);
    1340             :         }
    1341             : 
    1342             :         template <typename T>
    1343             :         static typename boost::enable_if_c<
    1344             :           boost::unordered::detail::has_destroy<Alloc, T>::value>::type
    1345             :         destroy(Alloc& a, T* p)
    1346             :         {
    1347             :           a.destroy(p);
    1348             :         }
    1349             : 
    1350             :         template <typename T>
    1351             :         static typename boost::disable_if_c<
    1352             :           boost::unordered::detail::has_destroy<Alloc, T>::value>::type
    1353             :         destroy(Alloc&, T* p)
    1354             :         {
    1355             :           boost::unordered::detail::func::destroy(p);
    1356             :         }
    1357             : 
    1358             : #else
    1359             : 
    1360             :         // If we don't have SFINAE expressions, only call construct for the
    1361             :         // copy constructor for the allocator's value_type - as that's
    1362             :         // the only construct method that old fashioned allocators support.
    1363             : 
    1364             :         template <typename T>
    1365             :         static void construct(Alloc& a, T* p, T const& x,
    1366             :           typename boost::enable_if_c<
    1367             :             boost::unordered::detail::has_construct<Alloc, T>::value &&
    1368             :               boost::is_same<T, value_type>::value,
    1369             :             void*>::type = 0)
    1370             :         {
    1371             :           a.construct(p, x);
    1372             :         }
    1373             : 
    1374             :         template <typename T>
    1375             :         static void construct(Alloc&, T* p, T const& x,
    1376             :           typename boost::disable_if_c<
    1377             :             boost::unordered::detail::has_construct<Alloc, T>::value &&
    1378             :               boost::is_same<T, value_type>::value,
    1379             :             void*>::type = 0)
    1380             :         {
    1381             :           new (static_cast<void*>(p)) T(x);
    1382             :         }
    1383             : 
    1384             :         template <typename T>
    1385             :         static void destroy(Alloc& a, T* p,
    1386             :           typename boost::enable_if_c<
    1387             :             boost::unordered::detail::has_destroy<Alloc, T>::value &&
    1388             :               boost::is_same<T, value_type>::value,
    1389             :             void*>::type = 0)
    1390             :         {
    1391             :           a.destroy(p);
    1392             :         }
    1393             : 
    1394             :         template <typename T>
    1395             :         static void destroy(Alloc&, T* p,
    1396             :           typename boost::disable_if_c<
    1397             :             boost::unordered::detail::has_destroy<Alloc, T>::value &&
    1398             :               boost::is_same<T, value_type>::value,
    1399             :             void*>::type = 0)
    1400             :         {
    1401             :           boost::unordered::detail::func::destroy(p);
    1402             :         }
    1403             : 
    1404             : #endif
    1405             : 
    1406             :         static size_type max_size(const Alloc& a)
    1407             :         {
    1408             :           return boost::unordered::detail::func::call_max_size<size_type>(a);
    1409             :         }
    1410             : 
    1411             :         // Allocator propagation on construction
    1412             : 
    1413             :         static Alloc select_on_container_copy_construction(Alloc const& rhs)
    1414             :         {
    1415             :           return boost::unordered::detail::func::
    1416             :             call_select_on_container_copy_construction(rhs);
    1417             :         }
    1418             : 
    1419             :         // Allocator propagation on assignment and swap.
    1420             :         // Return true if lhs is modified.
    1421             :         typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc,
    1422             :           propagate_on_container_copy_assignment,
    1423             :           false_type) propagate_on_container_copy_assignment;
    1424             :         typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc,
    1425             :           propagate_on_container_move_assignment,
    1426             :           false_type) propagate_on_container_move_assignment;
    1427             :         typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, propagate_on_container_swap,
    1428             :           false_type) propagate_on_container_swap;
    1429             : 
    1430             :         typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, is_always_equal,
    1431             :           typename boost::is_empty<Alloc>::type) is_always_equal;
    1432             :       };
    1433             :     }
    1434             :   }
    1435             : }
    1436             : 
    1437             : #undef BOOST_UNORDERED_DEFAULT_TYPE_TMPLT
    1438             : #undef BOOST_UNORDERED_DEFAULT_TYPE
    1439             : 
    1440             : ////////////////////////////////////////////////////////////////////////////////
    1441             : //
    1442             : // std::allocator_traits
    1443             : 
    1444             : #elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
    1445             : 
    1446             : #include <memory>
    1447             : 
    1448             : namespace boost {
    1449             :   namespace unordered {
    1450             :     namespace detail {
    1451             : 
    1452             :       BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(is_always_equal);
    1453             : 
    1454             :       template <typename Alloc>
    1455             :       struct allocator_traits : std::allocator_traits<Alloc>
    1456             :       {
    1457             :         // As is_always_equal was introduced in C++17, std::allocator_traits
    1458             :         // doesn't always have it. So use it when available, implement it
    1459             :         // ourselves when not. Would be simpler not to bother with
    1460             :         // std::allocator_traits, but I feel like I should try to use
    1461             :         // it where possible.
    1462             :         typedef BOOST_UNORDERED_DEFAULT_TYPE(std::allocator_traits<Alloc>,
    1463             :           is_always_equal,
    1464             :           BOOST_UNORDERED_DEFAULT_TYPE(Alloc, is_always_equal,
    1465             :             typename boost::is_empty<Alloc>::type)) is_always_equal;
    1466             :       };
    1467             : 
    1468             :       template <typename Alloc, typename T> struct rebind_wrap
    1469             :       {
    1470             :         typedef typename std::allocator_traits<Alloc>::template rebind_alloc<T>
    1471             :           type;
    1472             :       };
    1473             :     }
    1474             :   }
    1475             : }
    1476             : 
    1477             : ////////////////////////////////////////////////////////////////////////////////
    1478             : //
    1479             : // boost::container::allocator_traits
    1480             : 
    1481             : #elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 2
    1482             : 
    1483             : #include <boost/container/allocator_traits.hpp>
    1484             : 
    1485             : namespace boost {
    1486             :   namespace unordered {
    1487             :     namespace detail {
    1488             : 
    1489             :       template <typename Alloc>
    1490             :       struct allocator_traits : boost::container::allocator_traits<Alloc>
    1491             :       {
    1492             :       };
    1493             : 
    1494             :       template <typename Alloc, typename T>
    1495             :       struct rebind_wrap : boost::container::allocator_traits<
    1496             :                              Alloc>::template portable_rebind_alloc<T>
    1497             :       {
    1498             :       };
    1499             :     }
    1500             :   }
    1501             : }
    1502             : 
    1503             : #else
    1504             : 
    1505             : #error "Invalid BOOST_UNORDERED_USE_ALLOCATOR_TRAITS value."
    1506             : 
    1507             : #endif
    1508             : 
    1509             : ////////////////////////////////////////////////////////////////////////////
    1510             : // Functions used to construct nodes. Emulates variadic construction,
    1511             : // piecewise construction etc.
    1512             : 
    1513             : ////////////////////////////////////////////////////////////////////////////
    1514             : // construct_value
    1515             : //
    1516             : // Only use allocator_traits::construct, allocator_traits::destroy when full
    1517             : // C++11 support is available.
    1518             : 
    1519             : #if BOOST_UNORDERED_CXX11_CONSTRUCTION
    1520             : 
    1521             : #define BOOST_UNORDERED_CALL_CONSTRUCT1(Traits, alloc, address, a0)            \
    1522             :   Traits::construct(alloc, address, a0)
    1523             : #define BOOST_UNORDERED_CALL_DESTROY(Traits, alloc, x) Traits::destroy(alloc, x)
    1524             : 
    1525             : #elif !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
    1526             : 
    1527             : namespace boost {
    1528             :   namespace unordered {
    1529             :     namespace detail {
    1530             :       namespace func {
    1531             :         template <typename T, typename... Args>
    1532             :         inline void construct_value(T* address, BOOST_FWD_REF(Args)... args)
    1533             :         {
    1534             :           new ((void*)address) T(boost::forward<Args>(args)...);
    1535             :         }
    1536             :       }
    1537             :     }
    1538             :   }
    1539             : }
    1540             : 
    1541             : #define BOOST_UNORDERED_CALL_CONSTRUCT1(Traits, alloc, address, a0)            \
    1542             :   boost::unordered::detail::func::construct_value(address, a0)
    1543             : #define BOOST_UNORDERED_CALL_DESTROY(Traits, alloc, x)                         \
    1544             :   boost::unordered::detail::func::destroy(x)
    1545             : 
    1546             : #else
    1547             : 
    1548             : namespace boost {
    1549             :   namespace unordered {
    1550             :     namespace detail {
    1551             :       namespace func {
    1552             :         template <typename T> inline void construct_value(T* address)
    1553             :         {
    1554             :           new ((void*)address) T();
    1555             :         }
    1556             : 
    1557             :         template <typename T, typename A0>
    1558             :         inline void construct_value(T* address, BOOST_FWD_REF(A0) a0)
    1559             :         {
    1560             :           new ((void*)address) T(boost::forward<A0>(a0));
    1561             :         }
    1562             :       }
    1563             :     }
    1564             :   }
    1565             : }
    1566             : 
    1567             : #define BOOST_UNORDERED_CALL_CONSTRUCT1(Traits, alloc, address, a0)            \
    1568             :   boost::unordered::detail::func::construct_value(address, a0)
    1569             : #define BOOST_UNORDERED_CALL_DESTROY(Traits, alloc, x)                         \
    1570             :   boost::unordered::detail::func::destroy(x)
    1571             : 
    1572             : #endif
    1573             : 
    1574             : ////////////////////////////////////////////////////////////////////////////
    1575             : // Construct from tuple
    1576             : //
    1577             : // Used to emulate piecewise construction.
    1578             : 
    1579             : #define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(z, n, namespace_)                 \
    1580             :   template <typename Alloc, typename T,                                        \
    1581             :     BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)>                                  \
    1582             :   void construct_from_tuple(Alloc&, T* ptr,                                    \
    1583             :     namespace_::tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x)               \
    1584             :   {                                                                            \
    1585             :     new ((void*)ptr)                                                           \
    1586             :       T(BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_));      \
    1587             :   }
    1588             : 
    1589             : #define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) namespace_::get<n>(x)
    1590             : 
    1591             : // construct_from_tuple for boost::tuple
    1592             : // The workaround for old Sun compilers comes later in the file.
    1593             : 
    1594             : #if !BOOST_UNORDERED_SUN_WORKAROUNDS1
    1595             : 
    1596             : namespace boost {
    1597             :   namespace unordered {
    1598             :     namespace detail {
    1599             :       namespace func {
    1600             :         template <typename Alloc, typename T>
    1601             :         void construct_from_tuple(Alloc&, T* ptr, boost::tuple<>)
    1602             :         {
    1603             :           new ((void*)ptr) T();
    1604             :         }
    1605             : 
    1606             :         BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 1, boost)
    1607             :         BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 2, boost)
    1608             :         BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 3, boost)
    1609             :         BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 4, boost)
    1610             :         BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 5, boost)
    1611             :         BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 6, boost)
    1612             :         BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 7, boost)
    1613             :         BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 8, boost)
    1614             :         BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 9, boost)
    1615             :         BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 10, boost)
    1616             :       }
    1617             :     }
    1618             :   }
    1619             : }
    1620             : 
    1621             : #endif
    1622             : 
    1623             : // construct_from_tuple for std::tuple
    1624             : 
    1625             : #if !BOOST_UNORDERED_CXX11_CONSTRUCTION && BOOST_UNORDERED_TUPLE_ARGS
    1626             : 
    1627             : namespace boost {
    1628             :   namespace unordered {
    1629             :     namespace detail {
    1630             :       namespace func {
    1631             :         template <typename Alloc, typename T>
    1632             :         void construct_from_tuple(Alloc&, T* ptr, std::tuple<>)
    1633             :         {
    1634             :           new ((void*)ptr) T();
    1635             :         }
    1636             : 
    1637             :         BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 1, std)
    1638             :         BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 2, std)
    1639             :         BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 3, std)
    1640             :         BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 4, std)
    1641             :         BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 5, std)
    1642             : 
    1643             : #if BOOST_UNORDERED_TUPLE_ARGS >= 6
    1644             :         BOOST_PP_REPEAT_FROM_TO(6, BOOST_PP_INC(BOOST_UNORDERED_TUPLE_ARGS),
    1645             :           BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE, std)
    1646             : #endif
    1647             :       }
    1648             :     }
    1649             :   }
    1650             : }
    1651             : 
    1652             : #endif
    1653             : 
    1654             : #undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE
    1655             : #undef BOOST_UNORDERED_GET_TUPLE_ARG
    1656             : 
    1657             : // construct_from_tuple for boost::tuple on old versions of sunpro.
    1658             : //
    1659             : // Old versions of Sun C++ had problems with template overloads of
    1660             : // boost::tuple, so to fix it I added a distinct type for each length to
    1661             : // the overloads. That means there's no possible ambiguity between the
    1662             : // different overloads, so that the compiler doesn't get confused
    1663             : 
    1664             : #if BOOST_UNORDERED_SUN_WORKAROUNDS1
    1665             : 
    1666             : #define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(z, n, namespace_)                 \
    1667             :   template <typename Alloc, typename T,                                        \
    1668             :     BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)>                                  \
    1669             :   void construct_from_tuple_impl(boost::unordered::detail::func::length<n>,    \
    1670             :     Alloc&, T* ptr,                                                            \
    1671             :     namespace_::tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x)               \
    1672             :   {                                                                            \
    1673             :     new ((void*)ptr)                                                           \
    1674             :       T(BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_));      \
    1675             :   }
    1676             : 
    1677             : #define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) namespace_::get<n>(x)
    1678             : 
    1679             : namespace boost {
    1680             :   namespace unordered {
    1681             :     namespace detail {
    1682             :       namespace func {
    1683             :         template <int N> struct length
    1684             :         {
    1685             :         };
    1686             : 
    1687             :         template <typename Alloc, typename T>
    1688             :         void construct_from_tuple_impl(
    1689             :           boost::unordered::detail::func::length<0>, Alloc&, T* ptr,
    1690             :           boost::tuple<>)
    1691             :         {
    1692             :           new ((void*)ptr) T();
    1693             :         }
    1694             : 
    1695             :         BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 1, boost)
    1696             :         BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 2, boost)
    1697             :         BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 3, boost)
    1698             :         BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 4, boost)
    1699             :         BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 5, boost)
    1700             :         BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 6, boost)
    1701             :         BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 7, boost)
    1702             :         BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 8, boost)
    1703             :         BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 9, boost)
    1704             :         BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(1, 10, boost)
    1705             : 
    1706             :         template <typename Alloc, typename T, typename Tuple>
    1707             :         void construct_from_tuple(Alloc& alloc, T* ptr, Tuple const& x)
    1708             :         {
    1709             :           construct_from_tuple_impl(boost::unordered::detail::func::length<
    1710             :                                       boost::tuples::length<Tuple>::value>(),
    1711             :             alloc, ptr, x);
    1712             :         }
    1713             :       }
    1714             :     }
    1715             :   }
    1716             : }
    1717             : 
    1718             : #undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE
    1719             : #undef BOOST_UNORDERED_GET_TUPLE_ARG
    1720             : 
    1721             : #endif
    1722             : 
    1723             : namespace boost {
    1724             :   namespace unordered {
    1725             :     namespace detail {
    1726             :       namespace func {
    1727             :         ////////////////////////////////////////////////////////////////////////
    1728             :         // Trait to check for piecewise construction.
    1729             : 
    1730             :         template <typename A0> struct use_piecewise
    1731             :         {
    1732             :           static choice1::type test(
    1733             :             choice1, boost::unordered::piecewise_construct_t);
    1734             : 
    1735             :           static choice2::type test(choice2, ...);
    1736             : 
    1737             :           enum
    1738             :           {
    1739             :             value = sizeof(choice1::type) ==
    1740             :                     sizeof(test(choose(), boost::unordered::detail::make<A0>()))
    1741             :           };
    1742             :         };
    1743             : 
    1744             : #if BOOST_UNORDERED_CXX11_CONSTRUCTION
    1745             : 
    1746             :         ////////////////////////////////////////////////////////////////////////
    1747             :         // Construct from variadic parameters
    1748             : 
    1749             :         template <typename Alloc, typename T, typename... Args>
    1750     2448950 :         inline void construct_from_args(
    1751             :           Alloc& alloc, T* address, BOOST_FWD_REF(Args)... args)
    1752             :         {
    1753     4897900 :           boost::unordered::detail::allocator_traits<Alloc>::construct(
    1754             :             alloc, address, boost::forward<Args>(args)...);
    1755             :         }
    1756             : 
    1757             :         // For backwards compatibility, implement a special case for
    1758             :         // piecewise_construct with boost::tuple
    1759             : 
    1760             :         template <typename A0> struct detect_boost_tuple
    1761             :         {
    1762             :           template <typename T0, typename T1, typename T2, typename T3,
    1763             :             typename T4, typename T5, typename T6, typename T7, typename T8,
    1764             :             typename T9>
    1765             :           static choice1::type test(choice1,
    1766             :             boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> const&);
    1767             : 
    1768             :           static choice2::type test(choice2, ...);
    1769             : 
    1770             :           enum
    1771             :           {
    1772             :             value = sizeof(choice1::type) ==
    1773             :                     sizeof(test(choose(), boost::unordered::detail::make<A0>()))
    1774             :           };
    1775             :         };
    1776             : 
    1777             :         // Special case for piecewise_construct
    1778             : 
    1779             :         template <typename Alloc, typename A, typename B, typename A0,
    1780             :           typename A1, typename A2>
    1781             :         inline typename boost::enable_if_c<use_piecewise<A0>::value &&
    1782             :                                              detect_boost_tuple<A1>::value &&
    1783             :                                              detect_boost_tuple<A2>::value,
    1784             :           void>::type
    1785             :         construct_from_args(Alloc& alloc, std::pair<A, B>* address,
    1786             :           BOOST_FWD_REF(A0), BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
    1787             :         {
    1788             :           boost::unordered::detail::func::construct_from_tuple(
    1789             :             alloc, boost::addressof(address->first), boost::forward<A1>(a1));
    1790             :           BOOST_TRY
    1791             :           {
    1792             :             boost::unordered::detail::func::construct_from_tuple(
    1793             :               alloc, boost::addressof(address->second), boost::forward<A2>(a2));
    1794             :           }
    1795             :           BOOST_CATCH(...)
    1796             :           {
    1797             :             boost::unordered::detail::func::destroy(
    1798             :               boost::addressof(address->first));
    1799             :             BOOST_RETHROW
    1800             :           }
    1801             :           BOOST_CATCH_END
    1802             :         }
    1803             : 
    1804             : #elif !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
    1805             : 
    1806             :         ////////////////////////////////////////////////////////////////////////
    1807             :         // Construct from variadic parameters
    1808             : 
    1809             :         template <typename Alloc, typename T, typename... Args>
    1810             :         inline void construct_from_args(
    1811             :           Alloc&, T* address, BOOST_FWD_REF(Args)... args)
    1812             :         {
    1813             :           new ((void*)address) T(boost::forward<Args>(args)...);
    1814             :         }
    1815             : 
    1816             :         // Special case for piecewise_construct
    1817             : 
    1818             :         template <typename Alloc, typename A, typename B, typename A0,
    1819             :           typename A1, typename A2>
    1820             :         inline typename enable_if<use_piecewise<A0>, void>::type
    1821             :         construct_from_args(Alloc& alloc, std::pair<A, B>* address,
    1822             :           BOOST_FWD_REF(A0), BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
    1823             :         {
    1824             :           boost::unordered::detail::func::construct_from_tuple(
    1825             :             alloc, boost::addressof(address->first), boost::forward<A1>(a1));
    1826             :           BOOST_TRY
    1827             :           {
    1828             :             boost::unordered::detail::func::construct_from_tuple(
    1829             :               alloc, boost::addressof(address->second), boost::forward<A2>(a2));
    1830             :           }
    1831             :           BOOST_CATCH(...)
    1832             :           {
    1833             :             boost::unordered::detail::func::destroy(
    1834             :               boost::addressof(address->first));
    1835             :             BOOST_RETHROW
    1836             :           }
    1837             :           BOOST_CATCH_END
    1838             :         }
    1839             : 
    1840             : #else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
    1841             : 
    1842             :         ////////////////////////////////////////////////////////////////////////
    1843             :         // Construct from emplace_args
    1844             : 
    1845             :         // Explicitly write out first three overloads for the sake of sane
    1846             :         // error messages.
    1847             : 
    1848             :         template <typename Alloc, typename T, typename A0>
    1849             :         inline void construct_from_args(
    1850             :           Alloc&, T* address, emplace_args1<A0> const& args)
    1851             :         {
    1852             :           new ((void*)address) T(boost::forward<A0>(args.a0));
    1853             :         }
    1854             : 
    1855             :         template <typename Alloc, typename T, typename A0, typename A1>
    1856             :         inline void construct_from_args(
    1857             :           Alloc&, T* address, emplace_args2<A0, A1> const& args)
    1858             :         {
    1859             :           new ((void*)address)
    1860             :             T(boost::forward<A0>(args.a0), boost::forward<A1>(args.a1));
    1861             :         }
    1862             : 
    1863             :         template <typename Alloc, typename T, typename A0, typename A1,
    1864             :           typename A2>
    1865             :         inline void construct_from_args(
    1866             :           Alloc&, T* address, emplace_args3<A0, A1, A2> const& args)
    1867             :         {
    1868             :           new ((void*)address) T(boost::forward<A0>(args.a0),
    1869             :             boost::forward<A1>(args.a1), boost::forward<A2>(args.a2));
    1870             :         }
    1871             : 
    1872             : // Use a macro for the rest.
    1873             : 
    1874             : #define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _)                       \
    1875             :   template <typename Alloc, typename T,                                        \
    1876             :     BOOST_PP_ENUM_PARAMS_Z(z, num_params, typename A)>                         \
    1877             :   inline void construct_from_args(Alloc&, T* address,                          \
    1878             :     boost::unordered::detail::BOOST_PP_CAT(emplace_args, num_params) <         \
    1879             :       BOOST_PP_ENUM_PARAMS_Z(z, num_params, A) > const& args)                  \
    1880             :   {                                                                            \
    1881             :     new ((void*)address)                                                       \
    1882             :       T(BOOST_PP_ENUM_##z(num_params, BOOST_UNORDERED_CALL_FORWARD, args.a));  \
    1883             :   }
    1884             : 
    1885             :         BOOST_UNORDERED_CONSTRUCT_IMPL(1, 4, _)
    1886             :         BOOST_UNORDERED_CONSTRUCT_IMPL(1, 5, _)
    1887             :         BOOST_UNORDERED_CONSTRUCT_IMPL(1, 6, _)
    1888             :         BOOST_UNORDERED_CONSTRUCT_IMPL(1, 7, _)
    1889             :         BOOST_UNORDERED_CONSTRUCT_IMPL(1, 8, _)
    1890             :         BOOST_UNORDERED_CONSTRUCT_IMPL(1, 9, _)
    1891             :         BOOST_PP_REPEAT_FROM_TO(10, BOOST_PP_INC(BOOST_UNORDERED_EMPLACE_LIMIT),
    1892             :           BOOST_UNORDERED_CONSTRUCT_IMPL, _)
    1893             : 
    1894             : #undef BOOST_UNORDERED_CONSTRUCT_IMPL
    1895             : 
    1896             :         // Construct with piecewise_construct
    1897             : 
    1898             :         template <typename Alloc, typename A, typename B, typename A0,
    1899             :           typename A1, typename A2>
    1900             :         inline void construct_from_args(Alloc& alloc, std::pair<A, B>* address,
    1901             :           boost::unordered::detail::emplace_args3<A0, A1, A2> const& args,
    1902             :           typename enable_if<use_piecewise<A0>, void*>::type = 0)
    1903             :         {
    1904             :           boost::unordered::detail::func::construct_from_tuple(
    1905             :             alloc, boost::addressof(address->first), args.a1);
    1906             :           BOOST_TRY
    1907             :           {
    1908             :             boost::unordered::detail::func::construct_from_tuple(
    1909             :               alloc, boost::addressof(address->second), args.a2);
    1910             :           }
    1911             :           BOOST_CATCH(...)
    1912             :           {
    1913             :             boost::unordered::detail::func::destroy(
    1914             :               boost::addressof(address->first));
    1915             :             BOOST_RETHROW
    1916             :           }
    1917             :           BOOST_CATCH_END
    1918             :         }
    1919             : 
    1920             : #endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
    1921             :       }
    1922             :     }
    1923             :   }
    1924             : }
    1925             : 
    1926             : namespace boost {
    1927             :   namespace unordered {
    1928             :     namespace detail {
    1929             : 
    1930             :       ///////////////////////////////////////////////////////////////////
    1931             :       //
    1932             :       // Node construction
    1933             : 
    1934             :       template <typename NodeAlloc> struct node_constructor
    1935             :       {
    1936             :         typedef NodeAlloc node_allocator;
    1937             :         typedef boost::unordered::detail::allocator_traits<NodeAlloc>
    1938             :           node_allocator_traits;
    1939             :         typedef typename node_allocator_traits::value_type node;
    1940             :         typedef typename node_allocator_traits::pointer node_pointer;
    1941             :         typedef typename node::value_type value_type;
    1942             : 
    1943             :         node_allocator& alloc_;
    1944             :         node_pointer node_;
    1945             : 
    1946     2449030 :         node_constructor(node_allocator& n) : alloc_(n), node_() {}
    1947             : 
    1948             :         ~node_constructor();
    1949             : 
    1950             :         void create_node();
    1951             : 
    1952             :         // no throw
    1953     2449030 :         node_pointer release()
    1954             :         {
    1955           0 :           BOOST_ASSERT(node_);
    1956     2449030 :           node_pointer p = node_;
    1957           0 :           node_ = node_pointer();
    1958             :           return p;
    1959             :         }
    1960             : 
    1961           0 :         void reclaim(node_pointer p)
    1962             :         {
    1963           0 :           BOOST_ASSERT(!node_);
    1964           0 :           node_ = p;
    1965           0 :           BOOST_UNORDERED_CALL_DESTROY(
    1966             :             node_allocator_traits, alloc_, node_->value_ptr());
    1967           0 :         }
    1968             : 
    1969             :       private:
    1970             :         node_constructor(node_constructor const&);
    1971             :         node_constructor& operator=(node_constructor const&);
    1972             :       };
    1973             : 
    1974     2449030 :       template <typename Alloc> node_constructor<Alloc>::~node_constructor()
    1975             :       {
    1976           0 :         if (node_) {
    1977           0 :           boost::unordered::detail::func::destroy(boost::to_address(node_));
    1978           0 :           node_allocator_traits::deallocate(alloc_, node_, 1);
    1979             :         }
    1980             :       }
    1981             : 
    1982             :       template <typename Alloc> void node_constructor<Alloc>::create_node()
    1983             :       {
    1984             :         BOOST_ASSERT(!node_);
    1985             :         node_ = node_allocator_traits::allocate(alloc_, 1);
    1986             :         new ((void*)boost::to_address(node_)) node();
    1987             :       }
    1988             : 
    1989             :       template <typename NodeAlloc> struct node_tmp
    1990             :       {
    1991             :         typedef boost::unordered::detail::allocator_traits<NodeAlloc>
    1992             :           node_allocator_traits;
    1993             :         typedef typename node_allocator_traits::pointer node_pointer;
    1994             :         typedef typename node_allocator_traits::value_type node;
    1995             : 
    1996             :         NodeAlloc& alloc_;
    1997             :         node_pointer node_;
    1998             : 
    1999     2449030 :         explicit node_tmp(node_pointer n, NodeAlloc& a) : alloc_(a), node_(n) {}
    2000             : 
    2001             :         ~node_tmp();
    2002             : 
    2003             :         // no throw
    2004     2449030 :         node_pointer release()
    2005             :         {
    2006     2448950 :           node_pointer p = node_;
    2007     2449030 :           node_ = node_pointer();
    2008             :           return p;
    2009             :         }
    2010             :       };
    2011             : 
    2012     2449030 :       template <typename Alloc> node_tmp<Alloc>::~node_tmp()
    2013             :       {
    2014     2448950 :         if (node_) {
    2015           0 :           BOOST_UNORDERED_CALL_DESTROY(
    2016             :             node_allocator_traits, alloc_, node_->value_ptr());
    2017           0 :           boost::unordered::detail::func::destroy(boost::to_address(node_));
    2018           0 :           node_allocator_traits::deallocate(alloc_, node_, 1);
    2019             :         }
    2020     2448950 :       }
    2021             :     }
    2022             :   }
    2023             : }
    2024             : 
    2025             : namespace boost {
    2026             :   namespace unordered {
    2027             :     namespace detail {
    2028             :       namespace func {
    2029             : 
    2030             :         // Some nicer construct_node functions, might try to
    2031             :         // improve implementation later.
    2032             : 
    2033             :         template <typename Alloc, BOOST_UNORDERED_EMPLACE_TEMPLATE>
    2034             :         inline
    2035             :           typename boost::unordered::detail::allocator_traits<Alloc>::pointer
    2036     2448950 :           construct_node_from_args(Alloc& alloc, BOOST_UNORDERED_EMPLACE_ARGS)
    2037             :         {
    2038     4897900 :           node_constructor<Alloc> a(alloc);
    2039     2448950 :           a.create_node();
    2040     4897900 :           construct_from_args(
    2041     2448950 :             alloc, a.node_->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD);
    2042     2448950 :           return a.release();
    2043             :         }
    2044             : 
    2045             :         template <typename Alloc, typename U>
    2046             :         inline
    2047             :           typename boost::unordered::detail::allocator_traits<Alloc>::pointer
    2048           0 :           construct_node(Alloc& alloc, BOOST_FWD_REF(U) x)
    2049             :         {
    2050           0 :           node_constructor<Alloc> a(alloc);
    2051           0 :           a.create_node();
    2052           0 :           BOOST_UNORDERED_CALL_CONSTRUCT1(
    2053             :             boost::unordered::detail::allocator_traits<Alloc>, alloc,
    2054             :             a.node_->value_ptr(), boost::forward<U>(x));
    2055           0 :           return a.release();
    2056             :         }
    2057             : 
    2058             : #if BOOST_UNORDERED_CXX11_CONSTRUCTION
    2059             : 
    2060             :         template <typename Alloc, typename Key>
    2061             :         inline
    2062             :           typename boost::unordered::detail::allocator_traits<Alloc>::pointer
    2063          80 :           construct_node_pair(Alloc& alloc, BOOST_FWD_REF(Key) k)
    2064             :         {
    2065         160 :           node_constructor<Alloc> a(alloc);
    2066          80 :           a.create_node();
    2067          80 :           boost::unordered::detail::allocator_traits<Alloc>::construct(alloc,
    2068          80 :             a.node_->value_ptr(), std::piecewise_construct,
    2069             :             std::forward_as_tuple(boost::forward<Key>(k)),
    2070             :             std::forward_as_tuple());
    2071          80 :           return a.release();
    2072             :         }
    2073             : 
    2074             :         template <typename Alloc, typename Key, typename Mapped>
    2075             :         inline
    2076             :           typename boost::unordered::detail::allocator_traits<Alloc>::pointer
    2077             :           construct_node_pair(
    2078             :             Alloc& alloc, BOOST_FWD_REF(Key) k, BOOST_FWD_REF(Mapped) m)
    2079             :         {
    2080             :           node_constructor<Alloc> a(alloc);
    2081             :           a.create_node();
    2082             :           boost::unordered::detail::allocator_traits<Alloc>::construct(alloc,
    2083             :             a.node_->value_ptr(), std::piecewise_construct,
    2084             :             std::forward_as_tuple(boost::forward<Key>(k)),
    2085             :             std::forward_as_tuple(boost::forward<Mapped>(m)));
    2086             :           return a.release();
    2087             :         }
    2088             : 
    2089             :         template <typename Alloc, typename Key, typename... Args>
    2090             :         inline
    2091             :           typename boost::unordered::detail::allocator_traits<Alloc>::pointer
    2092             :           construct_node_pair_from_args(
    2093             :             Alloc& alloc, BOOST_FWD_REF(Key) k, BOOST_FWD_REF(Args)... args)
    2094             :         {
    2095             :           node_constructor<Alloc> a(alloc);
    2096             :           a.create_node();
    2097             : #if !(BOOST_COMP_CLANG && BOOST_COMP_CLANG < BOOST_VERSION_NUMBER(3, 8, 0) &&  \
    2098             :       defined(BOOST_LIBSTDCXX11))
    2099             :           boost::unordered::detail::allocator_traits<Alloc>::construct(alloc,
    2100             :             a.node_->value_ptr(), std::piecewise_construct,
    2101             :             std::forward_as_tuple(boost::forward<Key>(k)),
    2102             :             std::forward_as_tuple(boost::forward<Args>(args)...));
    2103             : #else
    2104             :           // It doesn't seem to be possible to construct a tuple with 3 variadic
    2105             :           // rvalue reference members when using older versions of clang with
    2106             :           // libstdc++, so just use std::make_tuple instead of
    2107             :           // std::forward_as_tuple.
    2108             :           boost::unordered::detail::allocator_traits<Alloc>::construct(alloc,
    2109             :             a.node_->value_ptr(), std::piecewise_construct,
    2110             :             std::forward_as_tuple(boost::forward<Key>(k)),
    2111             :             std::make_tuple(boost::forward<Args>(args)...));
    2112             : #endif
    2113             :           return a.release();
    2114             :         }
    2115             : 
    2116             : #else
    2117             : 
    2118             :         template <typename Alloc, typename Key>
    2119             :         inline
    2120             :           typename boost::unordered::detail::allocator_traits<Alloc>::pointer
    2121             :           construct_node_pair(Alloc& alloc, BOOST_FWD_REF(Key) k)
    2122             :         {
    2123             :           node_constructor<Alloc> a(alloc);
    2124             :           a.create_node();
    2125             :           boost::unordered::detail::func::construct_value(
    2126             :             boost::addressof(a.node_->value_ptr()->first),
    2127             :             boost::forward<Key>(k));
    2128             :           BOOST_TRY
    2129             :           {
    2130             :             boost::unordered::detail::func::construct_value(
    2131             :               boost::addressof(a.node_->value_ptr()->second));
    2132             :           }
    2133             :           BOOST_CATCH(...)
    2134             :           {
    2135             :             boost::unordered::detail::func::destroy(
    2136             :               boost::addressof(a.node_->value_ptr()->first));
    2137             :             BOOST_RETHROW
    2138             :           }
    2139             :           BOOST_CATCH_END
    2140             :           return a.release();
    2141             :         }
    2142             : 
    2143             :         template <typename Alloc, typename Key, typename Mapped>
    2144             :         inline
    2145             :           typename boost::unordered::detail::allocator_traits<Alloc>::pointer
    2146             :           construct_node_pair(
    2147             :             Alloc& alloc, BOOST_FWD_REF(Key) k, BOOST_FWD_REF(Mapped) m)
    2148             :         {
    2149             :           node_constructor<Alloc> a(alloc);
    2150             :           a.create_node();
    2151             :           boost::unordered::detail::func::construct_value(
    2152             :             boost::addressof(a.node_->value_ptr()->first),
    2153             :             boost::forward<Key>(k));
    2154             :           BOOST_TRY
    2155             :           {
    2156             :             boost::unordered::detail::func::construct_value(
    2157             :               boost::addressof(a.node_->value_ptr()->second),
    2158             :               boost::forward<Mapped>(m));
    2159             :           }
    2160             :           BOOST_CATCH(...)
    2161             :           {
    2162             :             boost::unordered::detail::func::destroy(
    2163             :               boost::addressof(a.node_->value_ptr()->first));
    2164             :             BOOST_RETHROW
    2165             :           }
    2166             :           BOOST_CATCH_END
    2167             :           return a.release();
    2168             :         }
    2169             : 
    2170             :         template <typename Alloc, typename Key,
    2171             :           BOOST_UNORDERED_EMPLACE_TEMPLATE>
    2172             :         inline
    2173             :           typename boost::unordered::detail::allocator_traits<Alloc>::pointer
    2174             :           construct_node_pair_from_args(
    2175             :             Alloc& alloc, BOOST_FWD_REF(Key) k, BOOST_UNORDERED_EMPLACE_ARGS)
    2176             :         {
    2177             :           node_constructor<Alloc> a(alloc);
    2178             :           a.create_node();
    2179             :           boost::unordered::detail::func::construct_value(
    2180             :             boost::addressof(a.node_->value_ptr()->first),
    2181             :             boost::forward<Key>(k));
    2182             :           BOOST_TRY
    2183             :           {
    2184             :             boost::unordered::detail::func::construct_from_args(alloc,
    2185             :               boost::addressof(a.node_->value_ptr()->second),
    2186             :               BOOST_UNORDERED_EMPLACE_FORWARD);
    2187             :           }
    2188             :           BOOST_CATCH(...)
    2189             :           {
    2190             :             boost::unordered::detail::func::destroy(
    2191             :               boost::addressof(a.node_->value_ptr()->first));
    2192             :             BOOST_RETHROW
    2193             :           }
    2194             :           BOOST_CATCH_END
    2195             :           return a.release();
    2196             :         }
    2197             : 
    2198             : #endif
    2199             :       }
    2200             :     }
    2201             :   }
    2202             : }
    2203             : 
    2204             : #if defined(BOOST_MSVC)
    2205             : #pragma warning(pop)
    2206             : #endif
    2207             : 
    2208             : // The 'iterator_detail' namespace was a misguided attempt at avoiding ADL
    2209             : // in the detail namespace. It didn't work because the template parameters
    2210             : // were in detail. I'm not changing it at the moment to be safe. I might
    2211             : // do in the future if I change the iterator types.
    2212             : namespace boost {
    2213             :   namespace unordered {
    2214             :     namespace iterator_detail {
    2215             : 
    2216             :       //////////////////////////////////////////////////////////////////////////
    2217             :       // Iterators
    2218             :       //
    2219             :       // all no throw
    2220             : 
    2221             :       template <typename Node> struct l_iterator
    2222             :       {
    2223             : #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
    2224             :         template <typename Node2>
    2225             :         friend struct boost::unordered::iterator_detail::cl_iterator;
    2226             : 
    2227             :       private:
    2228             : #endif
    2229             :         typedef typename Node::node_pointer node_pointer;
    2230             :         node_pointer ptr_;
    2231             :         std::size_t bucket_;
    2232             :         std::size_t bucket_count_;
    2233             : 
    2234             :       public:
    2235             :         typedef typename Node::value_type element_type;
    2236             :         typedef typename Node::value_type value_type;
    2237             :         typedef value_type* pointer;
    2238             :         typedef value_type& reference;
    2239             :         typedef std::ptrdiff_t difference_type;
    2240             :         typedef std::forward_iterator_tag iterator_category;
    2241             : 
    2242             :         l_iterator() BOOST_NOEXCEPT : ptr_() {}
    2243             : 
    2244             :         l_iterator(node_pointer n, std::size_t b, std::size_t c) BOOST_NOEXCEPT
    2245             :           : ptr_(n),
    2246             :             bucket_(b),
    2247             :             bucket_count_(c)
    2248             :         {
    2249             :         }
    2250             : 
    2251             :         value_type& operator*() const { return ptr_->value(); }
    2252             : 
    2253             :         value_type* operator->() const { return ptr_->value_ptr(); }
    2254             : 
    2255             :         l_iterator& operator++()
    2256             :         {
    2257             :           ptr_ = static_cast<node_pointer>(ptr_->next_);
    2258             :           if (ptr_ && ptr_->get_bucket() != bucket_)
    2259             :             ptr_ = node_pointer();
    2260             :           return *this;
    2261             :         }
    2262             : 
    2263             :         l_iterator operator++(int)
    2264             :         {
    2265             :           l_iterator tmp(*this);
    2266             :           ++(*this);
    2267             :           return tmp;
    2268             :         }
    2269             : 
    2270             :         bool operator==(l_iterator x) const BOOST_NOEXCEPT
    2271             :         {
    2272             :           return ptr_ == x.ptr_;
    2273             :         }
    2274             : 
    2275             :         bool operator!=(l_iterator x) const BOOST_NOEXCEPT
    2276             :         {
    2277             :           return ptr_ != x.ptr_;
    2278             :         }
    2279             :       };
    2280             : 
    2281             :       template <typename Node> struct cl_iterator
    2282             :       {
    2283             :         friend struct boost::unordered::iterator_detail::l_iterator<Node>;
    2284             : 
    2285             :       private:
    2286             :         typedef typename Node::node_pointer node_pointer;
    2287             :         node_pointer ptr_;
    2288             :         std::size_t bucket_;
    2289             :         std::size_t bucket_count_;
    2290             : 
    2291             :       public:
    2292             :         typedef typename Node::value_type const element_type;
    2293             :         typedef typename Node::value_type value_type;
    2294             :         typedef value_type const* pointer;
    2295             :         typedef value_type const& reference;
    2296             :         typedef std::ptrdiff_t difference_type;
    2297             :         typedef std::forward_iterator_tag iterator_category;
    2298             : 
    2299             :         cl_iterator() BOOST_NOEXCEPT : ptr_() {}
    2300             : 
    2301             :         cl_iterator(node_pointer n, std::size_t b, std::size_t c) BOOST_NOEXCEPT
    2302             :           : ptr_(n),
    2303             :             bucket_(b),
    2304             :             bucket_count_(c)
    2305             :         {
    2306             :         }
    2307             : 
    2308             :         cl_iterator(
    2309             :           boost::unordered::iterator_detail::l_iterator<Node> const& x)
    2310             :           BOOST_NOEXCEPT : ptr_(x.ptr_),
    2311             :                            bucket_(x.bucket_),
    2312             :                            bucket_count_(x.bucket_count_)
    2313             :         {
    2314             :         }
    2315             : 
    2316             :         value_type const& operator*() const { return ptr_->value(); }
    2317             : 
    2318             :         value_type const* operator->() const { return ptr_->value_ptr(); }
    2319             : 
    2320             :         cl_iterator& operator++()
    2321             :         {
    2322             :           ptr_ = static_cast<node_pointer>(ptr_->next_);
    2323             :           if (ptr_ && ptr_->get_bucket() != bucket_)
    2324             :             ptr_ = node_pointer();
    2325             :           return *this;
    2326             :         }
    2327             : 
    2328             :         cl_iterator operator++(int)
    2329             :         {
    2330             :           cl_iterator tmp(*this);
    2331             :           ++(*this);
    2332             :           return tmp;
    2333             :         }
    2334             : 
    2335             :         friend bool operator==(
    2336             :           cl_iterator const& x, cl_iterator const& y) BOOST_NOEXCEPT
    2337             :         {
    2338             :           return x.ptr_ == y.ptr_;
    2339             :         }
    2340             : 
    2341             :         friend bool operator!=(
    2342             :           cl_iterator const& x, cl_iterator const& y) BOOST_NOEXCEPT
    2343             :         {
    2344             :           return x.ptr_ != y.ptr_;
    2345             :         }
    2346             :       };
    2347             : 
    2348             :       template <typename Node> struct iterator
    2349             :       {
    2350             : #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
    2351             :         template <typename>
    2352             :         friend struct boost::unordered::iterator_detail::c_iterator;
    2353             :         template <typename> friend struct boost::unordered::detail::table;
    2354             : 
    2355             :       private:
    2356             : #endif
    2357             :         typedef typename Node::node_pointer node_pointer;
    2358             :         node_pointer node_;
    2359             : 
    2360             :       public:
    2361             :         typedef typename Node::value_type element_type;
    2362             :         typedef typename Node::value_type value_type;
    2363             :         typedef value_type* pointer;
    2364             :         typedef value_type& reference;
    2365             :         typedef std::ptrdiff_t difference_type;
    2366             :         typedef std::forward_iterator_tag iterator_category;
    2367             : 
    2368    15755469 :         iterator() BOOST_NOEXCEPT : node_() {}
    2369             : 
    2370    35837859 :         explicit iterator(typename Node::link_pointer x) BOOST_NOEXCEPT
    2371     5264006 :           : node_(static_cast<node_pointer>(x))
    2372             :         {
    2373             :         }
    2374             : 
    2375    24834407 :         value_type& operator*() const { return node_->value(); }
    2376             : 
    2377    58925272 :         value_type* operator->() const { return node_->value_ptr(); }
    2378             : 
    2379     3385763 :         iterator& operator++()
    2380             :         {
    2381     3249592 :           node_ = static_cast<node_pointer>(node_->next_);
    2382     3342922 :           return *this;
    2383             :         }
    2384             : 
    2385     5264006 :         iterator operator++(int)
    2386             :         {
    2387     5264006 :           iterator tmp(node_);
    2388     2010296 :           node_ = static_cast<node_pointer>(node_->next_);
    2389     4199306 :           return tmp;
    2390             :         }
    2391             : 
    2392       83348 :         bool operator==(iterator const& x) const BOOST_NOEXCEPT
    2393             :         {
    2394             :           return node_ == x.node_;
    2395             :         }
    2396             : 
    2397    47898932 :         bool operator!=(iterator const& x) const BOOST_NOEXCEPT
    2398             :         {
    2399       61103 :           return node_ != x.node_;
    2400             :         }
    2401             :       };
    2402             : 
    2403             :       template <typename Node> struct c_iterator
    2404             :       {
    2405             :         friend struct boost::unordered::iterator_detail::iterator<Node>;
    2406             : 
    2407             : #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
    2408             :         template <typename> friend struct boost::unordered::detail::table;
    2409             : 
    2410             :       private:
    2411             : #endif
    2412             :         typedef typename Node::node_pointer node_pointer;
    2413             :         typedef boost::unordered::iterator_detail::iterator<Node> n_iterator;
    2414             :         node_pointer node_;
    2415             : 
    2416             :       public:
    2417             :         typedef typename Node::value_type const element_type;
    2418             :         typedef typename Node::value_type value_type;
    2419             :         typedef value_type const* pointer;
    2420             :         typedef value_type const& reference;
    2421             :         typedef std::ptrdiff_t difference_type;
    2422             :         typedef std::forward_iterator_tag iterator_category;
    2423             : 
    2424           0 :         c_iterator() BOOST_NOEXCEPT : node_() {}
    2425             : 
    2426           0 :         explicit c_iterator(typename Node::link_pointer x) BOOST_NOEXCEPT
    2427           0 :           : node_(static_cast<node_pointer>(x))
    2428             :         {
    2429             :         }
    2430             : 
    2431      108030 :         c_iterator(n_iterator const& x) BOOST_NOEXCEPT : node_(x.node_) {}
    2432             : 
    2433           0 :         value_type const& operator*() const { return node_->value(); }
    2434             : 
    2435    12323390 :         value_type const* operator->() const { return node_->value_ptr(); }
    2436             : 
    2437    10183350 :         c_iterator& operator++()
    2438             :         {
    2439    10183350 :           node_ = static_cast<node_pointer>(node_->next_);
    2440    10183350 :           return *this;
    2441             :         }
    2442             : 
    2443           0 :         c_iterator operator++(int)
    2444             :         {
    2445           0 :           c_iterator tmp(node_);
    2446           0 :           node_ = static_cast<node_pointer>(node_->next_);
    2447           0 :           return tmp;
    2448             :         }
    2449             : 
    2450           0 :         friend bool operator==(
    2451             :           c_iterator const& x, c_iterator const& y) BOOST_NOEXCEPT
    2452             :         {
    2453             :           return x.node_ == y.node_;
    2454             :         }
    2455             : 
    2456    10264880 :         friend bool operator!=(
    2457             :           c_iterator const& x, c_iterator const& y) BOOST_NOEXCEPT
    2458             :         {
    2459           0 :           return x.node_ != y.node_;
    2460             :         }
    2461             :       };
    2462             :     }
    2463             :   }
    2464             : }
    2465             : 
    2466             : namespace boost {
    2467             :   namespace unordered {
    2468             :     namespace detail {
    2469             : 
    2470             :       ///////////////////////////////////////////////////////////////////
    2471             :       //
    2472             :       // Node Holder
    2473             :       //
    2474             :       // Temporary store for nodes. Deletes any that aren't used.
    2475             : 
    2476             :       template <typename NodeAlloc> struct node_holder
    2477             :       {
    2478             :       private:
    2479             :         typedef NodeAlloc node_allocator;
    2480             :         typedef boost::unordered::detail::allocator_traits<NodeAlloc>
    2481             :           node_allocator_traits;
    2482             :         typedef typename node_allocator_traits::value_type node;
    2483             :         typedef typename node_allocator_traits::pointer node_pointer;
    2484             :         typedef typename node::value_type value_type;
    2485             :         typedef typename node::link_pointer link_pointer;
    2486             :         typedef boost::unordered::iterator_detail::iterator<node> iterator;
    2487             : 
    2488             :         node_constructor<NodeAlloc> constructor_;
    2489             :         node_pointer nodes_;
    2490             : 
    2491             :       public:
    2492             :         template <typename Table>
    2493           0 :         explicit node_holder(Table& b) : constructor_(b.node_alloc()), nodes_()
    2494             :         {
    2495           0 :           if (b.size_) {
    2496           0 :             typename Table::link_pointer prev = b.get_previous_start();
    2497           0 :             nodes_ = static_cast<node_pointer>(prev->next_);
    2498           0 :             prev->next_ = link_pointer();
    2499           0 :             b.size_ = 0;
    2500             :           }
    2501           0 :         }
    2502             : 
    2503             :         ~node_holder();
    2504             : 
    2505           0 :         node_pointer pop_node()
    2506             :         {
    2507           0 :           node_pointer n = nodes_;
    2508           0 :           nodes_ = static_cast<node_pointer>(nodes_->next_);
    2509           0 :           n->next_ = link_pointer();
    2510             :           return n;
    2511             :         }
    2512             : 
    2513           0 :         template <typename T> inline node_pointer copy_of(T const& v)
    2514             :         {
    2515           0 :           if (nodes_) {
    2516           0 :             constructor_.reclaim(pop_node());
    2517             :           } else {
    2518           0 :             constructor_.create_node();
    2519             :           }
    2520           0 :           BOOST_UNORDERED_CALL_CONSTRUCT1(node_allocator_traits,
    2521             :             constructor_.alloc_, constructor_.node_->value_ptr(), v);
    2522           0 :           return constructor_.release();
    2523             :         }
    2524             : 
    2525             :         template <typename T> inline node_pointer move_copy_of(T& v)
    2526             :         {
    2527             :           if (nodes_) {
    2528             :             constructor_.reclaim(pop_node());
    2529             :           } else {
    2530             :             constructor_.create_node();
    2531             :           }
    2532             :           BOOST_UNORDERED_CALL_CONSTRUCT1(node_allocator_traits,
    2533             :             constructor_.alloc_, constructor_.node_->value_ptr(),
    2534             :             boost::move(v));
    2535             :           return constructor_.release();
    2536             :         }
    2537             : 
    2538             :         iterator begin() const { return iterator(nodes_); }
    2539             :       };
    2540             : 
    2541           0 :       template <typename Alloc> node_holder<Alloc>::~node_holder()
    2542             :       {
    2543           0 :         while (nodes_) {
    2544           0 :           node_pointer p = nodes_;
    2545           0 :           nodes_ = static_cast<node_pointer>(p->next_);
    2546             : 
    2547           0 :           BOOST_UNORDERED_CALL_DESTROY(
    2548             :             node_allocator_traits, constructor_.alloc_, p->value_ptr());
    2549           0 :           boost::unordered::detail::func::destroy(boost::to_address(p));
    2550           0 :           node_allocator_traits::deallocate(constructor_.alloc_, p, 1);
    2551             :         }
    2552           0 :       }
    2553             : 
    2554             :       ///////////////////////////////////////////////////////////////////
    2555             :       //
    2556             :       // Bucket
    2557             : 
    2558             :       template <typename NodePointer> struct bucket
    2559             :       {
    2560             :         typedef NodePointer link_pointer;
    2561             :         link_pointer next_;
    2562             : 
    2563             :         bucket() : next_() {}
    2564             :         bucket(link_pointer n) : next_(n) {}
    2565             : 
    2566             :         link_pointer first_from_start() { return next_; }
    2567             : 
    2568             :         enum
    2569             :         {
    2570             :           extra_node = true
    2571             :         };
    2572             :       };
    2573             : 
    2574             :       struct ptr_bucket
    2575             :       {
    2576             :         typedef ptr_bucket* link_pointer;
    2577             :         link_pointer next_;
    2578             : 
    2579    16514040 :         ptr_bucket() : next_(0) {}
    2580       82687 :         ptr_bucket(link_pointer n) : next_(n) {}
    2581             : 
    2582     1578425 :         link_pointer first_from_start() { return this; }
    2583             : 
    2584             :         enum
    2585             :         {
    2586             :           extra_node = false
    2587             :         };
    2588             :       };
    2589             : 
    2590             :       ///////////////////////////////////////////////////////////////////
    2591             :       //
    2592             :       // Hash Policy
    2593             : 
    2594             :       template <typename SizeT> struct prime_policy
    2595             :       {
    2596             :         template <typename Hash, typename T>
    2597           0 :         static inline SizeT apply_hash(Hash const& hf, T const& x)
    2598             :         {
    2599           0 :           return hf(x);
    2600             :         }
    2601             : 
    2602           0 :         static inline SizeT to_bucket(SizeT bucket_count, SizeT hash)
    2603             :         {
    2604           0 :           return hash % bucket_count;
    2605             :         }
    2606             : 
    2607           0 :         static inline SizeT new_bucket_count(SizeT min)
    2608             :         {
    2609           0 :           return boost::unordered::detail::next_prime(min);
    2610             :         }
    2611             : 
    2612             :         static inline SizeT prev_bucket_count(SizeT max)
    2613             :         {
    2614             :           return boost::unordered::detail::prev_prime(max);
    2615             :         }
    2616             :       };
    2617             : 
    2618             :       template <typename SizeT> struct mix64_policy
    2619             :       {
    2620             :         template <typename Hash, typename T>
    2621    40859022 :         static inline SizeT apply_hash(Hash const& hf, T const& x)
    2622             :         {
    2623    40859022 :           SizeT key = hf(x);
    2624    40859022 :           key = (~key) + (key << 21); // key = (key << 21) - key - 1;
    2625    40859022 :           key = key ^ (key >> 24);
    2626    40859022 :           key = (key + (key << 3)) + (key << 8); // key * 265
    2627    40859022 :           key = key ^ (key >> 14);
    2628    40859022 :           key = (key + (key << 2)) + (key << 4); // key * 21
    2629    40859022 :           key = key ^ (key >> 28);
    2630    40859022 :           key = key + (key << 31);
    2631    40859022 :           return key;
    2632             :         }
    2633             : 
    2634    43308114 :         static inline SizeT to_bucket(SizeT bucket_count, SizeT hash)
    2635             :         {
    2636    43308114 :           return hash & (bucket_count - 1);
    2637             :         }
    2638             : 
    2639      386790 :         static inline SizeT new_bucket_count(SizeT min)
    2640             :         {
    2641      304106 :           if (min <= 4)
    2642             :             return 4;
    2643      311631 :           --min;
    2644      311631 :           min |= min >> 1;
    2645      311631 :           min |= min >> 2;
    2646      311631 :           min |= min >> 4;
    2647      311631 :           min |= min >> 8;
    2648      311631 :           min |= min >> 16;
    2649      311631 :           min |= min >> 32;
    2650      304105 :           return min + 1;
    2651             :         }
    2652             : 
    2653             :         static inline SizeT prev_bucket_count(SizeT max)
    2654             :         {
    2655             :           max |= max >> 1;
    2656             :           max |= max >> 2;
    2657             :           max |= max >> 4;
    2658             :           max |= max >> 8;
    2659             :           max |= max >> 16;
    2660             :           max |= max >> 32;
    2661             :           return (max >> 1) + 1;
    2662             :         }
    2663             :       };
    2664             : 
    2665             :       template <int digits, int radix> struct pick_policy_impl
    2666             :       {
    2667             :         typedef prime_policy<std::size_t> type;
    2668             :       };
    2669             : 
    2670             :       template <> struct pick_policy_impl<64, 2>
    2671             :       {
    2672             :         typedef mix64_policy<std::size_t> type;
    2673             :       };
    2674             : 
    2675             :       template <typename T>
    2676             :       struct pick_policy2
    2677             :         : pick_policy_impl<std::numeric_limits<std::size_t>::digits,
    2678             :             std::numeric_limits<std::size_t>::radix>
    2679             :       {
    2680             :       };
    2681             : 
    2682             :       // While the mix policy is generally faster, the prime policy is a lot
    2683             :       // faster when a large number consecutive integers are used, because
    2684             :       // there are no collisions. Since that is probably quite common, use
    2685             :       // prime policy for integeral types. But not the smaller ones, as they
    2686             :       // don't have enough unique values for this to be an issue.
    2687             : 
    2688             :       template <> struct pick_policy2<int>
    2689             :       {
    2690             :         typedef prime_policy<std::size_t> type;
    2691             :       };
    2692             : 
    2693             :       template <> struct pick_policy2<unsigned int>
    2694             :       {
    2695             :         typedef prime_policy<std::size_t> type;
    2696             :       };
    2697             : 
    2698             :       template <> struct pick_policy2<long>
    2699             :       {
    2700             :         typedef prime_policy<std::size_t> type;
    2701             :       };
    2702             : 
    2703             :       template <> struct pick_policy2<unsigned long>
    2704             :       {
    2705             :         typedef prime_policy<std::size_t> type;
    2706             :       };
    2707             : 
    2708             : #if !defined(BOOST_NO_LONG_LONG)
    2709             :       template <> struct pick_policy2<boost::long_long_type>
    2710             :       {
    2711             :         typedef prime_policy<std::size_t> type;
    2712             :       };
    2713             : 
    2714             :       template <> struct pick_policy2<boost::ulong_long_type>
    2715             :       {
    2716             :         typedef prime_policy<std::size_t> type;
    2717             :       };
    2718             : #endif
    2719             : 
    2720             :       template <typename T>
    2721             :       struct pick_policy : pick_policy2<typename boost::remove_cv<T>::type>
    2722             :       {
    2723             :       };
    2724             : 
    2725             :       //////////////////////////////////////////////////////////////////////////
    2726             :       // Functions
    2727             :       //
    2728             :       // This double buffers the storage for the hash function and key equality
    2729             :       // predicate in order to have exception safe copy/swap. To do so,
    2730             :       // use 'construct_spare' to construct in the spare space, and then when
    2731             :       // ready to use 'switch_functions' to switch to the new functions.
    2732             :       // If an exception is thrown between these two calls, use
    2733             :       // 'cleanup_spare_functions' to destroy the unused constructed functions.
    2734             : 
    2735             :       template <class H, class P> class functions
    2736             :       {
    2737             :       public:
    2738             :         static const bool nothrow_move_assignable =
    2739             :           boost::is_nothrow_move_assignable<H>::value &&
    2740             :           boost::is_nothrow_move_assignable<P>::value;
    2741             :         static const bool nothrow_move_constructible =
    2742             :           boost::is_nothrow_move_constructible<H>::value &&
    2743             :           boost::is_nothrow_move_constructible<P>::value;
    2744             :         static const bool nothrow_swappable =
    2745             :           boost::is_nothrow_swappable<H>::value &&
    2746             :           boost::is_nothrow_swappable<P>::value;
    2747             : 
    2748             :       private:
    2749             :         functions& operator=(functions const&);
    2750             : 
    2751             :         typedef compressed<H, P> function_pair;
    2752             : 
    2753             :         typedef typename boost::aligned_storage<sizeof(function_pair),
    2754             :           boost::alignment_of<function_pair>::value>::type aligned_function;
    2755             : 
    2756             :         unsigned char current_; // 0/1 - Currently active functions
    2757             :                                 // +2 - Both constructed
    2758             :         aligned_function funcs_[2];
    2759             : 
    2760             :       public:
    2761      304103 :         functions(H const& hf, P const& eq) : current_(0)
    2762             :         {
    2763      304103 :           construct_functions(current_, hf, eq);
    2764             :         }
    2765             : 
    2766           0 :         functions(functions const& bf) : current_(0)
    2767             :         {
    2768           0 :           construct_functions(current_, bf.current_functions());
    2769             :         }
    2770             : 
    2771           0 :         functions(functions& bf, boost::unordered::detail::move_tag)
    2772           0 :             : current_(0)
    2773             :         {
    2774           0 :           construct_functions(current_, bf.current_functions(),
    2775             :             boost::unordered::detail::integral_constant<bool,
    2776             :               nothrow_move_constructible>());
    2777             :         }
    2778             : 
    2779       55170 :         ~functions()
    2780             :         {
    2781       55170 :           BOOST_ASSERT(!(current_ & 2));
    2782       55170 :           destroy_functions(current_);
    2783             :         }
    2784             : 
    2785    40859693 :         H const& hash_function() const { return current_functions().first(); }
    2786             : 
    2787    56394981 :         P const& key_eq() const { return current_functions().second(); }
    2788             : 
    2789    61990693 :         function_pair const& current_functions() const
    2790             :         {
    2791             :           return *static_cast<function_pair const*>(
    2792    29298093 :             static_cast<void const*>(funcs_[current_ & 1].address()));
    2793             :         }
    2794             : 
    2795           0 :         function_pair& current_functions()
    2796             :         {
    2797             :           return *static_cast<function_pair*>(
    2798           0 :             static_cast<void*>(funcs_[current_ & 1].address()));
    2799             :         }
    2800             : 
    2801             :         void construct_spare_functions(function_pair const& f)
    2802             :         {
    2803             :           BOOST_ASSERT(!(current_ & 2));
    2804             :           construct_functions(current_ ^ 1, f);
    2805             :           current_ |= 2;
    2806             :         }
    2807             : 
    2808           0 :         void cleanup_spare_functions()
    2809             :         {
    2810           0 :           if (current_ & 2) {
    2811           0 :             current_ = static_cast<unsigned char>(current_ & 1);
    2812           0 :             destroy_functions(current_ ^ 1);
    2813             :           }
    2814             :         }
    2815             : 
    2816             :         void switch_functions()
    2817             :         {
    2818             :           BOOST_ASSERT(current_ & 2);
    2819             :           destroy_functions(static_cast<unsigned char>(current_ & 1));
    2820             :           current_ ^= 3;
    2821             :         }
    2822             : 
    2823             :       private:
    2824      304103 :         void construct_functions(unsigned char which, H const& hf, P const& eq)
    2825             :         {
    2826           1 :           BOOST_ASSERT(!(which & 2));
    2827      304103 :           new ((void*)&funcs_[which]) function_pair(hf, eq);
    2828             :         }
    2829             : 
    2830           0 :         void construct_functions(unsigned char which, function_pair const& f,
    2831             :           boost::unordered::detail::false_type =
    2832             :             boost::unordered::detail::false_type())
    2833             :         {
    2834           0 :           BOOST_ASSERT(!(which & 2));
    2835           0 :           new ((void*)&funcs_[which]) function_pair(f);
    2836             :         }
    2837             : 
    2838           0 :         void construct_functions(unsigned char which, function_pair& f,
    2839             :           boost::unordered::detail::true_type)
    2840             :         {
    2841           0 :           BOOST_ASSERT(!(which & 2));
    2842           0 :           new ((void*)&funcs_[which])
    2843             :             function_pair(f, boost::unordered::detail::move_tag());
    2844             :         }
    2845             : 
    2846       55170 :         void destroy_functions(unsigned char which)
    2847             :         {
    2848       55170 :           BOOST_ASSERT(!(which & 2));
    2849       55170 :           boost::unordered::detail::func::destroy(
    2850       55170 :             (function_pair*)(&funcs_[which]));
    2851             :         }
    2852             :       };
    2853             : 
    2854             : ////////////////////////////////////////////////////////////////////////////
    2855             : // rvalue parameters when type can't be a BOOST_RV_REF(T) parameter
    2856             : // e.g. for int
    2857             : 
    2858             : #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
    2859             : #define BOOST_UNORDERED_RV_REF(T) BOOST_RV_REF(T)
    2860             : #else
    2861             :       struct please_ignore_this_overload
    2862             :       {
    2863             :         typedef please_ignore_this_overload type;
    2864             :       };
    2865             : 
    2866             :       template <typename T> struct rv_ref_impl
    2867             :       {
    2868             :         typedef BOOST_RV_REF(T) type;
    2869             :       };
    2870             : 
    2871             :       template <typename T>
    2872             :       struct rv_ref
    2873             :         : boost::detail::if_true<boost::is_class<T>::value>::
    2874             :             BOOST_NESTED_TEMPLATE then<boost::unordered::detail::rv_ref_impl<T>,
    2875             :               please_ignore_this_overload>::type
    2876             :       {
    2877             :       };
    2878             : 
    2879             : #define BOOST_UNORDERED_RV_REF(T)                                              \
    2880             :   typename boost::unordered::detail::rv_ref<T>::type
    2881             : #endif
    2882             : 
    2883             : #if defined(BOOST_MSVC)
    2884             : #pragma warning(push)
    2885             : #pragma warning(disable : 4127) // conditional expression is constant
    2886             : #endif
    2887             : 
    2888             :       //////////////////////////////////////////////////////////////////////////
    2889             :       // convert double to std::size_t
    2890             : 
    2891      165374 :       inline std::size_t double_to_size(double f)
    2892             :       {
    2893      165374 :         return f >= static_cast<double>(
    2894             :                       (std::numeric_limits<std::size_t>::max)())
    2895       82687 :                  ? (std::numeric_limits<std::size_t>::max)()
    2896             :                  : static_cast<std::size_t>(f);
    2897             :       }
    2898             : 
    2899             :       template <typename Types>
    2900             :       struct table : boost::unordered::detail::functions<typename Types::hasher,
    2901             :                        typename Types::key_equal>
    2902             :       {
    2903             :       private:
    2904             :         table(table const&);
    2905             :         table& operator=(table const&);
    2906             : 
    2907             :       public:
    2908             :         typedef typename Types::node node;
    2909             :         typedef typename Types::bucket bucket;
    2910             :         typedef typename Types::hasher hasher;
    2911             :         typedef typename Types::key_equal key_equal;
    2912             :         typedef typename Types::const_key_type const_key_type;
    2913             :         typedef typename Types::extractor extractor;
    2914             :         typedef typename Types::value_type value_type;
    2915             :         typedef typename Types::table table_impl;
    2916             :         typedef typename Types::link_pointer link_pointer;
    2917             :         typedef typename Types::policy policy;
    2918             :         typedef typename Types::iterator iterator;
    2919             :         typedef typename Types::c_iterator c_iterator;
    2920             :         typedef typename Types::l_iterator l_iterator;
    2921             :         typedef typename Types::cl_iterator cl_iterator;
    2922             : 
    2923             :         typedef boost::unordered::detail::functions<typename Types::hasher,
    2924             :           typename Types::key_equal>
    2925             :           functions;
    2926             : 
    2927             :         typedef typename Types::value_allocator value_allocator;
    2928             :         typedef typename boost::unordered::detail::rebind_wrap<value_allocator,
    2929             :           node>::type node_allocator;
    2930             :         typedef typename boost::unordered::detail::rebind_wrap<value_allocator,
    2931             :           bucket>::type bucket_allocator;
    2932             :         typedef boost::unordered::detail::allocator_traits<node_allocator>
    2933             :           node_allocator_traits;
    2934             :         typedef boost::unordered::detail::allocator_traits<bucket_allocator>
    2935             :           bucket_allocator_traits;
    2936             :         typedef typename node_allocator_traits::pointer node_pointer;
    2937             :         typedef
    2938             :           typename node_allocator_traits::const_pointer const_node_pointer;
    2939             :         typedef typename bucket_allocator_traits::pointer bucket_pointer;
    2940             :         typedef boost::unordered::detail::node_constructor<node_allocator>
    2941             :           node_constructor;
    2942             :         typedef boost::unordered::detail::node_tmp<node_allocator> node_tmp;
    2943             : 
    2944             :         typedef std::pair<iterator, bool> emplace_return;
    2945             : 
    2946             :         ////////////////////////////////////////////////////////////////////////
    2947             :         // Members
    2948             : 
    2949             :         boost::unordered::detail::compressed<bucket_allocator, node_allocator>
    2950             :           allocators_;
    2951             :         std::size_t bucket_count_;
    2952             :         std::size_t size_;
    2953             :         float mlf_;
    2954             :         std::size_t max_load_;
    2955             :         bucket_pointer buckets_;
    2956             : 
    2957             :         ////////////////////////////////////////////////////////////////////////
    2958             :         // Data access
    2959             : 
    2960       26493 :         static node_pointer get_node(c_iterator it) { return it.node_; }
    2961             : 
    2962    20225343 :         static node_pointer next_node(link_pointer n)
    2963             :         {
    2964             :           return static_cast<node_pointer>(n->next_);
    2965             :         }
    2966             : 
    2967             :         static node_pointer next_for_find(link_pointer n)
    2968             :         {
    2969             :           node_pointer n2 = static_cast<node_pointer>(n);
    2970             :           do {
    2971    11559460 :             n2 = next_node(n2);
    2972    11559460 :           } while (n2 && !n2->is_first_in_group());
    2973             :           return n2;
    2974             :         }
    2975             : 
    2976           0 :         node_pointer next_group(node_pointer n) const
    2977             :         {
    2978             :           node_pointer n1 = n;
    2979             :           do {
    2980     8226120 :             n1 = next_node(n1);
    2981     8226120 :           } while (n1 && !n1->is_first_in_group());
    2982             :           return n1;
    2983             :         }
    2984             : 
    2985             :         std::size_t group_count(node_pointer n) const
    2986             :         {
    2987             :           std::size_t x = 0;
    2988             :           node_pointer it = n;
    2989             :           do {
    2990       41352 :             ++x;
    2991       41352 :             it = next_node(it);
    2992       41352 :           } while (it && !it->is_first_in_group());
    2993             : 
    2994             :           return x;
    2995             :         }
    2996             : 
    2997    18544881 :         std::size_t node_bucket(node_pointer n) const
    2998             :         {
    2999    18544881 :           return n->get_bucket();
    3000             :         }
    3001             : 
    3002             :         bucket_allocator const& bucket_alloc() const
    3003             :         {
    3004             :           return allocators_.first();
    3005             :         }
    3006             : 
    3007           0 :         node_allocator const& node_alloc() const
    3008             :         {
    3009           0 :           return allocators_.second();
    3010             :         }
    3011             : 
    3012      102604 :         bucket_allocator& bucket_alloc() { return allocators_.first(); }
    3013             : 
    3014     2449110 :         node_allocator& node_alloc() { return allocators_.second(); }
    3015             : 
    3016             :         std::size_t max_bucket_count() const
    3017             :         {
    3018             :           // -1 to account for the start bucket.
    3019             :           return policy::prev_bucket_count(
    3020             :             bucket_allocator_traits::max_size(bucket_alloc()) - 1);
    3021             :         }
    3022             : 
    3023    45848380 :         bucket_pointer get_bucket_pointer(std::size_t bucket_index) const
    3024             :         {
    3025           0 :           BOOST_ASSERT(buckets_);
    3026    45848380 :           return buckets_ + static_cast<std::ptrdiff_t>(bucket_index);
    3027             :         }
    3028             : 
    3029     1566055 :         link_pointer get_previous_start() const
    3030             :         {
    3031      246871 :           return get_bucket_pointer(bucket_count_)->first_from_start();
    3032             :         }
    3033             : 
    3034    37410079 :         link_pointer get_previous_start(std::size_t bucket_index) const
    3035             :         {
    3036    37383579 :           return get_bucket_pointer(bucket_index)->next_;
    3037             :         }
    3038             : 
    3039      695285 :         node_pointer begin() const
    3040             :         {
    3041      942108 :           return size_ ? next_node(get_previous_start()) : node_pointer();
    3042             :         }
    3043             : 
    3044    37712881 :         node_pointer begin(std::size_t bucket_index) const
    3045             :         {
    3046    37712881 :           if (!size_)
    3047             :             return node_pointer();
    3048    37383579 :           link_pointer prev = get_previous_start(bucket_index);
    3049    37383579 :           return prev ? next_node(prev) : node_pointer();
    3050             :         }
    3051             : 
    3052    43308114 :         std::size_t hash_to_bucket(std::size_t hash_value) const
    3053             :         {
    3054    43308114 :           return policy::to_bucket(bucket_count_, hash_value);
    3055             :         }
    3056             : 
    3057           0 :         std::size_t bucket_size(std::size_t index) const
    3058             :         {
    3059           0 :           node_pointer n = begin(index);
    3060           0 :           if (!n)
    3061             :             return 0;
    3062             : 
    3063             :           std::size_t count = 0;
    3064           0 :           while (n && node_bucket(n) == index) {
    3065           0 :             ++count;
    3066           0 :             n = next_node(n);
    3067             :           }
    3068             : 
    3069             :           return count;
    3070             :         }
    3071             : 
    3072             :         ////////////////////////////////////////////////////////////////////////
    3073             :         // Load methods
    3074             : 
    3075       82687 :         void recalculate_max_load()
    3076             :         {
    3077             :           using namespace std;
    3078             : 
    3079             :           // From 6.3.1/13:
    3080             :           // Only resize when size >= mlf_ * count
    3081       82687 :           max_load_ = buckets_ ? boost::unordered::detail::double_to_size(
    3082       82687 :                                    ceil(static_cast<double>(mlf_) *
    3083       82687 :                                         static_cast<double>(bucket_count_)))
    3084             :                                : 0;
    3085       82687 :         }
    3086             : 
    3087             :         void max_load_factor(float z)
    3088             :         {
    3089             :           BOOST_ASSERT(z > 0);
    3090             :           mlf_ = (std::max)(z, minimum_max_load_factor);
    3091             :           recalculate_max_load();
    3092             :         }
    3093             : 
    3094       82687 :         std::size_t min_buckets_for_size(std::size_t size) const
    3095             :         {
    3096       82687 :           BOOST_ASSERT(mlf_ >= minimum_max_load_factor);
    3097             : 
    3098             :           using namespace std;
    3099             : 
    3100             :           // From insert/emplace requirements:
    3101             :           //
    3102             :           // size <= mlf_ * count
    3103             :           // => count >= size / mlf_
    3104             :           //
    3105             :           // Or from rehash post-condition:
    3106             :           //
    3107             :           // count >= size / mlf_
    3108             : 
    3109       82687 :           return policy::new_bucket_count(
    3110             :             boost::unordered::detail::double_to_size(
    3111       82687 :               floor(static_cast<double>(size) / static_cast<double>(mlf_)) +
    3112       82687 :               1));
    3113             :         }
    3114             : 
    3115             :         ////////////////////////////////////////////////////////////////////////
    3116             :         // Constructors
    3117             : 
    3118      304103 :         table(std::size_t num_buckets, hasher const& hf, key_equal const& eq,
    3119             :           node_allocator const& a)
    3120             :             : functions(hf, eq), allocators_(a, a),
    3121           1 :               bucket_count_(policy::new_bucket_count(num_buckets)), size_(0),
    3122      304103 :               mlf_(1.0f), max_load_(0), buckets_()
    3123             :         {
    3124      304102 :         }
    3125             : 
    3126           0 :         table(table const& x, node_allocator const& a)
    3127             :             : functions(x), allocators_(a, a),
    3128           0 :               bucket_count_(x.min_buckets_for_size(x.size_)), size_(0),
    3129           0 :               mlf_(x.mlf_), max_load_(0), buckets_()
    3130             :         {
    3131             :         }
    3132             : 
    3133           0 :         table(table& x, boost::unordered::detail::move_tag m)
    3134           0 :             : functions(x, m), allocators_(x.allocators_, m),
    3135           0 :               bucket_count_(x.bucket_count_), size_(x.size_), mlf_(x.mlf_),
    3136           0 :               max_load_(x.max_load_), buckets_(x.buckets_)
    3137             :         {
    3138           0 :           x.buckets_ = bucket_pointer();
    3139           0 :           x.size_ = 0;
    3140           0 :           x.max_load_ = 0;
    3141             :         }
    3142             : 
    3143             :         table(table& x, node_allocator const& a,
    3144             :           boost::unordered::detail::move_tag m)
    3145             :             : functions(x, m), allocators_(a, a),
    3146             :               bucket_count_(x.bucket_count_), size_(0), mlf_(x.mlf_),
    3147             :               max_load_(0), buckets_()
    3148             :         {
    3149             :         }
    3150             : 
    3151             :         ////////////////////////////////////////////////////////////////////////
    3152             :         // Clear buckets and Create buckets
    3153             :         //
    3154             :         // IMPORTANT: If the container already contains any elements, the
    3155             :         //            buckets will not contain any links to them. This will
    3156             :         //            need to be dealt with, for example by:
    3157             :         //            - deleting them
    3158             :         //            - putting them in a 'node_holder' for future use
    3159             :         //              (as in assignment)
    3160             :         //            - placing them in buckets (see rehash_impl)
    3161             : 
    3162             :         // Clear the bucket pointers.
    3163           0 :         void clear_buckets()
    3164             :         {
    3165           0 :           bucket_pointer end = get_bucket_pointer(bucket_count_);
    3166           0 :           for (bucket_pointer it = buckets_; it != end; ++it) {
    3167           0 :             it->next_ = node_pointer();
    3168             :           }
    3169           0 :         }
    3170             : 
    3171             :         // Create container buckets. If the container already contains any
    3172             :         // buckets
    3173             :         // the linked list will be transferred to the new buckets, but none
    3174             :         // of the bucket pointers will be set. See above note.
    3175             :         //
    3176             :         // Strong exception safety.
    3177       82687 :         void create_buckets(std::size_t new_count)
    3178             :         {
    3179             :           link_pointer dummy_node;
    3180             : 
    3181             :           // Construct the new buckets and dummy node, and destroy the old
    3182             :           // buckets
    3183       82687 :           if (buckets_) {
    3184        7529 :             dummy_node =
    3185        7529 :               (buckets_ + static_cast<std::ptrdiff_t>(bucket_count_))->next_;
    3186             :             bucket_pointer new_buckets =
    3187        7529 :               bucket_allocator_traits::allocate(bucket_alloc(), new_count + 1);
    3188        7529 :             destroy_buckets();
    3189        7529 :             buckets_ = new_buckets;
    3190             :           } else if (bucket::extra_node) {
    3191             :             node_constructor a(node_alloc());
    3192             :             a.create_node();
    3193             :             buckets_ =
    3194             :               bucket_allocator_traits::allocate(bucket_alloc(), new_count + 1);
    3195             :             dummy_node = a.release();
    3196             :           } else {
    3197       75158 :             dummy_node = link_pointer();
    3198       75158 :             buckets_ =
    3199      150316 :               bucket_allocator_traits::allocate(bucket_alloc(), new_count + 1);
    3200             :           }
    3201             : 
    3202             :           // nothrow from here...
    3203       82687 :           bucket_count_ = new_count;
    3204       82687 :           recalculate_max_load();
    3205             : 
    3206       82687 :           bucket_pointer end =
    3207       82687 :             buckets_ + static_cast<std::ptrdiff_t>(new_count);
    3208    16596744 :           for (bucket_pointer i = buckets_; i != end; ++i) {
    3209    16514040 :             new ((void*)boost::to_address(i)) bucket();
    3210             :           }
    3211       82687 :           new ((void*)boost::to_address(end)) bucket(dummy_node);
    3212       82687 :         }
    3213             : 
    3214             :         ////////////////////////////////////////////////////////////////////////
    3215             :         // Swap and Move
    3216             : 
    3217             :         void swap_allocators(table& other, false_type)
    3218             :         {
    3219             :           boost::unordered::detail::func::ignore_unused_variable_warning(other);
    3220             : 
    3221             :           // According to 23.2.1.8, if propagate_on_container_swap is
    3222             :           // false the behaviour is undefined unless the allocators
    3223             :           // are equal.
    3224             :           BOOST_ASSERT(node_alloc() == other.node_alloc());
    3225             :         }
    3226             : 
    3227             :         void swap_allocators(table& other, true_type)
    3228             :         {
    3229             :           allocators_.swap(other.allocators_);
    3230             :         }
    3231             : 
    3232             :         // Not nothrow swappable
    3233             :         void swap(table& x, false_type)
    3234             :         {
    3235             :           if (this == &x) {
    3236             :             return;
    3237             :           }
    3238             : 
    3239             :           this->construct_spare_functions(x.current_functions());
    3240             :           BOOST_TRY { x.construct_spare_functions(this->current_functions()); }
    3241             :           BOOST_CATCH(...)
    3242             :           {
    3243             :             this->cleanup_spare_functions();
    3244             :             BOOST_RETHROW
    3245             :           }
    3246             :           BOOST_CATCH_END
    3247             :           this->switch_functions();
    3248             :           x.switch_functions();
    3249             : 
    3250             :           swap_allocators(
    3251             :             x, boost::unordered::detail::integral_constant<bool,
    3252             :                  allocator_traits<
    3253             :                    node_allocator>::propagate_on_container_swap::value>());
    3254             : 
    3255             :           boost::swap(buckets_, x.buckets_);
    3256             :           boost::swap(bucket_count_, x.bucket_count_);
    3257             :           boost::swap(size_, x.size_);
    3258             :           std::swap(mlf_, x.mlf_);
    3259             :           std::swap(max_load_, x.max_load_);
    3260             :         }
    3261             : 
    3262             :         // Nothrow swappable
    3263             :         void swap(table& x, true_type)
    3264             :         {
    3265             :           swap_allocators(
    3266             :             x, boost::unordered::detail::integral_constant<bool,
    3267             :                  allocator_traits<
    3268             :                    node_allocator>::propagate_on_container_swap::value>());
    3269             : 
    3270             :           boost::swap(buckets_, x.buckets_);
    3271             :           boost::swap(bucket_count_, x.bucket_count_);
    3272             :           boost::swap(size_, x.size_);
    3273             :           std::swap(mlf_, x.mlf_);
    3274             :           std::swap(max_load_, x.max_load_);
    3275             :           this->current_functions().swap(x.current_functions());
    3276             :         }
    3277             : 
    3278             :         // Only swaps the allocators if propagate_on_container_swap.
    3279             :         // If not propagate_on_container_swap and allocators aren't
    3280             :         // equal, behaviour is undefined.
    3281             :         void swap(table& x)
    3282             :         {
    3283             :           BOOST_ASSERT(allocator_traits<
    3284             :                          node_allocator>::propagate_on_container_swap::value ||
    3285             :                        node_alloc() == x.node_alloc());
    3286             :           swap(x, boost::unordered::detail::integral_constant<bool,
    3287             :                     functions::nothrow_swappable>());
    3288             :         }
    3289             : 
    3290             :         // Only call with nodes allocated with the currect allocator, or
    3291             :         // one that is equal to it. (Can't assert because other's
    3292             :         // allocators might have already been moved).
    3293             :         void move_buckets_from(table& other)
    3294             :         {
    3295             :           BOOST_ASSERT(!buckets_);
    3296             :           buckets_ = other.buckets_;
    3297             :           bucket_count_ = other.bucket_count_;
    3298             :           size_ = other.size_;
    3299             :           max_load_ = other.max_load_;
    3300             :           other.buckets_ = bucket_pointer();
    3301             :           other.size_ = 0;
    3302             :           other.max_load_ = 0;
    3303             :         }
    3304             : 
    3305             :         // For use in the constructor when allocators might be different.
    3306             :         void move_construct_buckets(table& src)
    3307             :         {
    3308             :           if (this->node_alloc() == src.node_alloc()) {
    3309             :             move_buckets_from(src);
    3310             :           } else {
    3311             :             this->create_buckets(this->bucket_count_);
    3312             :             link_pointer prev = this->get_previous_start();
    3313             :             std::size_t last_bucket = this->bucket_count_;
    3314             :             for (node_pointer n = src.begin(); n; n = next_node(n)) {
    3315             :               std::size_t n_bucket = n->get_bucket();
    3316             :               if (n_bucket != last_bucket) {
    3317             :                 this->get_bucket_pointer(n_bucket)->next_ = prev;
    3318             :               }
    3319             :               node_pointer n2 = boost::unordered::detail::func::construct_node(
    3320             :                 this->node_alloc(), boost::move(n->value()));
    3321             :               n2->bucket_info_ = n->bucket_info_;
    3322             :               prev->next_ = n2;
    3323             :               ++size_;
    3324             :               prev = n2;
    3325             :               last_bucket = n_bucket;
    3326             :             }
    3327             :           }
    3328             :         }
    3329             : 
    3330             :         ////////////////////////////////////////////////////////////////////////
    3331             :         // Delete/destruct
    3332             : 
    3333       55170 :         ~table() { delete_buckets(); }
    3334             : 
    3335      128376 :         void destroy_node(node_pointer n)
    3336             :         {
    3337      128376 :           BOOST_UNORDERED_CALL_DESTROY(
    3338             :             node_allocator_traits, node_alloc(), n->value_ptr());
    3339      128376 :           boost::unordered::detail::func::destroy(boost::to_address(n));
    3340      128376 :           node_allocator_traits::deallocate(node_alloc(), n, 1);
    3341             :         }
    3342             : 
    3343       55170 :         void delete_buckets()
    3344             :         {
    3345       55170 :           if (buckets_) {
    3346       12388 :             node_pointer n = static_cast<node_pointer>(
    3347       12388 :               get_bucket_pointer(bucket_count_)->next_);
    3348             : 
    3349             :             if (bucket::extra_node) {
    3350             :               node_pointer next = next_node(n);
    3351             :               boost::unordered::detail::func::destroy(boost::to_address(n));
    3352             :               node_allocator_traits::deallocate(node_alloc(), n, 1);
    3353             :               n = next;
    3354             :             }
    3355             : 
    3356       12388 :             while (n) {
    3357           0 :               node_pointer next = next_node(n);
    3358           0 :               destroy_node(n);
    3359           0 :               n = next;
    3360             :             }
    3361             : 
    3362       12388 :             destroy_buckets();
    3363       12388 :             buckets_ = bucket_pointer();
    3364       12388 :             max_load_ = 0;
    3365       12388 :             size_ = 0;
    3366             :           }
    3367       55170 :         }
    3368             : 
    3369       19917 :         void destroy_buckets()
    3370             :         {
    3371       19917 :           bucket_pointer end = get_bucket_pointer(bucket_count_ + 1);
    3372       19917 :           for (bucket_pointer it = buckets_; it != end; ++it) {
    3373             :             boost::unordered::detail::func::destroy(boost::to_address(it));
    3374             :           }
    3375             : 
    3376       19917 :           bucket_allocator_traits::deallocate(
    3377             :             bucket_alloc(), buckets_, bucket_count_ + 1);
    3378       19917 :         }
    3379             : 
    3380             :         ////////////////////////////////////////////////////////////////////////
    3381             :         // Fix buckets after delete/extract
    3382             :         //
    3383             :         // (prev,next) should mark an open range of nodes in a single bucket
    3384             :         // which
    3385             :         // have either been unlinked, or are about to be.
    3386             : 
    3387       26493 :         std::size_t fix_bucket(
    3388             :           std::size_t bucket_index, link_pointer prev, node_pointer next)
    3389             :         {
    3390       26493 :           std::size_t bucket_index2 = bucket_index;
    3391             : 
    3392       26493 :           if (next) {
    3393       26356 :             bucket_index2 = node_bucket(next);
    3394             : 
    3395             :             // If next is in the same bucket, then there's nothing to do.
    3396       26356 :             if (bucket_index == bucket_index2) {
    3397             :               return bucket_index2;
    3398             :             }
    3399             : 
    3400             :             // Update the bucket containing next.
    3401       16906 :             get_bucket_pointer(bucket_index2)->next_ = prev;
    3402             :           }
    3403             : 
    3404             :           // Check if this bucket is now empty.
    3405       17043 :           bucket_pointer this_bucket = get_bucket_pointer(bucket_index);
    3406       17043 :           if (this_bucket->next_ == prev) {
    3407       10603 :             this_bucket->next_ = link_pointer();
    3408             :           }
    3409             : 
    3410             :           return bucket_index2;
    3411             :         }
    3412             : 
    3413             :         ////////////////////////////////////////////////////////////////////////
    3414             :         // Clear
    3415             : 
    3416             :         void clear_impl();
    3417             : 
    3418             :         ////////////////////////////////////////////////////////////////////////
    3419             :         // Assignment
    3420             : 
    3421             :         template <typename UniqueType>
    3422           0 :         void assign(table const& x, UniqueType is_unique)
    3423             :         {
    3424           0 :           if (this != &x) {
    3425           0 :             assign(x, is_unique,
    3426             :               boost::unordered::detail::integral_constant<bool,
    3427             :                 allocator_traits<node_allocator>::
    3428             :                   propagate_on_container_copy_assignment::value>());
    3429             :           }
    3430             :         }
    3431             : 
    3432             :         template <typename UniqueType>
    3433           0 :         void assign(table const& x, UniqueType is_unique, false_type)
    3434             :         {
    3435             :           // Strong exception safety.
    3436           0 :           this->construct_spare_functions(x.current_functions());
    3437             :           BOOST_TRY
    3438             :           {
    3439           0 :             mlf_ = x.mlf_;
    3440           0 :             recalculate_max_load();
    3441             : 
    3442           0 :             if (x.size_ > max_load_) {
    3443           0 :               create_buckets(min_buckets_for_size(x.size_));
    3444           0 :             } else if (size_) {
    3445           0 :               clear_buckets();
    3446             :             }
    3447             :           }
    3448           0 :           BOOST_CATCH(...)
    3449             :           {
    3450           0 :             this->cleanup_spare_functions();
    3451           0 :             BOOST_RETHROW
    3452             :           }
    3453             :           BOOST_CATCH_END
    3454           0 :           this->switch_functions();
    3455           0 :           assign_buckets(x, is_unique);
    3456           0 :         }
    3457             : 
    3458             :         template <typename UniqueType>
    3459             :         void assign(table const& x, UniqueType is_unique, true_type)
    3460             :         {
    3461             :           if (node_alloc() == x.node_alloc()) {
    3462             :             allocators_.assign(x.allocators_);
    3463             :             assign(x, is_unique, false_type());
    3464             :           } else {
    3465             :             this->construct_spare_functions(x.current_functions());
    3466             :             this->switch_functions();
    3467             : 
    3468             :             // Delete everything with current allocators before assigning
    3469             :             // the new ones.
    3470             :             delete_buckets();
    3471             :             allocators_.assign(x.allocators_);
    3472             : 
    3473             :             // Copy over other data, all no throw.
    3474             :             mlf_ = x.mlf_;
    3475             :             bucket_count_ = min_buckets_for_size(x.size_);
    3476             : 
    3477             :             // Finally copy the elements.
    3478             :             if (x.size_) {
    3479             :               copy_buckets(x, is_unique);
    3480             :             }
    3481             :           }
    3482             :         }
    3483             : 
    3484             :         template <typename UniqueType>
    3485             :         void move_assign(table& x, UniqueType is_unique)
    3486             :         {
    3487             :           if (this != &x) {
    3488             :             move_assign(x, is_unique,
    3489             :               boost::unordered::detail::integral_constant<bool,
    3490             :                 allocator_traits<node_allocator>::
    3491             :                   propagate_on_container_move_assignment::value>());
    3492             :           }
    3493             :         }
    3494             : 
    3495             :         // Propagate allocator
    3496             :         template <typename UniqueType>
    3497             :         void move_assign(table& x, UniqueType, true_type)
    3498             :         {
    3499             :           if (!functions::nothrow_move_assignable) {
    3500             :             this->construct_spare_functions(x.current_functions());
    3501             :             this->switch_functions();
    3502             :           } else {
    3503             :             this->current_functions().move_assign(x.current_functions());
    3504             :           }
    3505             :           delete_buckets();
    3506             :           allocators_.move_assign(x.allocators_);
    3507             :           mlf_ = x.mlf_;
    3508             :           move_buckets_from(x);
    3509             :         }
    3510             : 
    3511             :         // Don't propagate allocator
    3512             :         template <typename UniqueType>
    3513             :         void move_assign(table& x, UniqueType is_unique, false_type)
    3514             :         {
    3515             :           if (node_alloc() == x.node_alloc()) {
    3516             :             move_assign_equal_alloc(x);
    3517             :           } else {
    3518             :             move_assign_realloc(x, is_unique);
    3519             :           }
    3520             :         }
    3521             : 
    3522             :         void move_assign_equal_alloc(table& x)
    3523             :         {
    3524             :           if (!functions::nothrow_move_assignable) {
    3525             :             this->construct_spare_functions(x.current_functions());
    3526             :             this->switch_functions();
    3527             :           } else {
    3528             :             this->current_functions().move_assign(x.current_functions());
    3529             :           }
    3530             :           delete_buckets();
    3531             :           mlf_ = x.mlf_;
    3532             :           move_buckets_from(x);
    3533             :         }
    3534             : 
    3535             :         template <typename UniqueType>
    3536             :         void move_assign_realloc(table& x, UniqueType is_unique)
    3537             :         {
    3538             :           this->construct_spare_functions(x.current_functions());
    3539             :           BOOST_TRY
    3540             :           {
    3541             :             mlf_ = x.mlf_;
    3542             :             recalculate_max_load();
    3543             : 
    3544             :             if (x.size_ > max_load_) {
    3545             :               create_buckets(min_buckets_for_size(x.size_));
    3546             :             } else if (size_) {
    3547             :               clear_buckets();
    3548             :             }
    3549             :           }
    3550             :           BOOST_CATCH(...)
    3551             :           {
    3552             :             this->cleanup_spare_functions();
    3553             :             BOOST_RETHROW
    3554             :           }
    3555             :           BOOST_CATCH_END
    3556             :           this->switch_functions();
    3557             :           move_assign_buckets(x, is_unique);
    3558             :         }
    3559             : 
    3560             :         // Accessors
    3561             : 
    3562    45660034 :         const_key_type& get_key(node_pointer n) const
    3563             :         {
    3564    45660034 :           return extractor::extract(n->value());
    3565             :         }
    3566             : 
    3567    40859693 :         std::size_t hash(const_key_type& k) const
    3568             :         {
    3569    35263901 :           return policy::apply_hash(this->hash_function(), k);
    3570             :         }
    3571             : 
    3572             :         // Find Node
    3573             : 
    3574     2449030 :         node_pointer find_node(std::size_t key_hash, const_key_type& k) const
    3575             :         {
    3576     2449030 :           return this->find_node_impl(key_hash, k, this->key_eq());
    3577             :         }
    3578             : 
    3579    35263901 :         node_pointer find_node(const_key_type& k) const
    3580             :         {
    3581    35263901 :           return this->find_node_impl(hash(k), k, this->key_eq());
    3582             :         }
    3583             : 
    3584             :         template <class Key, class Pred>
    3585    37712322 :         node_pointer find_node_impl(
    3586             :           std::size_t key_hash, Key const& k, Pred const& eq) const
    3587             :         {
    3588    37712322 :           std::size_t bucket_index = this->hash_to_bucket(key_hash);
    3589    37712322 :           node_pointer n = this->begin(bucket_index);
    3590             : 
    3591             :           for (;;) {
    3592    48850722 :             if (!n)
    3593             :               return n;
    3594             : 
    3595    40064422 :             if (eq(k, this->get_key(n))) {
    3596    22870522 :               return n;
    3597    17193840 :             } else if (this->node_bucket(n) != bucket_index) {
    3598             :               return node_pointer();
    3599             :             }
    3600             : 
    3601    48850722 :             n = next_for_find(n);
    3602             :           }
    3603             :         }
    3604             : 
    3605             :         // Find the node before the key, so that it can be erased.
    3606           0 :         link_pointer find_previous_node(
    3607             :           const_key_type& k, std::size_t bucket_index)
    3608             :         {
    3609           0 :           link_pointer prev = this->get_previous_start(bucket_index);
    3610           0 :           if (!prev) {
    3611             :             return prev;
    3612             :           }
    3613             : 
    3614             :           for (;;) {
    3615           0 :             node_pointer n = next_node(prev);
    3616           0 :             if (!n) {
    3617             :               return link_pointer();
    3618           0 :             } else if (n->is_first_in_group()) {
    3619           0 :               if (node_bucket(n) != bucket_index) {
    3620             :                 return link_pointer();
    3621           0 :               } else if (this->key_eq()(k, this->get_key(n))) {
    3622           0 :                 return prev;
    3623             :               }
    3624             :             }
    3625             :             prev = n;
    3626             :           }
    3627             :         }
    3628             : 
    3629             :         // Extract and erase
    3630             : 
    3631             :         inline node_pointer extract_by_key(const_key_type& k)
    3632             :         {
    3633             :           if (!this->size_) {
    3634             :             return node_pointer();
    3635             :           }
    3636             :           std::size_t key_hash = this->hash(k);
    3637             :           std::size_t bucket_index = this->hash_to_bucket(key_hash);
    3638             :           link_pointer prev = this->find_previous_node(k, bucket_index);
    3639             :           if (!prev) {
    3640             :             return node_pointer();
    3641             :           }
    3642             :           node_pointer n = next_node(prev);
    3643             :           node_pointer n2 = next_node(n);
    3644             :           if (n2) {
    3645             :             n2->set_first_in_group();
    3646             :           }
    3647             :           prev->next_ = n2;
    3648             :           --this->size_;
    3649             :           this->fix_bucket(bucket_index, prev, n2);
    3650             :           n->next_ = link_pointer();
    3651             : 
    3652             :           return n;
    3653             :         }
    3654             : 
    3655             :         // Reserve and rehash
    3656             : 
    3657             :         void reserve_for_insert(std::size_t);
    3658             :         void rehash(std::size_t);
    3659             :         void reserve(std::size_t);
    3660             :         void rehash_impl(std::size_t);
    3661             : 
    3662             :         ////////////////////////////////////////////////////////////////////////
    3663             :         // Unique keys
    3664             : 
    3665             :         // equals
    3666             : 
    3667             :         bool equals_unique(table const& other) const
    3668             :         {
    3669             :           if (this->size_ != other.size_)
    3670             :             return false;
    3671             : 
    3672             :           for (node_pointer n1 = this->begin(); n1; n1 = next_node(n1)) {
    3673             :             node_pointer n2 = other.find_node(other.get_key(n1));
    3674             : 
    3675             :             if (!n2 || n1->value() != n2->value())
    3676             :               return false;
    3677             :           }
    3678             : 
    3679             :           return true;
    3680             :         }
    3681             : 
    3682             :         // Emplace/Insert
    3683             : 
    3684          80 :         inline node_pointer add_node_unique(
    3685             :           node_pointer n, std::size_t key_hash)
    3686             :         {
    3687          80 :           std::size_t bucket_index = this->hash_to_bucket(key_hash);
    3688          80 :           bucket_pointer b = this->get_bucket_pointer(bucket_index);
    3689             : 
    3690             :           n->bucket_info_ = bucket_index;
    3691          80 :           n->set_first_in_group();
    3692             : 
    3693          80 :           if (!b->next_) {
    3694          42 :             link_pointer start_node = this->get_previous_start();
    3695             : 
    3696          42 :             if (start_node->next_) {
    3697          41 :               this->get_bucket_pointer(node_bucket(next_node(start_node)))
    3698             :                 ->next_ = n;
    3699             :             }
    3700             : 
    3701          42 :             b->next_ = start_node;
    3702          42 :             n->next_ = start_node->next_;
    3703          42 :             start_node->next_ = n;
    3704             :           } else {
    3705          38 :             n->next_ = b->next_->next_;
    3706          38 :             b->next_->next_ = n;
    3707             :           }
    3708             : 
    3709          80 :           ++this->size_;
    3710          80 :           return n;
    3711             :         }
    3712             : 
    3713          80 :         inline node_pointer resize_and_add_node_unique(
    3714             :           node_pointer n, std::size_t key_hash)
    3715             :         {
    3716         160 :           node_tmp b(n, this->node_alloc());
    3717          80 :           this->reserve_for_insert(this->size_ + 1);
    3718          80 :           return this->add_node_unique(b.release(), key_hash);
    3719             :         }
    3720             : 
    3721             :         template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
    3722             :         iterator emplace_hint_unique(
    3723             :           c_iterator hint, const_key_type& k, BOOST_UNORDERED_EMPLACE_ARGS)
    3724             :         {
    3725             :           if (hint.node_ && this->key_eq()(k, this->get_key(hint.node_))) {
    3726             :             return iterator(hint.node_);
    3727             :           } else {
    3728             :             return emplace_unique(k, BOOST_UNORDERED_EMPLACE_FORWARD).first;
    3729             :           }
    3730             :         }
    3731             : 
    3732             :         template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
    3733           0 :         emplace_return emplace_unique(
    3734             :           const_key_type& k, BOOST_UNORDERED_EMPLACE_ARGS)
    3735             :         {
    3736           0 :           std::size_t key_hash = this->hash(k);
    3737           0 :           node_pointer pos = this->find_node(key_hash, k);
    3738           0 :           if (pos) {
    3739           0 :             return emplace_return(iterator(pos), false);
    3740             :           } else {
    3741             :             return emplace_return(
    3742           0 :               iterator(this->resize_and_add_node_unique(
    3743           0 :                 boost::unordered::detail::func::construct_node_from_args(
    3744             :                   this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD),
    3745             :                 key_hash)),
    3746           0 :               true);
    3747             :           }
    3748             :         }
    3749             : 
    3750             :         template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
    3751             :         iterator emplace_hint_unique(
    3752             :           c_iterator hint, no_key, BOOST_UNORDERED_EMPLACE_ARGS)
    3753             :         {
    3754             :           node_tmp b(boost::unordered::detail::func::construct_node_from_args(
    3755             :                        this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD),
    3756             :             this->node_alloc());
    3757             :           const_key_type& k = this->get_key(b.node_);
    3758             :           if (hint.node_ && this->key_eq()(k, this->get_key(hint.node_))) {
    3759             :             return iterator(hint.node_);
    3760             :           }
    3761             :           std::size_t key_hash = this->hash(k);
    3762             :           node_pointer pos = this->find_node(key_hash, k);
    3763             :           if (pos) {
    3764             :             return iterator(pos);
    3765             :           } else {
    3766             :             return iterator(
    3767             :               this->resize_and_add_node_unique(b.release(), key_hash));
    3768             :           }
    3769             :         }
    3770             : 
    3771             :         template <BOOST_UNORDERED_EMPLACE_TEMPLATE>
    3772             :         emplace_return emplace_unique(no_key, BOOST_UNORDERED_EMPLACE_ARGS)
    3773             :         {
    3774             :           node_tmp b(boost::unordered::detail::func::construct_node_from_args(
    3775             :                        this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD),
    3776             :             this->node_alloc());
    3777             :           const_key_type& k = this->get_key(b.node_);
    3778             :           std::size_t key_hash = this->hash(k);
    3779             :           node_pointer pos = this->find_node(key_hash, k);
    3780             :           if (pos) {
    3781             :             return emplace_return(iterator(pos), false);
    3782             :           } else {
    3783             :             return emplace_return(
    3784             :               iterator(this->resize_and_add_node_unique(b.release(), key_hash)),
    3785             :               true);
    3786             :           }
    3787             :         }
    3788             : 
    3789             :         template <typename Key>
    3790          80 :         emplace_return try_emplace_unique(BOOST_FWD_REF(Key) k)
    3791             :         {
    3792          80 :           std::size_t key_hash = this->hash(k);
    3793          80 :           node_pointer pos = this->find_node(key_hash, k);
    3794          80 :           if (pos) {
    3795           0 :             return emplace_return(iterator(pos), false);
    3796             :           } else {
    3797             :             return emplace_return(
    3798          80 :               iterator(this->resize_and_add_node_unique(
    3799          80 :                 boost::unordered::detail::func::construct_node_pair(
    3800             :                   this->node_alloc(), boost::forward<Key>(k)),
    3801             :                 key_hash)),
    3802         160 :               true);
    3803             :           }
    3804             :         }
    3805             : 
    3806             :         template <typename Key>
    3807             :         iterator try_emplace_hint_unique(c_iterator hint, BOOST_FWD_REF(Key) k)
    3808             :         {
    3809             :           if (hint.node_ && this->key_eq()(hint->first, k)) {
    3810             :             return iterator(hint.node_);
    3811             :           } else {
    3812             :             return try_emplace_unique(k).first;
    3813             :           }
    3814             :         }
    3815             : 
    3816             :         template <typename Key, BOOST_UNORDERED_EMPLACE_TEMPLATE>
    3817             :         emplace_return try_emplace_unique(
    3818             :           BOOST_FWD_REF(Key) k, BOOST_UNORDERED_EMPLACE_ARGS)
    3819             :         {
    3820             :           std::size_t key_hash = this->hash(k);
    3821             :           node_pointer pos = this->find_node(key_hash, k);
    3822             :           if (pos) {
    3823             :             return emplace_return(iterator(pos), false);
    3824             :           } else {
    3825             :             return emplace_return(
    3826             :               iterator(this->resize_and_add_node_unique(
    3827             :                 boost::unordered::detail::func::construct_node_pair_from_args(
    3828             :                   this->node_alloc(), boost::forward<Key>(k),
    3829             :                   BOOST_UNORDERED_EMPLACE_FORWARD),
    3830             :                 key_hash)),
    3831             :               true);
    3832             :           }
    3833             :         }
    3834             : 
    3835             :         template <typename Key, BOOST_UNORDERED_EMPLACE_TEMPLATE>
    3836             :         iterator try_emplace_hint_unique(
    3837             :           c_iterator hint, BOOST_FWD_REF(Key) k, BOOST_UNORDERED_EMPLACE_ARGS)
    3838             :         {
    3839             :           if (hint.node_ && this->key_eq()(hint->first, k)) {
    3840             :             return iterator(hint.node_);
    3841             :           } else {
    3842             :             return try_emplace_unique(k, BOOST_UNORDERED_EMPLACE_FORWARD).first;
    3843             :           }
    3844             :         }
    3845             : 
    3846             :         template <typename Key, typename M>
    3847             :         emplace_return insert_or_assign_unique(
    3848             :           BOOST_FWD_REF(Key) k, BOOST_FWD_REF(M) obj)
    3849             :         {
    3850             :           std::size_t key_hash = this->hash(k);
    3851             :           node_pointer pos = this->find_node(key_hash, k);
    3852             : 
    3853             :           if (pos) {
    3854             :             pos->value().second = boost::forward<M>(obj);
    3855             :             return emplace_return(iterator(pos), false);
    3856             :           } else {
    3857             :             return emplace_return(
    3858             :               iterator(this->resize_and_add_node_unique(
    3859             :                 boost::unordered::detail::func::construct_node_pair(
    3860             :                   this->node_alloc(), boost::forward<Key>(k),
    3861             :                   boost::forward<M>(obj)),
    3862             :                 key_hash)),
    3863             :               true);
    3864             :           }
    3865             :         }
    3866             : 
    3867             :         template <typename NodeType, typename InsertReturnType>
    3868             :         void move_insert_node_type_unique(
    3869             :           NodeType& np, InsertReturnType& result)
    3870             :         {
    3871             :           if (np) {
    3872             :             const_key_type& k = this->get_key(np.ptr_);
    3873             :             std::size_t key_hash = this->hash(k);
    3874             :             node_pointer pos = this->find_node(key_hash, k);
    3875             : 
    3876             :             if (pos) {
    3877             :               result.node = boost::move(np);
    3878             :               result.position = iterator(pos);
    3879             :             } else {
    3880             :               this->reserve_for_insert(this->size_ + 1);
    3881             :               result.position =
    3882             :                 iterator(this->add_node_unique(np.ptr_, key_hash));
    3883             :               result.inserted = true;
    3884             :               np.ptr_ = node_pointer();
    3885             :             }
    3886             :           }
    3887             :         }
    3888             : 
    3889             :         template <typename NodeType>
    3890             :         iterator move_insert_node_type_with_hint_unique(
    3891             :           c_iterator hint, NodeType& np)
    3892             :         {
    3893             :           if (!np) {
    3894             :             return iterator();
    3895             :           }
    3896             :           const_key_type& k = this->get_key(np.ptr_);
    3897             :           if (hint.node_ && this->key_eq()(k, this->get_key(hint.node_))) {
    3898             :             return iterator(hint.node_);
    3899             :           }
    3900             :           std::size_t key_hash = this->hash(k);
    3901             :           node_pointer pos = this->find_node(key_hash, k);
    3902             :           if (!pos) {
    3903             :             this->reserve_for_insert(this->size_ + 1);
    3904             :             pos = this->add_node_unique(np.ptr_, key_hash);
    3905             :             np.ptr_ = node_pointer();
    3906             :           }
    3907             :           return iterator(pos);
    3908             :         }
    3909             : 
    3910             :         template <typename Types2>
    3911             :         void merge_unique(boost::unordered::detail::table<Types2>& other)
    3912             :         {
    3913             :           typedef boost::unordered::detail::table<Types2> other_table;
    3914             :           BOOST_STATIC_ASSERT(
    3915             :             (boost::is_same<node, typename other_table::node>::value));
    3916             :           BOOST_ASSERT(this->node_alloc() == other.node_alloc());
    3917             : 
    3918             :           if (other.size_) {
    3919             :             link_pointer prev = other.get_previous_start();
    3920             : 
    3921             :             while (prev->next_) {
    3922             :               node_pointer n = other_table::next_node(prev);
    3923             :               const_key_type& k = this->get_key(n);
    3924             :               std::size_t key_hash = this->hash(k);
    3925             :               node_pointer pos = this->find_node(key_hash, k);
    3926             : 
    3927             :               if (pos) {
    3928             :                 prev = n;
    3929             :               } else {
    3930             :                 this->reserve_for_insert(this->size_ + 1);
    3931             :                 node_pointer n2 = next_node(n);
    3932             :                 prev->next_ = n2;
    3933             :                 if (n2 && n->is_first_in_group()) {
    3934             :                   n2->set_first_in_group();
    3935             :                 }
    3936             :                 --other.size_;
    3937             :                 other.fix_bucket(other.node_bucket(n), prev, n2);
    3938             :                 this->add_node_unique(n, key_hash);
    3939             :               }
    3940             :             }
    3941             :           }
    3942             :         }
    3943             : 
    3944             :         ////////////////////////////////////////////////////////////////////////
    3945             :         // Insert range methods
    3946             :         //
    3947             :         // if hash function throws, or inserting > 1 element, basic exception
    3948             :         // safety strong otherwise
    3949             : 
    3950             :         template <class InputIt>
    3951           0 :         void insert_range_unique(const_key_type& k, InputIt i, InputIt j)
    3952             :         {
    3953           0 :           insert_range_unique2(k, i, j);
    3954             : 
    3955           0 :           while (++i != j) {
    3956             :             // Note: can't use get_key as '*i' might not be value_type - it
    3957             :             // could be a pair with first_types as key_type without const or
    3958             :             // a different second_type.
    3959           0 :             insert_range_unique2(extractor::extract(*i), i, j);
    3960             :           }
    3961           0 :         }
    3962             : 
    3963             :         template <class InputIt>
    3964           0 :         void insert_range_unique2(const_key_type& k, InputIt i, InputIt j)
    3965             :         {
    3966             :           // No side effects in this initial code
    3967           0 :           std::size_t key_hash = this->hash(k);
    3968           0 :           node_pointer pos = this->find_node(key_hash, k);
    3969             : 
    3970           0 :           if (!pos) {
    3971           0 :             node_tmp b(boost::unordered::detail::func::construct_node(
    3972           0 :                          this->node_alloc(), *i),
    3973             :               this->node_alloc());
    3974           0 :             if (this->size_ + 1 > this->max_load_)
    3975           0 :               this->reserve_for_insert(
    3976           0 :                 this->size_ + boost::unordered::detail::insert_size(i, j));
    3977           0 :             this->add_node_unique(b.release(), key_hash);
    3978             :           }
    3979           0 :         }
    3980             : 
    3981             :         template <class InputIt>
    3982             :         void insert_range_unique(no_key, InputIt i, InputIt j)
    3983             :         {
    3984             :           node_constructor a(this->node_alloc());
    3985             : 
    3986             :           do {
    3987             :             if (!a.node_) {
    3988             :               a.create_node();
    3989             :             }
    3990             :             BOOST_UNORDERED_CALL_CONSTRUCT1(
    3991             :               node_allocator_traits, a.alloc_, a.node_->value_ptr(), *i);
    3992             :             node_tmp b(a.release(), a.alloc_);
    3993             : 
    3994             :             const_key_type& k = this->get_key(b.node_);
    3995             :             std::size_t key_hash = this->hash(k);
    3996             :             node_pointer pos = this->find_node(key_hash, k);
    3997             : 
    3998             :             if (pos) {
    3999             :               a.reclaim(b.release());
    4000             :             } else {
    4001             :               // reserve has basic exception safety if the hash function
    4002             :               // throws, strong otherwise.
    4003             :               this->reserve_for_insert(this->size_ + 1);
    4004             :               this->add_node_unique(b.release(), key_hash);
    4005             :             }
    4006             :           } while (++i != j);
    4007             :         }
    4008             : 
    4009             :         ////////////////////////////////////////////////////////////////////////
    4010             :         // Extract
    4011             : 
    4012             :         inline node_pointer extract_by_iterator_unique(c_iterator i)
    4013             :         {
    4014             :           node_pointer n = i.node_;
    4015             :           BOOST_ASSERT(n);
    4016             :           std::size_t bucket_index = this->node_bucket(n);
    4017             :           link_pointer prev = this->get_previous_start(bucket_index);
    4018             :           while (prev->next_ != n) {
    4019             :             prev = prev->next_;
    4020             :           }
    4021             :           node_pointer n2 = next_node(n);
    4022             :           prev->next_ = n2;
    4023             :           --this->size_;
    4024             :           this->fix_bucket(bucket_index, prev, n2);
    4025             :           n->next_ = link_pointer();
    4026             :           return n;
    4027             :         }
    4028             : 
    4029             :         ////////////////////////////////////////////////////////////////////////
    4030             :         // Erase
    4031             :         //
    4032             :         // no throw
    4033             : 
    4034           0 :         std::size_t erase_key_unique(const_key_type& k)
    4035             :         {
    4036           0 :           if (!this->size_)
    4037             :             return 0;
    4038           0 :           std::size_t key_hash = this->hash(k);
    4039           0 :           std::size_t bucket_index = this->hash_to_bucket(key_hash);
    4040           0 :           link_pointer prev = this->find_previous_node(k, bucket_index);
    4041           0 :           if (!prev)
    4042             :             return 0;
    4043           0 :           node_pointer n = next_node(prev);
    4044           0 :           node_pointer n2 = next_node(n);
    4045           0 :           prev->next_ = n2;
    4046           0 :           --size_;
    4047           0 :           this->fix_bucket(bucket_index, prev, n2);
    4048           0 :           this->destroy_node(n);
    4049           0 :           return 1;
    4050             :         }
    4051             : 
    4052             :         void erase_nodes_unique(node_pointer i, node_pointer j)
    4053             :         {
    4054             :           std::size_t bucket_index = this->node_bucket(i);
    4055             : 
    4056             :           // Find the node before i.
    4057             :           link_pointer prev = this->get_previous_start(bucket_index);
    4058             :           while (prev->next_ != i)
    4059             :             prev = prev->next_;
    4060             : 
    4061             :           // Delete the nodes.
    4062             :           prev->next_ = j;
    4063             :           do {
    4064             :             node_pointer next = next_node(i);
    4065             :             destroy_node(i);
    4066             :             --size_;
    4067             :             bucket_index = this->fix_bucket(bucket_index, prev, next);
    4068             :             i = next;
    4069             :           } while (i != j);
    4070             :         }
    4071             : 
    4072             :         ////////////////////////////////////////////////////////////////////////
    4073             :         // fill_buckets_unique
    4074             : 
    4075             :         void copy_buckets(table const& src, true_type)
    4076             :         {
    4077             :           this->create_buckets(this->bucket_count_);
    4078             : 
    4079             :           for (node_pointer n = src.begin(); n; n = next_node(n)) {
    4080             :             std::size_t key_hash = this->hash(this->get_key(n));
    4081             :             this->add_node_unique(
    4082             :               boost::unordered::detail::func::construct_node(
    4083             :                 this->node_alloc(), n->value()),
    4084             :               key_hash);
    4085             :           }
    4086             :         }
    4087             : 
    4088             :         void assign_buckets(table const& src, true_type)
    4089             :         {
    4090             :           node_holder<node_allocator> holder(*this);
    4091             :           for (node_pointer n = src.begin(); n; n = next_node(n)) {
    4092             :             std::size_t key_hash = this->hash(this->get_key(n));
    4093             :             this->add_node_unique(holder.copy_of(n->value()), key_hash);
    4094             :           }
    4095             :         }
    4096             : 
    4097             :         void move_assign_buckets(table& src, true_type)
    4098             :         {
    4099             :           node_holder<node_allocator> holder(*this);
    4100             :           for (node_pointer n = src.begin(); n; n = next_node(n)) {
    4101             :             std::size_t key_hash = this->hash(this->get_key(n));
    4102             :             this->add_node_unique(holder.move_copy_of(n->value()), key_hash);
    4103             :           }
    4104             :         }
    4105             : 
    4106             :         ////////////////////////////////////////////////////////////////////////
    4107             :         // Equivalent keys
    4108             : 
    4109             :         // Equality
    4110             : 
    4111             :         bool equals_equiv(table const& other) const
    4112             :         {
    4113             :           if (this->size_ != other.size_)
    4114             :             return false;
    4115             : 
    4116             :           for (node_pointer n1 = this->begin(); n1;) {
    4117             :             node_pointer n2 = other.find_node(other.get_key(n1));
    4118             :             if (!n2)
    4119             :               return false;
    4120             :             node_pointer end1 = next_group(n1);
    4121             :             node_pointer end2 = next_group(n2);
    4122             :             if (!group_equals_equiv(n1, end1, n2, end2))
    4123             :               return false;
    4124             :             n1 = end1;
    4125             :           }
    4126             : 
    4127             :           return true;
    4128             :         }
    4129             : 
    4130             :         static bool group_equals_equiv(node_pointer n1, node_pointer end1,
    4131             :           node_pointer n2, node_pointer end2)
    4132             :         {
    4133             :           for (;;) {
    4134             :             if (n1->value() != n2->value())
    4135             :               break;
    4136             : 
    4137             :             n1 = next_node(n1);
    4138             :             n2 = next_node(n2);
    4139             : 
    4140             :             if (n1 == end1)
    4141             :               return n2 == end2;
    4142             :             if (n2 == end2)
    4143             :               return false;
    4144             :           }
    4145             : 
    4146             :           for (node_pointer n1a = n1, n2a = n2;;) {
    4147             :             n1a = next_node(n1a);
    4148             :             n2a = next_node(n2a);
    4149             : 
    4150             :             if (n1a == end1) {
    4151             :               if (n2a == end2)
    4152             :                 break;
    4153             :               else
    4154             :                 return false;
    4155             :             }
    4156             : 
    4157             :             if (n2a == end2)
    4158             :               return false;
    4159             :           }
    4160             : 
    4161             :           node_pointer start = n1;
    4162             :           for (; n1 != end1; n1 = next_node(n1)) {
    4163             :             value_type const& v = n1->value();
    4164             :             if (!find_equiv(start, n1, v)) {
    4165             :               std::size_t matches = count_equal_equiv(n2, end2, v);
    4166             :               if (!matches)
    4167             :                 return false;
    4168             :               if (matches != 1 + count_equal_equiv(next_node(n1), end1, v))
    4169             :                 return false;
    4170             :             }
    4171             :           }
    4172             : 
    4173             :           return true;
    4174             :         }
    4175             : 
    4176             :         static bool find_equiv(
    4177             :           node_pointer n, node_pointer end, value_type const& v)
    4178             :         {
    4179             :           for (; n != end; n = next_node(n))
    4180             :             if (n->value() == v)
    4181             :               return true;
    4182             :           return false;
    4183             :         }
    4184             : 
    4185             :         static std::size_t count_equal_equiv(
    4186             :           node_pointer n, node_pointer end, value_type const& v)
    4187             :         {
    4188             :           std::size_t count = 0;
    4189             :           for (; n != end; n = next_node(n))
    4190             :             if (n->value() == v)
    4191             :               ++count;
    4192             :           return count;
    4193             :         }
    4194             : 
    4195             :         // Emplace/Insert
    4196             : 
    4197     2448950 :         inline node_pointer add_node_equiv(
    4198             :           node_pointer n, std::size_t key_hash, node_pointer pos)
    4199             :         {
    4200     2448950 :           std::size_t bucket_index = this->hash_to_bucket(key_hash);
    4201             :           n->bucket_info_ = bucket_index;
    4202             : 
    4203     2448950 :           if (pos) {
    4204       63675 :             n->reset_first_in_group();
    4205       63675 :             n->next_ = pos->next_;
    4206       63675 :             pos->next_ = n;
    4207       63675 :             if (n->next_) {
    4208       61602 :               std::size_t next_bucket = this->node_bucket(next_node(n));
    4209       61602 :               if (next_bucket != bucket_index) {
    4210       24982 :                 this->get_bucket_pointer(next_bucket)->next_ = n;
    4211             :               }
    4212             :             }
    4213             :           } else {
    4214     2385280 :             n->set_first_in_group();
    4215     4770550 :             bucket_pointer b = this->get_bucket_pointer(bucket_index);
    4216             : 
    4217     2385280 :             if (!b->next_) {
    4218     1311660 :               link_pointer start_node = this->get_previous_start();
    4219             : 
    4220     1311660 :               if (start_node->next_) {
    4221     1236500 :                 this
    4222             :                   ->get_bucket_pointer(this->node_bucket(next_node(start_node)))
    4223             :                   ->next_ = n;
    4224             :               }
    4225             : 
    4226     1311660 :               b->next_ = start_node;
    4227     1311660 :               n->next_ = start_node->next_;
    4228     1311660 :               start_node->next_ = n;
    4229             :             } else {
    4230     1073620 :               n->next_ = b->next_->next_;
    4231     1073620 :               b->next_->next_ = n;
    4232             :             }
    4233             :           }
    4234     2448950 :           ++this->size_;
    4235     2448950 :           return n;
    4236             :         }
    4237             : 
    4238             :         inline node_pointer add_using_hint_equiv(
    4239             :           node_pointer n, node_pointer hint)
    4240             :         {
    4241             :           n->bucket_info_ = hint->bucket_info_;
    4242             :           n->reset_first_in_group();
    4243             :           n->next_ = hint->next_;
    4244             :           hint->next_ = n;
    4245             :           if (n->next_) {
    4246             :             std::size_t next_bucket = this->node_bucket(next_node(n));
    4247             :             if (next_bucket != this->node_bucket(n)) {
    4248             :               this->get_bucket_pointer(next_bucket)->next_ = n;
    4249             :             }
    4250             :           }
    4251             :           ++this->size_;
    4252             :           return n;
    4253             :         }
    4254             : 
    4255     2448950 :         iterator emplace_equiv(node_pointer n)
    4256             :         {
    4257           0 :           node_tmp a(n, this->node_alloc());
    4258     2448950 :           const_key_type& k = this->get_key(a.node_);
    4259     2448950 :           std::size_t key_hash = this->hash(k);
    4260     2448950 :           node_pointer position = this->find_node(key_hash, k);
    4261     2448950 :           this->reserve_for_insert(this->size_ + 1);
    4262     2448950 :           return iterator(
    4263     2448950 :             this->add_node_equiv(a.release(), key_hash, position));
    4264             :         }
    4265             : 
    4266             :         iterator emplace_hint_equiv(c_iterator hint, node_pointer n)
    4267             :         {
    4268             :           node_tmp a(n, this->node_alloc());
    4269             :           const_key_type& k = this->get_key(a.node_);
    4270             :           if (hint.node_ && this->key_eq()(k, this->get_key(hint.node_))) {
    4271             :             this->reserve_for_insert(this->size_ + 1);
    4272             :             return iterator(
    4273             :               this->add_using_hint_equiv(a.release(), hint.node_));
    4274             :           } else {
    4275             :             std::size_t key_hash = this->hash(k);
    4276             :             node_pointer position = this->find_node(key_hash, k);
    4277             :             this->reserve_for_insert(this->size_ + 1);
    4278             :             return iterator(
    4279             :               this->add_node_equiv(a.release(), key_hash, position));
    4280             :           }
    4281             :         }
    4282             : 
    4283             :         void emplace_no_rehash_equiv(node_pointer n)
    4284             :         {
    4285             :           node_tmp a(n, this->node_alloc());
    4286             :           const_key_type& k = this->get_key(a.node_);
    4287             :           std::size_t key_hash = this->hash(k);
    4288             :           node_pointer position = this->find_node(key_hash, k);
    4289             :           this->add_node_equiv(a.release(), key_hash, position);
    4290             :         }
    4291             : 
    4292             :         template <typename NodeType>
    4293             :         iterator move_insert_node_type_equiv(NodeType& np)
    4294             :         {
    4295             :           iterator result;
    4296             : 
    4297             :           if (np) {
    4298             :             const_key_type& k = this->get_key(np.ptr_);
    4299             :             std::size_t key_hash = this->hash(k);
    4300             :             node_pointer pos = this->find_node(key_hash, k);
    4301             :             this->reserve_for_insert(this->size_ + 1);
    4302             :             result = iterator(this->add_node_equiv(np.ptr_, key_hash, pos));
    4303             :             np.ptr_ = node_pointer();
    4304             :           }
    4305             : 
    4306             :           return result;
    4307             :         }
    4308             : 
    4309             :         template <typename NodeType>
    4310             :         iterator move_insert_node_type_with_hint_equiv(
    4311             :           c_iterator hint, NodeType& np)
    4312             :         {
    4313             :           iterator result;
    4314             : 
    4315             :           if (np) {
    4316             :             const_key_type& k = this->get_key(np.ptr_);
    4317             : 
    4318             :             if (hint.node_ && this->key_eq()(k, this->get_key(hint.node_))) {
    4319             :               this->reserve_for_insert(this->size_ + 1);
    4320             :               result =
    4321             :                 iterator(this->add_using_hint_equiv(np.ptr_, hint.node_));
    4322             :             } else {
    4323             :               std::size_t key_hash = this->hash(k);
    4324             :               node_pointer pos = this->find_node(key_hash, k);
    4325             :               this->reserve_for_insert(this->size_ + 1);
    4326             :               result = iterator(this->add_node_equiv(np.ptr_, key_hash, pos));
    4327             :             }
    4328             :             np.ptr_ = node_pointer();
    4329             :           }
    4330             : 
    4331             :           return result;
    4332             :         }
    4333             : 
    4334             :         ////////////////////////////////////////////////////////////////////////
    4335             :         // Insert range methods
    4336             : 
    4337             :         // if hash function throws, or inserting > 1 element, basic exception
    4338             :         // safety. Strong otherwise
    4339             :         template <class I>
    4340             :         void insert_range_equiv(I i, I j,
    4341             :           typename boost::unordered::detail::enable_if_forward<I, void*>::type =
    4342             :             0)
    4343             :         {
    4344             :           if (i == j)
    4345             :             return;
    4346             : 
    4347             :           std::size_t distance = static_cast<std::size_t>(std::distance(i, j));
    4348             :           if (distance == 1) {
    4349             :             emplace_equiv(boost::unordered::detail::func::construct_node(
    4350             :               this->node_alloc(), *i));
    4351             :           } else {
    4352             :             // Only require basic exception safety here
    4353             :             this->reserve_for_insert(this->size_ + distance);
    4354             : 
    4355             :             for (; i != j; ++i) {
    4356             :               emplace_no_rehash_equiv(
    4357             :                 boost::unordered::detail::func::construct_node(
    4358             :                   this->node_alloc(), *i));
    4359             :             }
    4360             :           }
    4361             :         }
    4362             : 
    4363             :         template <class I>
    4364             :         void insert_range_equiv(I i, I j,
    4365             :           typename boost::unordered::detail::disable_if_forward<I,
    4366             :             void*>::type = 0)
    4367             :         {
    4368             :           for (; i != j; ++i) {
    4369             :             emplace_equiv(boost::unordered::detail::func::construct_node(
    4370             :               this->node_alloc(), *i));
    4371             :           }
    4372             :         }
    4373             : 
    4374             :         ////////////////////////////////////////////////////////////////////////
    4375             :         // Extract
    4376             : 
    4377             :         inline node_pointer extract_by_iterator_equiv(c_iterator n)
    4378             :         {
    4379             :           node_pointer i = n.node_;
    4380             :           BOOST_ASSERT(i);
    4381             :           node_pointer j(next_node(i));
    4382             :           std::size_t bucket_index = this->node_bucket(i);
    4383             : 
    4384             :           link_pointer prev = this->get_previous_start(bucket_index);
    4385             :           while (prev->next_ != i) {
    4386             :             prev = next_node(prev);
    4387             :           }
    4388             : 
    4389             :           prev->next_ = j;
    4390             :           if (j && i->is_first_in_group()) {
    4391             :             j->set_first_in_group();
    4392             :           }
    4393             :           --this->size_;
    4394             :           this->fix_bucket(bucket_index, prev, j);
    4395             :           i->next_ = link_pointer();
    4396             : 
    4397             :           return i;
    4398             :         }
    4399             : 
    4400             :         ////////////////////////////////////////////////////////////////////////
    4401             :         // Erase
    4402             :         //
    4403             :         // no throw
    4404             : 
    4405           0 :         std::size_t erase_key_equiv(const_key_type& k)
    4406             :         {
    4407           0 :           if (!this->size_)
    4408             :             return 0;
    4409             : 
    4410           0 :           std::size_t key_hash = this->hash(k);
    4411           0 :           std::size_t bucket_index = this->hash_to_bucket(key_hash);
    4412           0 :           link_pointer prev = this->find_previous_node(k, bucket_index);
    4413           0 :           if (!prev)
    4414             :             return 0;
    4415             : 
    4416           0 :           std::size_t deleted_count = 0;
    4417           0 :           node_pointer n = next_node(prev);
    4418             :           do {
    4419           0 :             node_pointer n2 = next_node(n);
    4420           0 :             destroy_node(n);
    4421           0 :             ++deleted_count;
    4422           0 :             n = n2;
    4423           0 :           } while (n && !n->is_first_in_group());
    4424           0 :           size_ -= deleted_count;
    4425           0 :           prev->next_ = n;
    4426           0 :           this->fix_bucket(bucket_index, prev, n);
    4427           0 :           return deleted_count;
    4428             :         }
    4429             : 
    4430       26493 :         link_pointer erase_nodes_equiv(node_pointer i, node_pointer j)
    4431             :         {
    4432       26493 :           std::size_t bucket_index = this->node_bucket(i);
    4433             : 
    4434       26493 :           link_pointer prev = this->get_previous_start(bucket_index);
    4435       67625 :           while (prev->next_ != i) {
    4436             :             prev = next_node(prev);
    4437             :           }
    4438             : 
    4439             :           // Delete the nodes.
    4440             :           // Is it inefficient to call fix_bucket for every node?
    4441       26493 :           bool includes_first = false;
    4442       26493 :           prev->next_ = j;
    4443             :           do {
    4444       26493 :             includes_first = includes_first || i->is_first_in_group();
    4445       26493 :             node_pointer next = next_node(i);
    4446       52986 :             destroy_node(i);
    4447       26493 :             --size_;
    4448       26493 :             bucket_index = this->fix_bucket(bucket_index, prev, next);
    4449       26493 :             i = next;
    4450       26493 :           } while (i != j);
    4451       26493 :           if (j && includes_first) {
    4452       22641 :             j->set_first_in_group();
    4453             :           }
    4454             : 
    4455       26493 :           return prev;
    4456             :         }
    4457             : 
    4458             :         ////////////////////////////////////////////////////////////////////////
    4459             :         // fill_buckets
    4460             : 
    4461           0 :         void copy_buckets(table const& src, false_type)
    4462             :         {
    4463           0 :           this->create_buckets(this->bucket_count_);
    4464             : 
    4465           0 :           for (node_pointer n = src.begin(); n;) {
    4466           0 :             std::size_t key_hash = this->hash(this->get_key(n));
    4467           0 :             node_pointer group_end(next_group(n));
    4468           0 :             node_pointer pos = this->add_node_equiv(
    4469           0 :               boost::unordered::detail::func::construct_node(
    4470             :                 this->node_alloc(), n->value()),
    4471             :               key_hash, node_pointer());
    4472           0 :             for (n = next_node(n); n != group_end; n = next_node(n)) {
    4473           0 :               this->add_node_equiv(
    4474           0 :                 boost::unordered::detail::func::construct_node(
    4475             :                   this->node_alloc(), n->value()),
    4476             :                 key_hash, pos);
    4477             :             }
    4478             :           }
    4479           0 :         }
    4480             : 
    4481           0 :         void assign_buckets(table const& src, false_type)
    4482             :         {
    4483           0 :           node_holder<node_allocator> holder(*this);
    4484           0 :           for (node_pointer n = src.begin(); n;) {
    4485           0 :             std::size_t key_hash = this->hash(this->get_key(n));
    4486           0 :             node_pointer group_end(next_group(n));
    4487           0 :             node_pointer pos = this->add_node_equiv(
    4488             :               holder.copy_of(n->value()), key_hash, node_pointer());
    4489           0 :             for (n = next_node(n); n != group_end; n = next_node(n)) {
    4490           0 :               this->add_node_equiv(holder.copy_of(n->value()), key_hash, pos);
    4491             :             }
    4492             :           }
    4493           0 :         }
    4494             : 
    4495             :         void move_assign_buckets(table& src, false_type)
    4496             :         {
    4497             :           node_holder<node_allocator> holder(*this);
    4498             :           for (node_pointer n = src.begin(); n;) {
    4499             :             std::size_t key_hash = this->hash(this->get_key(n));
    4500             :             node_pointer group_end(next_group(n));
    4501             :             node_pointer pos = this->add_node_equiv(
    4502             :               holder.move_copy_of(n->value()), key_hash, node_pointer());
    4503             :             for (n = next_node(n); n != group_end; n = next_node(n)) {
    4504             :               this->add_node_equiv(
    4505             :                 holder.move_copy_of(n->value()), key_hash, pos);
    4506             :             }
    4507             :           }
    4508             :         }
    4509             :       };
    4510             : 
    4511             :       //////////////////////////////////////////////////////////////////////////
    4512             :       // Clear
    4513             : 
    4514       54459 :       template <typename Types> inline void table<Types>::clear_impl()
    4515             :       {
    4516       54459 :         if (size_) {
    4517       12373 :           bucket_pointer end = get_bucket_pointer(bucket_count_);
    4518     1201360 :           for (bucket_pointer it = buckets_; it != end; ++it) {
    4519     1188990 :             it->next_ = node_pointer();
    4520             :           }
    4521             : 
    4522       12373 :           link_pointer prev = end->first_from_start();
    4523       12373 :           node_pointer n = next_node(prev);
    4524       12373 :           prev->next_ = node_pointer();
    4525       12373 :           size_ = 0;
    4526             : 
    4527      114256 :           while (n) {
    4528      101883 :             node_pointer next = next_node(n);
    4529      203766 :             destroy_node(n);
    4530      101883 :             n = next;
    4531             :           }
    4532             :         }
    4533       54459 :       }
    4534             : 
    4535             :       //////////////////////////////////////////////////////////////////////////
    4536             :       // Reserve & Rehash
    4537             : 
    4538             :       // basic exception safety
    4539             :       template <typename Types>
    4540     2449030 :       inline void table<Types>::reserve_for_insert(std::size_t size)
    4541             :       {
    4542     2449030 :         if (!buckets_) {
    4543       75158 :           create_buckets((std::max)(bucket_count_, min_buckets_for_size(size)));
    4544     2373879 :         } else if (size > max_load_) {
    4545       15058 :           std::size_t num_buckets =
    4546       15058 :             min_buckets_for_size((std::max)(size, size_ + (size_ >> 1)));
    4547             : 
    4548        7529 :           if (num_buckets != bucket_count_)
    4549        7529 :             this->rehash_impl(num_buckets);
    4550             :         }
    4551     2449030 :       }
    4552             : 
    4553             :       // if hash function throws, basic exception safety
    4554             :       // strong otherwise.
    4555             : 
    4556             :       template <typename Types>
    4557           0 :       inline void table<Types>::rehash(std::size_t min_buckets)
    4558             :       {
    4559             :         using namespace std;
    4560             : 
    4561           0 :         if (!size_) {
    4562           0 :           delete_buckets();
    4563           0 :           bucket_count_ = policy::new_bucket_count(min_buckets);
    4564             :         } else {
    4565           0 :           min_buckets = policy::new_bucket_count((std::max)(min_buckets,
    4566           0 :             boost::unordered::detail::double_to_size(
    4567           0 :               floor(static_cast<double>(size_) / static_cast<double>(mlf_))) +
    4568           0 :               1));
    4569             : 
    4570           0 :           if (min_buckets != bucket_count_)
    4571           0 :             this->rehash_impl(min_buckets);
    4572             :         }
    4573           0 :       }
    4574             : 
    4575             :       template <typename Types>
    4576        7529 :       inline void table<Types>::rehash_impl(std::size_t num_buckets)
    4577             :       {
    4578        7529 :         BOOST_ASSERT(this->buckets_);
    4579             : 
    4580        7529 :         this->create_buckets(num_buckets);
    4581        7529 :         link_pointer prev = this->get_previous_start();
    4582             :         BOOST_TRY
    4583             :         {
    4584     3154265 :           while (prev->next_) {
    4585     3146732 :             node_pointer n = next_node(prev);
    4586     6293362 :             std::size_t key_hash = this->hash(this->get_key(n));
    4587     3146732 :             std::size_t bucket_index = this->hash_to_bucket(key_hash);
    4588             : 
    4589             :             n->bucket_info_ = bucket_index;
    4590     3146732 :             n->set_first_in_group();
    4591             : 
    4592             :             // Iterator through the rest of the group of equal nodes,
    4593             :             // setting the bucket.
    4594             :             for (;;) {
    4595     3187692 :               node_pointer next = next_node(n);
    4596     3187692 :               if (!next || next->is_first_in_group()) {
    4597             :                 break;
    4598             :               }
    4599       40961 :               n = next;
    4600             :               n->bucket_info_ = bucket_index;
    4601       40961 :               n->reset_first_in_group();
    4602             :             }
    4603             : 
    4604             :             // n is now the last node in the group
    4605     3146732 :             bucket_pointer b = this->get_bucket_pointer(bucket_index);
    4606     3146732 :             if (!b->next_) {
    4607     2472800 :               b->next_ = prev;
    4608     2472800 :               prev = n;
    4609             :             } else {
    4610      673931 :               link_pointer next = n->next_;
    4611      673931 :               n->next_ = b->next_->next_;
    4612      673931 :               b->next_->next_ = prev->next_;
    4613      673931 :               prev->next_ = next;
    4614             :             }
    4615             :           }
    4616             :         }
    4617           0 :         BOOST_CATCH(...)
    4618             :         {
    4619           0 :           node_pointer n = next_node(prev);
    4620           0 :           prev->next_ = node_pointer();
    4621           0 :           while (n) {
    4622           0 :             node_pointer next = next_node(n);
    4623           0 :             destroy_node(n);
    4624           0 :             --size_;
    4625           0 :             n = next;
    4626             :           }
    4627           0 :           BOOST_RETHROW
    4628             :         }
    4629             :         BOOST_CATCH_END
    4630        7529 :       }
    4631             : 
    4632             : #if defined(BOOST_MSVC)
    4633             : #pragma warning(pop)
    4634             : #endif
    4635             : 
    4636             :       ////////////////////////////////////////////////////////////////////////
    4637             :       // key extractors
    4638             :       //
    4639             :       // no throw
    4640             :       //
    4641             :       // 'extract_key' is called with the emplace parameters to return a
    4642             :       // key if available or 'no_key' is one isn't and will need to be
    4643             :       // constructed. This could be done by overloading the emplace
    4644             :       // implementation
    4645             :       // for the different cases, but that's a bit tricky on compilers without
    4646             :       // variadic templates.
    4647             : 
    4648             :       template <typename Key, typename T> struct is_key
    4649             :       {
    4650             :         template <typename T2> static choice1::type test(T2 const&);
    4651             :         static choice2::type test(Key const&);
    4652             : 
    4653             :         enum
    4654             :         {
    4655             :           value = sizeof(test(boost::unordered::detail::make<T>())) ==
    4656             :                   sizeof(choice2::type)
    4657             :         };
    4658             : 
    4659             :         typedef typename boost::detail::if_true<value>::BOOST_NESTED_TEMPLATE
    4660             :           then<Key const&, no_key>::type type;
    4661             :       };
    4662             : 
    4663             :       template <class ValueType> struct set_extractor
    4664             :       {
    4665             :         typedef ValueType value_type;
    4666             :         typedef ValueType key_type;
    4667             : 
    4668           0 :         static key_type const& extract(value_type const& v) { return v; }
    4669             : 
    4670           0 :         static key_type const& extract(BOOST_UNORDERED_RV_REF(value_type) v)
    4671             :         {
    4672             :           return v;
    4673             :         }
    4674             : 
    4675             :         static no_key extract() { return no_key(); }
    4676             : 
    4677             :         template <class Arg> static no_key extract(Arg const&)
    4678             :         {
    4679             :           return no_key();
    4680             :         }
    4681             : 
    4682             : #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
    4683             :         template <class Arg1, class Arg2, class... Args>
    4684             :         static no_key extract(Arg1 const&, Arg2 const&, Args const&...)
    4685             :         {
    4686             :           return no_key();
    4687             :         }
    4688             : #else
    4689             :         template <class Arg1, class Arg2>
    4690             :         static no_key extract(Arg1 const&, Arg2 const&)
    4691             :         {
    4692             :           return no_key();
    4693             :         }
    4694             : #endif
    4695             :       };
    4696             : 
    4697             :       template <class ValueType> struct map_extractor
    4698             :       {
    4699             :         typedef ValueType value_type;
    4700             :         typedef typename boost::remove_const<typename boost::unordered::detail::
    4701             :             pair_traits<ValueType>::first_type>::type key_type;
    4702             : 
    4703    45660034 :         static key_type const& extract(value_type const& v) { return v.first; }
    4704             : 
    4705             :         template <class Second>
    4706             :         static key_type const& extract(std::pair<key_type, Second> const& v)
    4707             :         {
    4708             :           return v.first;
    4709             :         }
    4710             : 
    4711             :         template <class Second>
    4712             :         static key_type const& extract(
    4713             :           std::pair<key_type const, Second> const& v)
    4714             :         {
    4715             :           return v.first;
    4716             :         }
    4717             : 
    4718             : #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
    4719             :         template <class Second>
    4720             :         static key_type const& extract(
    4721             :           boost::rv<std::pair<key_type, Second> > const& v)
    4722             :         {
    4723             :           return v.first;
    4724             :         }
    4725             : 
    4726             :         template <class Second>
    4727             :         static key_type const& extract(
    4728             :           boost::rv<std::pair<key_type const, Second> > const& v)
    4729             :         {
    4730             :           return v.first;
    4731             :         }
    4732             : #endif
    4733             : 
    4734             :         template <class Arg1>
    4735             :         static key_type const& extract(key_type const& k, Arg1 const&)
    4736             :         {
    4737             :           return k;
    4738             :         }
    4739             : 
    4740             :         static no_key extract() { return no_key(); }
    4741             : 
    4742             :         template <class Arg> static no_key extract(Arg const&)
    4743             :         {
    4744             :           return no_key();
    4745             :         }
    4746             : 
    4747             :         template <class Arg1, class Arg2>
    4748             :         static no_key extract(Arg1 const&, Arg2 const&)
    4749             :         {
    4750             :           return no_key();
    4751             :         }
    4752             : 
    4753             : #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
    4754             :         template <class Arg1, class Arg2, class Arg3, class... Args>
    4755             :         static no_key extract(
    4756             :           Arg1 const&, Arg2 const&, Arg3 const&, Args const&...)
    4757             :         {
    4758             :           return no_key();
    4759             :         }
    4760             : #endif
    4761             : 
    4762             : #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
    4763             : 
    4764             : #define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_)                             \
    4765             :   template <typename T2>                                                       \
    4766             :   static no_key extract(boost::unordered::piecewise_construct_t,               \
    4767             :     namespace_ tuple<> const&, T2 const&)                                      \
    4768             :   {                                                                            \
    4769             :     return no_key();                                                           \
    4770             :   }                                                                            \
    4771             :                                                                                \
    4772             :   template <typename T, typename T2>                                           \
    4773             :   static typename is_key<key_type, T>::type extract(                           \
    4774             :     boost::unordered::piecewise_construct_t, namespace_ tuple<T> const& k,     \
    4775             :     T2 const&)                                                                 \
    4776             :   {                                                                            \
    4777             :     return typename is_key<key_type, T>::type(namespace_ get<0>(k));           \
    4778             :   }
    4779             : 
    4780             : #else
    4781             : 
    4782             : #define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_)                             \
    4783             :   static no_key extract(                                                       \
    4784             :     boost::unordered::piecewise_construct_t, namespace_ tuple<> const&)        \
    4785             :   {                                                                            \
    4786             :     return no_key();                                                           \
    4787             :   }                                                                            \
    4788             :                                                                                \
    4789             :   template <typename T>                                                        \
    4790             :   static typename is_key<key_type, T>::type extract(                           \
    4791             :     boost::unordered::piecewise_construct_t, namespace_ tuple<T> const& k)     \
    4792             :   {                                                                            \
    4793             :     return typename is_key<key_type, T>::type(namespace_ get<0>(k));           \
    4794             :   }
    4795             : 
    4796             : #endif
    4797             : 
    4798             :         BOOST_UNORDERED_KEY_FROM_TUPLE(boost::)
    4799             : 
    4800             : #if BOOST_UNORDERED_TUPLE_ARGS
    4801             :         BOOST_UNORDERED_KEY_FROM_TUPLE(std::)
    4802             : #endif
    4803             : 
    4804             : #undef BOOST_UNORDERED_KEY_FROM_TUPLE
    4805             :       };
    4806             : 
    4807             :       ////////////////////////////////////////////////////////////////////////
    4808             :       // Unique nodes
    4809             : 
    4810             :       template <typename A, typename T>
    4811             :       struct node : boost::unordered::detail::value_base<T>
    4812             :       {
    4813             :         typedef
    4814             :           typename ::boost::unordered::detail::rebind_wrap<A, node<A, T> >::type
    4815             :             allocator;
    4816             :         typedef typename ::boost::unordered::detail::allocator_traits<
    4817             :           allocator>::pointer node_pointer;
    4818             :         typedef node_pointer link_pointer;
    4819             :         typedef typename ::boost::unordered::detail::rebind_wrap<A,
    4820             :           bucket<node_pointer> >::type bucket_allocator;
    4821             :         typedef typename ::boost::unordered::detail::allocator_traits<
    4822             :           bucket_allocator>::pointer bucket_pointer;
    4823             : 
    4824             :         link_pointer next_;
    4825             :         std::size_t bucket_info_;
    4826             : 
    4827             :         node() : next_(), bucket_info_(0) {}
    4828             : 
    4829             :         std::size_t get_bucket() const
    4830             :         {
    4831             :           return bucket_info_ & ((std::size_t)-1 >> 1);
    4832             :         }
    4833             : 
    4834             :         std::size_t is_first_in_group() const
    4835             :         {
    4836             :           return !(bucket_info_ & ~((std::size_t)-1 >> 1));
    4837             :         }
    4838             : 
    4839             :         void set_first_in_group()
    4840             :         {
    4841             :           bucket_info_ = bucket_info_ & ((std::size_t)-1 >> 1);
    4842             :         }
    4843             : 
    4844             :         void reset_first_in_group()
    4845             :         {
    4846             :           bucket_info_ = bucket_info_ | ~((std::size_t)-1 >> 1);
    4847             :         }
    4848             : 
    4849             :       private:
    4850             :         node& operator=(node const&);
    4851             :       };
    4852             : 
    4853             :       template <typename T>
    4854             :       struct ptr_node : boost::unordered::detail::ptr_bucket
    4855             :       {
    4856             :         typedef T value_type;
    4857             :         typedef boost::unordered::detail::ptr_bucket bucket_base;
    4858             :         typedef ptr_node<T>* node_pointer;
    4859             :         typedef ptr_bucket* link_pointer;
    4860             :         typedef ptr_bucket* bucket_pointer;
    4861             : 
    4862             :         std::size_t bucket_info_;
    4863             :         boost::unordered::detail::value_base<T> value_base_;
    4864             : 
    4865             :         ptr_node() : bucket_base(), bucket_info_(0) {}
    4866             : 
    4867             :         void* address() { return value_base_.address(); }
    4868    69494651 :         value_type& value() { return value_base_.value(); }
    4869    57774138 :         value_type* value_ptr() { return value_base_.value_ptr(); }
    4870             : 
    4871    18544881 :         std::size_t get_bucket() const
    4872             :         {
    4873    18544881 :           return bucket_info_ & ((std::size_t)-1 >> 1);
    4874             :         }
    4875             : 
    4876    22855309 :         std::size_t is_first_in_group() const
    4877             :         {
    4878    22855309 :           return !(bucket_info_ & ~((std::size_t)-1 >> 1));
    4879             :         }
    4880             : 
    4881     5554732 :         void set_first_in_group()
    4882             :         {
    4883     2385360 :           bucket_info_ = bucket_info_ & ((std::size_t)-1 >> 1);
    4884     3169372 :         }
    4885             : 
    4886      104636 :         void reset_first_in_group()
    4887             :         {
    4888       63675 :           bucket_info_ = bucket_info_ | ~((std::size_t)-1 >> 1);
    4889       40961 :         }
    4890             : 
    4891             :       private:
    4892             :         ptr_node& operator=(ptr_node const&);
    4893             :       };
    4894             : 
    4895             :       // If the allocator uses raw pointers use ptr_node
    4896             :       // Otherwise use node.
    4897             : 
    4898             :       template <typename A, typename T, typename NodePtr, typename BucketPtr>
    4899             :       struct pick_node2
    4900             :       {
    4901             :         typedef boost::unordered::detail::node<A, T> node;
    4902             : 
    4903             :         typedef typename boost::unordered::detail::allocator_traits<
    4904             :           typename boost::unordered::detail::rebind_wrap<A,
    4905             :             node>::type>::pointer node_pointer;
    4906             : 
    4907             :         typedef boost::unordered::detail::bucket<node_pointer> bucket;
    4908             :         typedef node_pointer link_pointer;
    4909             :       };
    4910             : 
    4911             :       template <typename A, typename T>
    4912             :       struct pick_node2<A, T, boost::unordered::detail::ptr_node<T>*,
    4913             :         boost::unordered::detail::ptr_bucket*>
    4914             :       {
    4915             :         typedef boost::unordered::detail::ptr_node<T> node;
    4916             :         typedef boost::unordered::detail::ptr_bucket bucket;
    4917             :         typedef bucket* link_pointer;
    4918             :       };
    4919             : 
    4920             :       template <typename A, typename T> struct pick_node
    4921             :       {
    4922             :         typedef typename boost::remove_const<T>::type nonconst;
    4923             : 
    4924             :         typedef boost::unordered::detail::allocator_traits<
    4925             :           typename boost::unordered::detail::rebind_wrap<A,
    4926             :             boost::unordered::detail::ptr_node<nonconst> >::type>
    4927             :           tentative_node_traits;
    4928             : 
    4929             :         typedef boost::unordered::detail::allocator_traits<
    4930             :           typename boost::unordered::detail::rebind_wrap<A,
    4931             :             boost::unordered::detail::ptr_bucket>::type>
    4932             :           tentative_bucket_traits;
    4933             : 
    4934             :         typedef pick_node2<A, nonconst, typename tentative_node_traits::pointer,
    4935             :           typename tentative_bucket_traits::pointer>
    4936             :           pick;
    4937             : 
    4938             :         typedef typename pick::node node;
    4939             :         typedef typename pick::bucket bucket;
    4940             :         typedef typename pick::link_pointer link_pointer;
    4941             :       };
    4942             :     }
    4943             :   }
    4944             : }
    4945             : 
    4946             : #undef BOOST_UNORDERED_EMPLACE_TEMPLATE
    4947             : #undef BOOST_UNORDERED_EMPLACE_ARGS
    4948             : #undef BOOST_UNORDERED_EMPLACE_FORWARD
    4949             : #undef BOOST_UNORDERED_CALL_CONSTRUCT1
    4950             : #undef BOOST_UNORDERED_CALL_DESTROY
    4951             : 
    4952             : #endif

Generated by: LCOV version 1.14