rnd_index_ops.hpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /* Copyright 2003-2009 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_RND_INDEX_OPS_HPP
  9. #define BOOST_MULTI_INDEX_DETAIL_RND_INDEX_OPS_HPP
  10. #if defined(_MSC_VER)&&(_MSC_VER>=1200)
  11. #pragma once
  12. #endif
  13. #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
  14. #include <algorithm>
  15. #include <boost/multi_index/detail/rnd_index_ptr_array.hpp>
  16. #include <functional>
  17. namespace boost{
  18. namespace multi_index{
  19. namespace detail{
  20. /* Common code for random_access_index memfuns having templatized and
  21. * non-templatized versions.
  22. */
  23. template<typename Node,typename Allocator,typename Predicate>
  24. Node* random_access_index_remove(
  25. random_access_index_ptr_array<Allocator>& ptrs,Predicate pred
  26. BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
  27. {
  28. typedef typename Node::value_type value_type;
  29. typedef typename Node::impl_ptr_pointer impl_ptr_pointer;
  30. impl_ptr_pointer first=ptrs.begin(),
  31. res=first,
  32. last=ptrs.end();
  33. for(;first!=last;++first){
  34. if(!pred(
  35. const_cast<const value_type&>(Node::from_impl(*first)->value()))){
  36. if(first!=res){
  37. std::swap(*first,*res);
  38. (*first)->up()=first;
  39. (*res)->up()=res;
  40. }
  41. ++res;
  42. }
  43. }
  44. return Node::from_impl(*res);
  45. }
  46. template<typename Node,typename Allocator,class BinaryPredicate>
  47. Node* random_access_index_unique(
  48. random_access_index_ptr_array<Allocator>& ptrs,BinaryPredicate binary_pred
  49. BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
  50. {
  51. typedef typename Node::value_type value_type;
  52. typedef typename Node::impl_ptr_pointer impl_ptr_pointer;
  53. impl_ptr_pointer first=ptrs.begin(),
  54. res=first,
  55. last=ptrs.end();
  56. if(first!=last){
  57. for(;++first!=last;){
  58. if(!binary_pred(
  59. const_cast<const value_type&>(Node::from_impl(*res)->value()),
  60. const_cast<const value_type&>(Node::from_impl(*first)->value()))){
  61. ++res;
  62. if(first!=res){
  63. std::swap(*first,*res);
  64. (*first)->up()=first;
  65. (*res)->up()=res;
  66. }
  67. }
  68. }
  69. ++res;
  70. }
  71. return Node::from_impl(*res);
  72. }
  73. template<typename Node,typename Allocator,typename Compare>
  74. void random_access_index_inplace_merge(
  75. const Allocator& al,
  76. random_access_index_ptr_array<Allocator>& ptrs,
  77. BOOST_DEDUCED_TYPENAME Node::impl_ptr_pointer first1,Compare comp
  78. BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
  79. {
  80. typedef typename Node::value_type value_type;
  81. typedef typename Node::impl_pointer impl_pointer;
  82. typedef typename Node::impl_ptr_pointer impl_ptr_pointer;
  83. auto_space<impl_pointer,Allocator> spc(al,ptrs.size());
  84. impl_ptr_pointer first0=ptrs.begin(),
  85. last0=first1,
  86. last1=ptrs.end(),
  87. out=spc.data();
  88. while(first0!=last0&&first1!=last1){
  89. if(comp(
  90. const_cast<const value_type&>(Node::from_impl(*first1)->value()),
  91. const_cast<const value_type&>(Node::from_impl(*first0)->value()))){
  92. *out++=*first1++;
  93. }
  94. else{
  95. *out++=*first0++;
  96. }
  97. }
  98. std::copy(&*first0,&*last0,&*out);
  99. std::copy(&*first1,&*last1,&*out);
  100. first1=ptrs.begin();
  101. out=spc.data();
  102. while(first1!=last1){
  103. *first1=*out++;
  104. (*first1)->up()=first1;
  105. ++first1;
  106. }
  107. }
  108. /* sorting */
  109. /* auxiliary stuff */
  110. template<typename Node,typename Compare>
  111. struct random_access_index_sort_compare:
  112. std::binary_function<
  113. typename Node::impl_pointer,
  114. typename Node::impl_pointer,bool>
  115. {
  116. random_access_index_sort_compare(Compare comp_=Compare()):comp(comp_){}
  117. bool operator()(
  118. typename Node::impl_pointer x,typename Node::impl_pointer y)const
  119. {
  120. typedef typename Node::value_type value_type;
  121. return comp(
  122. const_cast<const value_type&>(Node::from_impl(x)->value()),
  123. const_cast<const value_type&>(Node::from_impl(y)->value()));
  124. }
  125. private:
  126. Compare comp;
  127. };
  128. template<typename Node,typename Allocator,class Compare>
  129. void random_access_index_sort(
  130. const Allocator& al,
  131. random_access_index_ptr_array<Allocator>& ptrs,
  132. Compare comp
  133. BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
  134. {
  135. /* The implementation is extremely simple: an auxiliary
  136. * array of pointers is sorted using stdlib facilities and
  137. * then used to rearrange the index. This is suboptimal
  138. * in space and time, but has some advantages over other
  139. * possible approaches:
  140. * - Use std::stable_sort() directly on ptrs using some
  141. * special iterator in charge of maintaining pointers
  142. * and up() pointers in sync: we cannot guarantee
  143. * preservation of the container invariants in the face of
  144. * exceptions, if, for instance, std::stable_sort throws
  145. * when ptrs transitorily contains duplicate elements.
  146. * - Rewrite the internal algorithms of std::stable_sort
  147. * adapted for this case: besides being a fair amount of
  148. * work, making a stable sort compatible with Boost.MultiIndex
  149. * invariants (basically, no duplicates or missing elements
  150. * even if an exception is thrown) is complicated, error-prone
  151. * and possibly won't perform much better than the
  152. * solution adopted.
  153. */
  154. if(ptrs.size()<=1)return;
  155. typedef typename Node::value_type value_type;
  156. typedef typename Node::impl_pointer impl_pointer;
  157. typedef typename Node::impl_ptr_pointer impl_ptr_pointer;
  158. typedef random_access_index_sort_compare<
  159. Node,Compare> ptr_compare;
  160. impl_ptr_pointer first=ptrs.begin();
  161. impl_ptr_pointer last=ptrs.end();
  162. auto_space<
  163. impl_pointer,
  164. Allocator> spc(al,ptrs.size());
  165. impl_ptr_pointer buf=spc.data();
  166. std::copy(&*first,&*last,&*buf);
  167. std::stable_sort(&*buf,&*buf+ptrs.size(),ptr_compare(comp));
  168. while(first!=last){
  169. *first=*buf++;
  170. (*first)->up()=first;
  171. ++first;
  172. }
  173. }
  174. } /* namespace multi_index::detail */
  175. } /* namespace multi_index */
  176. } /* namespace boost */
  177. #endif