blob: 4d6a8ed7effe29dea497be96658d16a4c4d54113 [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
Jeff Thompson3d613fd2013-10-15 15:39:04 -07009#ifndef NDNBOOST_UNORDERED_ALLOCATE_HPP
10#define NDNBOOST_UNORDERED_ALLOCATE_HPP
Jeff Thompsona28eed82013-08-22 16:21:10 -070011
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
Jeff Thompson3d613fd2013-10-15 15:39:04 -070034#if !defined(NDNBOOST_NO_CXX11_HDR_TUPLE)
Jeff Thompsona28eed82013-08-22 16:21:10 -070035#include <tuple>
36#endif
37
Jeff Thompson3d613fd2013-10-15 15:39:04 -070038#if defined(NDNBOOST_MSVC)
Jeff Thompsona28eed82013-08-22 16:21:10 -070039#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
Jeff Thompson3d613fd2013-10-15 15:39:04 -070046#define NDNBOOST_UNORDERED_EMPLACE_LIMIT 10
Jeff Thompsona28eed82013-08-22 16:21:10 -070047
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
Jeff Thompson3d613fd2013-10-15 15:39:04 -070088#if !defined(NDNBOOST_NO_CXX11_VARIADIC_TEMPLATES)
Jeff Thompsona28eed82013-08-22 16:21:10 -070089
Jeff Thompson3d613fd2013-10-15 15:39:04 -070090#define NDNBOOST_UNORDERED_EMPLACE_TEMPLATE typename... Args
91#define NDNBOOST_UNORDERED_EMPLACE_ARGS NDNBOOST_FWD_REF(Args)... args
92#define NDNBOOST_UNORDERED_EMPLACE_FORWARD ndnboost::forward<Args>(args)...
Jeff Thompsona28eed82013-08-22 16:21:10 -070093
Jeff Thompson3d613fd2013-10-15 15:39:04 -070094#define NDNBOOST_UNORDERED_EMPLACE_ARGS1(a0) a0
95#define NDNBOOST_UNORDERED_EMPLACE_ARGS2(a0, a1) a0, a1
96#define NDNBOOST_UNORDERED_EMPLACE_ARGS3(a0, a1, a2) a0, a1, a2
Jeff Thompsona28eed82013-08-22 16:21:10 -070097
98#else
99
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700100#define NDNBOOST_UNORDERED_EMPLACE_TEMPLATE typename Args
101#define NDNBOOST_UNORDERED_EMPLACE_ARGS Args const& args
102#define NDNBOOST_UNORDERED_EMPLACE_FORWARD args
Jeff Thompsona28eed82013-08-22 16:21:10 -0700103
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700104#define NDNBOOST_UNORDERED_FWD_PARAM(z, n, a) \
105 NDNBOOST_FWD_REF(NDNBOOST_PP_CAT(A, n)) NDNBOOST_PP_CAT(a, n)
Jeff Thompsona28eed82013-08-22 16:21:10 -0700106
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700107#define NDNBOOST_UNORDERED_CALL_FORWARD(z, i, a) \
108 ndnboost::forward<NDNBOOST_PP_CAT(A,i)>(NDNBOOST_PP_CAT(a,i))
Jeff Thompsona28eed82013-08-22 16:21:10 -0700109
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700110#define NDNBOOST_UNORDERED_EARGS(z, n, _) \
111 template <NDNBOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
112 struct NDNBOOST_PP_CAT(emplace_args, n) \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700113 { \
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700114 NDNBOOST_PP_REPEAT_##z(n, NDNBOOST_UNORDERED_EARGS_MEMBER, _) \
115 NDNBOOST_PP_CAT(emplace_args, n) ( \
116 NDNBOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, Arg, b) \
117 ) : NDNBOOST_PP_ENUM_##z(n, NDNBOOST_UNORDERED_EARGS_INIT, _) \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700118 {} \
119 \
120 }; \
121 \
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700122 template <NDNBOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
123 inline NDNBOOST_PP_CAT(emplace_args, n) < \
124 NDNBOOST_PP_ENUM_PARAMS_Z(z, n, A) \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700125 > create_emplace_args( \
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700126 NDNBOOST_PP_ENUM_##z(n, NDNBOOST_UNORDERED_FWD_PARAM, b) \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700127 ) \
128 { \
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700129 NDNBOOST_PP_CAT(emplace_args, n) < \
130 NDNBOOST_PP_ENUM_PARAMS_Z(z, n, A) \
131 > e(NDNBOOST_PP_ENUM_PARAMS_Z(z, n, b)); \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700132 return e; \
133 }
134
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700135#define NDNBOOST_UNORDERED_EMPLACE_ARGS1 create_emplace_args
136#define NDNBOOST_UNORDERED_EMPLACE_ARGS2 create_emplace_args
137#define NDNBOOST_UNORDERED_EMPLACE_ARGS3 create_emplace_args
Jeff Thompsona28eed82013-08-22 16:21:10 -0700138
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700139#if defined(NDNBOOST_NO_CXX11_RVALUE_REFERENCES)
Jeff Thompsona28eed82013-08-22 16:21:10 -0700140
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700141#define NDNBOOST_UNORDERED_EARGS_MEMBER(z, n, _) \
142 typedef NDNBOOST_FWD_REF(NDNBOOST_PP_CAT(A, n)) NDNBOOST_PP_CAT(Arg, n); \
143 NDNBOOST_PP_CAT(Arg, n) NDNBOOST_PP_CAT(a, n);
Jeff Thompsona28eed82013-08-22 16:21:10 -0700144
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700145#define NDNBOOST_UNORDERED_EARGS_INIT(z, n, _) \
146 NDNBOOST_PP_CAT(a, n)( \
147 ndnboost::forward<NDNBOOST_PP_CAT(A,n)>(NDNBOOST_PP_CAT(b, n)))
Jeff Thompsona28eed82013-08-22 16:21:10 -0700148
149#else
150
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700151#define NDNBOOST_UNORDERED_EARGS_MEMBER(z, n, _) \
152 typedef typename ndnboost::add_lvalue_reference<NDNBOOST_PP_CAT(A, n)>::type \
153 NDNBOOST_PP_CAT(Arg, n); \
154 NDNBOOST_PP_CAT(Arg, n) NDNBOOST_PP_CAT(a, n);
Jeff Thompsona28eed82013-08-22 16:21:10 -0700155
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700156#define NDNBOOST_UNORDERED_EARGS_INIT(z, n, _) \
157 NDNBOOST_PP_CAT(a, n)(NDNBOOST_PP_CAT(b, n))
Jeff Thompsona28eed82013-08-22 16:21:10 -0700158
159#endif
160
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700161NDNBOOST_PP_REPEAT_FROM_TO(1, NDNBOOST_UNORDERED_EMPLACE_LIMIT, NDNBOOST_UNORDERED_EARGS,
Jeff Thompsona28eed82013-08-22 16:21:10 -0700162 _)
163
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700164#undef NDNBOOST_UNORDERED_DEFINE_EMPLACE_ARGS
165#undef NDNBOOST_UNORDERED_EARGS_MEMBER
166#undef NDNBOOST_UNORDERED_EARGS_INIT
Jeff Thompsona28eed82013-08-22 16:21:10 -0700167
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
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700180#if !defined(NDNBOOST_UNORDERED_USE_ALLOCATOR_TRAITS)
Jeff Thompsona28eed82013-08-22 16:21:10 -0700181# if defined(__GXX_EXPERIMENTAL_CXX0X__) && \
182 (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700183# define NDNBOOST_UNORDERED_USE_ALLOCATOR_TRAITS 0
184# elif defined(NDNBOOST_MSVC)
185# if NDNBOOST_MSVC < 1400
Jeff Thompsona28eed82013-08-22 16:21:10 -0700186 // Use container's allocator_traits for older versions of Visual
187 // C++ as I don't test with them.
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700188# define NDNBOOST_UNORDERED_USE_ALLOCATOR_TRAITS 2
Jeff Thompsona28eed82013-08-22 16:21:10 -0700189# endif
190# endif
191#endif
192
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700193#if !defined(NDNBOOST_UNORDERED_USE_ALLOCATOR_TRAITS)
194# define NDNBOOST_UNORDERED_USE_ALLOCATOR_TRAITS 0
Jeff Thompsona28eed82013-08-22 16:21:10 -0700195#endif
196
197////////////////////////////////////////////////////////////////////////////////
198//
199// Some utilities for implementing allocator_traits, but useful elsewhere so
200// they're always defined.
201
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700202#if !defined(NDNBOOST_NO_CXX11_HDR_TYPE_TRAITS)
Jeff Thompsona28eed82013-08-22 16:21:10 -0700203# 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
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700213#if !defined(NDNBOOST_NO_CXX11_HDR_TYPE_TRAITS)
Jeff Thompsona28eed82013-08-22 16:21:10 -0700214
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
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700232#if defined(NDNBOOST_MSVC)
Jeff Thompsona28eed82013-08-22 16:21:10 -0700233#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
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700242#if defined(NDNBOOST_MSVC)
Jeff Thompsona28eed82013-08-22 16:21:10 -0700243#pragma warning(pop)
244#endif
245
246 ////////////////////////////////////////////////////////////////////////////
247 // Expression test mechanism
248 //
249 // When SFINAE expressions are available, define
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700250 // NDNBOOST_UNORDERED_HAS_FUNCTION which can check if a function call is
251 // supported by a class, otherwise define NDNBOOST_UNORDERED_HAS_MEMBER which
Jeff Thompsona28eed82013-08-22 16:21:10 -0700252 // 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
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700256#if !defined(NDNBOOST_NO_SFINAE_EXPR)
Jeff Thompsona28eed82013-08-22 16:21:10 -0700257
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
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700262# define NDNBOOST_UNORDERED_CHECK_EXPRESSION(count, result, expression) \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700263 template <typename U> \
264 static typename ndnboost::unordered::detail::expr_test< \
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700265 NDNBOOST_PP_CAT(choice, result), \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700266 sizeof(ndnboost::unordered::detail::for_expr_test(( \
267 (expression), \
268 0)))>::type test( \
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700269 NDNBOOST_PP_CAT(choice, count))
Jeff Thompsona28eed82013-08-22 16:21:10 -0700270
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700271# define NDNBOOST_UNORDERED_DEFAULT_EXPRESSION(count, result) \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700272 template <typename U> \
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700273 static NDNBOOST_PP_CAT(choice, result)::type test( \
274 NDNBOOST_PP_CAT(choice, count))
Jeff Thompsona28eed82013-08-22 16:21:10 -0700275
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700276# define NDNBOOST_UNORDERED_HAS_FUNCTION(name, thing, args, _) \
277 struct NDNBOOST_PP_CAT(has_, name) \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700278 { \
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700279 NDNBOOST_UNORDERED_CHECK_EXPRESSION(1, 1, \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700280 ndnboost::unordered::detail::make< thing >().name args); \
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700281 NDNBOOST_UNORDERED_DEFAULT_EXPRESSION(2, 2); \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700282 \
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
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700290# define NDNBOOST_UNORDERED_CHECK_MEMBER(count, result, name, member) \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700291 \
292 typedef typename ndnboost::unordered::detail::identity<member>::type \
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700293 NDNBOOST_PP_CAT(check, count); \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700294 \
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700295 template <NDNBOOST_PP_CAT(check, count) e> \
296 struct NDNBOOST_PP_CAT(test, count) { \
297 typedef NDNBOOST_PP_CAT(choice, result) type; \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700298 }; \
299 \
300 template <class U> static typename \
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700301 NDNBOOST_PP_CAT(test, count)<&U::name>::type \
302 test(NDNBOOST_PP_CAT(choice, count))
Jeff Thompsona28eed82013-08-22 16:21:10 -0700303
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700304# define NDNBOOST_UNORDERED_DEFAULT_MEMBER(count, result) \
305 template <class U> static NDNBOOST_PP_CAT(choice, result)::type \
306 test(NDNBOOST_PP_CAT(choice, count))
Jeff Thompsona28eed82013-08-22 16:21:10 -0700307
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700308# define NDNBOOST_UNORDERED_HAS_MEMBER(name) \
309 struct NDNBOOST_PP_CAT(has_, name) \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700310 { \
311 struct impl { \
312 struct base_mixin { int name; }; \
313 struct base : public T, public base_mixin {}; \
314 \
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700315 NDNBOOST_UNORDERED_CHECK_MEMBER(1, 1, name, int base_mixin::*); \
316 NDNBOOST_UNORDERED_DEFAULT_MEMBER(2, 2); \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700317 \
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
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700336#if NDNBOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 0
Jeff Thompsona28eed82013-08-22 16:21:10 -0700337
338# include <ndnboost/limits.hpp>
339# include <ndnboost/utility/enable_if.hpp>
340# include <ndnboost/pointer_to_other.hpp>
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700341# if defined(NDNBOOST_NO_SFINAE_EXPR)
Jeff Thompsona28eed82013-08-22 16:21:10 -0700342# include <ndnboost/type_traits/is_same.hpp>
343# endif
344
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700345# if !defined(NDNBOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
346 !defined(NDNBOOST_NO_SFINAE_EXPR)
347# define NDNBOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 1
Jeff Thompsona28eed82013-08-22 16:21:10 -0700348# else
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700349# define NDNBOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 0
Jeff Thompsona28eed82013-08-22 16:21:10 -0700350# 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 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700358 typedef typename Alloc::NDNBOOST_NESTED_TEMPLATE rebind<T>::other type;
Jeff Thompsona28eed82013-08-22 16:21:10 -0700359 };
360
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700361# if defined(NDNBOOST_MSVC) && NDNBOOST_MSVC <= 1400
Jeff Thompsona28eed82013-08-22 16:21:10 -0700362
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700363# define NDNBOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700364 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>:: \
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700378 NDNBOOST_NESTED_TEMPLATE then<Tp, DefaultWrap> \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700379 ::type::tname type; \
380 }
381
382# else
383
384 template <typename T, typename T2>
385 struct sfinae : T2 {};
386
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700387# define NDNBOOST_UNORDERED_DEFAULT_TYPE_TMPLT(tname) \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700388 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>:: \
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700404 NDNBOOST_NESTED_TEMPLATE then<Tp, DefaultWrap> \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700405 ::type::tname type; \
406 }
407
408# endif
409
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700410# define NDNBOOST_UNORDERED_DEFAULT_TYPE(T,tname, arg) \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700411 typename default_type_ ## tname<T, arg>::type
412
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700413 NDNBOOST_UNORDERED_DEFAULT_TYPE_TMPLT(pointer);
414 NDNBOOST_UNORDERED_DEFAULT_TYPE_TMPLT(const_pointer);
415 NDNBOOST_UNORDERED_DEFAULT_TYPE_TMPLT(void_pointer);
416 NDNBOOST_UNORDERED_DEFAULT_TYPE_TMPLT(const_void_pointer);
417 NDNBOOST_UNORDERED_DEFAULT_TYPE_TMPLT(difference_type);
418 NDNBOOST_UNORDERED_DEFAULT_TYPE_TMPLT(size_type);
419 NDNBOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_copy_assignment);
420 NDNBOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_move_assignment);
421 NDNBOOST_UNORDERED_DEFAULT_TYPE_TMPLT(propagate_on_container_swap);
Jeff Thompsona28eed82013-08-22 16:21:10 -0700422
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700423# if !defined(NDNBOOST_NO_SFINAE_EXPR)
Jeff Thompsona28eed82013-08-22 16:21:10 -0700424
425 template <typename T>
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700426 NDNBOOST_UNORDERED_HAS_FUNCTION(
Jeff Thompsona28eed82013-08-22 16:21:10 -0700427 select_on_container_copy_construction, U const, (), 0
428 );
429
430 template <typename T>
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700431 NDNBOOST_UNORDERED_HAS_FUNCTION(
Jeff Thompsona28eed82013-08-22 16:21:10 -0700432 max_size, U const, (), 0
433 );
434
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700435# if !defined(NDNBOOST_NO_CXX11_VARIADIC_TEMPLATES)
Jeff Thompsona28eed82013-08-22 16:21:10 -0700436
437 template <typename T, typename ValueType, typename... Args>
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700438 NDNBOOST_UNORDERED_HAS_FUNCTION(
Jeff Thompsona28eed82013-08-22 16:21:10 -0700439 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>
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700447 NDNBOOST_UNORDERED_HAS_FUNCTION(
Jeff Thompsona28eed82013-08-22 16:21:10 -0700448 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>
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700456 NDNBOOST_UNORDERED_HAS_FUNCTION(
Jeff Thompsona28eed82013-08-22 16:21:10 -0700457 destroy, U, (ndnboost::unordered::detail::make<ValueType*>()), 1
458 );
459
460# else
461
462 template <typename T>
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700463 NDNBOOST_UNORDERED_HAS_MEMBER(select_on_container_copy_construction);
Jeff Thompsona28eed82013-08-22 16:21:10 -0700464
465 template <typename T>
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700466 NDNBOOST_UNORDERED_HAS_MEMBER(max_size);
Jeff Thompsona28eed82013-08-22 16:21:10 -0700467
468 template <typename T, typename ValueType>
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700469 NDNBOOST_UNORDERED_HAS_MEMBER(construct);
Jeff Thompsona28eed82013-08-22 16:21:10 -0700470
471 template <typename T, typename ValueType>
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700472 NDNBOOST_UNORDERED_HAS_MEMBER(destroy);
Jeff Thompsona28eed82013-08-22 16:21:10 -0700473
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
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700519 typedef NDNBOOST_UNORDERED_DEFAULT_TYPE(Alloc, pointer, value_type*)
Jeff Thompsona28eed82013-08-22 16:21:10 -0700520 pointer;
521
522 template <typename T>
523 struct pointer_to_other : ndnboost::pointer_to_other<pointer, T> {};
524
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700525 typedef NDNBOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_pointer,
Jeff Thompsona28eed82013-08-22 16:21:10 -0700526 typename pointer_to_other<const value_type>::type)
527 const_pointer;
528
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700529 //typedef NDNBOOST_UNORDERED_DEFAULT_TYPE(Alloc, void_pointer,
Jeff Thompsona28eed82013-08-22 16:21:10 -0700530 // typename pointer_to_other<void>::type)
531 // void_pointer;
532 //
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700533 //typedef NDNBOOST_UNORDERED_DEFAULT_TYPE(Alloc, const_void_pointer,
Jeff Thompsona28eed82013-08-22 16:21:10 -0700534 // typename pointer_to_other<const void>::type)
535 // const_void_pointer;
536
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700537 typedef NDNBOOST_UNORDERED_DEFAULT_TYPE(Alloc, difference_type,
Jeff Thompsona28eed82013-08-22 16:21:10 -0700538 std::ptrdiff_t) difference_type;
539
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700540 typedef NDNBOOST_UNORDERED_DEFAULT_TYPE(Alloc, size_type, std::size_t)
Jeff Thompsona28eed82013-08-22 16:21:10 -0700541 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
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700559# if NDNBOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
Jeff Thompsona28eed82013-08-22 16:21:10 -0700560
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
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700565 construct(Alloc& a, T* p, NDNBOOST_FWD_REF(Args)... x)
Jeff Thompsona28eed82013-08-22 16:21:10 -0700566 {
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
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700574 construct(Alloc&, T* p, NDNBOOST_FWD_REF(Args)... x)
Jeff Thompsona28eed82013-08-22 16:21:10 -0700575 {
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
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700595# elif !defined(NDNBOOST_NO_SFINAE_EXPR)
Jeff Thompsona28eed82013-08-22 16:21:10 -0700596
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.
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700692 typedef NDNBOOST_UNORDERED_DEFAULT_TYPE(
Jeff Thompsona28eed82013-08-22 16:21:10 -0700693 Alloc, propagate_on_container_copy_assignment, false_type)
694 propagate_on_container_copy_assignment;
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700695 typedef NDNBOOST_UNORDERED_DEFAULT_TYPE(
Jeff Thompsona28eed82013-08-22 16:21:10 -0700696 Alloc,propagate_on_container_move_assignment, false_type)
697 propagate_on_container_move_assignment;
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700698 typedef NDNBOOST_UNORDERED_DEFAULT_TYPE(
Jeff Thompsona28eed82013-08-22 16:21:10 -0700699 Alloc,propagate_on_container_swap,false_type)
700 propagate_on_container_swap;
701 };
702}}}
703
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700704# undef NDNBOOST_UNORDERED_DEFAULT_TYPE_TMPLT
705# undef NDNBOOST_UNORDERED_DEFAULT_TYPE
Jeff Thompsona28eed82013-08-22 16:21:10 -0700706
707////////////////////////////////////////////////////////////////////////////////
708//
709// std::allocator_traits
710
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700711#elif NDNBOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 1
Jeff Thompsona28eed82013-08-22 16:21:10 -0700712
713# include <memory>
714
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700715# define NDNBOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 1
Jeff Thompsona28eed82013-08-22 16:21:10 -0700716
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
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700734#elif NDNBOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 2
Jeff Thompsona28eed82013-08-22 16:21:10 -0700735
736# include <ndnboost/container/allocator_traits.hpp>
737
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700738# define NDNBOOST_UNORDERED_DETAIL_FULL_CONSTRUCT 0
Jeff Thompsona28eed82013-08-22 16:21:10 -0700739
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
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700756#error "Invalid NDNBOOST_UNORDERED_USE_ALLOCATOR_TRAITS value."
Jeff Thompsona28eed82013-08-22 16:21:10 -0700757
758#endif
759
760
761namespace ndnboost { namespace unordered { namespace detail {
762
763 ////////////////////////////////////////////////////////////////////////////
764 // call_construct
765
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700766#if !defined(NDNBOOST_NO_CXX11_VARIADIC_TEMPLATES)
Jeff Thompsona28eed82013-08-22 16:21:10 -0700767
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700768# if NDNBOOST_UNORDERED_DETAIL_FULL_CONSTRUCT
Jeff Thompsona28eed82013-08-22 16:21:10 -0700769
770 template <typename Alloc, typename T, typename... Args>
771 inline void call_construct(Alloc& alloc, T* address,
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700772 NDNBOOST_FWD_REF(Args)... args)
Jeff Thompsona28eed82013-08-22 16:21:10 -0700773 {
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,
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700788 NDNBOOST_FWD_REF(Args)... args)
Jeff Thompsona28eed82013-08-22 16:21:10 -0700789 {
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
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700815#if !defined(NDNBOOST_NO_CXX11_VARIADIC_TEMPLATES)
Jeff Thompsona28eed82013-08-22 16:21:10 -0700816
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700817# define NDNBOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700818 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 \
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700824 NDNBOOST_PP_REPEAT_FROM_TO(1, n, \
825 NDNBOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_)
Jeff Thompsona28eed82013-08-22 16:21:10 -0700826
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700827# define NDNBOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_) \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700828 template<typename Alloc, typename T, \
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700829 NDNBOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700830 void construct_from_tuple(Alloc& alloc, T* ptr, \
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700831 namespace_ tuple<NDNBOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700832 { \
833 ndnboost::unordered::detail::call_construct(alloc, ptr, \
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700834 NDNBOOST_PP_ENUM_##z(n, NDNBOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700835 ); \
836 }
837
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700838# define NDNBOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700839 namespace_ get<n>(x)
840
841#elif !defined(__SUNPRO_CC)
842
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700843# define NDNBOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700844 template<typename Alloc, typename T> \
845 void construct_from_tuple(Alloc&, T* ptr, namespace_ tuple<>) \
846 { \
847 new ((void*) ptr) T(); \
848 } \
849 \
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700850 NDNBOOST_PP_REPEAT_FROM_TO(1, n, \
851 NDNBOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_)
Jeff Thompsona28eed82013-08-22 16:21:10 -0700852
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700853# define NDNBOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_) \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700854 template<typename Alloc, typename T, \
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700855 NDNBOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700856 void construct_from_tuple(Alloc&, T* ptr, \
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700857 namespace_ tuple<NDNBOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700858 { \
859 new ((void*) ptr) T( \
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700860 NDNBOOST_PP_ENUM_##z(n, NDNBOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700861 ); \
862 }
863
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700864# define NDNBOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700865 namespace_ get<n>(x)
866
867#else
868
869 template <int N> struct length {};
870
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700871# define NDNBOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(n, namespace_) \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700872 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 \
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700880 NDNBOOST_PP_REPEAT_FROM_TO(1, n, \
881 NDNBOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL, namespace_)
Jeff Thompsona28eed82013-08-22 16:21:10 -0700882
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700883# define NDNBOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL(z, n, namespace_) \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700884 template<typename Alloc, typename T, \
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700885 NDNBOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700886 void construct_from_tuple_impl( \
887 ndnboost::unordered::detail::length<n>, Alloc&, T* ptr, \
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700888 namespace_ tuple<NDNBOOST_PP_ENUM_PARAMS_Z(z, n, A)> const& x) \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700889 { \
890 new ((void*) ptr) T( \
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700891 NDNBOOST_PP_ENUM_##z(n, NDNBOOST_UNORDERED_GET_TUPLE_ARG, namespace_) \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700892 ); \
893 }
894
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700895# define NDNBOOST_UNORDERED_GET_TUPLE_ARG(z, n, namespace_) \
Jeff Thompsona28eed82013-08-22 16:21:10 -0700896 namespace_ get<n>(x)
897
898#endif
899
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700900NDNBOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, ndnboost::)
Jeff Thompsona28eed82013-08-22 16:21:10 -0700901
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700902#if !defined(__SUNPRO_CC) && !defined(NDNBOOST_NO_CXX11_HDR_TUPLE)
903 NDNBOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, std::)
Jeff Thompsona28eed82013-08-22 16:21:10 -0700904#endif
905
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700906#undef NDNBOOST_UNORDERED_CONSTRUCT_FROM_TUPLE
907#undef NDNBOOST_UNORDERED_CONSTRUCT_FROM_TUPLE_IMPL
908#undef NDNBOOST_UNORDERED_GET_TUPLE_ARG
Jeff Thompsona28eed82013-08-22 16:21:10 -0700909
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
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700937#if !defined(NDNBOOST_NO_CXX11_VARIADIC_TEMPLATES)
Jeff Thompsona28eed82013-08-22 16:21:10 -0700938
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,
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700946 NDNBOOST_FWD_REF(Args)... args)
Jeff Thompsona28eed82013-08-22 16:21:10 -0700947 {
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,
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700961 NDNBOOST_FWD_REF(A0), NDNBOOST_FWD_REF(A1) a1, NDNBOOST_FWD_REF(A2) a2)
Jeff Thompsona28eed82013-08-22 16:21:10 -0700962 {
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
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700969#else // NDNBOOST_NO_CXX11_VARIADIC_TEMPLATES
Jeff Thompsona28eed82013-08-22 16:21:10 -0700970
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
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001007#define NDNBOOST_UNORDERED_CONSTRUCT_IMPL(z, num_params, _) \
Jeff Thompsona28eed82013-08-22 16:21:10 -07001008 template < \
1009 typename Alloc, typename T, \
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001010 NDNBOOST_PP_ENUM_PARAMS_Z(z, num_params, typename A) \
Jeff Thompsona28eed82013-08-22 16:21:10 -07001011 > \
1012 inline void construct_value_impl(Alloc&, T* address, \
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001013 ndnboost::unordered::detail::NDNBOOST_PP_CAT(emplace_args,num_params) < \
1014 NDNBOOST_PP_ENUM_PARAMS_Z(z, num_params, A) \
Jeff Thompsona28eed82013-08-22 16:21:10 -07001015 > const& args) \
1016 { \
1017 new((void*) address) T( \
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001018 NDNBOOST_PP_ENUM_##z(num_params, NDNBOOST_UNORDERED_CALL_FORWARD, \
Jeff Thompsona28eed82013-08-22 16:21:10 -07001019 args.a)); \
1020 }
1021
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001022 NDNBOOST_PP_REPEAT_FROM_TO(4, NDNBOOST_UNORDERED_EMPLACE_LIMIT,
1023 NDNBOOST_UNORDERED_CONSTRUCT_IMPL, _)
Jeff Thompsona28eed82013-08-22 16:21:10 -07001024
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001025#undef NDNBOOST_UNORDERED_CONSTRUCT_IMPL
Jeff Thompsona28eed82013-08-22 16:21:10 -07001026
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
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001041#endif // NDNBOOST_NO_CXX11_VARIADIC_TEMPLATES
Jeff Thompsona28eed82013-08-22 16:21:10 -07001042
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 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001089 NDNBOOST_ASSERT(!ptr_);
Jeff Thompsona28eed82013-08-22 16:21:10 -07001090 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
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001116#if defined(NDNBOOST_MSVC)
Jeff Thompsona28eed82013-08-22 16:21:10 -07001117#pragma warning(pop)
1118#endif
1119
1120#endif