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