hash_index_node.hpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772
  1. /* Copyright 2003-2019 Joaquin M Lopez Munoz.
  2. * Distributed under the Boost Software License, Version 1.0.
  3. * (See accompanying file LICENSE_1_0.txt or copy at
  4. * http://www.boost.org/LICENSE_1_0.txt)
  5. *
  6. * See http://www.boost.org/libs/multi_index for library home page.
  7. */
  8. #ifndef BOOST_MULTI_INDEX_DETAIL_HASH_INDEX_NODE_HPP
  9. #define BOOST_MULTI_INDEX_DETAIL_HASH_INDEX_NODE_HPP
  10. #if defined(_MSC_VER)
  11. #pragma once
  12. #endif
  13. #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
  14. #include <boost/multi_index/detail/allocator_traits.hpp>
  15. #include <boost/multi_index/detail/raw_ptr.hpp>
  16. #include <utility>
  17. namespace boost{
  18. namespace multi_index{
  19. namespace detail{
  20. /* Certain C++ requirements on unordered associative containers (see LWG issue
  21. * #579) imply a data structure where nodes are linked in a single list, which
  22. * in its turn forces implementors to add additional overhed per node to
  23. * associate each with its corresponding bucket. Others resort to storing hash
  24. * values, we use an alternative structure providing unconditional O(1)
  25. * manipulation, even in situations of unfair hash distribution, plus some
  26. * lookup speedups. For unique indices we maintain a doubly linked list of
  27. * nodes except that if N is the first node of a bucket its associated
  28. * bucket node is embedded between N and the preceding node in the following
  29. * manner:
  30. *
  31. * +---+ +---+ +---+ +---+
  32. * <--+ |<--+ | <--+ |<--+ |
  33. * ... | B0| | B1| ... | B1| | B2| ...
  34. * | |-+ | +--> | |-+ | +-->
  35. * +-+-+ | +---+ +-+-+ | +---+
  36. * | ^ | ^
  37. * | | | |
  38. * | +-+ | +-+
  39. * | | | |
  40. * v | v |
  41. * --+---+---+---+-- --+---+---+---+--
  42. * ... | | B1| | ... | | B2| | ...
  43. * --+---+---+---+-- --+---+---+---+--
  44. *
  45. *
  46. * The fist and last nodes of buckets can be checked with
  47. *
  48. * first node of a bucket: Npn != N
  49. * last node of a bucket: Nnp != N
  50. *
  51. * (n and p short for ->next(), ->prior(), bucket nodes have prior pointers
  52. * only). Pure insert and erase (without lookup) can be unconditionally done
  53. * in O(1).
  54. * For non-unique indices we add the following additional complexity: when
  55. * there is a group of 3 or more equivalent elements, they are linked as
  56. * follows:
  57. *
  58. * +-----------------------+
  59. * | v
  60. * +---+ | +---+ +---+ +---+
  61. * | | +-+ | | |<--+ |
  62. * | F | | S | ... | P | | L |
  63. * | +-->| | | +-+ | |
  64. * +---+ +---+ +---+ | +---+
  65. * ^ |
  66. * +-----------------------+
  67. *
  68. * F, S, P and L are the first, second, penultimate and last node in the
  69. * group, respectively (S and P can coincide if the group has size 3.) This
  70. * arrangement is used to skip equivalent elements in O(1) when doing lookup,
  71. * while preserving O(1) insert/erase. The following invariants identify
  72. * special positions (some of the operations have to be carefully implemented
  73. * as Xnn is not valid if Xn points to a bucket):
  74. *
  75. * first node of a bucket: Npnp == N
  76. * last node of a bucket: Nnpp == N
  77. * first node of a group: Nnp != N && Nnppn == N
  78. * second node of a group: Npn != N && Nppnn == N
  79. * n-1 node of a group: Nnp != N && Nnnpp == N
  80. * last node of a group: Npn != N && Npnnp == N
  81. *
  82. * The memory overhead is one pointer per bucket plus two pointers per node,
  83. * probably unbeatable. The resulting structure is bidirectonally traversable,
  84. * though currently we are just providing forward iteration.
  85. */
  86. template<typename Allocator>
  87. struct hashed_index_node_impl;
  88. /* half-header (only prior() pointer) to use for the bucket array */
  89. template<typename Allocator>
  90. struct hashed_index_base_node_impl
  91. {
  92. typedef typename rebind_alloc_for<
  93. Allocator,hashed_index_base_node_impl
  94. >::type base_allocator;
  95. typedef typename rebind_alloc_for<
  96. Allocator,hashed_index_node_impl<Allocator>
  97. >::type node_allocator;
  98. typedef allocator_traits<base_allocator> base_alloc_traits;
  99. typedef allocator_traits<node_allocator> node_alloc_traits;
  100. typedef typename base_alloc_traits::pointer base_pointer;
  101. typedef typename base_alloc_traits::const_pointer const_base_pointer;
  102. typedef typename node_alloc_traits::pointer pointer;
  103. typedef typename node_alloc_traits::const_pointer const_pointer;
  104. typedef typename node_alloc_traits::difference_type difference_type;
  105. pointer& prior(){return prior_;}
  106. pointer prior()const{return prior_;}
  107. private:
  108. pointer prior_;
  109. };
  110. /* full header (prior() and next()) for the nodes */
  111. template<typename Allocator>
  112. struct hashed_index_node_impl:hashed_index_base_node_impl<Allocator>
  113. {
  114. private:
  115. typedef hashed_index_base_node_impl<Allocator> super;
  116. public:
  117. typedef typename super::base_pointer base_pointer;
  118. typedef typename super::const_base_pointer const_base_pointer;
  119. typedef typename super::pointer pointer;
  120. typedef typename super::const_pointer const_pointer;
  121. base_pointer& next(){return next_;}
  122. base_pointer next()const{return next_;}
  123. static pointer pointer_from(base_pointer x)
  124. {
  125. return static_cast<pointer>(
  126. static_cast<hashed_index_node_impl*>(
  127. raw_ptr<super*>(x)));
  128. }
  129. static base_pointer base_pointer_from(pointer x)
  130. {
  131. return static_cast<base_pointer>(
  132. raw_ptr<hashed_index_node_impl*>(x));
  133. }
  134. private:
  135. base_pointer next_;
  136. };
  137. /* Boost.MultiIndex requires machinery to reverse unlink operations. A simple
  138. * way to make a pointer-manipulation function undoable is to templatize
  139. * its internal pointer assignments with a functor that, besides doing the
  140. * assignment, keeps track of the original pointer values and can later undo
  141. * the operations in reverse order.
  142. */
  143. struct default_assigner
  144. {
  145. template<typename T> void operator()(T& x,const T& val){x=val;}
  146. };
  147. template<typename Node>
  148. struct unlink_undo_assigner
  149. {
  150. typedef typename Node::base_pointer base_pointer;
  151. typedef typename Node::pointer pointer;
  152. unlink_undo_assigner():pointer_track_count(0),base_pointer_track_count(0){}
  153. void operator()(pointer& x,pointer val)
  154. {
  155. pointer_tracks[pointer_track_count].x=&x;
  156. pointer_tracks[pointer_track_count++].val=x;
  157. x=val;
  158. }
  159. void operator()(base_pointer& x,base_pointer val)
  160. {
  161. base_pointer_tracks[base_pointer_track_count].x=&x;
  162. base_pointer_tracks[base_pointer_track_count++].val=x;
  163. x=val;
  164. }
  165. void operator()() /* undo op */
  166. {
  167. /* in the absence of aliasing, restitution order is immaterial */
  168. while(pointer_track_count--){
  169. *(pointer_tracks[pointer_track_count].x)=
  170. pointer_tracks[pointer_track_count].val;
  171. }
  172. while(base_pointer_track_count--){
  173. *(base_pointer_tracks[base_pointer_track_count].x)=
  174. base_pointer_tracks[base_pointer_track_count].val;
  175. }
  176. }
  177. struct pointer_track {pointer* x; pointer val;};
  178. struct base_pointer_track{base_pointer* x; base_pointer val;};
  179. /* We know the maximum number of pointer and base pointer assignments that
  180. * the two unlink versions do, so we can statically reserve the needed
  181. * storage.
  182. */
  183. pointer_track pointer_tracks[3];
  184. int pointer_track_count;
  185. base_pointer_track base_pointer_tracks[2];
  186. int base_pointer_track_count;
  187. };
  188. /* algorithmic stuff for unique and non-unique variants */
  189. struct hashed_unique_tag{};
  190. struct hashed_non_unique_tag{};
  191. template<typename Node,typename Category>
  192. struct hashed_index_node_alg;
  193. template<typename Node>
  194. struct hashed_index_node_alg<Node,hashed_unique_tag>
  195. {
  196. typedef typename Node::base_pointer base_pointer;
  197. typedef typename Node::const_base_pointer const_base_pointer;
  198. typedef typename Node::pointer pointer;
  199. typedef typename Node::const_pointer const_pointer;
  200. static bool is_first_of_bucket(pointer x)
  201. {
  202. return x->prior()->next()!=base_pointer_from(x);
  203. }
  204. static pointer after(pointer x)
  205. {
  206. return is_last_of_bucket(x)?x->next()->prior():pointer_from(x->next());
  207. }
  208. static pointer after_local(pointer x)
  209. {
  210. return is_last_of_bucket(x)?pointer(0):pointer_from(x->next());
  211. }
  212. static pointer next_to_inspect(pointer x)
  213. {
  214. return is_last_of_bucket(x)?pointer(0):pointer_from(x->next());
  215. }
  216. static void link(pointer x,base_pointer buc,pointer end)
  217. {
  218. if(buc->prior()==pointer(0)){ /* empty bucket */
  219. x->prior()=end->prior();
  220. x->next()=end->prior()->next();
  221. x->prior()->next()=buc;
  222. buc->prior()=x;
  223. end->prior()=x;
  224. }
  225. else{
  226. x->prior()=buc->prior()->prior();
  227. x->next()=base_pointer_from(buc->prior());
  228. buc->prior()=x;
  229. x->next()->prior()=x;
  230. }
  231. }
  232. static void unlink(pointer x)
  233. {
  234. default_assigner assign;
  235. unlink(x,assign);
  236. }
  237. typedef unlink_undo_assigner<Node> unlink_undo;
  238. template<typename Assigner>
  239. static void unlink(pointer x,Assigner& assign)
  240. {
  241. if(is_first_of_bucket(x)){
  242. if(is_last_of_bucket(x)){
  243. assign(x->prior()->next()->prior(),pointer(0));
  244. assign(x->prior()->next(),x->next());
  245. assign(x->next()->prior()->prior(),x->prior());
  246. }
  247. else{
  248. assign(x->prior()->next()->prior(),pointer_from(x->next()));
  249. assign(x->next()->prior(),x->prior());
  250. }
  251. }
  252. else if(is_last_of_bucket(x)){
  253. assign(x->prior()->next(),x->next());
  254. assign(x->next()->prior()->prior(),x->prior());
  255. }
  256. else{
  257. assign(x->prior()->next(),x->next());
  258. assign(x->next()->prior(),x->prior());
  259. }
  260. }
  261. /* used only at rehashing */
  262. static void append(pointer x,pointer end)
  263. {
  264. x->prior()=end->prior();
  265. x->next()=end->prior()->next();
  266. x->prior()->next()=base_pointer_from(x);
  267. end->prior()=x;
  268. }
  269. static bool unlink_last(pointer end)
  270. {
  271. /* returns true iff bucket is emptied */
  272. pointer x=end->prior();
  273. if(x->prior()->next()==base_pointer_from(x)){
  274. x->prior()->next()=x->next();
  275. end->prior()=x->prior();
  276. return false;
  277. }
  278. else{
  279. x->prior()->next()->prior()=pointer(0);
  280. x->prior()->next()=x->next();
  281. end->prior()=x->prior();
  282. return true;
  283. }
  284. }
  285. private:
  286. static pointer pointer_from(base_pointer x)
  287. {
  288. return Node::pointer_from(x);
  289. }
  290. static base_pointer base_pointer_from(pointer x)
  291. {
  292. return Node::base_pointer_from(x);
  293. }
  294. static bool is_last_of_bucket(pointer x)
  295. {
  296. return x->next()->prior()!=x;
  297. }
  298. };
  299. template<typename Node>
  300. struct hashed_index_node_alg<Node,hashed_non_unique_tag>
  301. {
  302. typedef typename Node::base_pointer base_pointer;
  303. typedef typename Node::const_base_pointer const_base_pointer;
  304. typedef typename Node::pointer pointer;
  305. typedef typename Node::const_pointer const_pointer;
  306. static bool is_first_of_bucket(pointer x)
  307. {
  308. return x->prior()->next()->prior()==x;
  309. }
  310. static bool is_first_of_group(pointer x)
  311. {
  312. return
  313. x->next()->prior()!=x&&
  314. x->next()->prior()->prior()->next()==base_pointer_from(x);
  315. }
  316. static pointer after(pointer x)
  317. {
  318. if(x->next()->prior()==x)return pointer_from(x->next());
  319. if(x->next()->prior()->prior()==x)return x->next()->prior();
  320. if(x->next()->prior()->prior()->next()==base_pointer_from(x))
  321. return pointer_from(x->next());
  322. return pointer_from(x->next())->next()->prior();
  323. }
  324. static pointer after_local(pointer x)
  325. {
  326. if(x->next()->prior()==x)return pointer_from(x->next());
  327. if(x->next()->prior()->prior()==x)return pointer(0);
  328. if(x->next()->prior()->prior()->next()==base_pointer_from(x))
  329. return pointer_from(x->next());
  330. return pointer_from(x->next())->next()->prior();
  331. }
  332. static pointer next_to_inspect(pointer x)
  333. {
  334. if(x->next()->prior()==x)return pointer_from(x->next());
  335. if(x->next()->prior()->prior()==x)return pointer(0);
  336. if(x->next()->prior()->next()->prior()!=x->next()->prior())
  337. return pointer(0);
  338. return pointer_from(x->next()->prior()->next());
  339. }
  340. static void link(pointer x,base_pointer buc,pointer end)
  341. {
  342. if(buc->prior()==pointer(0)){ /* empty bucket */
  343. x->prior()=end->prior();
  344. x->next()=end->prior()->next();
  345. x->prior()->next()=buc;
  346. buc->prior()=x;
  347. end->prior()=x;
  348. }
  349. else{
  350. x->prior()=buc->prior()->prior();
  351. x->next()=base_pointer_from(buc->prior());
  352. buc->prior()=x;
  353. x->next()->prior()=x;
  354. }
  355. }
  356. static void link(pointer x,pointer first,pointer last)
  357. {
  358. x->prior()=first->prior();
  359. x->next()=base_pointer_from(first);
  360. if(is_first_of_bucket(first)){
  361. x->prior()->next()->prior()=x;
  362. }
  363. else{
  364. x->prior()->next()=base_pointer_from(x);
  365. }
  366. if(first==last){
  367. last->prior()=x;
  368. }
  369. else if(first->next()==base_pointer_from(last)){
  370. first->prior()=last;
  371. first->next()=base_pointer_from(x);
  372. }
  373. else{
  374. pointer second=pointer_from(first->next()),
  375. lastbutone=last->prior();
  376. second->prior()=first;
  377. first->prior()=last;
  378. lastbutone->next()=base_pointer_from(x);
  379. }
  380. }
  381. static void unlink(pointer x)
  382. {
  383. default_assigner assign;
  384. unlink(x,assign);
  385. }
  386. typedef unlink_undo_assigner<Node> unlink_undo;
  387. template<typename Assigner>
  388. static void unlink(pointer x,Assigner& assign)
  389. {
  390. if(x->prior()->next()==base_pointer_from(x)){
  391. if(x->next()->prior()==x){
  392. left_unlink(x,assign);
  393. right_unlink(x,assign);
  394. }
  395. else if(x->next()->prior()->prior()==x){ /* last of bucket */
  396. left_unlink(x,assign);
  397. right_unlink_last_of_bucket(x,assign);
  398. }
  399. else if(x->next()->prior()->prior()->next()==
  400. base_pointer_from(x)){ /* first of group size */
  401. left_unlink(x,assign);
  402. right_unlink_first_of_group(x,assign);
  403. }
  404. else{ /* n-1 of group */
  405. unlink_last_but_one_of_group(x,assign);
  406. }
  407. }
  408. else if(x->prior()->next()->prior()==x){ /* first of bucket */
  409. if(x->next()->prior()==x){
  410. left_unlink_first_of_bucket(x,assign);
  411. right_unlink(x,assign);
  412. }
  413. else if(x->next()->prior()->prior()==x){ /* last of bucket */
  414. assign(x->prior()->next()->prior(),pointer(0));
  415. assign(x->prior()->next(),x->next());
  416. assign(x->next()->prior()->prior(),x->prior());
  417. }
  418. else{ /* first of group */
  419. left_unlink_first_of_bucket(x,assign);
  420. right_unlink_first_of_group(x,assign);
  421. }
  422. }
  423. else if(x->next()->prior()->prior()==x){ /* last of group and bucket */
  424. left_unlink_last_of_group(x,assign);
  425. right_unlink_last_of_bucket(x,assign);
  426. }
  427. else if(pointer_from(x->prior()->prior()->next())
  428. ->next()==base_pointer_from(x)){ /* second of group */
  429. unlink_second_of_group(x,assign);
  430. }
  431. else{ /* last of group, ~(last of bucket) */
  432. left_unlink_last_of_group(x,assign);
  433. right_unlink(x,assign);
  434. }
  435. }
  436. /* used only at rehashing */
  437. static void link_range(
  438. pointer first,pointer last,base_pointer buc,pointer cend)
  439. {
  440. if(buc->prior()==pointer(0)){ /* empty bucket */
  441. first->prior()=cend->prior();
  442. last->next()=cend->prior()->next();
  443. first->prior()->next()=buc;
  444. buc->prior()=first;
  445. cend->prior()=last;
  446. }
  447. else{
  448. first->prior()=buc->prior()->prior();
  449. last->next()=base_pointer_from(buc->prior());
  450. buc->prior()=first;
  451. last->next()->prior()=last;
  452. }
  453. }
  454. static void append_range(pointer first,pointer last,pointer cend)
  455. {
  456. first->prior()=cend->prior();
  457. last->next()=cend->prior()->next();
  458. first->prior()->next()=base_pointer_from(first);
  459. cend->prior()=last;
  460. }
  461. static std::pair<pointer,bool> unlink_last_group(pointer end)
  462. {
  463. /* returns first of group true iff bucket is emptied */
  464. pointer x=end->prior();
  465. if(x->prior()->next()==base_pointer_from(x)){
  466. x->prior()->next()=x->next();
  467. end->prior()=x->prior();
  468. return std::make_pair(x,false);
  469. }
  470. else if(x->prior()->next()->prior()==x){
  471. x->prior()->next()->prior()=pointer(0);
  472. x->prior()->next()=x->next();
  473. end->prior()=x->prior();
  474. return std::make_pair(x,true);
  475. }
  476. else{
  477. pointer y=pointer_from(x->prior()->next());
  478. if(y->prior()->next()==base_pointer_from(y)){
  479. y->prior()->next()=x->next();
  480. end->prior()=y->prior();
  481. return std::make_pair(y,false);
  482. }
  483. else{
  484. y->prior()->next()->prior()=pointer(0);
  485. y->prior()->next()=x->next();
  486. end->prior()=y->prior();
  487. return std::make_pair(y,true);
  488. }
  489. }
  490. }
  491. static void unlink_range(pointer first,pointer last)
  492. {
  493. if(is_first_of_bucket(first)){
  494. if(is_last_of_bucket(last)){
  495. first->prior()->next()->prior()=pointer(0);
  496. first->prior()->next()=last->next();
  497. last->next()->prior()->prior()=first->prior();
  498. }
  499. else{
  500. first->prior()->next()->prior()=pointer_from(last->next());
  501. last->next()->prior()=first->prior();
  502. }
  503. }
  504. else if(is_last_of_bucket(last)){
  505. first->prior()->next()=last->next();
  506. last->next()->prior()->prior()=first->prior();
  507. }
  508. else{
  509. first->prior()->next()=last->next();
  510. last->next()->prior()=first->prior();
  511. }
  512. }
  513. private:
  514. static pointer pointer_from(base_pointer x)
  515. {
  516. return Node::pointer_from(x);
  517. }
  518. static base_pointer base_pointer_from(pointer x)
  519. {
  520. return Node::base_pointer_from(x);
  521. }
  522. static bool is_last_of_bucket(pointer x)
  523. {
  524. return x->next()->prior()->prior()==x;
  525. }
  526. template<typename Assigner>
  527. static void left_unlink(pointer x,Assigner& assign)
  528. {
  529. assign(x->prior()->next(),x->next());
  530. }
  531. template<typename Assigner>
  532. static void right_unlink(pointer x,Assigner& assign)
  533. {
  534. assign(x->next()->prior(),x->prior());
  535. }
  536. template<typename Assigner>
  537. static void left_unlink_first_of_bucket(pointer x,Assigner& assign)
  538. {
  539. assign(x->prior()->next()->prior(),pointer_from(x->next()));
  540. }
  541. template<typename Assigner>
  542. static void right_unlink_last_of_bucket(pointer x,Assigner& assign)
  543. {
  544. assign(x->next()->prior()->prior(),x->prior());
  545. }
  546. template<typename Assigner>
  547. static void right_unlink_first_of_group(pointer x,Assigner& assign)
  548. {
  549. pointer second=pointer_from(x->next()),
  550. last=second->prior(),
  551. lastbutone=last->prior();
  552. if(second==lastbutone){
  553. assign(second->next(),base_pointer_from(last));
  554. assign(second->prior(),x->prior());
  555. }
  556. else{
  557. assign(lastbutone->next(),base_pointer_from(second));
  558. assign(second->next()->prior(),last);
  559. assign(second->prior(),x->prior());
  560. }
  561. }
  562. template<typename Assigner>
  563. static void left_unlink_last_of_group(pointer x,Assigner& assign)
  564. {
  565. pointer lastbutone=x->prior(),
  566. first=pointer_from(lastbutone->next()),
  567. second=pointer_from(first->next());
  568. if(lastbutone==second){
  569. assign(lastbutone->prior(),first);
  570. assign(lastbutone->next(),x->next());
  571. }
  572. else{
  573. assign(second->prior(),lastbutone);
  574. assign(lastbutone->prior()->next(),base_pointer_from(first));
  575. assign(lastbutone->next(),x->next());
  576. }
  577. }
  578. template<typename Assigner>
  579. static void unlink_last_but_one_of_group(pointer x,Assigner& assign)
  580. {
  581. pointer first=pointer_from(x->next()),
  582. second=pointer_from(first->next()),
  583. last=second->prior();
  584. if(second==x){
  585. assign(last->prior(),first);
  586. assign(first->next(),base_pointer_from(last));
  587. }
  588. else{
  589. assign(last->prior(),x->prior());
  590. assign(x->prior()->next(),base_pointer_from(first));
  591. }
  592. }
  593. template<typename Assigner>
  594. static void unlink_second_of_group(pointer x,Assigner& assign)
  595. {
  596. pointer last=x->prior(),
  597. lastbutone=last->prior(),
  598. first=pointer_from(lastbutone->next());
  599. if(lastbutone==x){
  600. assign(first->next(),base_pointer_from(last));
  601. assign(last->prior(),first);
  602. }
  603. else{
  604. assign(first->next(),x->next());
  605. assign(x->next()->prior(),last);
  606. }
  607. }
  608. };
  609. template<typename Super>
  610. struct hashed_index_node_trampoline:
  611. hashed_index_node_impl<
  612. typename rebind_alloc_for<
  613. typename Super::allocator_type,char
  614. >::type
  615. >
  616. {
  617. typedef typename rebind_alloc_for<
  618. typename Super::allocator_type,char
  619. >::type impl_allocator_type;
  620. typedef hashed_index_node_impl<impl_allocator_type> impl_type;
  621. };
  622. template<typename Super,typename Category>
  623. struct hashed_index_node:
  624. Super,hashed_index_node_trampoline<Super>
  625. {
  626. private:
  627. typedef hashed_index_node_trampoline<Super> trampoline;
  628. public:
  629. typedef typename trampoline::impl_type impl_type;
  630. typedef hashed_index_node_alg<
  631. impl_type,Category> node_alg;
  632. typedef typename trampoline::base_pointer impl_base_pointer;
  633. typedef typename trampoline::const_base_pointer const_impl_base_pointer;
  634. typedef typename trampoline::pointer impl_pointer;
  635. typedef typename trampoline::const_pointer const_impl_pointer;
  636. typedef typename trampoline::difference_type difference_type;
  637. impl_pointer& prior(){return trampoline::prior();}
  638. impl_pointer prior()const{return trampoline::prior();}
  639. impl_base_pointer& next(){return trampoline::next();}
  640. impl_base_pointer next()const{return trampoline::next();}
  641. impl_pointer impl()
  642. {
  643. return static_cast<impl_pointer>(
  644. static_cast<impl_type*>(static_cast<trampoline*>(this)));
  645. }
  646. const_impl_pointer impl()const
  647. {
  648. return static_cast<const_impl_pointer>(
  649. static_cast<const impl_type*>(static_cast<const trampoline*>(this)));
  650. }
  651. static hashed_index_node* from_impl(impl_pointer x)
  652. {
  653. return
  654. static_cast<hashed_index_node*>(
  655. static_cast<trampoline*>(
  656. raw_ptr<impl_type*>(x)));
  657. }
  658. static const hashed_index_node* from_impl(const_impl_pointer x)
  659. {
  660. return
  661. static_cast<const hashed_index_node*>(
  662. static_cast<const trampoline*>(
  663. raw_ptr<const impl_type*>(x)));
  664. }
  665. /* interoperability with hashed_index_iterator */
  666. static void increment(hashed_index_node*& x)
  667. {
  668. x=from_impl(node_alg::after(x->impl()));
  669. }
  670. static void increment_local(hashed_index_node*& x)
  671. {
  672. x=from_impl(node_alg::after_local(x->impl()));
  673. }
  674. };
  675. } /* namespace multi_index::detail */
  676. } /* namespace multi_index */
  677. } /* namespace boost */
  678. #endif