rnd_index_ops.hpp 5.9 KB

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