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