blob: 4ad67247cb9eab3e55ce4c2a996db8018ec94d45 [file] [log] [blame]
Jeff Thompsona28eed82013-08-22 16:21:10 -07001
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)
6
7// See http://www.boost.org/libs/unordered for documentation
8
9#ifndef BOOST_UNORDERED_ALLOCATE_HPP
10#define BOOST_UNORDERED_ALLOCATE_HPP
11
12#if defined(_MSC_VER) && (_MSC_VER >= 1020)
13# pragma once
14#endif
15
16#include <ndnboost/unordered/detail/fwd.hpp>
17#include <ndnboost/move/move.hpp>
18#include <ndnboost/preprocessor/cat.hpp>
19#include <ndnboost/preprocessor/inc.hpp>
20#include <ndnboost/preprocessor/dec.hpp>
21#include <ndnboost/preprocessor/repetition/enum.hpp>
22#include <ndnboost/preprocessor/repetition/enum_params.hpp>
23#include <ndnboost/preprocessor/repetition/enum_binary_params.hpp>
24#include <ndnboost/preprocessor/repetition/repeat_from_to.hpp>
25#include <ndnboost/type_traits/is_class.hpp>
26#include <ndnboost/type_traits/add_lvalue_reference.hpp>
27#include <ndnboost/tuple/tuple.hpp>
28#include <ndnboost/utility/enable_if.hpp>
29#include <ndnboost/utility/addressof.hpp>
30#include <ndnboost/detail/select_type.hpp>
31#include <ndnboost/assert.hpp>
32#include <utility>
33
34#if !defined(BOOST_NO_CXX11_HDR_TUPLE)
35#include <tuple>
36#endif
37
38#if defined(BOOST_MSVC)
39#pragma warning(push)
40#pragma warning(disable:4512) // assignment operator could not be generated.
41#pragma warning(disable:4345) // behavior change: an object of POD type
42 // constructed with an initializer of the form ()
43 // will be default-initialized.
44#endif
45
46#define BOOST_UNORDERED_EMPLACE_LIMIT 10
47
48namespace ndnboost { namespace unordered { namespace detail {
49
50 ////////////////////////////////////////////////////////////////////////////
51 // Bits and pieces for implementing traits
52
53 template <typename T> typename ndnboost::add_lvalue_reference<T>::type make();
54 struct choice9 { typedef char (&type)[9]; };
55 struct choice8 : choice9 { typedef char (&type)[8]; };
56 struct choice7 : choice8 { typedef char (&type)[7]; };
57 struct choice6 : choice7 { typedef char (&type)[6]; };
58 struct choice5 : choice6 { typedef char (&type)[5]; };
59 struct choice4 : choice5 { typedef char (&type)[4]; };
60 struct choice3 : choice4 { typedef char (&type)[3]; };
61 struct choice2 : choice3 { typedef char (&type)[2]; };
62 struct choice1 : choice2 { typedef char (&type)[1]; };
63 choice1 choose();
64
65 typedef choice1::type yes_type;
66 typedef choice2::type no_type;
67
68 struct private_type
69 {
70 private_type const &operator,(int) const;
71 };
72
73 template <typename T>
74 no_type is_private_type(T const&);
75 yes_type is_private_type(private_type const&);
76
77 struct convert_from_anything {
78 template <typename T>
79 convert_from_anything(T const&);
80 };
81
82 ////////////////////////////////////////////////////////////////////////////
83 // emplace_args
84 //
85 // Either forwarding variadic arguments, or storing the arguments in
86 // emplace_args##n
87
88#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
89
90#define BOOST_UNORDERED_EMPLACE_TEMPLATE typename... Args
91#define BOOST_UNORDERED_EMPLACE_ARGS BOOST_FWD_REF(Args)... args
92#define BOOST_UNORDERED_EMPLACE_FORWARD ndnboost::forward<Args>(args)...
93
94#define BOOST_UNORDERED_EMPLACE_ARGS1(a0) a0
95#define BOOST_UNORDERED_EMPLACE_ARGS2(a0, a1) a0, a1
96#define BOOST_UNORDERED_EMPLACE_ARGS3(a0, a1, a2) a0, a1, a2
97
98#else
99
100#define BOOST_UNORDERED_EMPLACE_TEMPLATE typename Args
101#define BOOST_UNORDERED_EMPLACE_ARGS Args const& args
102#define BOOST_UNORDERED_EMPLACE_FORWARD args
103
104#define BOOST_UNORDERED_FWD_PARAM(z, n, a) \
105 BOOST_FWD_REF(BOOST_PP_CAT(A, n)) BOOST_PP_CAT(a, n)
106
107#define BOOST_UNORDERED_CALL_FORWARD(z, i, a) \
108 ndnboost::forward<BOOST_PP_CAT(A,i)>(BOOST_PP_CAT(a,i))
109
110#define BOOST_UNORDERED_EARGS(z, n, _) \
111 template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
112 struct BOOST_PP_CAT(emplace_args, n) \
113 { \
114 BOOST_PP_REPEAT_##z(n, BOOST_UNORDERED_EARGS_MEMBER, _) \
115 BOOST_PP_CAT(emplace_args, n) ( \
116 BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, Arg, b) \
117 ) : BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_EARGS_INIT, _) \
118 {} \
119 \
120 }; \
121 \
122 template <BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
123 inline BOOST_PP_CAT(emplace_args, n) < \
124 BOOST_PP_ENUM_PARAMS_Z(z, n, A) \
125 > create_emplace_args( \
126 BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, b) \
127 ) \
128 { \
129 BOOST_PP_CAT(emplace_args, n) < \
130 BOOST_PP_ENUM_PARAMS_Z(z, n, A) \
131 > e(BOOST_PP_ENUM_PARAMS_Z(z, n, b)); \
132 return e; \
133 }
134
135#define BOOST_UNORDERED_EMPLACE_ARGS1 create_emplace_args
136#define BOOST_UNORDERED_EMPLACE_ARGS2 create_emplace_args
137#define BOOST_UNORDERED_EMPLACE_ARGS3 create_emplace_args
138
139#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
140
141#define BOOST_UNORDERED_EARGS_MEMBER(z, n, _) \
142 typedef BOOST_FWD_REF(BOOST_PP_CAT(A, n)) BOOST_PP_CAT(Arg, n); \
143 BOOST_PP_CAT(Arg, n) BOOST_PP_CAT(a, n);
144
145#define BOOST_UNORDERED_EARGS_INIT(z, n, _) \
146 BOOST_PP_CAT(a, n)( \
147 ndnboost::forward<BOOST_PP_CAT(A,n)>(BOOST_PP_CAT(b, n)))
148
149#else
150
151#define BOOST_UNORDERED_EARGS_MEMBER(z, n, _) \
152 typedef typename ndnboost::add_lvalue_reference<BOOST_PP_CAT(A, n)>::type \
153 BOOST_PP_CAT(Arg, n); \
154 BOOST_PP_CAT(Arg, n) BOOST_PP_CAT(a, n);
155
156#define BOOST_UNORDERED_EARGS_INIT(z, n, _) \
157 BOOST_PP_CAT(a, n)(BOOST_PP_CAT(b, n))
158
159#endif
160
161BOOST_PP_REPEAT_FROM_TO(1, BOOST_UNORDERED_EMPLACE_LIMIT, BOOST_UNORDERED_EARGS,
162 _)
163
164#undef BOOST_UNORDERED_DEFINE_EMPLACE_ARGS
165#undef BOOST_UNORDERED_EARGS_MEMBER
166#undef BOOST_UNORDERED_EARGS_INIT
167
168#endif
169
170}}}
171
172////////////////////////////////////////////////////////////////////////////////
173//
174// Pick which version of allocator_traits to use
175//
176// 0 = Own partial implementation
177// 1 = std::allocator_traits
178// 2 = ndnboost::container::allocator_traits
179
180#if !defined(BOOST_UNORDERED_USE_ALLOCATOR_TRAITS)
181# if defined(__GXX_EXPERIMENTAL_CXX0X__) && \
182 (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))
183# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 0
184# elif defined(BOOST_MSVC)
185# if BOOST_MSVC < 1400
186 // Use container's allocator_traits for older versions of Visual
187 // C++ as I don't test with them.
188# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 2
189# endif
190# endif
191#endif
192
193#if !defined(BOOST_UNORDERED_USE_ALLOCATOR_TRAITS)
194# define BOOST_UNORDERED_USE_ALLOCATOR_TRAITS 0
195#endif
196
197////////////////////////////////////////////////////////////////////////////////
198//
199// Some utilities for implementing allocator_traits, but useful elsewhere so
200// they're always defined.
201
202#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
203# include <type_traits>
204#endif
205
206namespace ndnboost { namespace unordered { namespace detail {
207
208 ////////////////////////////////////////////////////////////////////////////
209 // Integral_constrant, true_type, false_type
210 //
211 // Uses the standard versions if available.
212
213#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS)
214
215 using std::integral_constant;
216 using std::true_type;
217 using std::false_type;
218
219#else
220
221 template <typename T, T Value>
222 struct integral_constant { enum { value = Value }; };
223
224 typedef ndnboost::unordered::detail::integral_constant<bool, true> true_type;
225 typedef ndnboost::unordered::detail::integral_constant<bool, false> false_type;
226
227#endif
228
229 ////////////////////////////////////////////////////////////////////////////
230 // Explicitly call a destructor
231
232#if defined(BOOST_MSVC)
233#pragma warning(push)
234#pragma warning(disable:4100) // unreferenced formal parameter
235#endif
236
237 template <class T>
238 inline void destroy(T* x) {
239 x->~T();
240 }
241
242#if defined(BOOST_MSVC)
243#pragma warning(pop)
244#endif
245
246 ////////////////////////////////////////////////////////////////////////////
247 // Expression test mechanism
248 //
249 // When SFINAE expressions are available, define
250 // BOOST_UNORDERED_HAS_FUNCTION which can check if a function call is
251 // supported by a class, otherwise define BOOST_UNORDERED_HAS_MEMBER which
252 // can detect if a class has the specified member, but not that it has the
253 // correct type, this is good enough for a passable impression of
254 // allocator_traits.
255
256#if !defined(BOOST_NO_SFINAE_EXPR)
257
258 template <typename T, unsigned int> struct expr_test;
259 template <typename T> struct expr_test<T, sizeof(char)> : T {};
260 template <typename U> static char for_expr_test(U const&);
261
262# define BOOST_UNORDERED_CHECK_EXPRESSION(count, result, expression) \
263 template <typename U> \
264 static typename ndnboost::unordered::detail::expr_test< \
265 BOOST_PP_CAT(choice, result), \
266 sizeof(ndnboost::unordered::detail::for_expr_test(( \
267 (expression), \
268 0)))>::type test( \
269 BOOST_PP_CAT(choice, count))
270
271# define BOOST_UNORDERED_DEFAULT_EXPRESSION(count, result) \
272 template <typename U> \
273 static BOOST_PP_CAT(choice, result)::type test( \
274 BOOST_PP_CAT(choice, count))
275
276# define BOOST_UNORDERED_HAS_FUNCTION(name, thing, args, _) \
277 struct BOOST_PP_CAT(has_, name) \
278 { \
279 BOOST_UNORDERED_CHECK_EXPRESSION(1, 1, \
280 ndnboost::unordered::detail::make< thing >().name args); \
281 BOOST_UNORDERED_DEFAULT_EXPRESSION(2, 2); \
282 \
283 enum { value = sizeof(test<T>(choose())) == sizeof(choice1::type) };\
284 }
285
286#else
287
288 template <typename T> struct identity { typedef T type; };
289
290# define BOOST_UNORDERED_CHECK_MEMBER(count, result, name, member) \
291 \
292 typedef typename ndnboost::unordered::detail::identity<member>::type \
293 BOOST_PP_CAT(check, count); \
294 \
295 template <BOOST_PP_CAT(check, count) e> \
296 struct BOOST_PP_CAT(test, count) { \
297 typedef BOOST_PP_CAT(choice, result) type; \
298 }; \
299 \
300 template <class U> static typename \
301 BOOST_PP_CAT(test, count)<&U::name>::type \
302 test(BOOST_PP_CAT(choice, count))
303
304# define BOOST_UNORDERED_DEFAULT_MEMBER(count, result) \
305 template <class U> static BOOST_PP_CAT(choice, result)::type \
306 test(BOOST_PP_CAT(choice, count))
307
308# define BOOST_UNORDERED_HAS_MEMBER(name) \
309 struct BOOST_PP_CAT(has_, name) \
310 { \
311 struct impl { \
312 struct base_mixin { int name; }; \
313 struct base : public T, public base_mixin {}; \
314 \
315 BOOST_UNORDERED_CHECK_MEMBER(1, 1, name, int base_mixin::*); \
316 BOOST_UNORDERED_DEFAULT_MEMBER(2, 2); \
317 \
318 enum { value = sizeof(choice2::type) == \
319 sizeof(test<base>(choose())) \
320 }; \
321 }; \
322 \
323 enum { value = impl::value }; \
324 }
325
326#endif
327
328}}}
329
330////////////////////////////////////////////////////////////////////////////////
331//
332// Allocator traits
333//
334// First our implementation, then later light wrappers around the alternatives
335
336#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 0
337
338# include <ndnboost/limits.hpp>
339# include <ndnboost/utility/enable_if.hpp>
340# include <ndnboost/pointer_to_other.hpp>
341# if defined(BOOST_NO_SFINAE_EXPR)
342# include <ndnboost/type_traits/is_same.hpp>
343# endif
344
345# if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
346 !defined(BOOST_NO_SFINAE_EXPR)
347# define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 1
348# else
349# define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 0
350# endif
351
352namespace ndnboost { namespace unordered { namespace detail {
353
354 // TODO: Does this match std::allocator_traits<Alloc>::rebind_alloc<T>?
355 template <typename Alloc, typename T>
356 struct rebind_wrap
357 {
358 typedef typename Alloc::BOOST_NESTED_TEMPLATE rebind<T>::other type;
359 };
360
361# if defined(BOOST_MSVC) && BOOST_MSVC <= 1400
362
363# define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \
364 template <typename Tp, typename Default> \
365 struct default_type_ ## tname { \
366 \
367 template <typename X> \
368 static choice1::type test(choice1, typename X::tname* = 0); \
369 \
370 template <typename X> \
371 static choice2::type test(choice2, void* = 0); \
372 \
373 struct DefaultWrap { typedef Default tname; }; \
374 \
375 enum { value = (1 == sizeof(test<Tp>(choose()))) }; \
376 \
377 typedef typename ndnboost::detail::if_true<value>:: \
378 BOOST_NESTED_TEMPLATE then<Tp, DefaultWrap> \
379 ::type::tname type; \
380 }
381
382# else
383
384 template <typename T, typename T2>
385 struct sfinae : T2 {};
386
387# define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \
388 template <typename Tp, typename Default> \
389 struct default_type_ ## tname { \
390 \
391 template <typename X> \
392 static typename ndnboost::unordered::detail::sfinae< \
393 typename X::tname, choice1>::type \
394 test(choice1); \
395 \
396 template <typename X> \
397 static choice2::type test(choice2); \
398 \
399 struct DefaultWrap { typedef Default tname; }; \
400 \
401 enum { value = (1 == sizeof(test<Tp>(choose()))) }; \
402 \
403 typedef typename ndnboost::detail::if_true<value>:: \
404 BOOST_NESTED_TEMPLATE then<Tp, DefaultWrap> \
405 ::type::tname type; \
406 }
407
408# endif
409
410# define BOOST_UNORDERED_DEFAULT_TYPE(T,tname, arg) \
411 typename default_type_ ## tname<T, arg>::type
412
413 BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(pointer);
414 BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(const_pointer);
415 BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(void_pointer);
416 BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(const_void_pointer);
417 BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(difference_type);
418 BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(size_type);
419 BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_copy_assignment);
420 BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_move_assignment);
421 BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_swap);
422
423# if !defined(BOOST_NO_SFINAE_EXPR)
424
425 template <typename T>
426 BOOST_UNORDERED_HAS_FUNCTION(
427 select_on_container_copy_construction, U const, (), 0
428 );
429
430 template <typename T>
431 BOOST_UNORDERED_HAS_FUNCTION(
432 max_size, U const, (), 0
433 );
434
435# if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
436
437 template <typename T, typename ValueType, typename... Args>
438 BOOST_UNORDERED_HAS_FUNCTION(
439 construct, U, (
440 ndnboost::unordered::detail::make<ValueType*>(),
441 ndnboost::unordered::detail::make<Args const>()...), 2
442 );
443
444# else
445
446 template <typename T, typename ValueType>
447 BOOST_UNORDERED_HAS_FUNCTION(
448 construct, U, (
449 ndnboost::unordered::detail::make<ValueType*>(),
450 ndnboost::unordered::detail::make<ValueType const>()), 2
451 );
452
453# endif
454
455 template <typename T, typename ValueType>
456 BOOST_UNORDERED_HAS_FUNCTION(
457 destroy, U, (ndnboost::unordered::detail::make<ValueType*>()), 1
458 );
459
460# else
461
462 template <typename T>
463 BOOST_UNORDERED_HAS_MEMBER(select_on_container_copy_construction);
464
465 template <typename T>
466 BOOST_UNORDERED_HAS_MEMBER(max_size);
467
468 template <typename T, typename ValueType>
469 BOOST_UNORDERED_HAS_MEMBER(construct);
470
471 template <typename T, typename ValueType>
472 BOOST_UNORDERED_HAS_MEMBER(destroy);
473
474# endif
475
476 template <typename Alloc>
477 inline Alloc call_select_on_container_copy_construction(const Alloc& rhs,
478 typename ndnboost::enable_if_c<
479 ndnboost::unordered::detail::
480 has_select_on_container_copy_construction<Alloc>::value, void*
481 >::type = 0)
482 {
483 return rhs.select_on_container_copy_construction();
484 }
485
486 template <typename Alloc>
487 inline Alloc call_select_on_container_copy_construction(const Alloc& rhs,
488 typename ndnboost::disable_if_c<
489 ndnboost::unordered::detail::
490 has_select_on_container_copy_construction<Alloc>::value, void*
491 >::type = 0)
492 {
493 return rhs;
494 }
495
496 template <typename SizeType, typename Alloc>
497 inline SizeType call_max_size(const Alloc& a,
498 typename ndnboost::enable_if_c<
499 ndnboost::unordered::detail::has_max_size<Alloc>::value, void*
500 >::type = 0)
501 {
502 return a.max_size();
503 }
504
505 template <typename SizeType, typename Alloc>
506 inline SizeType call_max_size(const Alloc&, typename ndnboost::disable_if_c<
507 ndnboost::unordered::detail::has_max_size<Alloc>::value, void*
508 >::type = 0)
509 {
510 return (std::numeric_limits<SizeType>::max)();
511 }
512
513 template <typename Alloc>
514 struct allocator_traits
515 {
516 typedef Alloc allocator_type;
517 typedef typename Alloc::value_type value_type;
518
519 typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, pointer, value_type*)
520 pointer;
521
522 template <typename T>
523 struct pointer_to_other : ndnboost::pointer_to_other<pointer, T> {};
524
525 typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_pointer,
526 typename pointer_to_other<const value_type>::type)
527 const_pointer;
528
529 //typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, void_pointer,
530 // typename pointer_to_other<void>::type)
531 // void_pointer;
532 //
533 //typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_void_pointer,
534 // typename pointer_to_other<const void>::type)
535 // const_void_pointer;
536
537 typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, difference_type,
538 std::ptrdiff_t) difference_type;
539
540 typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, size_type, std::size_t)
541 size_type;
542
543 // TODO: rebind_alloc and rebind_traits
544
545 static pointer allocate(Alloc& a, size_type n)
546 { return a.allocate(n); }
547
548 // I never use this, so I'll just comment it out for now.
549 //
550 //static pointer allocate(Alloc& a, size_type n,
551 // const_void_pointer hint)
552 // { return DEFAULT_FUNC(allocate, pointer)(a, n, hint); }
553
554 static void deallocate(Alloc& a, pointer p, size_type n)
555 { a.deallocate(p, n); }
556
557 public:
558
559# if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
560
561 template <typename T, typename... Args>
562 static typename ndnboost::enable_if_c<
563 ndnboost::unordered::detail::has_construct<Alloc, T, Args...>
564 ::value>::type
565 construct(Alloc& a, T* p, BOOST_FWD_REF(Args)... x)
566 {
567 a.construct(p, ndnboost::forward<Args>(x)...);
568 }
569
570 template <typename T, typename... Args>
571 static typename ndnboost::disable_if_c<
572 ndnboost::unordered::detail::has_construct<Alloc, T, Args...>
573 ::value>::type
574 construct(Alloc&, T* p, BOOST_FWD_REF(Args)... x)
575 {
576 new ((void*) p) T(ndnboost::forward<Args>(x)...);
577 }
578
579 template <typename T>
580 static typename ndnboost::enable_if_c<
581 ndnboost::unordered::detail::has_destroy<Alloc, T>::value>::type
582 destroy(Alloc& a, T* p)
583 {
584 a.destroy(p);
585 }
586
587 template <typename T>
588 static typename ndnboost::disable_if_c<
589 ndnboost::unordered::detail::has_destroy<Alloc, T>::value>::type
590 destroy(Alloc&, T* p)
591 {
592 ndnboost::unordered::detail::destroy(p);
593 }
594
595# elif !defined(BOOST_NO_SFINAE_EXPR)
596
597 template <typename T>
598 static typename ndnboost::enable_if_c<
599 ndnboost::unordered::detail::has_construct<Alloc, T>::value>::type
600 construct(Alloc& a, T* p, T const& x)
601 {
602 a.construct(p, x);
603 }
604
605 template <typename T>
606 static typename ndnboost::disable_if_c<
607 ndnboost::unordered::detail::has_construct<Alloc, T>::value>::type
608 construct(Alloc&, T* p, T const& x)
609 {
610 new ((void*) p) T(x);
611 }
612
613 template <typename T>
614 static typename ndnboost::enable_if_c<
615 ndnboost::unordered::detail::has_destroy<Alloc, T>::value>::type
616 destroy(Alloc& a, T* p)
617 {
618 a.destroy(p);
619 }
620
621 template <typename T>
622 static typename ndnboost::disable_if_c<
623 ndnboost::unordered::detail::has_destroy<Alloc, T>::value>::type
624 destroy(Alloc&, T* p)
625 {
626 ndnboost::unordered::detail::destroy(p);
627 }
628
629# else
630
631 // If we don't have SFINAE expressions, only call construct for the
632 // copy constructor for the allocator's value_type - as that's
633 // the only construct method that old fashioned allocators support.
634
635 template <typename T>
636 static void construct(Alloc& a, T* p, T const& x,
637 typename ndnboost::enable_if_c<
638 ndnboost::unordered::detail::has_construct<Alloc, T>::value &&
639 ndnboost::is_same<T, value_type>::value,
640 void*>::type = 0)
641 {
642 a.construct(p, x);
643 }
644
645 template <typename T>
646 static void construct(Alloc&, T* p, T const& x,
647 typename ndnboost::disable_if_c<
648 ndnboost::unordered::detail::has_construct<Alloc, T>::value &&
649 ndnboost::is_same<T, value_type>::value,
650 void*>::type = 0)
651 {
652 new ((void*) p) T(x);
653 }
654
655 template <typename T>
656 static void destroy(Alloc& a, T* p,
657 typename ndnboost::enable_if_c<
658 ndnboost::unordered::detail::has_destroy<Alloc, T>::value &&
659 ndnboost::is_same<T, value_type>::value,
660 void*>::type = 0)
661 {
662 a.destroy(p);
663 }
664
665 template <typename T>
666 static void destroy(Alloc&, T* p,
667 typename ndnboost::disable_if_c<
668 ndnboost::unordered::detail::has_destroy<Alloc, T>::value &&
669 ndnboost::is_same<T, value_type>::value,
670 void*>::type = 0)
671 {
672 ndnboost::unordered::detail::destroy(p);
673 }
674
675# endif
676
677 static size_type max_size(const Alloc& a)
678 {
679 return ndnboost::unordered::detail::call_max_size<size_type>(a);
680 }
681
682 // Allocator propagation on construction
683
684 static Alloc select_on_container_copy_construction(Alloc const& rhs)
685 {
686 return ndnboost::unordered::detail::
687 call_select_on_container_copy_construction(rhs);
688 }
689
690 // Allocator propagation on assignment and swap.
691 // Return true if lhs is modified.
692 typedef BOOST_UNORDERED_DEFAULT_TYPE(
693 Alloc, propagate_on_container_copy_assignment, false_type)
694 propagate_on_container_copy_assignment;
695 typedef BOOST_UNORDERED_DEFAULT_TYPE(
696 Alloc,propagate_on_container_move_assignment, false_type)
697 propagate_on_container_move_assignment;
698 typedef BOOST_UNORDERED_DEFAULT_TYPE(
699 Alloc,propagate_on_container_swap,false_type)
700 propagate_on_container_swap;
701 };
702}}}
703
704# undef BOOST_UNORDERED_DEFAULT_TYPE_TMPLT
705# undef BOOST_UNORDERED_DEFAULT_TYPE
706
707////////////////////////////////////////////////////////////////////////////////
708//
709// std::allocator_traits
710
711#elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
712
713# include <memory>
714
715# define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 1
716
717namespace ndnboost { namespace unordered { namespace detail {
718
719 template <typename Alloc>
720 struct allocator_traits : std::allocator_traits<Alloc> {};
721
722 template <typename Alloc, typename T>
723 struct rebind_wrap
724 {
725 typedef typename std::allocator_traits<Alloc>::
726 template rebind_alloc<T> type;
727 };
728}}}
729
730////////////////////////////////////////////////////////////////////////////////
731//
732// ndnboost::container::allocator_traits
733
734#elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 2
735
736# include <ndnboost/container/allocator_traits.hpp>
737
738# define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 0
739
740namespace ndnboost { namespace unordered { namespace detail {
741
742 template <typename Alloc>
743 struct allocator_traits :
744 ndnboost::container::allocator_traits<Alloc> {};
745
746 template <typename Alloc, typename T>
747 struct rebind_wrap :
748 ndnboost::container::allocator_traits<Alloc>::
749 template portable_rebind_alloc<T>
750 {};
751
752}}}
753
754#else
755
756#error "Invalid BOOST_UNORDERED_USE_ALLOCATOR_TRAITS value."
757
758#endif
759
760
761namespace ndnboost { namespace unordered { namespace detail {
762
763 ////////////////////////////////////////////////////////////////////////////
764 // call_construct
765
766#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
767
768# if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
769
770 template <typename Alloc, typename T, typename... Args>
771 inline void call_construct(Alloc& alloc, T* address,
772 BOOST_FWD_REF(Args)... args)
773 {
774 ndnboost::unordered::detail::allocator_traits<Alloc>::construct(alloc,
775 address, ndnboost::forward<Args>(args)...);
776 }
777
778 template <typename Alloc, typename T>
779 inline void destroy_value_impl(Alloc& alloc, T* x) {
780 ndnboost::unordered::detail::allocator_traits<Alloc>::destroy(alloc, x);
781 }
782
783
784# else
785
786 template <typename Alloc, typename T, typename... Args>
787 inline void call_construct(Alloc&, T* address,
788 BOOST_FWD_REF(Args)... args)
789 {
790 new((void*) address) T(ndnboost::forward<Args>(args)...);
791 }
792
793 template <typename Alloc, typename T>
794 inline void destroy_value_impl(Alloc&, T* x) {
795 ndnboost::unordered::detail::destroy(x);
796 }
797
798
799# endif
800
801#else
802
803 template <typename Alloc, typename T>
804 inline void destroy_value_impl(Alloc&, T* x) {
805 ndnboost::unordered::detail::destroy(x);
806 }
807
808#endif
809
810 ////////////////////////////////////////////////////////////////////////////
811 // Construct from tuple
812 //
813 // Used for piecewise construction.
814
815#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
816
817# define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \
818 template<typename Alloc, typename T> \
819 void construct_from_tuple(Alloc& alloc, T* ptr, namespace_ tuple<>) \
820 { \
821 ndnboost::unordered::detail::call_construct(alloc, ptr); \
822 } \
823 \
824 BOOST_PP_REPEAT_FROM_TO(1, n, \
825 BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_)
826
827# define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_) \
828 template<typename Alloc, typename T, \
829 BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
830 void construct_from_tuple(Alloc& alloc, T* ptr, \
831 namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
832 { \
833 ndnboost::unordered::detail::call_construct(alloc, ptr, \
834 BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \
835 ); \
836 }
837
838# define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) \
839 namespace_ get<n>(x)
840
841#elif !defined(__SUNPRO_CC)
842
843# define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \
844 template<typename Alloc, typename T> \
845 void construct_from_tuple(Alloc&, T* ptr, namespace_ tuple<>) \
846 { \
847 new ((void*) ptr) T(); \
848 } \
849 \
850 BOOST_PP_REPEAT_FROM_TO(1, n, \
851 BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_)
852
853# define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_) \
854 template<typename Alloc, typename T, \
855 BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
856 void construct_from_tuple(Alloc&, T* ptr, \
857 namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
858 { \
859 new ((void*) ptr) T( \
860 BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \
861 ); \
862 }
863
864# define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) \
865 namespace_ get<n>(x)
866
867#else
868
869 template <int N> struct length {};
870
871# define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \
872 template<typename Alloc, typename T> \
873 void construct_from_tuple_impl( \
874 ndnboost::unordered::detail::length<0>, Alloc&, T* ptr, \
875 namespace_ tuple<>) \
876 { \
877 new ((void*) ptr) T(); \
878 } \
879 \
880 BOOST_PP_REPEAT_FROM_TO(1, n, \
881 BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_)
882
883# define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_) \
884 template<typename Alloc, typename T, \
885 BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
886 void construct_from_tuple_impl( \
887 ndnboost::unordered::detail::length<n>, Alloc&, T* ptr, \
888 namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
889 { \
890 new ((void*) ptr) T( \
891 BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \
892 ); \
893 }
894
895# define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) \
896 namespace_ get<n>(x)
897
898#endif
899
900BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, ndnboost::)
901
902#if !defined(__SUNPRO_CC) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
903 BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std::)
904#endif
905
906#undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE
907#undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL
908#undef BOOST_UNORDERED_GET_TUPLE_ARG
909
910#if defined(__SUNPRO_CC)
911
912 template <typename Alloc, typename T, typename Tuple>
913 void construct_from_tuple(Alloc& alloc, T* ptr, Tuple const& x)
914 {
915 construct_from_tuple_impl(
916 ndnboost::unordered::detail::length<
917 ndnboost::tuples::length<Tuple>::value>(),
918 alloc, ptr, x);
919 }
920
921#endif
922
923 ////////////////////////////////////////////////////////////////////////////
924 // Trait to check for piecewise construction.
925
926 template <typename A0>
927 struct use_piecewise {
928 static choice1::type test(choice1,
929 ndnboost::unordered::piecewise_construct_t);
930
931 static choice2::type test(choice2, ...);
932
933 enum { value = sizeof(choice1::type) ==
934 sizeof(test(choose(), ndnboost::unordered::detail::make<A0>())) };
935 };
936
937#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
938
939 ////////////////////////////////////////////////////////////////////////////
940 // Construct from variadic parameters
941
942 // For the standard pair constructor.
943
944 template <typename Alloc, typename T, typename... Args>
945 inline void construct_value_impl(Alloc& alloc, T* address,
946 BOOST_FWD_REF(Args)... args)
947 {
948 ndnboost::unordered::detail::call_construct(alloc,
949 address, ndnboost::forward<Args>(args)...);
950 }
951
952 // Special case for piece_construct
953 //
954 // TODO: When possible, it might be better to use std::pair's
955 // constructor for std::piece_construct with std::tuple.
956
957 template <typename Alloc, typename A, typename B,
958 typename A0, typename A1, typename A2>
959 inline typename enable_if<use_piecewise<A0>, void>::type
960 construct_value_impl(Alloc& alloc, std::pair<A, B>* address,
961 BOOST_FWD_REF(A0), BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
962 {
963 ndnboost::unordered::detail::construct_from_tuple(alloc,
964 ndnboost::addressof(address->first), ndnboost::forward<A1>(a1));
965 ndnboost::unordered::detail::construct_from_tuple(alloc,
966 ndnboost::addressof(address->second), ndnboost::forward<A2>(a2));
967 }
968
969#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
970
971////////////////////////////////////////////////////////////////////////////////
972// Construct from emplace_args
973
974 // Explicitly write out first three overloads for the sake of sane
975 // error messages.
976
977 template <typename Alloc, typename T, typename A0>
978 inline void construct_value_impl(Alloc&, T* address,
979 emplace_args1<A0> const& args)
980 {
981 new((void*) address) T(ndnboost::forward<A0>(args.a0));
982 }
983
984 template <typename Alloc, typename T, typename A0, typename A1>
985 inline void construct_value_impl(Alloc&, T* address,
986 emplace_args2<A0, A1> const& args)
987 {
988 new((void*) address) T(
989 ndnboost::forward<A0>(args.a0),
990 ndnboost::forward<A1>(args.a1)
991 );
992 }
993
994 template <typename Alloc, typename T, typename A0, typename A1, typename A2>
995 inline void construct_value_impl(Alloc&, T* address,
996 emplace_args3<A0, A1, A2> const& args)
997 {
998 new((void*) address) T(
999 ndnboost::forward<A0>(args.a0),
1000 ndnboost::forward<A1>(args.a1),
1001 ndnboost::forward<A2>(args.a2)
1002 );
1003 }
1004
1005 // Use a macro for the rest.
1006
1007#define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _) \
1008 template < \
1009 typename Alloc, typename T, \
1010 BOOST_PP_ENUM_PARAMS_Z(z, num_params, typename A) \
1011 > \
1012 inline void construct_value_impl(Alloc&, T* address, \
1013 ndnboost::unordered::detail::BOOST_PP_CAT(emplace_args,num_params) < \
1014 BOOST_PP_ENUM_PARAMS_Z(z, num_params, A) \
1015 > const& args) \
1016 { \
1017 new((void*) address) T( \
1018 BOOST_PP_ENUM_##z(num_params, BOOST_UNORDERED_CALL_FORWARD, \
1019 args.a)); \
1020 }
1021
1022 BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
1023 BOOST_UNORDERED_CONSTRUCT_IMPL, _)
1024
1025#undef BOOST_UNORDERED_CONSTRUCT_IMPL
1026
1027 // Construct with piece_construct
1028
1029 template <typename Alloc, typename A, typename B,
1030 typename A0, typename A1, typename A2>
1031 inline void construct_value_impl(Alloc& alloc, std::pair<A, B>* address,
1032 ndnboost::unordered::detail::emplace_args3<A0, A1, A2> const& args,
1033 typename enable_if<use_piecewise<A0>, void*>::type = 0)
1034 {
1035 ndnboost::unordered::detail::construct_from_tuple(alloc,
1036 ndnboost::addressof(address->first), args.a1);
1037 ndnboost::unordered::detail::construct_from_tuple(alloc,
1038 ndnboost::addressof(address->second), args.a2);
1039 }
1040
1041#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
1042
1043}}}
1044
1045////////////////////////////////////////////////////////////////////////////////
1046//
1047// Some helper functions for allocating & constructing
1048
1049namespace ndnboost { namespace unordered { namespace detail {
1050
1051 ////////////////////////////////////////////////////////////////////////////
1052 //
1053 // array_constructor
1054 //
1055 // Allocate and construct an array in an exception safe manner, and
1056 // clean up if an exception is thrown before the container takes charge
1057 // of it.
1058
1059 template <typename Allocator>
1060 struct array_constructor
1061 {
1062 typedef ndnboost::unordered::detail::allocator_traits<Allocator> traits;
1063 typedef typename traits::pointer pointer;
1064
1065 Allocator& alloc_;
1066 pointer ptr_;
1067 pointer constructed_;
1068 std::size_t length_;
1069
1070 array_constructor(Allocator& a)
1071 : alloc_(a), ptr_(), constructed_(), length_(0)
1072 {
1073 constructed_ = pointer();
1074 ptr_ = pointer();
1075 }
1076
1077 ~array_constructor() {
1078 if (ptr_) {
1079 for(pointer p = ptr_; p != constructed_; ++p)
1080 traits::destroy(alloc_, ndnboost::addressof(*p));
1081
1082 traits::deallocate(alloc_, ptr_, length_);
1083 }
1084 }
1085
1086 template <typename V>
1087 void construct(V const& v, std::size_t l)
1088 {
1089 BOOST_ASSERT(!ptr_);
1090 length_ = l;
1091 ptr_ = traits::allocate(alloc_, length_);
1092 pointer end = ptr_ + static_cast<std::ptrdiff_t>(length_);
1093 for(constructed_ = ptr_; constructed_ != end; ++constructed_)
1094 traits::construct(alloc_, ndnboost::addressof(*constructed_), v);
1095 }
1096
1097 pointer get() const
1098 {
1099 return ptr_;
1100 }
1101
1102 pointer release()
1103 {
1104 pointer p(ptr_);
1105 ptr_ = pointer();
1106 return p;
1107 }
1108
1109 private:
1110
1111 array_constructor(array_constructor const&);
1112 array_constructor& operator=(array_constructor const&);
1113 };
1114}}}
1115
1116#if defined(BOOST_MSVC)
1117#pragma warning(pop)
1118#endif
1119
1120#endif