allocate.hpp 42 KB

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