diff --git a/_clang-format b/_clang-format new file mode 100644 index 00000000..5ca4ced9 --- /dev/null +++ b/_clang-format @@ -0,0 +1,37 @@ + +# Copyright 2017 Daniel James. +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +# Using clang format 3.8 +# http://llvm.org/releases/3.8.0/tools/clang/docs/ClangFormatStyleOptions.html + +# Becuase you have to start somewhere. +BasedOnStyle: LLVM + +# Basic settings +ColumnLimit: 80 +ContinuationIndentWidth: 4 +IndentWidth: 4 +UseTab: Never +Language: Cpp +Standard: Cpp03 + +# Code layout +AlignAfterOpenBracket: DontAlign +AlignTrailingComments: true +BreakBeforeBraces: Custom +BraceWrapping: + AfterNamespace: false + AfterClass: true + AfterStruct: true + AfterUnion: true + AfterEnum: true + AfterFunction: true + AfterControlStatement: false + BeforeCatch: false + BeforeElse: false +PointerAlignment: Left + +# Boost specific stuff +ForEachMacros: [ BOOST_FOREACH ] diff --git a/include/boost/unordered/detail/allocate.hpp b/include/boost/unordered/detail/allocate.hpp deleted file mode 100644 index 2da85be8..00000000 --- a/include/boost/unordered/detail/allocate.hpp +++ /dev/null @@ -1,1429 +0,0 @@ - -// Copyright 2005-2011 Daniel James. -// Copyright 2009 Pablo Halpern. -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -// See http://www.boost.org/libs/unordered for documentation - -#ifndef BOOST_UNORDERED_ALLOCATE_HPP -#define BOOST_UNORDERED_ALLOCATE_HPP - -#include -#if defined(BOOST_HAS_PRAGMA_ONCE) -#pragma once -#endif - -// Some of these includes are required for other detail headers. -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if !defined(BOOST_NO_CXX11_HDR_TUPLE) -#include -#endif - -#if defined(BOOST_MSVC) -#pragma warning(push) -#pragma warning(disable:4512) // assignment operator could not be generated. -#pragma warning(disable:4345) // behavior change: an object of POD type - // constructed with an initializer of the form () - // will be default-initialized. -#endif - -// Maximum number of arguments supported by emplace + 1. -#define BOOST_UNORDERED_EMPLACE_LIMIT 11 - -namespace boost { namespace unordered { namespace detail { - - //////////////////////////////////////////////////////////////////////////// - // Bits and pieces for implementing traits - - template typename boost::add_lvalue_reference::type make(); - struct choice9 { typedef char (&type)[9]; }; - struct choice8 : choice9 { typedef char (&type)[8]; }; - struct choice7 : choice8 { typedef char (&type)[7]; }; - struct choice6 : choice7 { typedef char (&type)[6]; }; - struct choice5 : choice6 { typedef char (&type)[5]; }; - struct choice4 : choice5 { typedef char (&type)[4]; }; - struct choice3 : choice4 { typedef char (&type)[3]; }; - struct choice2 : choice3 { typedef char (&type)[2]; }; - struct choice1 : choice2 { typedef char (&type)[1]; }; - choice1 choose(); - - typedef choice1::type yes_type; - typedef choice2::type no_type; - - struct private_type - { - private_type const &operator,(int) const; - }; - - template - no_type is_private_type(T const&); - yes_type is_private_type(private_type const&); - - struct convert_from_anything { - template - convert_from_anything(T const&); - }; - - namespace func { - // This is a bit nasty, when constructing the individual members - // of a std::pair, need to cast away 'const'. For modern compilers, - // should be able to use std::piecewise_construct instead. - template T* const_cast_pointer(T* x) { return x; } - template T* const_cast_pointer(T const* x) { - return const_cast(x); - } - } - - //////////////////////////////////////////////////////////////////////////// - // emplace_args - // - // Either forwarding variadic arguments, or storing the arguments in - // emplace_args##n - -#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - -#define BOOST_UNORDERED_EMPLACE_ARGS1(a0) a0 -#define BOOST_UNORDERED_EMPLACE_ARGS2(a0, a1) a0, a1 -#define BOOST_UNORDERED_EMPLACE_ARGS3(a0, a1, a2) a0, a1, a2 - -#define BOOST_UNORDERED_EMPLACE_TEMPLATE typename... Args -#define BOOST_UNORDERED_EMPLACE_ARGS BOOST_FWD_REF(Args)... args -#define BOOST_UNORDERED_EMPLACE_FORWARD boost::forward(args)... - -#else - -#define BOOST_UNORDERED_EMPLACE_ARGS1 create_emplace_args -#define BOOST_UNORDERED_EMPLACE_ARGS2 create_emplace_args -#define BOOST_UNORDERED_EMPLACE_ARGS3 create_emplace_args - -#define BOOST_UNORDERED_EMPLACE_TEMPLATE typename Args -#define BOOST_UNORDERED_EMPLACE_ARGS Args const& args -#define BOOST_UNORDERED_EMPLACE_FORWARD args - -#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - -#define BOOST_UNORDERED_EARGS_MEMBER(z, n, _) \ - typedef BOOST_FWD_REF(BOOST_PP_CAT(A, n)) BOOST_PP_CAT(Arg, n); \ - BOOST_PP_CAT(Arg, n) BOOST_PP_CAT(a, n); - -#else - -#define BOOST_UNORDERED_EARGS_MEMBER(z, n, _) \ - typedef typename boost::add_lvalue_reference::type \ - BOOST_PP_CAT(Arg, n); \ - BOOST_PP_CAT(Arg, n) BOOST_PP_CAT(a, n); - -#endif - -template -struct emplace_args1 -{ - BOOST_UNORDERED_EARGS_MEMBER(1, 0, _) - - emplace_args1(Arg0 b0) : a0(b0) {} -}; - -template -inline emplace_args1 create_emplace_args( - BOOST_FWD_REF(A0) b0) -{ - emplace_args1 e(b0); - return e; -} - -template -struct emplace_args2 -{ - BOOST_UNORDERED_EARGS_MEMBER(1, 0, _) - BOOST_UNORDERED_EARGS_MEMBER(1, 1, _) - - emplace_args2(Arg0 b0, Arg1 b1) : a0(b0), a1(b1) {} -}; - -template -inline emplace_args2 create_emplace_args( - BOOST_FWD_REF(A0) b0, - BOOST_FWD_REF(A1) b1) -{ - emplace_args2 e(b0, b1); - return e; -} - -template -struct emplace_args3 -{ - BOOST_UNORDERED_EARGS_MEMBER(1, 0, _) - BOOST_UNORDERED_EARGS_MEMBER(1, 1, _) - BOOST_UNORDERED_EARGS_MEMBER(1, 2, _) - - emplace_args3(Arg0 b0, Arg1 b1, Arg2 b2) : a0(b0), a1(b1), a2(b2) {} -}; - -template -inline emplace_args3 create_emplace_args( - BOOST_FWD_REF(A0) b0, - BOOST_FWD_REF(A1) b1, - BOOST_FWD_REF(A2) b2) -{ - emplace_args3 e(b0, b1, b2); - return e; -} - -#define BOOST_UNORDERED_FWD_PARAM(z, n, a) \ - BOOST_FWD_REF(BOOST_PP_CAT(A, n)) BOOST_PP_CAT(a, n) - -#define BOOST_UNORDERED_CALL_FORWARD(z, i, a) \ - boost::forward(BOOST_PP_CAT(a,i)) - -#define BOOST_UNORDERED_EARGS_INIT(z, n, _) \ -BOOST_PP_CAT(a, n)(BOOST_PP_CAT(b, n)) - -#define BOOST_UNORDERED_EARGS(z, n, _) \ - template \ - struct BOOST_PP_CAT(emplace_args, n) \ - { \ - BOOST_PP_REPEAT_##z(n, BOOST_UNORDERED_EARGS_MEMBER, _) \ - BOOST_PP_CAT(emplace_args, n) ( \ - BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, Arg, b) \ - ) : BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_EARGS_INIT, _) \ - {} \ - \ - }; \ - \ - template \ - inline BOOST_PP_CAT(emplace_args, n) < \ - BOOST_PP_ENUM_PARAMS_Z(z, n, A) \ - > create_emplace_args( \ - BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, b) \ - ) \ - { \ - BOOST_PP_CAT(emplace_args, n) < \ - BOOST_PP_ENUM_PARAMS_Z(z, n, A) \ - > e(BOOST_PP_ENUM_PARAMS_Z(z, n, b)); \ - return e; \ - } - -BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_EARGS, - _) - -#undef BOOST_UNORDERED_DEFINE_EMPLACE_ARGS -#undef BOOST_UNORDERED_EARGS_MEMBER -#undef BOOST_UNORDERED_EARGS_INIT - -#endif - -}}} - -//////////////////////////////////////////////////////////////////////////////// -// -// Pick which version of allocator_traits to use -// -// 0 = Own partial implementation -// 1 = std::allocator_traits -// 2 = boost::container::allocator_traits - -#if !defined(BOOST_UNORDERED_USE_ALLOCATOR_TRAITS) -# if !defined(BOOST_NO_CXX11_ALLOCATOR) -# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 1 -# elif defined(BOOST_MSVC) -# if BOOST_MSVC < 1400 - // Use container's allocator_traits for older versions of Visual - // C++ as I don't test with them. -# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 2 -# endif -# endif -#endif - -#if !defined(BOOST_UNORDERED_USE_ALLOCATOR_TRAITS) -# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 0 -#endif - -//////////////////////////////////////////////////////////////////////////////// -// -// Some utilities for implementing allocator_traits, but useful elsewhere so -// they're always defined. - -#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) -# include -#endif - -namespace boost { namespace unordered { namespace detail { - - //////////////////////////////////////////////////////////////////////////// - // Integral_constrant, true_type, false_type - // - // Uses the standard versions if available. - -#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) - - using std::integral_constant; - using std::true_type; - using std::false_type; - -#else - - template - struct integral_constant { enum { value = Value }; }; - - typedef boost::unordered::detail::integral_constant true_type; - typedef boost::unordered::detail::integral_constant false_type; - -#endif - - //////////////////////////////////////////////////////////////////////////// - // Explicitly call a destructor - -#if defined(BOOST_MSVC) -#pragma warning(push) -#pragma warning(disable:4100) // unreferenced formal parameter -#endif - - namespace func { - template - inline void destroy(T* x) { - x->~T(); - } - } - -#if defined(BOOST_MSVC) -#pragma warning(pop) -#endif - - //////////////////////////////////////////////////////////////////////////// - // Expression test mechanism - // - // When SFINAE expressions are available, define - // BOOST_UNORDERED_HAS_FUNCTION which can check if a function call is - // supported by a class, otherwise define BOOST_UNORDERED_HAS_MEMBER which - // can detect if a class has the specified member, but not that it has the - // correct type, this is good enough for a passable impression of - // allocator_traits. - -#if !defined(BOOST_NO_SFINAE_EXPR) - - template struct expr_test; - template struct expr_test : T {}; - -# define BOOST_UNORDERED_CHECK_EXPRESSION(count, result, expression) \ - template \ - static typename boost::unordered::detail::expr_test< \ - BOOST_PP_CAT(choice, result), \ - sizeof(for_expr_test(( \ - (expression), \ - 0)))>::type test( \ - BOOST_PP_CAT(choice, count)) - -# define BOOST_UNORDERED_DEFAULT_EXPRESSION(count, result) \ - template \ - static BOOST_PP_CAT(choice, result)::type test( \ - BOOST_PP_CAT(choice, count)) - -# define BOOST_UNORDERED_HAS_FUNCTION(name, thing, args, _) \ - struct BOOST_PP_CAT(has_, name) \ - { \ - template static char for_expr_test(U const&); \ - BOOST_UNORDERED_CHECK_EXPRESSION(1, 1, \ - boost::unordered::detail::make< thing >().name args); \ - BOOST_UNORDERED_DEFAULT_EXPRESSION(2, 2); \ - \ - enum { value = sizeof(test(choose())) == sizeof(choice1::type) };\ - } - -#else - - template struct identity { typedef T type; }; - -# define BOOST_UNORDERED_CHECK_MEMBER(count, result, name, member) \ - \ - typedef typename boost::unordered::detail::identity::type \ - BOOST_PP_CAT(check, count); \ - \ - template \ - struct BOOST_PP_CAT(test, count) { \ - typedef BOOST_PP_CAT(choice, result) type; \ - }; \ - \ - template static typename \ - BOOST_PP_CAT(test, count)<&U::name>::type \ - test(BOOST_PP_CAT(choice, count)) - -# define BOOST_UNORDERED_DEFAULT_MEMBER(count, result) \ - template static BOOST_PP_CAT(choice, result)::type \ - test(BOOST_PP_CAT(choice, count)) - -# define BOOST_UNORDERED_HAS_MEMBER(name) \ - struct BOOST_PP_CAT(has_, name) \ - { \ - struct impl { \ - struct base_mixin { int name; }; \ - struct base : public T, public base_mixin {}; \ - \ - BOOST_UNORDERED_CHECK_MEMBER(1, 1, name, int base_mixin::*); \ - BOOST_UNORDERED_DEFAULT_MEMBER(2, 2); \ - \ - enum { value = sizeof(choice2::type) == \ - sizeof(test(choose())) \ - }; \ - }; \ - \ - enum { value = impl::value }; \ - } - -#endif - -}}} - -//////////////////////////////////////////////////////////////////////////////// -// -// Allocator traits -// -// First our implementation, then later light wrappers around the alternatives - -#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 0 - -# include -# include -# include -# if defined(BOOST_NO_SFINAE_EXPR) -# include -# endif - -# if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \ - !defined(BOOST_NO_SFINAE_EXPR) -# define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 1 -# else -# define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 0 -# endif - -namespace boost { namespace unordered { namespace detail { - - template - struct rebind_alloc; - -#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - - template class Alloc, - typename U, typename T, typename... Args> - struct rebind_alloc, T> - { - typedef Alloc type; - }; - -#else - - template < - template class Alloc, - typename U, typename T> - struct rebind_alloc, T> - { - typedef Alloc type; - }; - - template < - template class Alloc, - typename U, typename T, - typename A0> - struct rebind_alloc, T> - { - typedef Alloc type; - }; - - template < - template class Alloc, - typename U, typename T, - typename A0, typename A1> - struct rebind_alloc, T> - { - typedef Alloc type; - }; - -#endif - - template - struct rebind_wrap - { - template - static choice1::type test(choice1, - typename X::BOOST_NESTED_TEMPLATE rebind::other* = 0); - template - static choice2::type test(choice2, void* = 0); - - enum { value = (1 == sizeof(test(choose()))) }; - - struct fallback { - template - struct rebind { - typedef typename rebind_alloc::type other; - }; - }; - - typedef typename boost::detail::if_true:: - BOOST_NESTED_TEMPLATE then - ::type::BOOST_NESTED_TEMPLATE rebind::other type; - }; - -# if defined(BOOST_MSVC) && BOOST_MSVC <= 1400 - -# define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \ - template \ - struct default_type_ ## tname { \ - \ - template \ - static choice1::type test(choice1, typename X::tname* = 0); \ - \ - template \ - static choice2::type test(choice2, void* = 0); \ - \ - struct DefaultWrap { typedef Default tname; }; \ - \ - enum { value = (1 == sizeof(test(choose()))) }; \ - \ - typedef typename boost::detail::if_true:: \ - BOOST_NESTED_TEMPLATE then \ - ::type::tname type; \ - } - -# else - - template - struct sfinae : T2 {}; - -# define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \ - template \ - struct default_type_ ## tname { \ - \ - template \ - static typename boost::unordered::detail::sfinae< \ - typename X::tname, choice1>::type \ - test(choice1); \ - \ - template \ - static choice2::type test(choice2); \ - \ - struct DefaultWrap { typedef Default tname; }; \ - \ - enum { value = (1 == sizeof(test(choose()))) }; \ - \ - typedef typename boost::detail::if_true:: \ - BOOST_NESTED_TEMPLATE then \ - ::type::tname type; \ - } - -# endif - -# define BOOST_UNORDERED_DEFAULT_TYPE(T,tname, arg) \ - typename default_type_ ## tname::type - - BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(pointer); - BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(const_pointer); - BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(void_pointer); - BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(const_void_pointer); - BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(difference_type); - BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(size_type); - BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_copy_assignment); - BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_move_assignment); - BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_swap); - -# if !defined(BOOST_NO_SFINAE_EXPR) - - template - BOOST_UNORDERED_HAS_FUNCTION( - select_on_container_copy_construction, U const, (), 0 - ); - - template - BOOST_UNORDERED_HAS_FUNCTION( - max_size, U const, (), 0 - ); - -# if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - - template - BOOST_UNORDERED_HAS_FUNCTION( - construct, U, ( - boost::unordered::detail::make(), - boost::unordered::detail::make()...), 2 - ); - -# else - - template - BOOST_UNORDERED_HAS_FUNCTION( - construct, U, ( - boost::unordered::detail::make(), - boost::unordered::detail::make()), 2 - ); - -# endif - - template - BOOST_UNORDERED_HAS_FUNCTION( - destroy, U, (boost::unordered::detail::make()), 1 - ); - -# else - - template - BOOST_UNORDERED_HAS_MEMBER(select_on_container_copy_construction); - - template - BOOST_UNORDERED_HAS_MEMBER(max_size); - - template - BOOST_UNORDERED_HAS_MEMBER(construct); - - template - BOOST_UNORDERED_HAS_MEMBER(destroy); - -# endif - - namespace func - { - - template - inline Alloc call_select_on_container_copy_construction(const Alloc& rhs, - typename boost::enable_if_c< - boost::unordered::detail:: - has_select_on_container_copy_construction::value, void* - >::type = 0) - { - return rhs.select_on_container_copy_construction(); - } - - template - inline Alloc call_select_on_container_copy_construction(const Alloc& rhs, - typename boost::disable_if_c< - boost::unordered::detail:: - has_select_on_container_copy_construction::value, void* - >::type = 0) - { - return rhs; - } - - template - inline SizeType call_max_size(const Alloc& a, - typename boost::enable_if_c< - boost::unordered::detail::has_max_size::value, void* - >::type = 0) - { - return a.max_size(); - } - - template - inline SizeType call_max_size(const Alloc&, typename boost::disable_if_c< - boost::unordered::detail::has_max_size::value, void* - >::type = 0) - { - return (std::numeric_limits::max)(); - } - - } // namespace func. - - template - struct allocator_traits - { - typedef Alloc allocator_type; - typedef typename Alloc::value_type value_type; - - typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, pointer, value_type*) - pointer; - - template - struct pointer_to_other : boost::pointer_to_other {}; - - typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_pointer, - typename pointer_to_other::type) - const_pointer; - - //typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, void_pointer, - // typename pointer_to_other::type) - // void_pointer; - // - //typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_void_pointer, - // typename pointer_to_other::type) - // const_void_pointer; - - typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, difference_type, - std::ptrdiff_t) difference_type; - - typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, size_type, std::size_t) - size_type; - -#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) - template - using rebind_alloc = typename rebind_wrap::type; - - template - using rebind_traits = - boost::unordered::detail::allocator_traits >; -#endif - - static pointer allocate(Alloc& a, size_type n) - { return a.allocate(n); } - - // I never use this, so I'll just comment it out for now. - // - //static pointer allocate(Alloc& a, size_type n, - // const_void_pointer hint) - // { return DEFAULT_FUNC(allocate, pointer)(a, n, hint); } - - static void deallocate(Alloc& a, pointer p, size_type n) - { a.deallocate(p, n); } - - public: - -# if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT - - template - static typename boost::enable_if_c< - boost::unordered::detail::has_construct - ::value>::type - construct(Alloc& a, T* p, BOOST_FWD_REF(Args)... x) - { - a.construct(p, boost::forward(x)...); - } - - template - static typename boost::disable_if_c< - boost::unordered::detail::has_construct - ::value>::type - construct(Alloc&, T* p, BOOST_FWD_REF(Args)... x) - { - new (static_cast(p)) T(boost::forward(x)...); - } - - template - static typename boost::enable_if_c< - boost::unordered::detail::has_destroy::value>::type - destroy(Alloc& a, T* p) - { - a.destroy(p); - } - - template - static typename boost::disable_if_c< - boost::unordered::detail::has_destroy::value>::type - destroy(Alloc&, T* p) - { - boost::unordered::detail::func::destroy(p); - } - -# elif !defined(BOOST_NO_SFINAE_EXPR) - - template - static typename boost::enable_if_c< - boost::unordered::detail::has_construct::value>::type - construct(Alloc& a, T* p, T const& x) - { - a.construct(p, x); - } - - template - static typename boost::disable_if_c< - boost::unordered::detail::has_construct::value>::type - construct(Alloc&, T* p, T const& x) - { - new (static_cast(p)) T(x); - } - - template - static typename boost::enable_if_c< - boost::unordered::detail::has_destroy::value>::type - destroy(Alloc& a, T* p) - { - a.destroy(p); - } - - template - static typename boost::disable_if_c< - boost::unordered::detail::has_destroy::value>::type - destroy(Alloc&, T* p) - { - boost::unordered::detail::func::destroy(p); - } - -# else - - // If we don't have SFINAE expressions, only call construct for the - // copy constructor for the allocator's value_type - as that's - // the only construct method that old fashioned allocators support. - - template - static void construct(Alloc& a, T* p, T const& x, - typename boost::enable_if_c< - boost::unordered::detail::has_construct::value && - boost::is_same::value, - void*>::type = 0) - { - a.construct(p, x); - } - - template - static void construct(Alloc&, T* p, T const& x, - typename boost::disable_if_c< - boost::unordered::detail::has_construct::value && - boost::is_same::value, - void*>::type = 0) - { - new (static_cast(p)) T(x); - } - - template - static void destroy(Alloc& a, T* p, - typename boost::enable_if_c< - boost::unordered::detail::has_destroy::value && - boost::is_same::value, - void*>::type = 0) - { - a.destroy(p); - } - - template - static void destroy(Alloc&, T* p, - typename boost::disable_if_c< - boost::unordered::detail::has_destroy::value && - boost::is_same::value, - void*>::type = 0) - { - boost::unordered::detail::func::destroy(p); - } - -# endif - - static size_type max_size(const Alloc& a) - { - return boost::unordered::detail::func:: - call_max_size(a); - } - - // Allocator propagation on construction - - static Alloc select_on_container_copy_construction(Alloc const& rhs) - { - return boost::unordered::detail::func:: - call_select_on_container_copy_construction(rhs); - } - - // Allocator propagation on assignment and swap. - // Return true if lhs is modified. - typedef BOOST_UNORDERED_DEFAULT_TYPE( - Alloc, propagate_on_container_copy_assignment, false_type) - propagate_on_container_copy_assignment; - typedef BOOST_UNORDERED_DEFAULT_TYPE( - Alloc,propagate_on_container_move_assignment, false_type) - propagate_on_container_move_assignment; - typedef BOOST_UNORDERED_DEFAULT_TYPE( - Alloc,propagate_on_container_swap,false_type) - propagate_on_container_swap; - }; -}}} - -# undef BOOST_UNORDERED_DEFAULT_TYPE_TMPLT -# undef BOOST_UNORDERED_DEFAULT_TYPE - -//////////////////////////////////////////////////////////////////////////////// -// -// std::allocator_traits - -#elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1 - -# include - -# define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 1 - -namespace boost { namespace unordered { namespace detail { - - template - struct allocator_traits : std::allocator_traits {}; - - template - struct rebind_wrap - { - typedef typename std::allocator_traits:: - template rebind_alloc type; - }; -}}} - -//////////////////////////////////////////////////////////////////////////////// -// -// boost::container::allocator_traits - -#elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 2 - -# include - -# define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 0 - -namespace boost { namespace unordered { namespace detail { - - template - struct allocator_traits : - boost::container::allocator_traits {}; - - template - struct rebind_wrap : - boost::container::allocator_traits:: - template portable_rebind_alloc - {}; - -}}} - -#else - -#error "Invalid BOOST_UNORDERED_USE_ALLOCATOR_TRAITS value." - -#endif - - -namespace boost { namespace unordered { namespace detail { namespace func { - - //////////////////////////////////////////////////////////////////////////// - // call_construct - -#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - -# if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT - - template - inline void call_construct(Alloc& alloc, T* address, - BOOST_FWD_REF(Args)... args) - { - boost::unordered::detail::allocator_traits::construct(alloc, - address, boost::forward(args)...); - } - - template - inline void call_destroy(Alloc& alloc, T* x) { - boost::unordered::detail::allocator_traits::destroy(alloc, x); - } - - -# else - - template - inline void call_construct(Alloc&, T* address, - BOOST_FWD_REF(Args)... args) - { - new((void*) address) T(boost::forward(args)...); - } - - template - inline void call_destroy(Alloc&, T* x) { - boost::unordered::detail::func::destroy(x); - } - - -# endif - -#else - template - inline void call_construct(Alloc&, T* address) - { - new ((void*) address) T(); - } - - template - inline void call_construct(Alloc&, T* address, - BOOST_FWD_REF(A0) a0) - { - new ((void*) address) T(boost::forward(a0)); - } - - template - inline void call_destroy(Alloc&, T* x) { - boost::unordered::detail::func::destroy(x); - } - -#endif - - //////////////////////////////////////////////////////////////////////////// - // Construct from tuple - // - // Used for piecewise construction. - -#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - -# define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \ - template \ - void construct_from_tuple(Alloc& alloc, T* ptr, namespace_ tuple<>) \ - { \ - boost::unordered::detail::func::call_construct(alloc, ptr); \ - } \ - \ - BOOST_PP_REPEAT_FROM_TO(1, n, \ - BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_) - -# define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_) \ - template \ - void construct_from_tuple(Alloc& alloc, T* ptr, \ - namespace_ tuple const& x) \ - { \ - boost::unordered::detail::func::call_construct(alloc, ptr, \ - BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \ - ); \ - } - -# define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) \ - namespace_ get(x) - -#elif !defined(__SUNPRO_CC) - -# define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \ - template \ - void construct_from_tuple(Alloc&, T* ptr, namespace_ tuple<>) \ - { \ - new ((void*) ptr) T(); \ - } \ - \ - BOOST_PP_REPEAT_FROM_TO(1, n, \ - BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_) - -# define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_) \ - template \ - void construct_from_tuple(Alloc&, T* ptr, \ - namespace_ tuple const& x) \ - { \ - new ((void*) ptr) T( \ - BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \ - ); \ - } - -# define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) \ - namespace_ get(x) - -#else - - template struct length {}; - -# define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \ - template \ - void construct_from_tuple_impl( \ - boost::unordered::detail::func::length<0>, Alloc&, T* ptr, \ - namespace_ tuple<>) \ - { \ - new ((void*) ptr) T(); \ - } \ - \ - BOOST_PP_REPEAT_FROM_TO(1, n, \ - BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_) - -# define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_) \ - template \ - void construct_from_tuple_impl( \ - boost::unordered::detail::func::length, Alloc&, T* ptr, \ - namespace_ tuple const& x) \ - { \ - new ((void*) ptr) T( \ - BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \ - ); \ - } - -# define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) \ - namespace_ get(x) - -#endif - -BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::) - -#if !defined(__SUNPRO_CC) && !defined(BOOST_NO_CXX11_HDR_TUPLE) - BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std::) -#endif - -#undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE -#undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL -#undef BOOST_UNORDERED_GET_TUPLE_ARG - -#if defined(__SUNPRO_CC) - - template - void construct_from_tuple(Alloc& alloc, T* ptr, Tuple const& x) - { - construct_from_tuple_impl( - boost::unordered::detail::func::length< - boost::tuples::length::value>(), - alloc, ptr, x); - } - -#endif - - //////////////////////////////////////////////////////////////////////////// - // Trait to check for piecewise construction. - - template - struct use_piecewise { - static choice1::type test(choice1, - boost::unordered::piecewise_construct_t); - - static choice2::type test(choice2, ...); - - enum { value = sizeof(choice1::type) == - sizeof(test(choose(), boost::unordered::detail::make())) }; - }; - -#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - - //////////////////////////////////////////////////////////////////////////// - // Construct from variadic parameters - - // For the standard pair constructor. - - template - inline void construct_from_args(Alloc& alloc, T* address, - BOOST_FWD_REF(Args)... args) - { - boost::unordered::detail::func::call_construct(alloc, - address, boost::forward(args)...); - } - - // Special case for piece_construct - // - // TODO: When possible, it might be better to use std::pair's - // constructor for std::piece_construct with std::tuple. - - template - inline typename enable_if, void>::type - construct_from_args(Alloc& alloc, std::pair* address, - BOOST_FWD_REF(A0), BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) - { - boost::unordered::detail::func::construct_from_tuple(alloc, - boost::unordered::detail::func::const_cast_pointer( - boost::addressof(address->first)), - boost::forward(a1)); - BOOST_TRY { - boost::unordered::detail::func::construct_from_tuple(alloc, - boost::unordered::detail::func::const_cast_pointer( - boost::addressof(address->second)), - boost::forward(a2)); - } - BOOST_CATCH(...) { - boost::unordered::detail::func::call_destroy(alloc, - boost::unordered::detail::func::const_cast_pointer( - boost::addressof(address->first))); - BOOST_RETHROW; - } - BOOST_CATCH_END - } - -#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES - - //////////////////////////////////////////////////////////////////////////// - // Construct from emplace_args - - // Explicitly write out first three overloads for the sake of sane - // error messages. - - template - inline void construct_from_args(Alloc&, T* address, - emplace_args1 const& args) - { - new((void*) address) T(boost::forward(args.a0)); - } - - template - inline void construct_from_args(Alloc&, T* address, - emplace_args2 const& args) - { - new((void*) address) T( - boost::forward(args.a0), - boost::forward(args.a1) - ); - } - - template - inline void construct_from_args(Alloc&, T* address, - emplace_args3 const& args) - { - new((void*) address) T( - boost::forward(args.a0), - boost::forward(args.a1), - boost::forward(args.a2) - ); - } - - // Use a macro for the rest. - -#define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _) \ - template < \ - typename Alloc, typename T, \ - BOOST_PP_ENUM_PARAMS_Z(z, num_params, typename A) \ - > \ - inline void construct_from_args(Alloc&, T* address, \ - boost::unordered::detail::BOOST_PP_CAT(emplace_args,num_params) < \ - BOOST_PP_ENUM_PARAMS_Z(z, num_params, A) \ - > const& args) \ - { \ - new((void*) address) T( \ - BOOST_PP_ENUM_##z(num_params, BOOST_UNORDERED_CALL_FORWARD, \ - args.a)); \ - } - - BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT, - BOOST_UNORDERED_CONSTRUCT_IMPL, _) - -#undef BOOST_UNORDERED_CONSTRUCT_IMPL - - // Construct with piece_construct - - template - inline void construct_from_args(Alloc& alloc, std::pair* address, - boost::unordered::detail::emplace_args3 const& args, - typename enable_if, void*>::type = 0) - { - boost::unordered::detail::func::construct_from_tuple(alloc, - boost::unordered::detail::func::const_cast_pointer( - boost::addressof(address->first)), - args.a1); - BOOST_TRY { - boost::unordered::detail::func::construct_from_tuple(alloc, - boost::unordered::detail::func::const_cast_pointer( - boost::addressof(address->second)), - args.a2); - } - BOOST_CATCH(...) { - boost::unordered::detail::func::call_destroy(alloc, - boost::unordered::detail::func::const_cast_pointer( - boost::addressof(address->first))); - BOOST_RETHROW; - } - BOOST_CATCH_END - } - -#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES - -}}}} - -namespace boost { namespace unordered { namespace detail { - - /////////////////////////////////////////////////////////////////// - // - // Node construction - - template - struct node_constructor - { - typedef NodeAlloc node_allocator; - typedef boost::unordered::detail::allocator_traits - node_allocator_traits; - typedef typename node_allocator_traits::value_type node; - typedef typename node_allocator_traits::pointer node_pointer; - typedef typename node::value_type value_type; - - node_allocator& alloc_; - node_pointer node_; - bool node_constructed_; - - node_constructor(node_allocator& n) : - alloc_(n), - node_(), - node_constructed_(false) - { - } - - ~node_constructor(); - - void create_node(); - - // no throw - node_pointer release() - { - BOOST_ASSERT(node_ && node_constructed_); - node_pointer p = node_; - node_ = node_pointer(); - return p; - } - - void reclaim(node_pointer p) { - BOOST_ASSERT(!node_); - node_ = p; - node_constructed_ = true; - boost::unordered::detail::func::call_destroy(alloc_, - node_->value_ptr()); - } - - private: - node_constructor(node_constructor const&); - node_constructor& operator=(node_constructor const&); - }; - - template - node_constructor::~node_constructor() - { - if (node_) { - if (node_constructed_) { - boost::unordered::detail::func::destroy( - boost::addressof(*node_)); - } - - node_allocator_traits::deallocate(alloc_, node_, 1); - } - } - - template - void node_constructor::create_node() - { - BOOST_ASSERT(!node_); - node_constructed_ = false; - - node_ = node_allocator_traits::allocate(alloc_, 1); - - new ((void*) boost::addressof(*node_)) node(); - node_->init(node_); - node_constructed_ = true; - } - - template - struct node_tmp - { - typedef boost::unordered::detail::allocator_traits - node_allocator_traits; - typedef typename node_allocator_traits::pointer node_pointer; - - NodeAlloc& alloc_; - node_pointer node_; - - explicit node_tmp(node_pointer n, NodeAlloc& a): - alloc_(a), - node_(n) - { - } - - ~node_tmp(); - - // no throw - node_pointer release() - { - node_pointer p = node_; - node_ = node_pointer(); - return p; - } - }; - - template - node_tmp::~node_tmp() - { - if (node_) { - boost::unordered::detail::func::call_destroy(alloc_, - node_->value_ptr()); - boost::unordered::detail::func::destroy( - boost::addressof(*node_)); - node_allocator_traits::deallocate(alloc_, node_, 1); - } - } -}}} - -namespace boost { namespace unordered { namespace detail { namespace func { - - // Some nicer construct_node functions, might try to - // improve implementation later. - - template - inline typename boost::unordered::detail::allocator_traits::pointer - construct_node_from_args(Alloc& alloc, BOOST_UNORDERED_EMPLACE_ARGS) - { - node_constructor a(alloc); - a.create_node(); - construct_from_args(alloc, a.node_->value_ptr(), - BOOST_UNORDERED_EMPLACE_FORWARD); - return a.release(); - } - - template - inline typename boost::unordered::detail::allocator_traits::pointer - construct_node(Alloc& alloc, BOOST_FWD_REF(U) x) - { - node_constructor a(alloc); - a.create_node(); - boost::unordered::detail::func::call_construct( - alloc, a.node_->value_ptr(), boost::forward(x)); - return a.release(); - } - - // TODO: When possible, it might be better to use std::pair's - // constructor for std::piece_construct with std::tuple. - template - inline typename boost::unordered::detail::allocator_traits::pointer - construct_node_pair(Alloc& alloc, BOOST_FWD_REF(Key) k) - { - node_constructor a(alloc); - a.create_node(); - boost::unordered::detail::func::call_construct(alloc, - boost::unordered::detail::func::const_cast_pointer( - boost::addressof(a.node_->value_ptr()->first)), - boost::forward(k)); - BOOST_TRY { - boost::unordered::detail::func::call_construct(alloc, - boost::unordered::detail::func::const_cast_pointer( - boost::addressof(a.node_->value_ptr()->second))); - } - BOOST_CATCH(...) { - boost::unordered::detail::func::call_destroy(alloc, - boost::unordered::detail::func::const_cast_pointer( - boost::addressof(a.node_->value_ptr()->first))); - BOOST_RETHROW; - } - BOOST_CATCH_END - return a.release(); - } - - template - inline typename boost::unordered::detail::allocator_traits::pointer - construct_node_pair(Alloc& alloc, BOOST_FWD_REF(Key) k, BOOST_FWD_REF(Mapped) m) - { - node_constructor a(alloc); - a.create_node(); - boost::unordered::detail::func::call_construct(alloc, - boost::unordered::detail::func::const_cast_pointer( - boost::addressof(a.node_->value_ptr()->first)), - boost::forward(k)); - BOOST_TRY { - boost::unordered::detail::func::call_construct(alloc, - boost::unordered::detail::func::const_cast_pointer( - boost::addressof(a.node_->value_ptr()->second)), - boost::forward(m)); - } - BOOST_CATCH(...) { - boost::unordered::detail::func::call_destroy(alloc, - boost::unordered::detail::func::const_cast_pointer( - boost::addressof(a.node_->value_ptr()->first))); - BOOST_RETHROW; - } - BOOST_CATCH_END - return a.release(); - } -}}}} - -#if defined(BOOST_MSVC) -#pragma warning(pop) -#endif - -#endif diff --git a/include/boost/unordered/detail/buckets.hpp b/include/boost/unordered/detail/buckets.hpp deleted file mode 100644 index bd9a5cbb..00000000 --- a/include/boost/unordered/detail/buckets.hpp +++ /dev/null @@ -1,774 +0,0 @@ - -// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard. -// Copyright (C) 2005-2011 Daniel James -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_UNORDERED_DETAIL_MANAGER_HPP_INCLUDED -#define BOOST_UNORDERED_DETAIL_MANAGER_HPP_INCLUDED - -#include -#if defined(BOOST_HAS_PRAGMA_ONCE) -#pragma once -#endif - -#include -#include - -namespace boost { namespace unordered { namespace detail { - - template struct table; - template struct bucket; - struct ptr_bucket; - template struct table_impl; - template struct grouped_table_impl; - -}}} - -// The 'iterator_detail' namespace was a misguided attempt at avoiding ADL -// in the detail namespace. It didn't work because the template parameters -// were in detail. I'm not changing it at the moment to be safe. I might -// do in the future if I change the iterator types. -namespace boost { namespace unordered { namespace iterator_detail { - - //////////////////////////////////////////////////////////////////////////// - // Iterators - // - // all no throw - - template struct iterator; - template struct c_iterator; - template struct l_iterator; - template - struct cl_iterator; - - // Local Iterators - // - // all no throw - - template - struct l_iterator - : public std::iterator< - std::forward_iterator_tag, - typename Node::value_type, - std::ptrdiff_t, - typename Node::value_type*, - typename Node::value_type&> - { -#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) - template - friend struct boost::unordered::iterator_detail::cl_iterator; - private: -#endif - typedef typename Node::node_pointer node_pointer; - node_pointer ptr_; - std::size_t bucket_; - std::size_t bucket_count_; - - public: - - typedef typename Node::value_type value_type; - - l_iterator() BOOST_NOEXCEPT : ptr_() {} - - l_iterator(node_pointer n, std::size_t b, std::size_t c) BOOST_NOEXCEPT - : ptr_(n), bucket_(b), bucket_count_(c) {} - - value_type& operator*() const { - return ptr_->value(); - } - - value_type* operator->() const { - return ptr_->value_ptr(); - } - - l_iterator& operator++() { - ptr_ = static_cast(ptr_->next_); - if (ptr_ && Policy::to_bucket(bucket_count_, ptr_->hash_) - != bucket_) - ptr_ = node_pointer(); - return *this; - } - - l_iterator operator++(int) { - l_iterator tmp(*this); - ++(*this); - return tmp; - } - - bool operator==(l_iterator x) const BOOST_NOEXCEPT { - return ptr_ == x.ptr_; - } - - bool operator!=(l_iterator x) const BOOST_NOEXCEPT { - return ptr_ != x.ptr_; - } - }; - - template - struct cl_iterator - : public std::iterator< - std::forward_iterator_tag, - typename Node::value_type, - std::ptrdiff_t, - typename Node::value_type const*, - typename Node::value_type const&> - { - friend struct boost::unordered::iterator_detail::l_iterator - ; - private: - - typedef typename Node::node_pointer node_pointer; - node_pointer ptr_; - std::size_t bucket_; - std::size_t bucket_count_; - - public: - - typedef typename Node::value_type value_type; - - cl_iterator() BOOST_NOEXCEPT : ptr_() {} - - cl_iterator(node_pointer n, std::size_t b, std::size_t c) BOOST_NOEXCEPT : - ptr_(n), bucket_(b), bucket_count_(c) {} - - cl_iterator(boost::unordered::iterator_detail::l_iterator< - Node, Policy> const& x) BOOST_NOEXCEPT : - ptr_(x.ptr_), bucket_(x.bucket_), bucket_count_(x.bucket_count_) - {} - - value_type const& operator*() const { - return ptr_->value(); - } - - value_type const* operator->() const { - return ptr_->value_ptr(); - } - - cl_iterator& operator++() { - ptr_ = static_cast(ptr_->next_); - if (ptr_ && Policy::to_bucket(bucket_count_, ptr_->hash_) - != bucket_) - ptr_ = node_pointer(); - return *this; - } - - cl_iterator operator++(int) { - cl_iterator tmp(*this); - ++(*this); - return tmp; - } - - friend bool operator==(cl_iterator const& x, cl_iterator const& y) - BOOST_NOEXCEPT - { - return x.ptr_ == y.ptr_; - } - - friend bool operator!=(cl_iterator const& x, cl_iterator const& y) - BOOST_NOEXCEPT - { - return x.ptr_ != y.ptr_; - } - }; - - template - struct iterator - : public std::iterator< - std::forward_iterator_tag, - typename Node::value_type, - std::ptrdiff_t, - typename Node::value_type*, - typename Node::value_type&> - { -#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) - template - friend struct boost::unordered::iterator_detail::c_iterator; - template - friend struct boost::unordered::detail::table; - template - friend struct boost::unordered::detail::table_impl; - template - friend struct boost::unordered::detail::grouped_table_impl; - private: -#endif - typedef typename Node::node_pointer node_pointer; - node_pointer node_; - - public: - - typedef typename Node::value_type value_type; - - iterator() BOOST_NOEXCEPT : node_() {} - - explicit iterator(typename Node::link_pointer x) BOOST_NOEXCEPT : - node_(static_cast(x)) {} - - value_type& operator*() const { - return node_->value(); - } - - value_type* operator->() const { - return node_->value_ptr(); - } - - iterator& operator++() { - node_ = static_cast(node_->next_); - return *this; - } - - iterator operator++(int) { - iterator tmp(node_); - node_ = static_cast(node_->next_); - return tmp; - } - - bool operator==(iterator const& x) const BOOST_NOEXCEPT { - return node_ == x.node_; - } - - bool operator!=(iterator const& x) const BOOST_NOEXCEPT { - return node_ != x.node_; - } - }; - - template - struct c_iterator - : public std::iterator< - std::forward_iterator_tag, - typename Node::value_type, - std::ptrdiff_t, - typename Node::value_type const*, - typename Node::value_type const&> - { - friend struct boost::unordered::iterator_detail::iterator; - -#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) - template - friend struct boost::unordered::detail::table; - template - friend struct boost::unordered::detail::table_impl; - template - friend struct boost::unordered::detail::grouped_table_impl; - - private: -#endif - typedef typename Node::node_pointer node_pointer; - typedef boost::unordered::iterator_detail::iterator n_iterator; - node_pointer node_; - - public: - - typedef typename Node::value_type value_type; - - c_iterator() BOOST_NOEXCEPT : node_() {} - - explicit c_iterator(typename Node::link_pointer x) BOOST_NOEXCEPT : - node_(static_cast(x)) {} - - c_iterator(n_iterator const& x) BOOST_NOEXCEPT : node_(x.node_) {} - - value_type const& operator*() const { - return node_->value(); - } - - value_type const* operator->() const { - return node_->value_ptr(); - } - - c_iterator& operator++() { - node_ = static_cast(node_->next_); - return *this; - } - - c_iterator operator++(int) { - c_iterator tmp(node_); - node_ = static_cast(node_->next_); - return tmp; - } - - friend bool operator==(c_iterator const& x, c_iterator const& y) - BOOST_NOEXCEPT - { - return x.node_ == y.node_; - } - - friend bool operator!=(c_iterator const& x, c_iterator const& y) - BOOST_NOEXCEPT - { - return x.node_ != y.node_; - } - }; -}}} - -namespace boost { namespace unordered { namespace detail { - - /////////////////////////////////////////////////////////////////// - // - // Node Holder - // - // Temporary store for nodes. Deletes any that aren't used. - - template - struct node_holder - { - private: - typedef NodeAlloc node_allocator; - typedef boost::unordered::detail::allocator_traits - node_allocator_traits; - typedef typename node_allocator_traits::value_type node; - typedef typename node_allocator_traits::pointer node_pointer; - typedef typename node::value_type value_type; - typedef typename node::link_pointer link_pointer; - typedef boost::unordered::iterator_detail::iterator iterator; - - node_constructor constructor_; - node_pointer nodes_; - - public: - - template - explicit node_holder(Table& b) : - constructor_(b.node_alloc()), - nodes_() - { - if (b.size_) { - typename Table::link_pointer prev = b.get_previous_start(); - nodes_ = static_cast(prev->next_); - prev->next_ = link_pointer(); - b.size_ = 0; - } - } - - ~node_holder(); - - node_pointer pop_node() - { - node_pointer n = nodes_; - nodes_ = static_cast(nodes_->next_); - n->init(n); - n->next_ = link_pointer(); - return n; - } - - template - inline node_pointer copy_of(T const& v) { - if (nodes_) { - constructor_.reclaim(pop_node()); - } - else { - constructor_.create_node(); - } - boost::unordered::detail::func::call_construct( - constructor_.alloc_, constructor_.node_->value_ptr(), v); - return constructor_.release(); - } - - template - inline node_pointer move_copy_of(T& v) { - if (nodes_) { - constructor_.reclaim(pop_node()); - } - else { - constructor_.create_node(); - } - boost::unordered::detail::func::call_construct( - constructor_.alloc_, constructor_.node_->value_ptr(), - boost::move(v)); - return constructor_.release(); - } - - iterator begin() const - { - return iterator(nodes_); - } - }; - - template - node_holder::~node_holder() - { - while (nodes_) { - node_pointer p = nodes_; - nodes_ = static_cast(p->next_); - - boost::unordered::detail::func::call_destroy(constructor_.alloc_, - p->value_ptr()); - boost::unordered::detail::func::destroy(boost::addressof(*p)); - node_allocator_traits::deallocate(constructor_.alloc_, p, 1); - } - } - - /////////////////////////////////////////////////////////////////// - // - // Bucket - - template - struct bucket - { - typedef NodePointer link_pointer; - link_pointer next_; - - bucket() : next_() {} - - link_pointer first_from_start() - { - return next_; - } - - enum { extra_node = true }; - }; - - struct ptr_bucket - { - typedef ptr_bucket* link_pointer; - link_pointer next_; - - ptr_bucket() : next_(0) {} - - link_pointer first_from_start() - { - return this; - } - - enum { extra_node = false }; - }; - - /////////////////////////////////////////////////////////////////// - // - // Hash Policy - - template - struct prime_policy - { - template - static inline SizeT apply_hash(Hash const& hf, T const& x) { - return hf(x); - } - - static inline SizeT to_bucket(SizeT bucket_count, SizeT hash) { - return hash % bucket_count; - } - - static inline SizeT new_bucket_count(SizeT min) { - return boost::unordered::detail::next_prime(min); - } - - static inline SizeT prev_bucket_count(SizeT max) { - return boost::unordered::detail::prev_prime(max); - } - }; - - template - struct mix64_policy - { - template - static inline SizeT apply_hash(Hash const& hf, T const& x) { - SizeT key = hf(x); - key = (~key) + (key << 21); // key = (key << 21) - key - 1; - key = key ^ (key >> 24); - key = (key + (key << 3)) + (key << 8); // key * 265 - key = key ^ (key >> 14); - key = (key + (key << 2)) + (key << 4); // key * 21 - key = key ^ (key >> 28); - key = key + (key << 31); - return key; - } - - static inline SizeT to_bucket(SizeT bucket_count, SizeT hash) { - return hash & (bucket_count - 1); - } - - static inline SizeT new_bucket_count(SizeT min) { - if (min <= 4) return 4; - --min; - min |= min >> 1; - min |= min >> 2; - min |= min >> 4; - min |= min >> 8; - min |= min >> 16; - min |= min >> 32; - return min + 1; - } - - static inline SizeT prev_bucket_count(SizeT max) { - max |= max >> 1; - max |= max >> 2; - max |= max >> 4; - max |= max >> 8; - max |= max >> 16; - max |= max >> 32; - return (max >> 1) + 1; - } - }; - - template - struct pick_policy_impl { - typedef prime_policy type; - }; - - template <> - struct pick_policy_impl<64, 2> { - typedef mix64_policy type; - }; - - template - struct pick_policy : - pick_policy_impl< - std::numeric_limits::digits, - std::numeric_limits::radix> {}; - - // While the mix policy is generally faster, the prime policy is a lot - // faster when a large number consecutive integers are used, because - // there are no collisions. Since that is probably quite common, use - // prime policy for integeral types. But not the smaller ones, as they - // don't have enough unique values for this to be an issue. - - template <> - struct pick_policy { - typedef prime_policy type; - }; - - template <> - struct pick_policy { - typedef prime_policy type; - }; - - template <> - struct pick_policy { - typedef prime_policy type; - }; - - template <> - struct pick_policy { - typedef prime_policy type; - }; - - // TODO: Maybe not if std::size_t is smaller than long long. -#if !defined(BOOST_NO_LONG_LONG) - template <> - struct pick_policy { - typedef prime_policy type; - }; - - template <> - struct pick_policy { - typedef prime_policy type; - }; -#endif - - //////////////////////////////////////////////////////////////////////////// - // Functions - - // Assigning and swapping the equality and hash function objects - // needs strong exception safety. To implement that normally we'd - // require one of them to be known to not throw and the other to - // guarantee strong exception safety. Unfortunately they both only - // have basic exception safety. So to acheive strong exception - // safety we have storage space for two copies, and assign the new - // copies to the unused space. Then switch to using that to use - // them. This is implemented in 'set_hash_functions' which - // atomically assigns the new function objects in a strongly - // exception safe manner. - - template - class set_hash_functions; - - template - class functions - { - public: - static const bool nothrow_move_assignable = - boost::is_nothrow_move_assignable::value && - boost::is_nothrow_move_assignable

