123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- /* Copyright 2003-2015 Joaquin M Lopez Munoz.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE_1_0.txt or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- *
- * See http://www.boost.org/libs/multi_index for library home page.
- */
- #ifndef BOOST_MULTI_INDEX_DETAIL_RND_INDEX_OPS_HPP
- #define BOOST_MULTI_INDEX_DETAIL_RND_INDEX_OPS_HPP
- #if defined(_MSC_VER)
- #pragma once
- #endif
- #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
- #include <algorithm>
- #include <boost/multi_index/detail/rnd_index_ptr_array.hpp>
- namespace boost{
- namespace multi_index{
- namespace detail{
- /* Common code for random_access_index memfuns having templatized and
- * non-templatized versions.
- */
- template<typename Node,typename Allocator,typename Predicate>
- Node* random_access_index_remove(
- random_access_index_ptr_array<Allocator>& ptrs,Predicate pred)
- {
- typedef typename Node::value_type value_type;
- typedef typename Node::impl_ptr_pointer impl_ptr_pointer;
- impl_ptr_pointer first=ptrs.begin(),
- res=first,
- last=ptrs.end();
- for(;first!=last;++first){
- if(!pred(
- const_cast<const value_type&>(Node::from_impl(*first)->value()))){
- if(first!=res){
- std::swap(*first,*res);
- (*first)->up()=first;
- (*res)->up()=res;
- }
- ++res;
- }
- }
- return Node::from_impl(*res);
- }
- template<typename Node,typename Allocator,class BinaryPredicate>
- Node* random_access_index_unique(
- random_access_index_ptr_array<Allocator>& ptrs,BinaryPredicate binary_pred)
- {
- typedef typename Node::value_type value_type;
- typedef typename Node::impl_ptr_pointer impl_ptr_pointer;
- impl_ptr_pointer first=ptrs.begin(),
- res=first,
- last=ptrs.end();
- if(first!=last){
- for(;++first!=last;){
- if(!binary_pred(
- const_cast<const value_type&>(Node::from_impl(*res)->value()),
- const_cast<const value_type&>(Node::from_impl(*first)->value()))){
- ++res;
- if(first!=res){
- std::swap(*first,*res);
- (*first)->up()=first;
- (*res)->up()=res;
- }
- }
- }
- ++res;
- }
- return Node::from_impl(*res);
- }
- template<typename Node,typename Allocator,typename Compare>
- void random_access_index_inplace_merge(
- const Allocator& al,
- random_access_index_ptr_array<Allocator>& ptrs,
- BOOST_DEDUCED_TYPENAME Node::impl_ptr_pointer first1,Compare comp)
- {
- typedef typename Node::value_type value_type;
- typedef typename Node::impl_pointer impl_pointer;
- typedef typename Node::impl_ptr_pointer impl_ptr_pointer;
- auto_space<impl_pointer,Allocator> spc(al,ptrs.size());
- impl_ptr_pointer first0=ptrs.begin(),
- last0=first1,
- last1=ptrs.end(),
- out=spc.data();
- while(first0!=last0&&first1!=last1){
- if(comp(
- const_cast<const value_type&>(Node::from_impl(*first1)->value()),
- const_cast<const value_type&>(Node::from_impl(*first0)->value()))){
- *out++=*first1++;
- }
- else{
- *out++=*first0++;
- }
- }
- std::copy(&*first0,&*last0,&*out);
- std::copy(&*first1,&*last1,&*out);
- first1=ptrs.begin();
- out=spc.data();
- while(first1!=last1){
- *first1=*out++;
- (*first1)->up()=first1;
- ++first1;
- }
- }
- /* sorting */
- /* auxiliary stuff */
- template<typename Node,typename Compare>
- struct random_access_index_sort_compare
- {
- typedef typename Node::impl_pointer first_argument_type;
- typedef typename Node::impl_pointer second_argument_type;
- typedef bool result_type;
- random_access_index_sort_compare(Compare comp_=Compare()):comp(comp_){}
- bool operator()(
- typename Node::impl_pointer x,typename Node::impl_pointer y)const
- {
- typedef typename Node::value_type value_type;
- return comp(
- const_cast<const value_type&>(Node::from_impl(x)->value()),
- const_cast<const value_type&>(Node::from_impl(y)->value()));
- }
- private:
- Compare comp;
- };
- template<typename Node,typename Allocator,class Compare>
- void random_access_index_sort(
- const Allocator& al,
- random_access_index_ptr_array<Allocator>& ptrs,
- Compare comp)
- {
- /* The implementation is extremely simple: an auxiliary
- * array of pointers is sorted using stdlib facilities and
- * then used to rearrange the index. This is suboptimal
- * in space and time, but has some advantages over other
- * possible approaches:
- * - Use std::stable_sort() directly on ptrs using some
- * special iterator in charge of maintaining pointers
- * and up() pointers in sync: we cannot guarantee
- * preservation of the container invariants in the face of
- * exceptions, if, for instance, std::stable_sort throws
- * when ptrs transitorily contains duplicate elements.
- * - Rewrite the internal algorithms of std::stable_sort
- * adapted for this case: besides being a fair amount of
- * work, making a stable sort compatible with Boost.MultiIndex
- * invariants (basically, no duplicates or missing elements
- * even if an exception is thrown) is complicated, error-prone
- * and possibly won't perform much better than the
- * solution adopted.
- */
- if(ptrs.size()<=1)return;
- typedef typename Node::impl_pointer impl_pointer;
- typedef typename Node::impl_ptr_pointer impl_ptr_pointer;
- typedef random_access_index_sort_compare<
- Node,Compare> ptr_compare;
-
- impl_ptr_pointer first=ptrs.begin();
- impl_ptr_pointer last=ptrs.end();
- auto_space<
- impl_pointer,
- Allocator> spc(al,ptrs.size());
- impl_ptr_pointer buf=spc.data();
- std::copy(&*first,&*last,&*buf);
- std::stable_sort(&*buf,&*buf+ptrs.size(),ptr_compare(comp));
- while(first!=last){
- *first=*buf++;
- (*first)->up()=first;
- ++first;
- }
- }
- } /* namespace multi_index::detail */
- } /* namespace multi_index */
- } /* namespace boost */
- #endif
|