2 // Copyright 2005-2011 Daniel James.
3 // Copyright 2009 Pablo Halpern.
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 // See http://www.boost.org/libs/unordered for documentation
9 #ifndef BOOST_UNORDERED_ALLOCATE_HPP
10 #define BOOST_UNORDERED_ALLOCATE_HPP
12 #include <boost/config.hpp>
13 #if defined(BOOST_HAS_PRAGMA_ONCE)
17 // Some of these includes are required for other detail headers.
18 #include <boost/unordered/detail/fwd.hpp>
19 #include <boost/move/move.hpp>
20 #include <boost/preprocessor/cat.hpp>
21 #include <boost/preprocessor/repetition/enum.hpp>
22 #include <boost/preprocessor/repetition/enum_params.hpp>
23 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
24 #include <boost/preprocessor/repetition/repeat_from_to.hpp>
25 #include <boost/type_traits/is_class.hpp>
26 #include <boost/type_traits/add_lvalue_reference.hpp>
27 #include <boost/type_traits/aligned_storage.hpp>
28 #include <boost/type_traits/alignment_of.hpp>
29 #include <boost/type_traits/is_nothrow_move_constructible.hpp>
30 #include <boost/type_traits/is_nothrow_move_assignable.hpp>
31 #include <boost/tuple/tuple.hpp>
32 #include <boost/utility/enable_if.hpp>
33 #include <boost/utility/addressof.hpp>
34 #include <boost/detail/no_exceptions_support.hpp>
35 #include <boost/detail/select_type.hpp>
36 #include <boost/swap.hpp>
37 #include <boost/assert.hpp>
38 #include <boost/limits.hpp>
43 #if !defined(BOOST_NO_CXX11_HDR_TUPLE)
47 #if defined(BOOST_MSVC)
49 #pragma warning(disable:4512) // assignment operator could not be generated.
50 #pragma warning(disable:4345) // behavior change: an object of POD type
51 // constructed with an initializer of the form ()
52 // will be default-initialized.
55 #define BOOST_UNORDERED_EMPLACE_LIMIT 10
57 namespace boost { namespace unordered { namespace detail {
59 ////////////////////////////////////////////////////////////////////////////
60 // Bits and pieces for implementing traits
62 template <typename T> typename boost::add_lvalue_reference<T>::type make();
63 struct choice9 { typedef char (&type)[9]; };
64 struct choice8 : choice9 { typedef char (&type)[8]; };
65 struct choice7 : choice8 { typedef char (&type)[7]; };
66 struct choice6 : choice7 { typedef char (&type)[6]; };
67 struct choice5 : choice6 { typedef char (&type)[5]; };
68 struct choice4 : choice5 { typedef char (&type)[4]; };
69 struct choice3 : choice4 { typedef char (&type)[3]; };
70 struct choice2 : choice3 { typedef char (&type)[2]; };
71 struct choice1 : choice2 { typedef char (&type)[1]; };
74 typedef choice1::type yes_type;
75 typedef choice2::type no_type;
79 private_type const &operator,(int) const;
83 no_type is_private_type(T const&);
84 yes_type is_private_type(private_type const&);
86 struct convert_from_anything {
88 convert_from_anything(T const&);
92 // This is a bit nasty, when constructing the individual members
93 // of a std::pair, need to cast away 'const'. For modern compilers,
94 // should be able to use std::piecewise_construct instead.
95 template <typename T> T* const_cast_pointer(T* x) { return x; }
96 template <typename T> T* const_cast_pointer(T const* x) {
97 return const_cast<T*>(x);
101 ////////////////////////////////////////////////////////////////////////////
104 // Either forwarding variadic arguments, or storing the arguments in
107 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
109 #define BOOST_UNORDERED_EMPLACE_ARGS1(a0) a0
110 #define BOOST_UNORDERED_EMPLACE_ARGS2(a0, a1) a0, a1
111 #define BOOST_UNORDERED_EMPLACE_ARGS3(a0, a1, a2) a0, a1, a2
113 #define BOOST_UNORDERED_EMPLACE_TEMPLATE typename... Args
114 #define BOOST_UNORDERED_EMPLACE_ARGS BOOST_FWD_REF(Args)... args
115 #define BOOST_UNORDERED_EMPLACE_FORWARD boost::forward<Args>(args)...
119 #define BOOST_UNORDERED_EMPLACE_ARGS1 create_emplace_args
120 #define BOOST_UNORDERED_EMPLACE_ARGS2 create_emplace_args
121 #define BOOST_UNORDERED_EMPLACE_ARGS3 create_emplace_args
123 #define BOOST_UNORDERED_EMPLACE_TEMPLATE typename Args
124 #define BOOST_UNORDERED_EMPLACE_ARGS Args const& args
125 #define BOOST_UNORDERED_EMPLACE_FORWARD args
127 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
129 #define BOOST_UNORDERED_EARGS_MEMBER(z, n, _) \
130 typedef BOOST_FWD_REF(BOOST_PP_CAT(A, n)) BOOST_PP_CAT(Arg, n); \
131 BOOST_PP_CAT(Arg, n) BOOST_PP_CAT(a, n);
135 #define BOOST_UNORDERED_EARGS_MEMBER(z, n, _) \
136 typedef typename boost::add_lvalue_reference<BOOST_PP_CAT(A, n)>::type \
137 BOOST_PP_CAT(Arg, n); \
138 BOOST_PP_CAT(Arg, n) BOOST_PP_CAT(a, n);
142 template <typename A0>
145 BOOST_UNORDERED_EARGS_MEMBER(1, 0, _)
147 emplace_args1(Arg0 b0) : a0(b0) {}
150 template <typename A0>
151 inline emplace_args1<A0> create_emplace_args(
152 BOOST_FWD_REF(A0) b0)
154 emplace_args1<A0> e(b0);
158 template <typename A0, typename A1>
161 BOOST_UNORDERED_EARGS_MEMBER(1, 0, _)
162 BOOST_UNORDERED_EARGS_MEMBER(1, 1, _)
164 emplace_args2(Arg0 b0, Arg1 b1) : a0(b0), a1(b1) {}
167 template <typename A0, typename A1>
168 inline emplace_args2<A0, A1> create_emplace_args(
169 BOOST_FWD_REF(A0) b0,
170 BOOST_FWD_REF(A1) b1)
172 emplace_args2<A0, A1> e(b0, b1);
176 template <typename A0, typename A1, typename A2>
179 BOOST_UNORDERED_EARGS_MEMBER(1, 0, _)
180 BOOST_UNORDERED_EARGS_MEMBER(1, 1, _)
181 BOOST_UNORDERED_EARGS_MEMBER(1, 2, _)
183 emplace_args3(Arg0 b0, Arg1 b1, Arg2 b2) : a0(b0), a1(b1), a2(b2) {}
186 template <typename A0, typename A1, typename A2>
187 inline emplace_args3<A0, A1, A2> create_emplace_args(
188 BOOST_FWD_REF(A0) b0,
189 BOOST_FWD_REF(A1) b1,
190 BOOST_FWD_REF(A2) b2)
192 emplace_args3<A0, A1, A2> e(b0, b1, b2);
196 #define BOOST_UNORDERED_FWD_PARAM(z, n, a) \
197 BOOST_FWD_REF(BOOST_PP_CAT(A, n)) BOOST_PP_CAT(a, n)
199 #define BOOST_UNORDERED_CALL_FORWARD(z, i, a) \
200 boost::forward<BOOST_PP_CAT(A,i)>(BOOST_PP_CAT(a,i))
202 #define BOOST_UNORDERED_EARGS_INIT(z, n, _) \
203 BOOST_PP_CAT(a, n)(BOOST_PP_CAT(b, n))
205 #define BOOST_UNORDERED_EARGS(z, n, _) \
206 template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
207 struct BOOST_PP_CAT(emplace_args, n) \
209 BOOST_PP_REPEAT_##z(n, BOOST_UNORDERED_EARGS_MEMBER, _) \
210 BOOST_PP_CAT(emplace_args, n) ( \
211 BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, Arg, b) \
212 ) : BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_EARGS_INIT, _) \
217 template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
218 inline BOOST_PP_CAT(emplace_args, n) < \
219 BOOST_PP_ENUM_PARAMS_Z(z, n, A) \
220 > create_emplace_args( \
221 BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, b) \
224 BOOST_PP_CAT(emplace_args, n) < \
225 BOOST_PP_ENUM_PARAMS_Z(z, n, A) \
226 > e(BOOST_PP_ENUM_PARAMS_Z(z, n, b)); \
230 BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_EARGS,
233 #undef BOOST_UNORDERED_DEFINE_EMPLACE_ARGS
234 #undef BOOST_UNORDERED_EARGS_MEMBER
235 #undef BOOST_UNORDERED_EARGS_INIT
241 ////////////////////////////////////////////////////////////////////////////////
243 // Pick which version of allocator_traits to use
245 // 0 = Own partial implementation
246 // 1 = std::allocator_traits
247 // 2 = boost::container::allocator_traits
249 #if !defined(BOOST_UNORDERED_USE_ALLOCATOR_TRAITS)
250 # if !defined(BOOST_NO_CXX11_ALLOCATOR)
251 # define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 1
252 # elif defined(BOOST_MSVC)
253 # if BOOST_MSVC < 1400
254 // Use container's allocator_traits for older versions of Visual
255 // C++ as I don't test with them.
256 # define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 2
261 #if !defined(BOOST_UNORDERED_USE_ALLOCATOR_TRAITS)
262 # define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 0
265 ////////////////////////////////////////////////////////////////////////////////
267 // Some utilities for implementing allocator_traits, but useful elsewhere so
268 // they're always defined.
270 #if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
271 # include <type_traits>
274 namespace boost { namespace unordered { namespace detail {
276 ////////////////////////////////////////////////////////////////////////////
277 // Integral_constrant, true_type, false_type
279 // Uses the standard versions if available.
281 #if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
283 using std::integral_constant;
284 using std::true_type;
285 using std::false_type;
289 template <typename T, T Value>
290 struct integral_constant { enum { value = Value }; };
292 typedef boost::unordered::detail::integral_constant<bool, true> true_type;
293 typedef boost::unordered::detail::integral_constant<bool, false> false_type;
297 ////////////////////////////////////////////////////////////////////////////
298 // Explicitly call a destructor
300 #if defined(BOOST_MSVC)
301 #pragma warning(push)
302 #pragma warning(disable:4100) // unreferenced formal parameter
307 inline void destroy(T* x) {
312 #if defined(BOOST_MSVC)
316 ////////////////////////////////////////////////////////////////////////////
317 // Expression test mechanism
319 // When SFINAE expressions are available, define
320 // BOOST_UNORDERED_HAS_FUNCTION which can check if a function call is
321 // supported by a class, otherwise define BOOST_UNORDERED_HAS_MEMBER which
322 // can detect if a class has the specified member, but not that it has the
323 // correct type, this is good enough for a passable impression of
326 #if !defined(BOOST_NO_SFINAE_EXPR)
328 template <typename T, long unsigned int> struct expr_test;
329 template <typename T> struct expr_test<T, sizeof(char)> : T {};
331 # define BOOST_UNORDERED_CHECK_EXPRESSION(count, result, expression) \
332 template <typename U> \
333 static typename boost::unordered::detail::expr_test< \
334 BOOST_PP_CAT(choice, result), \
335 sizeof(for_expr_test(( \
338 BOOST_PP_CAT(choice, count))
340 # define BOOST_UNORDERED_DEFAULT_EXPRESSION(count, result) \
341 template <typename U> \
342 static BOOST_PP_CAT(choice, result)::type test( \
343 BOOST_PP_CAT(choice, count))
345 # define BOOST_UNORDERED_HAS_FUNCTION(name, thing, args, _) \
346 struct BOOST_PP_CAT(has_, name) \
348 template <typename U> static char for_expr_test(U const&); \
349 BOOST_UNORDERED_CHECK_EXPRESSION(1, 1, \
350 boost::unordered::detail::make< thing >().name args); \
351 BOOST_UNORDERED_DEFAULT_EXPRESSION(2, 2); \
353 enum { value = sizeof(test<T>(choose())) == sizeof(choice1::type) };\
358 template <typename T> struct identity { typedef T type; };
360 # define BOOST_UNORDERED_CHECK_MEMBER(count, result, name, member) \
362 typedef typename boost::unordered::detail::identity<member>::type \
363 BOOST_PP_CAT(check, count); \
365 template <BOOST_PP_CAT(check, count) e> \
366 struct BOOST_PP_CAT(test, count) { \
367 typedef BOOST_PP_CAT(choice, result) type; \
370 template <class U> static typename \
371 BOOST_PP_CAT(test, count)<&U::name>::type \
372 test(BOOST_PP_CAT(choice, count))
374 # define BOOST_UNORDERED_DEFAULT_MEMBER(count, result) \
375 template <class U> static BOOST_PP_CAT(choice, result)::type \
376 test(BOOST_PP_CAT(choice, count))
378 # define BOOST_UNORDERED_HAS_MEMBER(name) \
379 struct BOOST_PP_CAT(has_, name) \
382 struct base_mixin { int name; }; \
383 struct base : public T, public base_mixin {}; \
385 BOOST_UNORDERED_CHECK_MEMBER(1, 1, name, int base_mixin::*); \
386 BOOST_UNORDERED_DEFAULT_MEMBER(2, 2); \
388 enum { value = sizeof(choice2::type) == \
389 sizeof(test<base>(choose())) \
393 enum { value = impl::value }; \
400 ////////////////////////////////////////////////////////////////////////////////
404 // First our implementation, then later light wrappers around the alternatives
406 #if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 0
408 # include <boost/limits.hpp>
409 # include <boost/utility/enable_if.hpp>
410 # include <boost/pointer_to_other.hpp>
411 # if defined(BOOST_NO_SFINAE_EXPR)
412 # include <boost/type_traits/is_same.hpp>
415 # if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
416 !defined(BOOST_NO_SFINAE_EXPR)
417 # define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 1
419 # define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 0
422 namespace boost { namespace unordered { namespace detail {
424 template <typename Alloc, typename T>
427 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
429 template <template<typename, typename...> class Alloc,
430 typename U, typename T, typename... Args>
431 struct rebind_alloc<Alloc<U, Args...>, T>
433 typedef Alloc<T, Args...> type;
439 template<typename> class Alloc,
440 typename U, typename T>
441 struct rebind_alloc<Alloc<U>, T>
443 typedef Alloc<T> type;
447 template<typename, typename> class Alloc,
448 typename U, typename T,
450 struct rebind_alloc<Alloc<U, A0>, T>
452 typedef Alloc<T, A0> type;
456 template<typename, typename, typename> class Alloc,
457 typename U, typename T,
458 typename A0, typename A1>
459 struct rebind_alloc<Alloc<U, A0, A1>, T>
461 typedef Alloc<T, A0, A1> type;
466 template <typename Alloc, typename T>
469 template <typename X>
470 static choice1::type test(choice1,
471 typename X::BOOST_NESTED_TEMPLATE rebind<T>::other* = 0);
472 template <typename X>
473 static choice2::type test(choice2, void* = 0);
475 enum { value = (1 == sizeof(test<Alloc>(choose()))) };
478 template <typename U>
480 typedef typename rebind_alloc<Alloc, T>::type other;
484 typedef typename boost::detail::if_true<value>::
485 BOOST_NESTED_TEMPLATE then<Alloc, fallback>
486 ::type::BOOST_NESTED_TEMPLATE rebind<T>::other type;
489 # if defined(BOOST_MSVC) && BOOST_MSVC <= 1400
491 # define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \
492 template <typename Tp, typename Default> \
493 struct default_type_ ## tname { \
495 template <typename X> \
496 static choice1::type test(choice1, typename X::tname* = 0); \
498 template <typename X> \
499 static choice2::type test(choice2, void* = 0); \
501 struct DefaultWrap { typedef Default tname; }; \
503 enum { value = (1 == sizeof(test<Tp>(choose()))) }; \
505 typedef typename boost::detail::if_true<value>:: \
506 BOOST_NESTED_TEMPLATE then<Tp, DefaultWrap> \
507 ::type::tname type; \
512 template <typename T, typename T2>
513 struct sfinae : T2 {};
515 # define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \
516 template <typename Tp, typename Default> \
517 struct default_type_ ## tname { \
519 template <typename X> \
520 static typename boost::unordered::detail::sfinae< \
521 typename X::tname, choice1>::type \
524 template <typename X> \
525 static choice2::type test(choice2); \
527 struct DefaultWrap { typedef Default tname; }; \
529 enum { value = (1 == sizeof(test<Tp>(choose()))) }; \
531 typedef typename boost::detail::if_true<value>:: \
532 BOOST_NESTED_TEMPLATE then<Tp, DefaultWrap> \
533 ::type::tname type; \
538 # define BOOST_UNORDERED_DEFAULT_TYPE(T,tname, arg) \
539 typename default_type_ ## tname<T, arg>::type
541 BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(pointer);
542 BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(const_pointer);
543 BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(void_pointer);
544 BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(const_void_pointer);
545 BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(difference_type);
546 BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(size_type);
547 BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_copy_assignment);
548 BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_move_assignment);
549 BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_swap);
551 # if !defined(BOOST_NO_SFINAE_EXPR)
553 template <typename T>
554 BOOST_UNORDERED_HAS_FUNCTION(
555 select_on_container_copy_construction, U const, (), 0
558 template <typename T>
559 BOOST_UNORDERED_HAS_FUNCTION(
560 max_size, U const, (), 0
563 # if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
565 template <typename T, typename ValueType, typename... Args>
566 BOOST_UNORDERED_HAS_FUNCTION(
568 boost::unordered::detail::make<ValueType*>(),
569 boost::unordered::detail::make<Args const>()...), 2
574 template <typename T, typename ValueType>
575 BOOST_UNORDERED_HAS_FUNCTION(
577 boost::unordered::detail::make<ValueType*>(),
578 boost::unordered::detail::make<ValueType const>()), 2
583 template <typename T, typename ValueType>
584 BOOST_UNORDERED_HAS_FUNCTION(
585 destroy, U, (boost::unordered::detail::make<ValueType*>()), 1
590 template <typename T>
591 BOOST_UNORDERED_HAS_MEMBER(select_on_container_copy_construction);
593 template <typename T>
594 BOOST_UNORDERED_HAS_MEMBER(max_size);
596 template <typename T, typename ValueType>
597 BOOST_UNORDERED_HAS_MEMBER(construct);
599 template <typename T, typename ValueType>
600 BOOST_UNORDERED_HAS_MEMBER(destroy);
607 template <typename Alloc>
608 inline Alloc call_select_on_container_copy_construction(const Alloc& rhs,
609 typename boost::enable_if_c<
610 boost::unordered::detail::
611 has_select_on_container_copy_construction<Alloc>::value, void*
614 return rhs.select_on_container_copy_construction();
617 template <typename Alloc>
618 inline Alloc call_select_on_container_copy_construction(const Alloc& rhs,
619 typename boost::disable_if_c<
620 boost::unordered::detail::
621 has_select_on_container_copy_construction<Alloc>::value, void*
627 template <typename SizeType, typename Alloc>
628 inline SizeType call_max_size(const Alloc& a,
629 typename boost::enable_if_c<
630 boost::unordered::detail::has_max_size<Alloc>::value, void*
636 template <typename SizeType, typename Alloc>
637 inline SizeType call_max_size(const Alloc&, typename boost::disable_if_c<
638 boost::unordered::detail::has_max_size<Alloc>::value, void*
641 return (std::numeric_limits<SizeType>::max)();
646 template <typename Alloc>
647 struct allocator_traits
649 typedef Alloc allocator_type;
650 typedef typename Alloc::value_type value_type;
652 typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, pointer, value_type*)
655 template <typename T>
656 struct pointer_to_other : boost::pointer_to_other<pointer, T> {};
658 typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_pointer,
659 typename pointer_to_other<const value_type>::type)
662 //typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, void_pointer,
663 // typename pointer_to_other<void>::type)
666 //typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_void_pointer,
667 // typename pointer_to_other<const void>::type)
668 // const_void_pointer;
670 typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, difference_type,
671 std::ptrdiff_t) difference_type;
673 typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, size_type, std::size_t)
676 #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
677 template <typename T>
678 using rebind_alloc = typename rebind_wrap<Alloc, T>::type;
680 template <typename T>
681 using rebind_traits =
682 boost::unordered::detail::allocator_traits<rebind_alloc<T> >;
685 static pointer allocate(Alloc& a, size_type n)
686 { return a.allocate(n); }
688 // I never use this, so I'll just comment it out for now.
690 //static pointer allocate(Alloc& a, size_type n,
691 // const_void_pointer hint)
692 // { return DEFAULT_FUNC(allocate, pointer)(a, n, hint); }
694 static void deallocate(Alloc& a, pointer p, size_type n)
695 { a.deallocate(p, n); }
699 # if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
701 template <typename T, typename... Args>
702 static typename boost::enable_if_c<
703 boost::unordered::detail::has_construct<Alloc, T, Args...>
705 construct(Alloc& a, T* p, BOOST_FWD_REF(Args)... x)
707 a.construct(p, boost::forward<Args>(x)...);
710 template <typename T, typename... Args>
711 static typename boost::disable_if_c<
712 boost::unordered::detail::has_construct<Alloc, T, Args...>
714 construct(Alloc&, T* p, BOOST_FWD_REF(Args)... x)
716 new (static_cast<void*>(p)) T(boost::forward<Args>(x)...);
719 template <typename T>
720 static typename boost::enable_if_c<
721 boost::unordered::detail::has_destroy<Alloc, T>::value>::type
722 destroy(Alloc& a, T* p)
727 template <typename T>
728 static typename boost::disable_if_c<
729 boost::unordered::detail::has_destroy<Alloc, T>::value>::type
730 destroy(Alloc&, T* p)
732 boost::unordered::detail::func::destroy(p);
735 # elif !defined(BOOST_NO_SFINAE_EXPR)
737 template <typename T>
738 static typename boost::enable_if_c<
739 boost::unordered::detail::has_construct<Alloc, T>::value>::type
740 construct(Alloc& a, T* p, T const& x)
745 template <typename T>
746 static typename boost::disable_if_c<
747 boost::unordered::detail::has_construct<Alloc, T>::value>::type
748 construct(Alloc&, T* p, T const& x)
750 new (static_cast<void*>(p)) T(x);
753 template <typename T>
754 static typename boost::enable_if_c<
755 boost::unordered::detail::has_destroy<Alloc, T>::value>::type
756 destroy(Alloc& a, T* p)
761 template <typename T>
762 static typename boost::disable_if_c<
763 boost::unordered::detail::has_destroy<Alloc, T>::value>::type
764 destroy(Alloc&, T* p)
766 boost::unordered::detail::func::destroy(p);
771 // If we don't have SFINAE expressions, only call construct for the
772 // copy constructor for the allocator's value_type - as that's
773 // the only construct method that old fashioned allocators support.
775 template <typename T>
776 static void construct(Alloc& a, T* p, T const& x,
777 typename boost::enable_if_c<
778 boost::unordered::detail::has_construct<Alloc, T>::value &&
779 boost::is_same<T, value_type>::value,
785 template <typename T>
786 static void construct(Alloc&, T* p, T const& x,
787 typename boost::disable_if_c<
788 boost::unordered::detail::has_construct<Alloc, T>::value &&
789 boost::is_same<T, value_type>::value,
792 new (static_cast<void*>(p)) T(x);
795 template <typename T>
796 static void destroy(Alloc& a, T* p,
797 typename boost::enable_if_c<
798 boost::unordered::detail::has_destroy<Alloc, T>::value &&
799 boost::is_same<T, value_type>::value,
805 template <typename T>
806 static void destroy(Alloc&, T* p,
807 typename boost::disable_if_c<
808 boost::unordered::detail::has_destroy<Alloc, T>::value &&
809 boost::is_same<T, value_type>::value,
812 boost::unordered::detail::func::destroy(p);
817 static size_type max_size(const Alloc& a)
819 return boost::unordered::detail::func::
820 call_max_size<size_type>(a);
823 // Allocator propagation on construction
825 static Alloc select_on_container_copy_construction(Alloc const& rhs)
827 return boost::unordered::detail::func::
828 call_select_on_container_copy_construction(rhs);
831 // Allocator propagation on assignment and swap.
832 // Return true if lhs is modified.
833 typedef BOOST_UNORDERED_DEFAULT_TYPE(
834 Alloc, propagate_on_container_copy_assignment, false_type)
835 propagate_on_container_copy_assignment;
836 typedef BOOST_UNORDERED_DEFAULT_TYPE(
837 Alloc,propagate_on_container_move_assignment, false_type)
838 propagate_on_container_move_assignment;
839 typedef BOOST_UNORDERED_DEFAULT_TYPE(
840 Alloc,propagate_on_container_swap,false_type)
841 propagate_on_container_swap;
845 # undef BOOST_UNORDERED_DEFAULT_TYPE_TMPLT
846 # undef BOOST_UNORDERED_DEFAULT_TYPE
848 ////////////////////////////////////////////////////////////////////////////////
850 // std::allocator_traits
852 #elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
856 # define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 1
858 namespace boost { namespace unordered { namespace detail {
860 template <typename Alloc>
861 struct allocator_traits : std::allocator_traits<Alloc> {};
863 template <typename Alloc, typename T>
866 typedef typename std::allocator_traits<Alloc>::
867 template rebind_alloc<T> type;
871 ////////////////////////////////////////////////////////////////////////////////
873 // boost::container::allocator_traits
875 #elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 2
877 # include <boost/container/allocator_traits.hpp>
879 # define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 0
881 namespace boost { namespace unordered { namespace detail {
883 template <typename Alloc>
884 struct allocator_traits :
885 boost::container::allocator_traits<Alloc> {};
887 template <typename Alloc, typename T>
889 boost::container::allocator_traits<Alloc>::
890 template portable_rebind_alloc<T>
897 #error "Invalid BOOST_UNORDERED_USE_ALLOCATOR_TRAITS value."
902 namespace boost { namespace unordered { namespace detail { namespace func {
904 ////////////////////////////////////////////////////////////////////////////
907 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
909 # if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
911 template <typename Alloc, typename T, typename... Args>
912 inline void call_construct(Alloc& alloc, T* address,
913 BOOST_FWD_REF(Args)... args)
915 boost::unordered::detail::allocator_traits<Alloc>::construct(alloc,
916 address, boost::forward<Args>(args)...);
919 template <typename Alloc, typename T>
920 inline void call_destroy(Alloc& alloc, T* x) {
921 boost::unordered::detail::allocator_traits<Alloc>::destroy(alloc, x);
927 template <typename Alloc, typename T, typename... Args>
928 inline void call_construct(Alloc&, T* address,
929 BOOST_FWD_REF(Args)... args)
931 new((void*) address) T(boost::forward<Args>(args)...);
934 template <typename Alloc, typename T>
935 inline void call_destroy(Alloc&, T* x) {
936 boost::unordered::detail::func::destroy(x);
943 template <typename Alloc, typename T>
944 inline void call_construct(Alloc&, T* address)
946 new ((void*) address) T();
949 template <typename Alloc, typename T, typename A0>
950 inline void call_construct(Alloc&, T* address,
951 BOOST_FWD_REF(A0) a0)
953 new ((void*) address) T(boost::forward<A0>(a0));
956 template <typename Alloc, typename T>
957 inline void call_destroy(Alloc&, T* x) {
958 boost::unordered::detail::func::destroy(x);
963 ////////////////////////////////////////////////////////////////////////////
964 // Construct from tuple
966 // Used for piecewise construction.
968 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
970 # define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \
971 template<typename Alloc, typename T> \
972 void construct_from_tuple(Alloc& alloc, T* ptr, namespace_ tuple<>) \
974 boost::unordered::detail::func::call_construct(alloc, ptr); \
977 BOOST_PP_REPEAT_FROM_TO(1, n, \
978 BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_)
980 # define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_) \
981 template<typename Alloc, typename T, \
982 BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
983 void construct_from_tuple(Alloc& alloc, T* ptr, \
984 namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
986 boost::unordered::detail::func::call_construct(alloc, ptr, \
987 BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \
991 # define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) \
994 #elif !defined(__SUNPRO_CC)
996 # define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \
997 template<typename Alloc, typename T> \
998 void construct_from_tuple(Alloc&, T* ptr, namespace_ tuple<>) \
1000 new ((void*) ptr) T(); \
1003 BOOST_PP_REPEAT_FROM_TO(1, n, \
1004 BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_)
1006 # define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_) \
1007 template<typename Alloc, typename T, \
1008 BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
1009 void construct_from_tuple(Alloc&, T* ptr, \
1010 namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
1012 new ((void*) ptr) T( \
1013 BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \
1017 # define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) \
1018 namespace_ get<n>(x)
1022 template <int N> struct length {};
1024 # define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \
1025 template<typename Alloc, typename T> \
1026 void construct_from_tuple_impl( \
1027 boost::unordered::detail::func::length<0>, Alloc&, T* ptr, \
1028 namespace_ tuple<>) \
1030 new ((void*) ptr) T(); \
1033 BOOST_PP_REPEAT_FROM_TO(1, n, \
1034 BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_)
1036 # define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_) \
1037 template<typename Alloc, typename T, \
1038 BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
1039 void construct_from_tuple_impl( \
1040 boost::unordered::detail::func::length<n>, Alloc&, T* ptr, \
1041 namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
1043 new ((void*) ptr) T( \
1044 BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \
1048 # define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) \
1049 namespace_ get<n>(x)
1053 BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
1055 #if !defined(__SUNPRO_CC) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
1056 BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std::)
1059 #undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE
1060 #undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL
1061 #undef BOOST_UNORDERED_GET_TUPLE_ARG
1063 #if defined(__SUNPRO_CC)
1065 template <typename Alloc, typename T, typename Tuple>
1066 void construct_from_tuple(Alloc& alloc, T* ptr, Tuple const& x)
1068 construct_from_tuple_impl(
1069 boost::unordered::detail::func::length<
1070 boost::tuples::length<Tuple>::value>(),
1076 ////////////////////////////////////////////////////////////////////////////
1077 // Trait to check for piecewise construction.
1079 template <typename A0>
1080 struct use_piecewise {
1081 static choice1::type test(choice1,
1082 boost::unordered::piecewise_construct_t);
1084 static choice2::type test(choice2, ...);
1086 enum { value = sizeof(choice1::type) ==
1087 sizeof(test(choose(), boost::unordered::detail::make<A0>())) };
1090 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1092 ////////////////////////////////////////////////////////////////////////////
1093 // Construct from variadic parameters
1095 // For the standard pair constructor.
1097 template <typename Alloc, typename T, typename... Args>
1098 inline void construct_from_args(Alloc& alloc, T* address,
1099 BOOST_FWD_REF(Args)... args)
1101 boost::unordered::detail::func::call_construct(alloc,
1102 address, boost::forward<Args>(args)...);
1105 // Special case for piece_construct
1107 // TODO: When possible, it might be better to use std::pair's
1108 // constructor for std::piece_construct with std::tuple.
1110 template <typename Alloc, typename A, typename B,
1111 typename A0, typename A1, typename A2>
1112 inline typename enable_if<use_piecewise<A0>, void>::type
1113 construct_from_args(Alloc& alloc, std::pair<A, B>* address,
1114 BOOST_FWD_REF(A0), BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
1116 boost::unordered::detail::func::construct_from_tuple(alloc,
1117 boost::unordered::detail::func::const_cast_pointer(
1118 boost::addressof(address->first)),
1119 boost::forward<A1>(a1));
1120 boost::unordered::detail::func::construct_from_tuple(alloc,
1121 boost::unordered::detail::func::const_cast_pointer(
1122 boost::addressof(address->second)),
1123 boost::forward<A2>(a2));
1126 #else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
1128 ////////////////////////////////////////////////////////////////////////////
1129 // Construct from emplace_args
1131 // Explicitly write out first three overloads for the sake of sane
1134 template <typename Alloc, typename T, typename A0>
1135 inline void construct_from_args(Alloc&, T* address,
1136 emplace_args1<A0> const& args)
1138 new((void*) address) T(boost::forward<A0>(args.a0));
1141 template <typename Alloc, typename T, typename A0, typename A1>
1142 inline void construct_from_args(Alloc&, T* address,
1143 emplace_args2<A0, A1> const& args)
1145 new((void*) address) T(
1146 boost::forward<A0>(args.a0),
1147 boost::forward<A1>(args.a1)
1151 template <typename Alloc, typename T, typename A0, typename A1, typename A2>
1152 inline void construct_from_args(Alloc&, T* address,
1153 emplace_args3<A0, A1, A2> const& args)
1155 new((void*) address) T(
1156 boost::forward<A0>(args.a0),
1157 boost::forward<A1>(args.a1),
1158 boost::forward<A2>(args.a2)
1162 // Use a macro for the rest.
1164 #define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _) \
1166 typename Alloc, typename T, \
1167 BOOST_PP_ENUM_PARAMS_Z(z, num_params, typename A) \
1169 inline void construct_from_args(Alloc&, T* address, \
1170 boost::unordered::detail::BOOST_PP_CAT(emplace_args,num_params) < \
1171 BOOST_PP_ENUM_PARAMS_Z(z, num_params, A) \
1174 new((void*) address) T( \
1175 BOOST_PP_ENUM_##z(num_params, BOOST_UNORDERED_CALL_FORWARD, \
1179 BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
1180 BOOST_UNORDERED_CONSTRUCT_IMPL, _)
1182 #undef BOOST_UNORDERED_CONSTRUCT_IMPL
1184 // Construct with piece_construct
1186 template <typename Alloc, typename A, typename B,
1187 typename A0, typename A1, typename A2>
1188 inline void construct_from_args(Alloc& alloc, std::pair<A, B>* address,
1189 boost::unordered::detail::emplace_args3<A0, A1, A2> const& args,
1190 typename enable_if<use_piecewise<A0>, void*>::type = 0)
1192 boost::unordered::detail::func::construct_from_tuple(alloc,
1193 boost::unordered::detail::func::const_cast_pointer(
1194 boost::addressof(address->first)),
1196 boost::unordered::detail::func::construct_from_tuple(alloc,
1197 boost::unordered::detail::func::const_cast_pointer(
1198 boost::addressof(address->second)),
1202 #endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
1206 namespace boost { namespace unordered { namespace detail {
1208 ///////////////////////////////////////////////////////////////////
1210 // Node construction
1212 template <typename NodeAlloc>
1213 struct node_constructor
1215 typedef NodeAlloc node_allocator;
1216 typedef boost::unordered::detail::allocator_traits<NodeAlloc>
1217 node_allocator_traits;
1218 typedef typename node_allocator_traits::value_type node;
1219 typedef typename node_allocator_traits::pointer node_pointer;
1220 typedef typename node::value_type value_type;
1222 node_allocator& alloc_;
1224 bool node_constructed_;
1226 node_constructor(node_allocator& n) :
1229 node_constructed_(false)
1233 ~node_constructor();
1238 node_pointer release()
1240 BOOST_ASSERT(node_ && node_constructed_);
1241 node_pointer p = node_;
1242 node_ = node_pointer();
1246 void reclaim(node_pointer p) {
1247 BOOST_ASSERT(!node_);
1249 node_constructed_ = true;
1250 boost::unordered::detail::func::call_destroy(alloc_,
1251 node_->value_ptr());
1255 node_constructor(node_constructor const&);
1256 node_constructor& operator=(node_constructor const&);
1259 template <typename Alloc>
1260 node_constructor<Alloc>::~node_constructor()
1263 if (node_constructed_) {
1264 boost::unordered::detail::func::destroy(
1265 boost::addressof(*node_));
1268 node_allocator_traits::deallocate(alloc_, node_, 1);
1272 template <typename Alloc>
1273 void node_constructor<Alloc>::create_node()
1275 BOOST_ASSERT(!node_);
1276 node_constructed_ = false;
1278 node_ = node_allocator_traits::allocate(alloc_, 1);
1280 new ((void*) boost::addressof(*node_)) node();
1282 node_constructed_ = true;
1285 template <typename NodeAlloc>
1288 typedef boost::unordered::detail::allocator_traits<NodeAlloc>
1289 node_allocator_traits;
1290 typedef typename node_allocator_traits::pointer node_pointer;
1295 explicit node_tmp(node_pointer n, NodeAlloc& a):
1304 node_pointer release()
1306 node_pointer p = node_;
1307 node_ = node_pointer();
1312 template <typename Alloc>
1313 node_tmp<Alloc>::~node_tmp()
1316 boost::unordered::detail::func::call_destroy(alloc_,
1317 node_->value_ptr());
1318 boost::unordered::detail::func::destroy(
1319 boost::addressof(*node_));
1320 node_allocator_traits::deallocate(alloc_, node_, 1);
1325 namespace boost { namespace unordered { namespace detail { namespace func {
1327 // Some nicer construct_node functions, might try to
1328 // improve implementation later.
1330 template <typename Alloc, BOOST_UNORDERED_EMPLACE_TEMPLATE>
1331 inline typename boost::unordered::detail::allocator_traits<Alloc>::pointer
1332 construct_node_from_args(Alloc& alloc, BOOST_UNORDERED_EMPLACE_ARGS)
1334 node_constructor<Alloc> a(alloc);
1336 construct_from_args(alloc, a.node_->value_ptr(),
1337 BOOST_UNORDERED_EMPLACE_FORWARD);
1341 template <typename Alloc, typename U>
1342 inline typename boost::unordered::detail::allocator_traits<Alloc>::pointer
1343 construct_node(Alloc& alloc, BOOST_FWD_REF(U) x)
1345 node_constructor<Alloc> a(alloc);
1347 boost::unordered::detail::func::call_construct(
1348 alloc, a.node_->value_ptr(), boost::forward<U>(x));
1352 // TODO: When possible, it might be better to use std::pair's
1353 // constructor for std::piece_construct with std::tuple.
1354 template <typename Alloc, typename Key>
1355 inline typename boost::unordered::detail::allocator_traits<Alloc>::pointer
1356 construct_node_pair(Alloc& alloc, BOOST_FWD_REF(Key) k)
1358 node_constructor<Alloc> a(alloc);
1360 boost::unordered::detail::func::call_construct(alloc,
1361 boost::unordered::detail::func::const_cast_pointer(
1362 boost::addressof(a.node_->value_ptr()->first)),
1363 boost::forward<Key>(k));
1364 boost::unordered::detail::func::call_construct(alloc,
1365 boost::unordered::detail::func::const_cast_pointer(
1366 boost::addressof(a.node_->value_ptr()->second)));
1370 template <typename Alloc, typename Key, typename Mapped>
1371 inline typename boost::unordered::detail::allocator_traits<Alloc>::pointer
1372 construct_node_pair(Alloc& alloc, BOOST_FWD_REF(Key) k, BOOST_FWD_REF(Mapped) m)
1374 node_constructor<Alloc> a(alloc);
1376 boost::unordered::detail::func::call_construct(alloc,
1377 boost::unordered::detail::func::const_cast_pointer(
1378 boost::addressof(a.node_->value_ptr()->first)),
1379 boost::forward<Key>(k));
1380 boost::unordered::detail::func::call_construct(alloc,
1381 boost::unordered::detail::func::const_cast_pointer(
1382 boost::addressof(a.node_->value_ptr()->second)),
1383 boost::forward<Mapped>(m));
1388 #if defined(BOOST_MSVC)
1389 #pragma warning(pop)