::value; - static const bool nothrow_move_constructible = - boost::is_nothrow_move_constructible::value && - boost::is_nothrow_move_constructible

::value; - - private: - friend class boost::unordered::detail::set_hash_functions; - functions& operator=(functions const&); - - typedef compressed function_pair; - - typedef typename boost::aligned_storage< - sizeof(function_pair), - boost::alignment_of::value>::type aligned_function; - - bool current_; // The currently active functions. - aligned_function funcs_[2]; - - function_pair const& current() const { - return *static_cast( - static_cast(&funcs_[current_])); - } - - function_pair& current() { - return *static_cast( - static_cast(&funcs_[current_])); - } - - void construct(bool which, H const& hf, P const& eq) - { - new((void*) &funcs_[which]) function_pair(hf, eq); - } - - void construct(bool which, function_pair const& f, - boost::unordered::detail::false_type = - boost::unordered::detail::false_type()) - { - new((void*) &funcs_[which]) function_pair(f); - } - - void construct(bool which, function_pair& f, - boost::unordered::detail::true_type) - { - new((void*) &funcs_[which]) function_pair(f, - boost::unordered::detail::move_tag()); - } - - void destroy(bool which) - { - boost::unordered::detail::func::destroy((function_pair*)(&funcs_[which])); - } - - public: - - typedef boost::unordered::detail::set_hash_functions set_hash_functions; - - functions(H const& hf, P const& eq) - : current_(false) - { - construct(current_, hf, eq); - } - - functions(functions const& bf) - : current_(false) - { - construct(current_, bf.current()); - } - - functions(functions& bf, boost::unordered::detail::move_tag) - : current_(false) - { - construct(current_, bf.current(), - boost::unordered::detail::integral_constant()); - } - - ~functions() { - this->destroy(current_); - } - - H const& hash_function() const { - return current().first(); - } - - P const& key_eq() const { - return current().second(); - } - }; - - template - class set_hash_functions - { - set_hash_functions(set_hash_functions const&); - set_hash_functions& operator=(set_hash_functions const&); - - typedef functions functions_type; - - functions_type& functions_; - bool tmp_functions_; - - public: - - set_hash_functions(functions_type& f, H const& h, P const& p) - : functions_(f), - tmp_functions_(!f.current_) - { - f.construct(tmp_functions_, h, p); - } - - set_hash_functions(functions_type& f, functions_type const& other) - : functions_(f), - tmp_functions_(!f.current_) - { - f.construct(tmp_functions_, other.current()); - } - - ~set_hash_functions() - { - functions_.destroy(tmp_functions_); - } - - void commit() - { - functions_.current_ = tmp_functions_; - tmp_functions_ = !tmp_functions_; - } - }; - - template - class set_hash_functions - { - set_hash_functions(set_hash_functions const&); - set_hash_functions& operator=(set_hash_functions const&); - - typedef functions functions_type; - - functions_type& functions_; - H hash_; - P pred_; - - public: - - set_hash_functions(functions_type& f, H const& h, P const& p) : - functions_(f), - hash_(h), - pred_(p) {} - - set_hash_functions(functions_type& f, functions_type const& other) : - functions_(f), - hash_(other.hash_function()), - pred_(other.key_eq()) {} - - void commit() - { - functions_.current().first() = boost::move(hash_); - functions_.current().second() = boost::move(pred_); - } - }; - - //////////////////////////////////////////////////////////////////////////// - // rvalue parameters when type can't be a BOOST_RV_REF(T) parameter - // e.g. for int - -#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) -# define BOOST_UNORDERED_RV_REF(T) BOOST_RV_REF(T) -#else - struct please_ignore_this_overload { - typedef please_ignore_this_overload type; - }; - - template - struct rv_ref_impl { - typedef BOOST_RV_REF(T) type; - }; - - template - struct rv_ref : - boost::detail::if_true< - boost::is_class::value - >::BOOST_NESTED_TEMPLATE then < - boost::unordered::detail::rv_ref_impl, - please_ignore_this_overload - >::type - {}; - -# define BOOST_UNORDERED_RV_REF(T) \ - typename boost::unordered::detail::rv_ref::type -#endif -}}} - -#endif diff --git a/include/boost/unordered/detail/equivalent.hpp b/include/boost/unordered/detail/equivalent.hpp deleted file mode 100644 index 618d3af9..00000000 --- a/include/boost/unordered/detail/equivalent.hpp +++ /dev/null @@ -1,735 +0,0 @@ - -// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard. -// Copyright (C) 2005-2011 Daniel James -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_UNORDERED_DETAIL_EQUIVALENT_HPP_INCLUDED -#define BOOST_UNORDERED_DETAIL_EQUIVALENT_HPP_INCLUDED - -#include -#if defined(BOOST_HAS_PRAGMA_ONCE) -#pragma once -#endif - -#include - -namespace boost { namespace unordered { namespace detail { - - template struct grouped_node; - template struct grouped_ptr_node; - template struct grouped_table_impl; - - template - struct grouped_node : - boost::unordered::detail::value_base - { - typedef typename ::boost::unordered::detail::rebind_wrap< - A, grouped_node >::type allocator; - typedef typename ::boost::unordered::detail:: - allocator_traits::pointer node_pointer; - typedef node_pointer link_pointer; - - link_pointer next_; - node_pointer group_prev_; - std::size_t hash_; - - grouped_node() : - next_(), - group_prev_(), - hash_(0) - {} - - void init(node_pointer self) - { - group_prev_ = self; - } - - private: - grouped_node& operator=(grouped_node const&); - }; - - template - struct grouped_ptr_node : - boost::unordered::detail::ptr_bucket - { - typedef T value_type; - typedef boost::unordered::detail::ptr_bucket bucket_base; - typedef grouped_ptr_node* node_pointer; - typedef ptr_bucket* link_pointer; - - node_pointer group_prev_; - std::size_t hash_; - boost::unordered::detail::value_base value_base_; - - grouped_ptr_node() : - bucket_base(), - group_prev_(0), - hash_(0) - {} - - void init(node_pointer self) - { - group_prev_ = self; - } - - void* address() { return value_base_.address(); } - value_type& value() { return value_base_.value(); } - value_type* value_ptr() { return value_base_.value_ptr(); } - - private: - grouped_ptr_node& operator=(grouped_ptr_node const&); - }; - - // If the allocator uses raw pointers use grouped_ptr_node - // Otherwise use grouped_node. - - template - struct pick_grouped_node2 - { - typedef boost::unordered::detail::grouped_node node; - - typedef typename boost::unordered::detail::allocator_traits< - typename boost::unordered::detail::rebind_wrap::type - >::pointer node_pointer; - - typedef boost::unordered::detail::bucket bucket; - typedef node_pointer link_pointer; - }; - - template - struct pick_grouped_node2*, - boost::unordered::detail::ptr_bucket*> - { - typedef boost::unordered::detail::grouped_ptr_node node; - typedef boost::unordered::detail::ptr_bucket bucket; - typedef bucket* link_pointer; - }; - - template - struct pick_grouped_node - { - typedef typename boost::remove_const::type nonconst; - - typedef boost::unordered::detail::allocator_traits< - typename boost::unordered::detail::rebind_wrap >::type - > tentative_node_traits; - - typedef boost::unordered::detail::allocator_traits< - typename boost::unordered::detail::rebind_wrap::type - > tentative_bucket_traits; - - typedef pick_grouped_node2 pick; - - typedef typename pick::node node; - typedef typename pick::bucket bucket; - typedef typename pick::link_pointer link_pointer; - }; - - template - struct grouped_table_impl : boost::unordered::detail::table - { - typedef boost::unordered::detail::table table; - typedef typename table::value_type value_type; - typedef typename table::bucket bucket; - typedef typename table::policy policy; - typedef typename table::node_pointer node_pointer; - typedef typename table::node_allocator node_allocator; - typedef typename table::node_allocator_traits node_allocator_traits; - typedef typename table::bucket_pointer bucket_pointer; - typedef typename table::link_pointer link_pointer; - typedef typename table::hasher hasher; - typedef typename table::key_equal key_equal; - typedef typename table::key_type key_type; - typedef typename table::node_constructor node_constructor; - typedef typename table::node_tmp node_tmp; - typedef typename table::extractor extractor; - typedef typename table::iterator iterator; - typedef typename table::c_iterator c_iterator; - - // Constructors - - grouped_table_impl(std::size_t n, - hasher const& hf, - key_equal const& eq, - node_allocator const& a) - : table(n, hf, eq, a) - {} - - grouped_table_impl(grouped_table_impl const& x) - : table(x, node_allocator_traits:: - select_on_container_copy_construction(x.node_alloc())) - { - this->init(x); - } - - grouped_table_impl(grouped_table_impl const& x, - node_allocator const& a) - : table(x, a) - { - this->init(x); - } - - grouped_table_impl(grouped_table_impl& x, - boost::unordered::detail::move_tag m) - : table(x, m) - {} - - grouped_table_impl(grouped_table_impl& x, - node_allocator const& a, - boost::unordered::detail::move_tag m) - : table(x, a, m) - { - this->move_init(x); - } - - // Node functions. - - static inline node_pointer next_node(link_pointer n) { - return static_cast(n->next_); - } - - static inline node_pointer next_group(node_pointer n) { - return static_cast(n->group_prev_->next_); - } - - // Accessors - - template - node_pointer find_node_impl( - std::size_t key_hash, - Key const& k, - Pred const& eq) const - { - std::size_t bucket_index = this->hash_to_bucket(key_hash); - node_pointer n = this->begin(bucket_index); - - for (;;) - { - if (!n) return n; - - std::size_t node_hash = n->hash_; - if (key_hash == node_hash) - { - if (eq(k, this->get_key(n->value()))) - return n; - } - else - { - if (this->hash_to_bucket(node_hash) != bucket_index) - return node_pointer(); - } - - n = next_group(n); - } - } - - std::size_t count(key_type const& k) const - { - node_pointer n = this->find_node(k); - if (!n) return 0; - - std::size_t x = 0; - node_pointer it = n; - do { - it = it->group_prev_; - ++x; - } while(it != n); - - return x; - } - - std::pair - equal_range(key_type const& k) const - { - node_pointer n = this->find_node(k); - return std::make_pair(iterator(n), iterator(n ? next_group(n) : n)); - } - - // Equality - - bool equals(grouped_table_impl const& other) const - { - if(this->size_ != other.size_) return false; - - for(node_pointer n1 = this->begin(); n1;) - { - node_pointer n2 = other.find_node(other.get_key(n1->value())); - if (!n2) return false; - node_pointer end1 = next_group(n1); - node_pointer end2 = next_group(n2); - if (!group_equals(n1, end1, n2, end2)) return false; - n1 = end1; - } - - return true; - } - - static bool group_equals(node_pointer n1, node_pointer end1, - node_pointer n2, node_pointer end2) - { - for(;;) - { - if (n1->value() != n2->value()) break; - - n1 = next_node(n1); - n2 = next_node(n2); - - if (n1 == end1) return n2 == end2; - if (n2 == end2) return false; - } - - for(node_pointer n1a = n1, n2a = n2;;) - { - n1a = next_node(n1a); - n2a = next_node(n2a); - - if (n1a == end1) - { - if (n2a == end2) break; - else return false; - } - - if (n2a == end2) return false; - } - - node_pointer start = n1; - for(;n1 != end1; n1 = next_node(n1)) - { - value_type const& v = n1->value(); - if (!find(start, n1, v)) { - std::size_t matches = count_equal(n2, end2, v); - if (!matches) return false; - if (matches != 1 + count_equal(next_node(n1), end1, v)) return false; - } - } - - return true; - } - - static bool find(node_pointer n, node_pointer end, value_type const& v) - { - for(;n != end; n = next_node(n)) - if (n->value() == v) - return true; - return false; - } - - static std::size_t count_equal(node_pointer n, node_pointer end, - value_type const& v) - { - std::size_t count = 0; - for(;n != end; n = next_node(n)) - if (n->value() == v) ++count; - return count; - } - - // Emplace/Insert - - // Add node 'n' to the group containing 'pos'. - // If 'pos' is the first node in group, add to the end of the group, - // otherwise add before 'pos'. - static inline void add_to_node_group( - node_pointer n, - node_pointer pos) - { - n->next_ = pos->group_prev_->next_; - n->group_prev_ = pos->group_prev_; - pos->group_prev_->next_ = n; - pos->group_prev_ = n; - } - - inline node_pointer add_node( - node_pointer n, - std::size_t key_hash, - node_pointer pos) - { - n->hash_ = key_hash; - if (pos) { - this->add_to_node_group(n, pos); - if (n->next_) { - std::size_t next_bucket = this->hash_to_bucket( - next_node(n)->hash_); - if (next_bucket != this->hash_to_bucket(key_hash)) { - this->get_bucket(next_bucket)->next_ = n; - } - } - } - else { - bucket_pointer b = this->get_bucket( - this->hash_to_bucket(key_hash)); - - if (!b->next_) - { - link_pointer start_node = this->get_previous_start(); - - if (start_node->next_) { - this->get_bucket(this->hash_to_bucket( - next_node(start_node)->hash_ - ))->next_ = n; - } - - b->next_ = start_node; - n->next_ = start_node->next_; - start_node->next_ = n; - } - else - { - n->next_ = b->next_->next_; - b->next_->next_ = n; - } - } - ++this->size_; - return n; - } - - inline node_pointer add_using_hint( - node_pointer n, - node_pointer hint) - { - n->hash_ = hint->hash_; - this->add_to_node_group(n, hint); - if (n->next_ != hint && n->next_) { - std::size_t next_bucket = this->hash_to_bucket( - next_node(n)->hash_); - if (next_bucket != this->hash_to_bucket(n->hash_)) { - this->get_bucket(next_bucket)->next_ = n; - } - } - ++this->size_; - return n; - } - - -#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) -# if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - iterator emplace(boost::unordered::detail::emplace_args1< - boost::unordered::detail::please_ignore_this_overload> const&) - { - BOOST_ASSERT(false); - return iterator(); - } - - iterator emplace_hint(c_iterator, boost::unordered::detail::emplace_args1< - boost::unordered::detail::please_ignore_this_overload> const&) - { - BOOST_ASSERT(false); - return iterator(); - } -# else - iterator emplace( - boost::unordered::detail::please_ignore_this_overload const&) - { - BOOST_ASSERT(false); - return iterator(); - } - - iterator emplace_hint(c_iterator, - boost::unordered::detail::please_ignore_this_overload const&) - { - BOOST_ASSERT(false); - return iterator(); - } -# endif -#endif - - template - iterator emplace(BOOST_UNORDERED_EMPLACE_ARGS) - { - return iterator(emplace_impl( - boost::unordered::detail::func::construct_node_from_args( - this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD))); - } - - template - iterator emplace_hint(c_iterator hint, BOOST_UNORDERED_EMPLACE_ARGS) - { - return iterator(emplace_hint_impl(hint, - boost::unordered::detail::func::construct_node_from_args( - this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD))); - } - - iterator emplace_impl(node_pointer n) - { - node_tmp a(n, this->node_alloc()); - key_type const& k = this->get_key(a.node_->value()); - std::size_t key_hash = this->hash(k); - node_pointer position = this->find_node(key_hash, k); - this->reserve_for_insert(this->size_ + 1); - return iterator(this->add_node(a.release(), key_hash, position)); - } - - iterator emplace_hint_impl(c_iterator hint, node_pointer n) - { - node_tmp a(n, this->node_alloc()); - key_type const& k = this->get_key(a.node_->value()); - if (hint.node_ && this->key_eq()(k, this->get_key(*hint))) { - this->reserve_for_insert(this->size_ + 1); - return iterator(this->add_using_hint(a.release(), hint.node_)); - } - else { - std::size_t key_hash = this->hash(k); - node_pointer position = this->find_node(key_hash, k); - this->reserve_for_insert(this->size_ + 1); - return iterator(this->add_node(a.release(), key_hash, position)); - } - } - - void emplace_impl_no_rehash(node_pointer n) - { - node_tmp a(n, this->node_alloc()); - key_type const& k = this->get_key(a.node_->value()); - std::size_t key_hash = this->hash(k); - node_pointer position = this->find_node(key_hash, k); - this->add_node(a.release(), key_hash, position); - } - - //////////////////////////////////////////////////////////////////////// - // Insert range methods - - // if hash function throws, or inserting > 1 element, basic exception - // safety. Strong otherwise - template - void insert_range(I i, I j, typename - boost::unordered::detail::enable_if_forward::type = 0) - { - if(i == j) return; - - std::size_t distance = static_cast(std::distance(i, j)); - if(distance == 1) { - emplace_impl( - boost::unordered::detail::func::construct_node( - this->node_alloc(), *i)); - } - else { - // Only require basic exception safety here - this->reserve_for_insert(this->size_ + distance); - - for (; i != j; ++i) { - emplace_impl_no_rehash( - boost::unordered::detail::func::construct_node( - this->node_alloc(), *i)); - } - } - } - - template - void insert_range(I i, I j, typename - boost::unordered::detail::disable_if_forward::type = 0) - { - for (; i != j; ++i) { - emplace_impl( - boost::unordered::detail::func::construct_node( - this->node_alloc(), *i)); - } - } - - //////////////////////////////////////////////////////////////////////// - // Erase - // - // no throw - - std::size_t erase_key(key_type const& k) - { - if(!this->size_) return 0; - - std::size_t key_hash = this->hash(k); - std::size_t bucket_index = this->hash_to_bucket(key_hash); - link_pointer prev = this->get_previous_start(bucket_index); - if (!prev) return 0; - - node_pointer first_node; - - for (;;) - { - if (!prev->next_) return 0; - first_node = next_node(prev); - std::size_t node_hash = first_node->hash_; - if (this->hash_to_bucket(node_hash) != bucket_index) - return 0; - if (node_hash == key_hash && - this->key_eq()(k, this->get_key(first_node->value()))) - break; - prev = first_node->group_prev_; - } - - link_pointer end = first_node->group_prev_->next_; - - std::size_t deleted_count = this->delete_nodes(prev, end); - this->fix_bucket(bucket_index, prev); - return deleted_count; - } - - iterator erase(c_iterator r) - { - BOOST_ASSERT(r.node_); - node_pointer next = next_node(r.node_); - erase_nodes(r.node_, next); - return iterator(next); - } - - iterator erase_range(c_iterator r1, c_iterator r2) - { - if (r1 == r2) return iterator(r2.node_); - erase_nodes(r1.node_, r2.node_); - return iterator(r2.node_); - } - - link_pointer erase_nodes(node_pointer i, node_pointer j) - { - std::size_t bucket_index = this->hash_to_bucket(i->hash_); - - // Split the groups containing 'i' and 'j'. - // And get the pointer to the node before i while - // we're at it. - link_pointer prev = split_groups(i, j); - - // If we don't have a 'prev' it means that i is at the - // beginning of a block, so search through the blocks in the - // same bucket. - if (!prev) { - prev = this->get_previous_start(bucket_index); - while (prev->next_ != i) - prev = next_node(prev)->group_prev_; - } - - // Delete the nodes. - do { - link_pointer group_end = next_group(next_node(prev)); - this->delete_nodes(prev, group_end); - bucket_index = this->fix_bucket(bucket_index, prev); - } while(prev->next_ != j); - - return prev; - } - - static link_pointer split_groups(node_pointer i, node_pointer j) - { - node_pointer prev = i->group_prev_; - if (prev->next_ != i) prev = node_pointer(); - - if (j) { - node_pointer first = j; - while (first != i && first->group_prev_->next_ == first) { - first = first->group_prev_; - } - - boost::swap(first->group_prev_, j->group_prev_); - if (first == i) return prev; - } - - if (prev) { - node_pointer first = prev; - while (first->group_prev_->next_ == first) { - first = first->group_prev_; - } - boost::swap(first->group_prev_, i->group_prev_); - } - - return prev; - } - - //////////////////////////////////////////////////////////////////////// - // fill_buckets - - void copy_buckets(table const& src) { - this->create_buckets(this->bucket_count_); - - for (node_pointer n = src.begin(); n;) { - std::size_t key_hash = n->hash_; - node_pointer group_end(next_group(n)); - node_pointer pos = this->add_node( - boost::unordered::detail::func::construct_node( - this->node_alloc(), n->value()), key_hash, node_pointer()); - for (n = next_node(n); n != group_end; n = next_node(n)) - { - this->add_node( - boost::unordered::detail::func::construct_node( - this->node_alloc(), n->value()), key_hash, pos); - } - } - } - - void move_buckets(table const& src) { - this->create_buckets(this->bucket_count_); - - for (node_pointer n = src.begin(); n;) { - std::size_t key_hash = n->hash_; - node_pointer group_end(next_group(n)); - node_pointer pos = this->add_node( - boost::unordered::detail::func::construct_node( - this->node_alloc(), boost::move(n->value())), key_hash, node_pointer()); - for (n = next_node(n); n != group_end; n = next_node(n)) - { - this->add_node( - boost::unordered::detail::func::construct_node( - this->node_alloc(), boost::move(n->value())), key_hash, pos); - } - } - } - - void assign_buckets(table const& src) { - node_holder holder(*this); - for (node_pointer n = src.begin(); n;) { - std::size_t key_hash = n->hash_; - node_pointer group_end(next_group(n)); - node_pointer pos = this->add_node(holder.copy_of(n->value()), key_hash, node_pointer()); - for (n = next_node(n); n != group_end; n = next_node(n)) - { - this->add_node(holder.copy_of(n->value()), key_hash, pos); - } - } - } - - void move_assign_buckets(table& src) { - node_holder holder(*this); - for (node_pointer n = src.begin(); n;) { - std::size_t key_hash = n->hash_; - node_pointer group_end(next_group(n)); - node_pointer pos = this->add_node(holder.move_copy_of(n->value()), key_hash, node_pointer()); - for (n = next_node(n); n != group_end; n = next_node(n)) - { - this->add_node(holder.move_copy_of(n->value()), key_hash, pos); - } - } - } - - // strong otherwise exception safety - void rehash_impl(std::size_t num_buckets) - { - BOOST_ASSERT(this->buckets_); - - this->create_buckets(num_buckets); - link_pointer prev = this->get_previous_start(); - while (prev->next_) - prev = place_in_bucket(*this, prev, next_node(prev)->group_prev_); - } - - // Iterate through the nodes placing them in the correct buckets. - // pre: prev->next_ is not null. - static link_pointer place_in_bucket(table& dst, - link_pointer prev, node_pointer end) - { - bucket_pointer b = dst.get_bucket(dst.hash_to_bucket(end->hash_)); - - if (!b->next_) { - b->next_ = prev; - return end; - } - else { - link_pointer next = end->next_; - end->next_ = b->next_->next_; - b->next_->next_ = prev->next_; - prev->next_ = next; - return prev; - } - } - }; -}}} - -#endif diff --git a/include/boost/unordered/detail/extract_key.hpp b/include/boost/unordered/detail/extract_key.hpp deleted file mode 100644 index 338e918c..00000000 --- a/include/boost/unordered/detail/extract_key.hpp +++ /dev/null @@ -1,188 +0,0 @@ - -// Copyright (C) 2005-2011 Daniel James -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_UNORDERED_DETAIL_EXTRACT_KEY_HPP_INCLUDED -#define BOOST_UNORDERED_DETAIL_EXTRACT_KEY_HPP_INCLUDED - -#include -#if defined(BOOST_HAS_PRAGMA_ONCE) -#pragma once -#endif - -#include - -namespace boost { -namespace unordered { -namespace detail { - - // key extractors - // - // no throw - // - // 'extract_key' is called with the emplace parameters to return a - // key if available or 'no_key' is one isn't and will need to be - // constructed. This could be done by overloading the emplace implementation - // for the different cases, but that's a bit tricky on compilers without - // variadic templates. - - struct no_key { - no_key() {} - template no_key(T const&) {} - }; - - template - struct is_key { - template - static choice1::type test(T2 const&); - static choice2::type test(Key const&); - - enum { value = sizeof(test(boost::unordered::detail::make())) == - sizeof(choice2::type) }; - - typedef typename boost::detail::if_true:: - BOOST_NESTED_TEMPLATE then::type type; - }; - - template - struct set_extractor - { - typedef ValueType value_type; - typedef ValueType key_type; - - static key_type const& extract(value_type const& v) - { - return v; - } - - static no_key extract() - { - return no_key(); - } - - template - static no_key extract(Arg const&) - { - return no_key(); - } - -#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - template - static no_key extract(Arg1 const&, Arg2 const&, Args const&...) - { - return no_key(); - } -#else - template - static no_key extract(Arg1 const&, Arg2 const&) - { - return no_key(); - } -#endif - }; - - template - struct map_extractor - { - typedef ValueType value_type; - typedef typename boost::remove_const::type key_type; - - static key_type const& extract(value_type const& v) - { - return v.first; - } - - template - static key_type const& extract(std::pair const& v) - { - return v.first; - } - - template - static key_type const& extract( - std::pair const& v) - { - return v.first; - } - - template - static key_type const& extract(key_type const& k, Arg1 const&) - { - return k; - } - - static no_key extract() - { - return no_key(); - } - - template - static no_key extract(Arg const&) - { - return no_key(); - } - - template - static no_key extract(Arg1 const&, Arg2 const&) - { - return no_key(); - } - -#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - template - static no_key extract(Arg1 const&, Arg2 const&, Arg3 const&, - Args const&...) - { - return no_key(); - } -#endif - -#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - -#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_) \ - template \ - static no_key extract(boost::unordered::piecewise_construct_t, \ - namespace_ tuple<> const&, T2 const&) \ - { \ - return no_key(); \ - } \ - \ - template \ - static typename is_key::type \ - extract(boost::unordered::piecewise_construct_t, \ - namespace_ tuple const& k, T2 const&) \ - { \ - return typename is_key::type( \ - namespace_ get<0>(k)); \ - } - -#else - -#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_) \ - static no_key extract(boost::unordered::piecewise_construct_t, \ - namespace_ tuple<> const&) \ - { \ - return no_key(); \ - } \ - \ - template \ - static typename is_key::type \ - extract(boost::unordered::piecewise_construct_t, \ - namespace_ tuple const& k) \ - { \ - return typename is_key::type( \ - namespace_ get<0>(k)); \ - } - -#endif - -BOOST_UNORDERED_KEY_FROM_TUPLE(boost::) - -#if !defined(BOOST_NO_CXX11_HDR_TUPLE) -BOOST_UNORDERED_KEY_FROM_TUPLE(std::) -#endif - }; -}}} - -#endif diff --git a/include/boost/unordered/detail/fwd.hpp b/include/boost/unordered/detail/fwd.hpp index 74419062..6a842042 100644 --- a/include/boost/unordered/detail/fwd.hpp +++ b/include/boost/unordered/detail/fwd.hpp @@ -15,21 +15,21 @@ // Already defined. #elif defined(BOOST_LIBSTDCXX11) // https://github.com/gcc-mirror/gcc/blob/gcc-4_6-branch/libstdc++-v3/include/bits/stl_pair.h#L70 -# if BOOST_LIBSTDCXX_VERSION > 40600 -# define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 1 -# endif +#if BOOST_LIBSTDCXX_VERSION > 40600 +#define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 1 +#endif #elif defined(_LIBCPP_VERSION) // https://github.com/llvm-mirror/libcxx/blob/release_30/include/utility#L206 -# if LIBCPP_VERSION >= 3000 -# define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 1 -# endif +#if LIBCPP_VERSION >= 3000 +#define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 1 +#endif #elif defined(BOOST_MSVC) // Apparently C++11 standard supported in Visual Studio 2012 // https://msdn.microsoft.com/en-us/library/hh567368.aspx#stl // 2012 = VC+11 = BOOST_MSVC 1700 Hopefully! -# if BOOST_MSVC >= 1700 -# define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 1 -# endif +#if BOOST_MSVC >= 1700 +#define BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT 1 +#endif #endif #if !defined(BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT) @@ -40,16 +40,16 @@ #include #endif -namespace boost -{ -namespace unordered -{ +namespace boost { +namespace unordered { #if BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT - using std::piecewise_construct_t; - using std::piecewise_construct; +using std::piecewise_construct_t; +using std::piecewise_construct; #else - struct piecewise_construct_t {}; - const piecewise_construct_t piecewise_construct = piecewise_construct_t(); +struct piecewise_construct_t +{ +}; +const piecewise_construct_t piecewise_construct = piecewise_construct_t(); #endif } } diff --git a/include/boost/unordered/detail/implementation.hpp b/include/boost/unordered/detail/implementation.hpp new file mode 100644 index 00000000..78850bba --- /dev/null +++ b/include/boost/unordered/detail/implementation.hpp @@ -0,0 +1,4627 @@ + +// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard. +// Copyright (C) 2005-2016 Daniel James + +#ifndef BOOST_UNORDERED_DETAIL_IMPLEMENTATION_HPP +#define BOOST_UNORDERED_DETAIL_IMPLEMENTATION_HPP + +#include +#if defined(BOOST_HAS_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(BOOST_NO_CXX11_HDR_TUPLE) +#include +#endif + +namespace boost { +namespace unordered { +namespace detail { + +static const float minimum_max_load_factor = 1e-3f; +static const std::size_t default_bucket_count = 11; +struct move_tag +{ +}; +struct empty_emplace +{ +}; + +namespace func { +template inline void ignore_unused_variable_warning(T const&) {} +} + +//////////////////////////////////////////////////////////////////////////// +// iterator SFINAE + +template +struct is_forward + : boost::is_convertible::type, + boost::forward_traversal_tag> +{ +}; + +template +struct enable_if_forward + : boost::enable_if_c::value, + ReturnType> +{ +}; + +template +struct disable_if_forward + : boost::disable_if_c::value, + ReturnType> +{ +}; + +//////////////////////////////////////////////////////////////////////////// +// primes + +// clang-format off +#define BOOST_UNORDERED_PRIMES \ + (17ul)(29ul)(37ul)(53ul)(67ul)(79ul) \ + (97ul)(131ul)(193ul)(257ul)(389ul)(521ul)(769ul) \ + (1031ul)(1543ul)(2053ul)(3079ul)(6151ul)(12289ul)(24593ul) \ + (49157ul)(98317ul)(196613ul)(393241ul)(786433ul) \ + (1572869ul)(3145739ul)(6291469ul)(12582917ul)(25165843ul) \ + (50331653ul)(100663319ul)(201326611ul)(402653189ul)(805306457ul) \ + (1610612741ul)(3221225473ul)(4294967291ul) +// clang-format on + +template struct prime_list_template +{ + static std::size_t const value[]; + +#if !defined(SUNPRO_CC) + static std::ptrdiff_t const length; +#else + static std::ptrdiff_t const length = + BOOST_PP_SEQ_SIZE(BOOST_UNORDERED_PRIMES); +#endif +}; + +template +std::size_t const prime_list_template::value[] = { + BOOST_PP_SEQ_ENUM(BOOST_UNORDERED_PRIMES)}; + +#if !defined(SUNPRO_CC) +template +std::ptrdiff_t const prime_list_template::length = BOOST_PP_SEQ_SIZE( + BOOST_UNORDERED_PRIMES); +#endif + +#undef BOOST_UNORDERED_PRIMES + +typedef prime_list_template prime_list; + +// no throw +inline std::size_t next_prime(std::size_t num) +{ + std::size_t const* const prime_list_begin = prime_list::value; + std::size_t const* const prime_list_end = + prime_list_begin + prime_list::length; + std::size_t const* bound = + std::lower_bound(prime_list_begin, prime_list_end, num); + if (bound == prime_list_end) + bound--; + return *bound; +} + +// no throw +inline std::size_t prev_prime(std::size_t num) +{ + std::size_t const* const prime_list_begin = prime_list::value; + std::size_t const* const prime_list_end = + prime_list_begin + prime_list::length; + std::size_t const* bound = + std::upper_bound(prime_list_begin, prime_list_end, num); + if (bound != prime_list_begin) + bound--; + return *bound; +} + +//////////////////////////////////////////////////////////////////////////// +// insert_size/initial_size + +template +inline std::size_t insert_size(I i, I j, + typename boost::unordered::detail::enable_if_forward::type = 0) +{ + return static_cast(std::distance(i, j)); +} + +template +inline std::size_t insert_size(I, I, + typename boost::unordered::detail::disable_if_forward::type = 0) +{ + return 1; +} + +template +inline std::size_t initial_size(I i, I j, + std::size_t num_buckets = boost::unordered::detail::default_bucket_count) +{ + // TODO: Why +1? + return (std::max)( + boost::unordered::detail::insert_size(i, j) + 1, num_buckets); +} + +//////////////////////////////////////////////////////////////////////////// +// compressed + +template struct compressed_base : private T +{ + compressed_base(T const& x) : T(x) {} + compressed_base(T& x, move_tag) : T(boost::move(x)) {} + + T& get() { return *this; } + T const& get() const { return *this; } +}; + +template struct uncompressed_base +{ + uncompressed_base(T const& x) : value_(x) {} + uncompressed_base(T& x, move_tag) : value_(boost::move(x)) {} + + T& get() { return value_; } + T const& get() const { return value_; } + private: + T value_; +}; + +template +struct generate_base + : boost::detail::if_true::value>::BOOST_NESTED_TEMPLATE + then, + boost::unordered::detail::uncompressed_base > +{ +}; + +template +struct compressed + : private boost::unordered::detail::generate_base::type, + private boost::unordered::detail::generate_base::type +{ + typedef typename generate_base::type base1; + typedef typename generate_base::type base2; + + typedef T1 first_type; + typedef T2 second_type; + + first_type& first() { return static_cast(this)->get(); } + + first_type const& first() const + { + return static_cast(this)->get(); + } + + second_type& second() { return static_cast(this)->get(); } + + second_type const& second() const + { + return static_cast(this)->get(); + } + + template + compressed(First const& x1, Second const& x2) : base1(x1), base2(x2) + { + } + + compressed(compressed const& x) : base1(x.first()), base2(x.second()) {} + + compressed(compressed& x, move_tag m) + : base1(x.first(), m), base2(x.second(), m) + { + } + + void assign(compressed const& x) + { + first() = x.first(); + second() = x.second(); + } + + void move_assign(compressed& x) + { + first() = boost::move(x.first()); + second() = boost::move(x.second()); + } + + void swap(compressed& x) + { + boost::swap(first(), x.first()); + boost::swap(second(), x.second()); + } + + private: + // Prevent assignment just to make use of assign or + // move_assign explicit. + compressed& operator=(compressed const&); +}; +} +} +} + +#if defined(BOOST_MSVC) +#pragma warning(push) +#pragma warning(disable : 4512) // assignment operator could not be generated. +#pragma warning(disable : 4345) // behavior change: an object of POD type +// constructed with an initializer of the form () +// will be default-initialized. +#endif + +// Maximum number of arguments supported by emplace + 1. +#define BOOST_UNORDERED_EMPLACE_LIMIT 11 + +namespace boost { +namespace unordered { +namespace detail { + +//////////////////////////////////////////////////////////////////////////// +// Bits and pieces for implementing traits + +template typename boost::add_lvalue_reference::type make(); +struct choice9 +{ + typedef char (&type)[9]; +}; +struct choice8 : choice9 +{ + typedef char (&type)[8]; +}; +struct choice7 : choice8 +{ + typedef char (&type)[7]; +}; +struct choice6 : choice7 +{ + typedef char (&type)[6]; +}; +struct choice5 : choice6 +{ + typedef char (&type)[5]; +}; +struct choice4 : choice5 +{ + typedef char (&type)[4]; +}; +struct choice3 : choice4 +{ + typedef char (&type)[3]; +}; +struct choice2 : choice3 +{ + typedef char (&type)[2]; +}; +struct choice1 : choice2 +{ + typedef char (&type)[1]; +}; +choice1 choose(); + +typedef choice1::type yes_type; +typedef choice2::type no_type; + +struct private_type +{ + private_type const& operator,(int) const; +}; + +template no_type is_private_type(T const&); +yes_type is_private_type(private_type const&); + +struct convert_from_anything +{ + template convert_from_anything(T const&); +}; + +namespace func { +// This is a bit nasty, when constructing the individual members +// of a std::pair, need to cast away 'const'. For modern compilers, +// should be able to use std::piecewise_construct instead. +template T* const_cast_pointer(T* x) { return x; } +template T* const_cast_pointer(T const* x) +{ + return const_cast(x); +} +} + +//////////////////////////////////////////////////////////////////////////// +// emplace_args +// +// Either forwarding variadic arguments, or storing the arguments in +// emplace_args##n + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + +#define BOOST_UNORDERED_EMPLACE_ARGS1(a0) a0 +#define BOOST_UNORDERED_EMPLACE_ARGS2(a0, a1) a0, a1 +#define BOOST_UNORDERED_EMPLACE_ARGS3(a0, a1, a2) a0, a1, a2 + +#define BOOST_UNORDERED_EMPLACE_TEMPLATE typename... Args +#define BOOST_UNORDERED_EMPLACE_ARGS BOOST_FWD_REF(Args)... args +#define BOOST_UNORDERED_EMPLACE_FORWARD boost::forward(args)... + +#else + +#define BOOST_UNORDERED_EMPLACE_ARGS1 create_emplace_args +#define BOOST_UNORDERED_EMPLACE_ARGS2 create_emplace_args +#define BOOST_UNORDERED_EMPLACE_ARGS3 create_emplace_args + +#define BOOST_UNORDERED_EMPLACE_TEMPLATE typename Args +#define BOOST_UNORDERED_EMPLACE_ARGS Args const& args +#define BOOST_UNORDERED_EMPLACE_FORWARD args + +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + +#define BOOST_UNORDERED_EARGS_MEMBER(z, n, _) \ + typedef BOOST_FWD_REF(BOOST_PP_CAT(A, n)) BOOST_PP_CAT(Arg, n); \ + BOOST_PP_CAT(Arg, n) BOOST_PP_CAT(a, n); + +#else + +#define BOOST_UNORDERED_EARGS_MEMBER(z, n, _) \ + typedef typename boost::add_lvalue_reference::type \ + BOOST_PP_CAT(Arg, n); \ + BOOST_PP_CAT(Arg, n) BOOST_PP_CAT(a, n); + +#endif + +template struct emplace_args1 +{ + BOOST_UNORDERED_EARGS_MEMBER(1, 0, _) + + emplace_args1(Arg0 b0) : a0(b0) {} +}; + +template +inline emplace_args1 create_emplace_args(BOOST_FWD_REF(A0) b0) +{ + emplace_args1 e(b0); + return e; +} + +template struct emplace_args2 +{ + BOOST_UNORDERED_EARGS_MEMBER(1, 0, _) + BOOST_UNORDERED_EARGS_MEMBER(1, 1, _) + + emplace_args2(Arg0 b0, Arg1 b1) : a0(b0), a1(b1) {} +}; + +template +inline emplace_args2 create_emplace_args( + BOOST_FWD_REF(A0) b0, BOOST_FWD_REF(A1) b1) +{ + emplace_args2 e(b0, b1); + return e; +} + +template struct emplace_args3 +{ + BOOST_UNORDERED_EARGS_MEMBER(1, 0, _) + BOOST_UNORDERED_EARGS_MEMBER(1, 1, _) + BOOST_UNORDERED_EARGS_MEMBER(1, 2, _) + + emplace_args3(Arg0 b0, Arg1 b1, Arg2 b2) : a0(b0), a1(b1), a2(b2) {} +}; + +template +inline emplace_args3 create_emplace_args( + BOOST_FWD_REF(A0) b0, BOOST_FWD_REF(A1) b1, BOOST_FWD_REF(A2) b2) +{ + emplace_args3 e(b0, b1, b2); + return e; +} + +#define BOOST_UNORDERED_FWD_PARAM(z, n, a) \ + BOOST_FWD_REF(BOOST_PP_CAT(A, n)) BOOST_PP_CAT(a, n) + +#define BOOST_UNORDERED_CALL_FORWARD(z, i, a) \ + boost::forward(BOOST_PP_CAT(a, i)) + +#define BOOST_UNORDERED_EARGS_INIT(z, n, _) \ + BOOST_PP_CAT(a, n)(BOOST_PP_CAT(b, n)) + +#define BOOST_UNORDERED_EARGS(z, n, _) \ + template \ + struct BOOST_PP_CAT(emplace_args, n) \ + { \ + BOOST_PP_REPEAT_##z(n, BOOST_UNORDERED_EARGS_MEMBER, _) BOOST_PP_CAT( \ + emplace_args, n)(BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, Arg, b)) \ + : BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_EARGS_INIT, _) \ + { \ + } \ + }; \ + \ + template \ + inline BOOST_PP_CAT(emplace_args, n) \ + create_emplace_args( \ + BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, b)) \ + { \ + BOOST_PP_CAT(emplace_args, n) e( \ + BOOST_PP_ENUM_PARAMS_Z(z, n, b)); \ + return e; \ + } + +BOOST_PP_REPEAT_FROM_TO( + 4, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_EARGS, _) + +#undef BOOST_UNORDERED_DEFINE_EMPLACE_ARGS +#undef BOOST_UNORDERED_EARGS_MEMBER +#undef BOOST_UNORDERED_EARGS_INIT + +#endif +} +} +} + +//////////////////////////////////////////////////////////////////////////////// +// +// Pick which version of allocator_traits to use +// +// 0 = Own partial implementation +// 1 = std::allocator_traits +// 2 = boost::container::allocator_traits + +#if !defined(BOOST_UNORDERED_USE_ALLOCATOR_TRAITS) +#if !defined(BOOST_NO_CXX11_ALLOCATOR) +#define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 1 +#elif defined(BOOST_MSVC) +#if BOOST_MSVC < 1400 +// Use container's allocator_traits for older versions of Visual +// C++ as I don't test with them. +#define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 2 +#endif +#endif +#endif + +#if !defined(BOOST_UNORDERED_USE_ALLOCATOR_TRAITS) +#define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 0 +#endif + +//////////////////////////////////////////////////////////////////////////////// +// +// Some utilities for implementing allocator_traits, but useful elsewhere so +// they're always defined. + +#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) +#include +#endif + +namespace boost { +namespace unordered { +namespace detail { + +//////////////////////////////////////////////////////////////////////////// +// Integral_constrant, true_type, false_type +// +// Uses the standard versions if available. + +#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) + +using std::integral_constant; +using std::true_type; +using std::false_type; + +#else + +template struct integral_constant +{ + enum + { + value = Value + }; +}; + +typedef boost::unordered::detail::integral_constant true_type; +typedef boost::unordered::detail::integral_constant false_type; + +#endif + +//////////////////////////////////////////////////////////////////////////// +// Explicitly call a destructor + +#if defined(BOOST_MSVC) +#pragma warning(push) +#pragma warning(disable : 4100) // unreferenced formal parameter +#endif + +namespace func { +template inline void destroy(T* x) { x->~T(); } +} + +#if defined(BOOST_MSVC) +#pragma warning(pop) +#endif + +//////////////////////////////////////////////////////////////////////////// +// Expression test mechanism +// +// When SFINAE expressions are available, define +// BOOST_UNORDERED_HAS_FUNCTION which can check if a function call is +// supported by a class, otherwise define BOOST_UNORDERED_HAS_MEMBER which +// can detect if a class has the specified member, but not that it has the +// correct type, this is good enough for a passable impression of +// allocator_traits. + +#if !defined(BOOST_NO_SFINAE_EXPR) + +template struct expr_test; +template struct expr_test : T +{ +}; + +#define BOOST_UNORDERED_CHECK_EXPRESSION(count, result, expression) \ + template \ + static typename boost::unordered::detail::expr_test::type \ + test(BOOST_PP_CAT(choice, count)) + +#define BOOST_UNORDERED_DEFAULT_EXPRESSION(count, result) \ + template \ + static BOOST_PP_CAT(choice, result)::type test( \ + BOOST_PP_CAT(choice, count)) + +#define BOOST_UNORDERED_HAS_FUNCTION(name, thing, args, _) \ + struct BOOST_PP_CAT(has_, name) \ + { \ + template static char for_expr_test(U const&); \ + BOOST_UNORDERED_CHECK_EXPRESSION( \ + 1, 1, boost::unordered::detail::make().name args); \ + BOOST_UNORDERED_DEFAULT_EXPRESSION(2, 2); \ + \ + enum \ + { \ + value = sizeof(test(choose())) == sizeof(choice1::type) \ + }; \ + } + +#else + +template struct identity +{ + typedef T type; +}; + +#define BOOST_UNORDERED_CHECK_MEMBER(count, result, name, member) \ + \ + typedef typename boost::unordered::detail::identity::type \ + BOOST_PP_CAT(check, count); \ + \ + template struct BOOST_PP_CAT(test, count) \ + { \ + typedef BOOST_PP_CAT(choice, result) type; \ + }; \ + \ + template \ + static typename BOOST_PP_CAT(test, count)<&U::name>::type test( \ + BOOST_PP_CAT(choice, count)) + +#define BOOST_UNORDERED_DEFAULT_MEMBER(count, result) \ + template \ + static BOOST_PP_CAT(choice, result)::type test( \ + BOOST_PP_CAT(choice, count)) + +#define BOOST_UNORDERED_HAS_MEMBER(name) \ + struct BOOST_PP_CAT(has_, name) \ + { \ + struct impl \ + { \ + struct base_mixin \ + { \ + int name; \ + }; \ + struct base : public T, public base_mixin \ + { \ + }; \ + \ + BOOST_UNORDERED_CHECK_MEMBER(1, 1, name, int base_mixin::*); \ + BOOST_UNORDERED_DEFAULT_MEMBER(2, 2); \ + \ + enum \ + { \ + value = sizeof(choice2::type) == sizeof(test(choose())) \ + }; \ + }; \ + \ + enum \ + { \ + value = impl::value \ + }; \ + } + +#endif +} +} +} + +//////////////////////////////////////////////////////////////////////////////// +// +// Allocator traits +// +// First our implementation, then later light wrappers around the alternatives + +#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 0 + +#include +#include +#include +#if defined(BOOST_NO_SFINAE_EXPR) +#include +#endif + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \ + !defined(BOOST_NO_SFINAE_EXPR) +#define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 1 +#else +#define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 0 +#endif + +namespace boost { +namespace unordered { +namespace detail { + +template struct rebind_alloc; + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + +template