comparison DEPENDENCIES/generic/include/boost/unordered/detail/allocate.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children c530137014c0
comparison
equal deleted inserted replaced
15:663ca0da4350 16:2665513ce2d3
1
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 <boost/unordered/detail/fwd.hpp>
17 #include <boost/move/move.hpp>
18 #include <boost/preprocessor/cat.hpp>
19 #include <boost/preprocessor/inc.hpp>
20 #include <boost/preprocessor/dec.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/tuple/tuple.hpp>
28 #include <boost/utility/enable_if.hpp>
29 #include <boost/utility/addressof.hpp>
30 #include <boost/detail/select_type.hpp>
31 #include <boost/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
48 namespace boost { namespace unordered { namespace detail {
49
50 ////////////////////////////////////////////////////////////////////////////
51 // Bits and pieces for implementing traits
52
53 template <typename T> typename boost::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 boost::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 boost::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 boost::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 boost::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
161 BOOST_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 = boost::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
206 namespace boost { 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 boost::unordered::detail::integral_constant<bool, true> true_type;
225 typedef boost::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 namespace func {
238 template <class T>
239 inline void destroy(T* x) {
240 x->~T();
241 }
242 }
243
244 #if defined(BOOST_MSVC)
245 #pragma warning(pop)
246 #endif
247
248 ////////////////////////////////////////////////////////////////////////////
249 // Expression test mechanism
250 //
251 // When SFINAE expressions are available, define
252 // BOOST_UNORDERED_HAS_FUNCTION which can check if a function call is
253 // supported by a class, otherwise define BOOST_UNORDERED_HAS_MEMBER which
254 // can detect if a class has the specified member, but not that it has the
255 // correct type, this is good enough for a passable impression of
256 // allocator_traits.
257
258 #if !defined(BOOST_NO_SFINAE_EXPR)
259
260 template <typename T, unsigned int> struct expr_test;
261 template <typename T> struct expr_test<T, sizeof(char)> : T {};
262
263 # define BOOST_UNORDERED_CHECK_EXPRESSION(count, result, expression) \
264 template <typename U> \
265 static typename boost::unordered::detail::expr_test< \
266 BOOST_PP_CAT(choice, result), \
267 sizeof(for_expr_test(( \
268 (expression), \
269 0)))>::type test( \
270 BOOST_PP_CAT(choice, count))
271
272 # define BOOST_UNORDERED_DEFAULT_EXPRESSION(count, result) \
273 template <typename U> \
274 static BOOST_PP_CAT(choice, result)::type test( \
275 BOOST_PP_CAT(choice, count))
276
277 # define BOOST_UNORDERED_HAS_FUNCTION(name, thing, args, _) \
278 struct BOOST_PP_CAT(has_, name) \
279 { \
280 template <typename U> static char for_expr_test(U const&); \
281 BOOST_UNORDERED_CHECK_EXPRESSION(1, 1, \
282 boost::unordered::detail::make< thing >().name args); \
283 BOOST_UNORDERED_DEFAULT_EXPRESSION(2, 2); \
284 \
285 enum { value = sizeof(test<T>(choose())) == sizeof(choice1::type) };\
286 }
287
288 #else
289
290 template <typename T> struct identity { typedef T type; };
291
292 # define BOOST_UNORDERED_CHECK_MEMBER(count, result, name, member) \
293 \
294 typedef typename boost::unordered::detail::identity<member>::type \
295 BOOST_PP_CAT(check, count); \
296 \
297 template <BOOST_PP_CAT(check, count) e> \
298 struct BOOST_PP_CAT(test, count) { \
299 typedef BOOST_PP_CAT(choice, result) type; \
300 }; \
301 \
302 template <class U> static typename \
303 BOOST_PP_CAT(test, count)<&U::name>::type \
304 test(BOOST_PP_CAT(choice, count))
305
306 # define BOOST_UNORDERED_DEFAULT_MEMBER(count, result) \
307 template <class U> static BOOST_PP_CAT(choice, result)::type \
308 test(BOOST_PP_CAT(choice, count))
309
310 # define BOOST_UNORDERED_HAS_MEMBER(name) \
311 struct BOOST_PP_CAT(has_, name) \
312 { \
313 struct impl { \
314 struct base_mixin { int name; }; \
315 struct base : public T, public base_mixin {}; \
316 \
317 BOOST_UNORDERED_CHECK_MEMBER(1, 1, name, int base_mixin::*); \
318 BOOST_UNORDERED_DEFAULT_MEMBER(2, 2); \
319 \
320 enum { value = sizeof(choice2::type) == \
321 sizeof(test<base>(choose())) \
322 }; \
323 }; \
324 \
325 enum { value = impl::value }; \
326 }
327
328 #endif
329
330 }}}
331
332 ////////////////////////////////////////////////////////////////////////////////
333 //
334 // Allocator traits
335 //
336 // First our implementation, then later light wrappers around the alternatives
337
338 #if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 0
339
340 # include <boost/limits.hpp>
341 # include <boost/utility/enable_if.hpp>
342 # include <boost/pointer_to_other.hpp>
343 # if defined(BOOST_NO_SFINAE_EXPR)
344 # include <boost/type_traits/is_same.hpp>
345 # endif
346
347 # if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
348 !defined(BOOST_NO_SFINAE_EXPR)
349 # define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 1
350 # else
351 # define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 0
352 # endif
353
354 namespace boost { namespace unordered { namespace detail {
355
356 // TODO: Does this match std::allocator_traits<Alloc>::rebind_alloc<T>?
357 template <typename Alloc, typename T>
358 struct rebind_wrap
359 {
360 typedef typename Alloc::BOOST_NESTED_TEMPLATE rebind<T>::other type;
361 };
362
363 # if defined(BOOST_MSVC) && BOOST_MSVC <= 1400
364
365 # define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \
366 template <typename Tp, typename Default> \
367 struct default_type_ ## tname { \
368 \
369 template <typename X> \
370 static choice1::type test(choice1, typename X::tname* = 0); \
371 \
372 template <typename X> \
373 static choice2::type test(choice2, void* = 0); \
374 \
375 struct DefaultWrap { typedef Default tname; }; \
376 \
377 enum { value = (1 == sizeof(test<Tp>(choose()))) }; \
378 \
379 typedef typename boost::detail::if_true<value>:: \
380 BOOST_NESTED_TEMPLATE then<Tp, DefaultWrap> \
381 ::type::tname type; \
382 }
383
384 # else
385
386 template <typename T, typename T2>
387 struct sfinae : T2 {};
388
389 # define BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \
390 template <typename Tp, typename Default> \
391 struct default_type_ ## tname { \
392 \
393 template <typename X> \
394 static typename boost::unordered::detail::sfinae< \
395 typename X::tname, choice1>::type \
396 test(choice1); \
397 \
398 template <typename X> \
399 static choice2::type test(choice2); \
400 \
401 struct DefaultWrap { typedef Default tname; }; \
402 \
403 enum { value = (1 == sizeof(test<Tp>(choose()))) }; \
404 \
405 typedef typename boost::detail::if_true<value>:: \
406 BOOST_NESTED_TEMPLATE then<Tp, DefaultWrap> \
407 ::type::tname type; \
408 }
409
410 # endif
411
412 # define BOOST_UNORDERED_DEFAULT_TYPE(T,tname, arg) \
413 typename default_type_ ## tname<T, arg>::type
414
415 BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(pointer);
416 BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(const_pointer);
417 BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(void_pointer);
418 BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(const_void_pointer);
419 BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(difference_type);
420 BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(size_type);
421 BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_copy_assignment);
422 BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_move_assignment);
423 BOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_swap);
424
425 # if !defined(BOOST_NO_SFINAE_EXPR)
426
427 template <typename T>
428 BOOST_UNORDERED_HAS_FUNCTION(
429 select_on_container_copy_construction, U const, (), 0
430 );
431
432 template <typename T>
433 BOOST_UNORDERED_HAS_FUNCTION(
434 max_size, U const, (), 0
435 );
436
437 # if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
438
439 template <typename T, typename ValueType, typename... Args>
440 BOOST_UNORDERED_HAS_FUNCTION(
441 construct, U, (
442 boost::unordered::detail::make<ValueType*>(),
443 boost::unordered::detail::make<Args const>()...), 2
444 );
445
446 # else
447
448 template <typename T, typename ValueType>
449 BOOST_UNORDERED_HAS_FUNCTION(
450 construct, U, (
451 boost::unordered::detail::make<ValueType*>(),
452 boost::unordered::detail::make<ValueType const>()), 2
453 );
454
455 # endif
456
457 template <typename T, typename ValueType>
458 BOOST_UNORDERED_HAS_FUNCTION(
459 destroy, U, (boost::unordered::detail::make<ValueType*>()), 1
460 );
461
462 # else
463
464 template <typename T>
465 BOOST_UNORDERED_HAS_MEMBER(select_on_container_copy_construction);
466
467 template <typename T>
468 BOOST_UNORDERED_HAS_MEMBER(max_size);
469
470 template <typename T, typename ValueType>
471 BOOST_UNORDERED_HAS_MEMBER(construct);
472
473 template <typename T, typename ValueType>
474 BOOST_UNORDERED_HAS_MEMBER(destroy);
475
476 # endif
477
478 namespace func
479 {
480
481 template <typename Alloc>
482 inline Alloc call_select_on_container_copy_construction(const Alloc& rhs,
483 typename boost::enable_if_c<
484 boost::unordered::detail::
485 has_select_on_container_copy_construction<Alloc>::value, void*
486 >::type = 0)
487 {
488 return rhs.select_on_container_copy_construction();
489 }
490
491 template <typename Alloc>
492 inline Alloc call_select_on_container_copy_construction(const Alloc& rhs,
493 typename boost::disable_if_c<
494 boost::unordered::detail::
495 has_select_on_container_copy_construction<Alloc>::value, void*
496 >::type = 0)
497 {
498 return rhs;
499 }
500
501 template <typename SizeType, typename Alloc>
502 inline SizeType call_max_size(const Alloc& a,
503 typename boost::enable_if_c<
504 boost::unordered::detail::has_max_size<Alloc>::value, void*
505 >::type = 0)
506 {
507 return a.max_size();
508 }
509
510 template <typename SizeType, typename Alloc>
511 inline SizeType call_max_size(const Alloc&, typename boost::disable_if_c<
512 boost::unordered::detail::has_max_size<Alloc>::value, void*
513 >::type = 0)
514 {
515 return (std::numeric_limits<SizeType>::max)();
516 }
517
518 } // namespace func.
519
520 template <typename Alloc>
521 struct allocator_traits
522 {
523 typedef Alloc allocator_type;
524 typedef typename Alloc::value_type value_type;
525
526 typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, pointer, value_type*)
527 pointer;
528
529 template <typename T>
530 struct pointer_to_other : boost::pointer_to_other<pointer, T> {};
531
532 typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_pointer,
533 typename pointer_to_other<const value_type>::type)
534 const_pointer;
535
536 //typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, void_pointer,
537 // typename pointer_to_other<void>::type)
538 // void_pointer;
539 //
540 //typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_void_pointer,
541 // typename pointer_to_other<const void>::type)
542 // const_void_pointer;
543
544 typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, difference_type,
545 std::ptrdiff_t) difference_type;
546
547 typedef BOOST_UNORDERED_DEFAULT_TYPE(Alloc, size_type, std::size_t)
548 size_type;
549
550 // TODO: rebind_alloc and rebind_traits
551
552 static pointer allocate(Alloc& a, size_type n)
553 { return a.allocate(n); }
554
555 // I never use this, so I'll just comment it out for now.
556 //
557 //static pointer allocate(Alloc& a, size_type n,
558 // const_void_pointer hint)
559 // { return DEFAULT_FUNC(allocate, pointer)(a, n, hint); }
560
561 static void deallocate(Alloc& a, pointer p, size_type n)
562 { a.deallocate(p, n); }
563
564 public:
565
566 # if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
567
568 template <typename T, typename... Args>
569 static typename boost::enable_if_c<
570 boost::unordered::detail::has_construct<Alloc, T, Args...>
571 ::value>::type
572 construct(Alloc& a, T* p, BOOST_FWD_REF(Args)... x)
573 {
574 a.construct(p, boost::forward<Args>(x)...);
575 }
576
577 template <typename T, typename... Args>
578 static typename boost::disable_if_c<
579 boost::unordered::detail::has_construct<Alloc, T, Args...>
580 ::value>::type
581 construct(Alloc&, T* p, BOOST_FWD_REF(Args)... x)
582 {
583 new ((void*) p) T(boost::forward<Args>(x)...);
584 }
585
586 template <typename T>
587 static typename boost::enable_if_c<
588 boost::unordered::detail::has_destroy<Alloc, T>::value>::type
589 destroy(Alloc& a, T* p)
590 {
591 a.destroy(p);
592 }
593
594 template <typename T>
595 static typename boost::disable_if_c<
596 boost::unordered::detail::has_destroy<Alloc, T>::value>::type
597 destroy(Alloc&, T* p)
598 {
599 boost::unordered::detail::func::destroy(p);
600 }
601
602 # elif !defined(BOOST_NO_SFINAE_EXPR)
603
604 template <typename T>
605 static typename boost::enable_if_c<
606 boost::unordered::detail::has_construct<Alloc, T>::value>::type
607 construct(Alloc& a, T* p, T const& x)
608 {
609 a.construct(p, x);
610 }
611
612 template <typename T>
613 static typename boost::disable_if_c<
614 boost::unordered::detail::has_construct<Alloc, T>::value>::type
615 construct(Alloc&, T* p, T const& x)
616 {
617 new ((void*) p) T(x);
618 }
619
620 template <typename T>
621 static typename boost::enable_if_c<
622 boost::unordered::detail::has_destroy<Alloc, T>::value>::type
623 destroy(Alloc& a, T* p)
624 {
625 a.destroy(p);
626 }
627
628 template <typename T>
629 static typename boost::disable_if_c<
630 boost::unordered::detail::has_destroy<Alloc, T>::value>::type
631 destroy(Alloc&, T* p)
632 {
633 boost::unordered::detail::func::destroy(p);
634 }
635
636 # else
637
638 // If we don't have SFINAE expressions, only call construct for the
639 // copy constructor for the allocator's value_type - as that's
640 // the only construct method that old fashioned allocators support.
641
642 template <typename T>
643 static void construct(Alloc& a, T* p, T const& x,
644 typename boost::enable_if_c<
645 boost::unordered::detail::has_construct<Alloc, T>::value &&
646 boost::is_same<T, value_type>::value,
647 void*>::type = 0)
648 {
649 a.construct(p, x);
650 }
651
652 template <typename T>
653 static void construct(Alloc&, T* p, T const& x,
654 typename boost::disable_if_c<
655 boost::unordered::detail::has_construct<Alloc, T>::value &&
656 boost::is_same<T, value_type>::value,
657 void*>::type = 0)
658 {
659 new ((void*) p) T(x);
660 }
661
662 template <typename T>
663 static void destroy(Alloc& a, T* p,
664 typename boost::enable_if_c<
665 boost::unordered::detail::has_destroy<Alloc, T>::value &&
666 boost::is_same<T, value_type>::value,
667 void*>::type = 0)
668 {
669 a.destroy(p);
670 }
671
672 template <typename T>
673 static void destroy(Alloc&, T* p,
674 typename boost::disable_if_c<
675 boost::unordered::detail::has_destroy<Alloc, T>::value &&
676 boost::is_same<T, value_type>::value,
677 void*>::type = 0)
678 {
679 boost::unordered::detail::func::destroy(p);
680 }
681
682 # endif
683
684 static size_type max_size(const Alloc& a)
685 {
686 return boost::unordered::detail::func::
687 call_max_size<size_type>(a);
688 }
689
690 // Allocator propagation on construction
691
692 static Alloc select_on_container_copy_construction(Alloc const& rhs)
693 {
694 return boost::unordered::detail::func::
695 call_select_on_container_copy_construction(rhs);
696 }
697
698 // Allocator propagation on assignment and swap.
699 // Return true if lhs is modified.
700 typedef BOOST_UNORDERED_DEFAULT_TYPE(
701 Alloc, propagate_on_container_copy_assignment, false_type)
702 propagate_on_container_copy_assignment;
703 typedef BOOST_UNORDERED_DEFAULT_TYPE(
704 Alloc,propagate_on_container_move_assignment, false_type)
705 propagate_on_container_move_assignment;
706 typedef BOOST_UNORDERED_DEFAULT_TYPE(
707 Alloc,propagate_on_container_swap,false_type)
708 propagate_on_container_swap;
709 };
710 }}}
711
712 # undef BOOST_UNORDERED_DEFAULT_TYPE_TMPLT
713 # undef BOOST_UNORDERED_DEFAULT_TYPE
714
715 ////////////////////////////////////////////////////////////////////////////////
716 //
717 // std::allocator_traits
718
719 #elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
720
721 # include <memory>
722
723 # define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 1
724
725 namespace boost { namespace unordered { namespace detail {
726
727 template <typename Alloc>
728 struct allocator_traits : std::allocator_traits<Alloc> {};
729
730 template <typename Alloc, typename T>
731 struct rebind_wrap
732 {
733 typedef typename std::allocator_traits<Alloc>::
734 template rebind_alloc<T> type;
735 };
736 }}}
737
738 ////////////////////////////////////////////////////////////////////////////////
739 //
740 // boost::container::allocator_traits
741
742 #elif BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 2
743
744 # include <boost/container/allocator_traits.hpp>
745
746 # define BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 0
747
748 namespace boost { namespace unordered { namespace detail {
749
750 template <typename Alloc>
751 struct allocator_traits :
752 boost::container::allocator_traits<Alloc> {};
753
754 template <typename Alloc, typename T>
755 struct rebind_wrap :
756 boost::container::allocator_traits<Alloc>::
757 template portable_rebind_alloc<T>
758 {};
759
760 }}}
761
762 #else
763
764 #error "Invalid BOOST_UNORDERED_USE_ALLOCATOR_TRAITS value."
765
766 #endif
767
768
769 namespace boost { namespace unordered { namespace detail { namespace func {
770
771 ////////////////////////////////////////////////////////////////////////////
772 // call_construct
773
774 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
775
776 # if BOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
777
778 template <typename Alloc, typename T, typename... Args>
779 inline void call_construct(Alloc& alloc, T* address,
780 BOOST_FWD_REF(Args)... args)
781 {
782 boost::unordered::detail::allocator_traits<Alloc>::construct(alloc,
783 address, boost::forward<Args>(args)...);
784 }
785
786 template <typename Alloc, typename T>
787 inline void destroy_value_impl(Alloc& alloc, T* x) {
788 boost::unordered::detail::allocator_traits<Alloc>::destroy(alloc, x);
789 }
790
791
792 # else
793
794 template <typename Alloc, typename T, typename... Args>
795 inline void call_construct(Alloc&, T* address,
796 BOOST_FWD_REF(Args)... args)
797 {
798 new((void*) address) T(boost::forward<Args>(args)...);
799 }
800
801 template <typename Alloc, typename T>
802 inline void destroy_value_impl(Alloc&, T* x) {
803 boost::unordered::detail::func::destroy(x);
804 }
805
806
807 # endif
808
809 #else
810
811 template <typename Alloc, typename T>
812 inline void destroy_value_impl(Alloc&, T* x) {
813 boost::unordered::detail::func::destroy(x);
814 }
815
816 #endif
817
818 ////////////////////////////////////////////////////////////////////////////
819 // Construct from tuple
820 //
821 // Used for piecewise construction.
822
823 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
824
825 # define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \
826 template<typename Alloc, typename T> \
827 void construct_from_tuple(Alloc& alloc, T* ptr, namespace_ tuple<>) \
828 { \
829 boost::unordered::detail::func::call_construct(alloc, ptr); \
830 } \
831 \
832 BOOST_PP_REPEAT_FROM_TO(1, n, \
833 BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_)
834
835 # define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_) \
836 template<typename Alloc, typename T, \
837 BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
838 void construct_from_tuple(Alloc& alloc, T* ptr, \
839 namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
840 { \
841 boost::unordered::detail::func::call_construct(alloc, ptr, \
842 BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \
843 ); \
844 }
845
846 # define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) \
847 namespace_ get<n>(x)
848
849 #elif !defined(__SUNPRO_CC)
850
851 # define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \
852 template<typename Alloc, typename T> \
853 void construct_from_tuple(Alloc&, T* ptr, namespace_ tuple<>) \
854 { \
855 new ((void*) ptr) T(); \
856 } \
857 \
858 BOOST_PP_REPEAT_FROM_TO(1, n, \
859 BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_)
860
861 # define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_) \
862 template<typename Alloc, typename T, \
863 BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
864 void construct_from_tuple(Alloc&, T* ptr, \
865 namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
866 { \
867 new ((void*) ptr) T( \
868 BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \
869 ); \
870 }
871
872 # define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) \
873 namespace_ get<n>(x)
874
875 #else
876
877 template <int N> struct length {};
878
879 # define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \
880 template<typename Alloc, typename T> \
881 void construct_from_tuple_impl( \
882 boost::unordered::detail::length<0>, Alloc&, T* ptr, \
883 namespace_ tuple<>) \
884 { \
885 new ((void*) ptr) T(); \
886 } \
887 \
888 BOOST_PP_REPEAT_FROM_TO(1, n, \
889 BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_)
890
891 # define BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_) \
892 template<typename Alloc, typename T, \
893 BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
894 void construct_from_tuple_impl( \
895 boost::unordered::detail::length<n>, Alloc&, T* ptr, \
896 namespace_ tuple<BOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
897 { \
898 new ((void*) ptr) T( \
899 BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \
900 ); \
901 }
902
903 # define BOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) \
904 namespace_ get<n>(x)
905
906 #endif
907
908 BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::)
909
910 #if !defined(__SUNPRO_CC) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
911 BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std::)
912 #endif
913
914 #undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE
915 #undef BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL
916 #undef BOOST_UNORDERED_GET_TUPLE_ARG
917
918 #if defined(__SUNPRO_CC)
919
920 template <typename Alloc, typename T, typename Tuple>
921 void construct_from_tuple(Alloc& alloc, T* ptr, Tuple const& x)
922 {
923 construct_from_tuple_impl(
924 boost::unordered::detail::length<
925 boost::tuples::length<Tuple>::value>(),
926 alloc, ptr, x);
927 }
928
929 #endif
930
931 ////////////////////////////////////////////////////////////////////////////
932 // Trait to check for piecewise construction.
933
934 template <typename A0>
935 struct use_piecewise {
936 static choice1::type test(choice1,
937 boost::unordered::piecewise_construct_t);
938
939 static choice2::type test(choice2, ...);
940
941 enum { value = sizeof(choice1::type) ==
942 sizeof(test(choose(), boost::unordered::detail::make<A0>())) };
943 };
944
945 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
946
947 ////////////////////////////////////////////////////////////////////////////
948 // Construct from variadic parameters
949
950 // For the standard pair constructor.
951
952 template <typename Alloc, typename T, typename... Args>
953 inline void construct_value_impl(Alloc& alloc, T* address,
954 BOOST_FWD_REF(Args)... args)
955 {
956 boost::unordered::detail::func::call_construct(alloc,
957 address, boost::forward<Args>(args)...);
958 }
959
960 // Special case for piece_construct
961 //
962 // TODO: When possible, it might be better to use std::pair's
963 // constructor for std::piece_construct with std::tuple.
964
965 template <typename Alloc, typename A, typename B,
966 typename A0, typename A1, typename A2>
967 inline typename enable_if<use_piecewise<A0>, void>::type
968 construct_value_impl(Alloc& alloc, std::pair<A, B>* address,
969 BOOST_FWD_REF(A0), BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2)
970 {
971 boost::unordered::detail::func::construct_from_tuple(alloc,
972 boost::addressof(address->first), boost::forward<A1>(a1));
973 boost::unordered::detail::func::construct_from_tuple(alloc,
974 boost::addressof(address->second), boost::forward<A2>(a2));
975 }
976
977 #else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
978
979 ////////////////////////////////////////////////////////////////////////////////
980 // Construct from emplace_args
981
982 // Explicitly write out first three overloads for the sake of sane
983 // error messages.
984
985 template <typename Alloc, typename T, typename A0>
986 inline void construct_value_impl(Alloc&, T* address,
987 emplace_args1<A0> const& args)
988 {
989 new((void*) address) T(boost::forward<A0>(args.a0));
990 }
991
992 template <typename Alloc, typename T, typename A0, typename A1>
993 inline void construct_value_impl(Alloc&, T* address,
994 emplace_args2<A0, A1> const& args)
995 {
996 new((void*) address) T(
997 boost::forward<A0>(args.a0),
998 boost::forward<A1>(args.a1)
999 );
1000 }
1001
1002 template <typename Alloc, typename T, typename A0, typename A1, typename A2>
1003 inline void construct_value_impl(Alloc&, T* address,
1004 emplace_args3<A0, A1, A2> const& args)
1005 {
1006 new((void*) address) T(
1007 boost::forward<A0>(args.a0),
1008 boost::forward<A1>(args.a1),
1009 boost::forward<A2>(args.a2)
1010 );
1011 }
1012
1013 // Use a macro for the rest.
1014
1015 #define BOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _) \
1016 template < \
1017 typename Alloc, typename T, \
1018 BOOST_PP_ENUM_PARAMS_Z(z, num_params, typename A) \
1019 > \
1020 inline void construct_value_impl(Alloc&, T* address, \
1021 boost::unordered::detail::BOOST_PP_CAT(emplace_args,num_params) < \
1022 BOOST_PP_ENUM_PARAMS_Z(z, num_params, A) \
1023 > const& args) \
1024 { \
1025 new((void*) address) T( \
1026 BOOST_PP_ENUM_##z(num_params, BOOST_UNORDERED_CALL_FORWARD, \
1027 args.a)); \
1028 }
1029
1030 BOOST_PP_REPEAT_FROM_TO(4, BOOST_UNORDERED_EMPLACE_LIMIT,
1031 BOOST_UNORDERED_CONSTRUCT_IMPL, _)
1032
1033 #undef BOOST_UNORDERED_CONSTRUCT_IMPL
1034
1035 // Construct with piece_construct
1036
1037 template <typename Alloc, typename A, typename B,
1038 typename A0, typename A1, typename A2>
1039 inline void construct_value_impl(Alloc& alloc, std::pair<A, B>* address,
1040 boost::unordered::detail::emplace_args3<A0, A1, A2> const& args,
1041 typename enable_if<use_piecewise<A0>, void*>::type = 0)
1042 {
1043 boost::unordered::detail::func::construct_from_tuple(alloc,
1044 boost::addressof(address->first), args.a1);
1045 boost::unordered::detail::func::construct_from_tuple(alloc,
1046 boost::addressof(address->second), args.a2);
1047 }
1048
1049 #endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
1050
1051 }}}}
1052
1053 namespace boost { namespace unordered { namespace detail {
1054
1055 ////////////////////////////////////////////////////////////////////////////
1056 //
1057 // array_constructor
1058 //
1059 // Allocate and construct an array in an exception safe manner, and
1060 // clean up if an exception is thrown before the container takes charge
1061 // of it.
1062
1063 template <typename Allocator>
1064 struct array_constructor
1065 {
1066 typedef boost::unordered::detail::allocator_traits<Allocator> traits;
1067 typedef typename traits::pointer pointer;
1068
1069 Allocator& alloc_;
1070 pointer ptr_;
1071 pointer constructed_;
1072 std::size_t length_;
1073
1074 array_constructor(Allocator& a)
1075 : alloc_(a), ptr_(), constructed_(), length_(0)
1076 {
1077 constructed_ = pointer();
1078 ptr_ = pointer();
1079 }
1080
1081 ~array_constructor() {
1082 if (ptr_) {
1083 for(pointer p = ptr_; p != constructed_; ++p)
1084 traits::destroy(alloc_, boost::addressof(*p));
1085
1086 traits::deallocate(alloc_, ptr_, length_);
1087 }
1088 }
1089
1090 template <typename V>
1091 void construct(V const& v, std::size_t l)
1092 {
1093 BOOST_ASSERT(!ptr_);
1094 length_ = l;
1095 ptr_ = traits::allocate(alloc_, length_);
1096 pointer end = ptr_ + static_cast<std::ptrdiff_t>(length_);
1097 for(constructed_ = ptr_; constructed_ != end; ++constructed_)
1098 traits::construct(alloc_, boost::addressof(*constructed_), v);
1099 }
1100
1101 pointer get() const
1102 {
1103 return ptr_;
1104 }
1105
1106 pointer release()
1107 {
1108 pointer p(ptr_);
1109 ptr_ = pointer();
1110 return p;
1111 }
1112
1113 private:
1114
1115 array_constructor(array_constructor const&);
1116 array_constructor& operator=(array_constructor const&);
1117 };
1118 }}}
1119
1120 #if defined(BOOST_MSVC)
1121 #pragma warning(pop)
1122 #endif
1123
1124 #endif