mirror of
https://github.com/boostorg/container.git
synced 2026-07-08 03:40:49 +02:00
Reimplement segmented_remove_copy_if to support recursively segmented iterators, make the implementation detail move-configurable, and make segmented_remove_if a thin wrapper again based on that.
This commit is contained in:
@@ -106,6 +106,22 @@ struct constref_generator
|
||||
BOOST_CONTAINER_FORCEINLINE const T& operator()() const { return value; }
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Transfer helper: copy (Move=false) or move (Move=true) a single element.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <bool> struct transfer_op;
|
||||
template <> struct transfer_op<false>
|
||||
{
|
||||
template <class D, class S>
|
||||
BOOST_CONTAINER_FORCEINLINE static void apply(D& d, S& s) { d = s; }
|
||||
};
|
||||
template <> struct transfer_op<true>
|
||||
{
|
||||
template <class D, class S>
|
||||
BOOST_CONTAINER_FORCEINLINE static void apply(D& d, S& s) { d = boost::move(s); }
|
||||
};
|
||||
|
||||
} // namespace detail_algo
|
||||
|
||||
//! Traits class to detect and decompose segmented iterators.
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
#include <boost/container/experimental/segmented_iterator_traits.hpp>
|
||||
#include <boost/container/detail/iterator.hpp>
|
||||
#include <boost/move/utility_core.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
@@ -31,82 +32,201 @@ OutIter segmented_remove_copy_if(InIter first, Sent last, OutIter result, Pred p
|
||||
|
||||
namespace detail_algo {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Bounded destination helper: fills [dst_first, dst_last) from source
|
||||
// elements not matching pred. Advances first_out (by reference) until
|
||||
// source is exhausted or destination is full.
|
||||
// Recursively walks destination segments when dst is segmented.
|
||||
// SrcCat is threaded through so the RA-optimized leaf is selected.
|
||||
//
|
||||
// When dst_last is unreachable_sentinel_t the destination-full check
|
||||
// is optimised away, giving the same code as an unbounded loop.
|
||||
//
|
||||
// Move (first template parameter): true = move, false = copy.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING)
|
||||
|
||||
template <class InIter, class OutIter, class Pred>
|
||||
OutIter segmented_remove_copy_if_dispatch
|
||||
(InIter first, InIter last, OutIter result, Pred pred, const non_segmented_iterator_tag &, const std::random_access_iterator_tag &)
|
||||
template <bool Move, class RASrcIter, class DstIter, class DstSent, class Pred>
|
||||
DstIter segmented_remove_copy_if_dst_bounded
|
||||
(RASrcIter& first_out, RASrcIter last, DstIter dst_first, DstSent dst_last, Pred pred,
|
||||
const non_segmented_iterator_tag &, const std::random_access_iterator_tag &)
|
||||
{
|
||||
typedef typename iterator_traits<InIter>::difference_type difference_type;
|
||||
typedef typename iterator_traits<RASrcIter>::difference_type difference_type;
|
||||
RASrcIter first = first_out;
|
||||
|
||||
difference_type n = last - first;
|
||||
|
||||
while(n >= difference_type(4)) {
|
||||
if(!pred(*first)) { *result = *first; ++result; } ++first;
|
||||
if(!pred(*first)) { *result = *first; ++result; } ++first;
|
||||
if(!pred(*first)) { *result = *first; ++result; } ++first;
|
||||
if(!pred(*first)) { *result = *first; ++result; } ++first;
|
||||
if(!pred(*first)) { if(dst_first == dst_last) goto out_path; transfer_op<Move>::apply(*dst_first, *first); ++dst_first; } ++first;
|
||||
if(!pred(*first)) { if(dst_first == dst_last) goto out_path; transfer_op<Move>::apply(*dst_first, *first); ++dst_first; } ++first;
|
||||
if(!pred(*first)) { if(dst_first == dst_last) goto out_path; transfer_op<Move>::apply(*dst_first, *first); ++dst_first; } ++first;
|
||||
if(!pred(*first)) { if(dst_first == dst_last) goto out_path; transfer_op<Move>::apply(*dst_first, *first); ++dst_first; } ++first;
|
||||
n -= 4;
|
||||
}
|
||||
|
||||
switch(n) {
|
||||
case 3:
|
||||
if(!pred(*first)) { *result = *first; ++result; } ++first;
|
||||
if(!pred(*first)) { *result = *first; ++result; } ++first;
|
||||
if(!pred(*first)) { *result = *first; ++result; }
|
||||
break;
|
||||
if(!pred(*first)) { if(dst_first == dst_last) goto out_path; transfer_op<Move>::apply(*dst_first, *first); ++dst_first; } ++first;
|
||||
BOOST_FALLTHROUGH;
|
||||
case 2:
|
||||
if(!pred(*first)) { *result = *first; ++result; } ++first;
|
||||
if(!pred(*first)) { *result = *first; ++result; }
|
||||
break;
|
||||
if(!pred(*first)) { if(dst_first == dst_last) goto out_path; transfer_op<Move>::apply(*dst_first, *first); ++dst_first; } ++first;
|
||||
BOOST_FALLTHROUGH;
|
||||
case 1:
|
||||
if(!pred(*first)) { *result = *first; ++result; }
|
||||
break;
|
||||
if(!pred(*first)) { if(dst_first == dst_last) goto out_path; transfer_op<Move>::apply(*dst_first, *first); ++dst_first; } ++first;
|
||||
BOOST_FALLTHROUGH;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
out_path:
|
||||
first_out = first;
|
||||
return dst_first;
|
||||
}
|
||||
|
||||
#endif //BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING
|
||||
|
||||
template <class InIter, class Sent, class OutIter, class Pred, class Tag, class Cat>
|
||||
typename algo_enable_if_c<
|
||||
!Tag::value || is_sentinel<Sent, InIter>::value, OutIter>::type
|
||||
segmented_remove_copy_if_dispatch
|
||||
(InIter first, Sent last, OutIter result, Pred pred, Tag, Cat)
|
||||
template <bool Move, class SrcIter, class Sent, class DstIter, class DstSent, class Pred, class DstTag, class SrcCat>
|
||||
typename algo_enable_if_c<!DstTag::value, DstIter>::type
|
||||
segmented_remove_copy_if_dst_bounded
|
||||
(SrcIter& first_out, Sent last, DstIter dst_first, DstSent dst_last, Pred pred, DstTag, SrcCat)
|
||||
{
|
||||
SrcIter first = first_out;
|
||||
|
||||
for(; first != last; ++first) {
|
||||
if(!pred(*first)) {
|
||||
*result = *first;
|
||||
++result;
|
||||
if(dst_first == dst_last)
|
||||
goto out_path;
|
||||
transfer_op<Move>::apply(*dst_first, *first);
|
||||
++dst_first;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
out_path:
|
||||
first_out = first;
|
||||
return dst_first;
|
||||
}
|
||||
|
||||
template <class SegIter, class OutIter, class Pred, class Cat>
|
||||
template <bool Move, class SrcIter, class Sent, class SegDstIter, class Pred, class SrcCat>
|
||||
SegDstIter segmented_remove_copy_if_dst_bounded
|
||||
(SrcIter& first, Sent last, SegDstIter dst_first, SegDstIter dst_last, Pred pred,
|
||||
segmented_iterator_tag, SrcCat)
|
||||
{
|
||||
typedef segmented_iterator_traits<SegDstIter> dst_traits;
|
||||
typedef typename dst_traits::local_iterator dst_local_iterator;
|
||||
typedef typename dst_traits::segment_iterator dst_segment_iterator;
|
||||
typedef typename segmented_iterator_traits<dst_local_iterator>::is_segmented_iterator dst_is_local_seg_t;
|
||||
|
||||
dst_segment_iterator sfirst = dst_traits::segment(dst_first);
|
||||
const dst_segment_iterator slast = dst_traits::segment(dst_last);
|
||||
|
||||
if(sfirst == slast) {
|
||||
dst_local_iterator r = (segmented_remove_copy_if_dst_bounded<Move>)
|
||||
(first, last, dst_traits::local(dst_first), dst_traits::local(dst_last), pred, dst_is_local_seg_t(), SrcCat());
|
||||
return dst_traits::compose(sfirst, r);
|
||||
}
|
||||
else {
|
||||
dst_local_iterator dst_local = (segmented_remove_copy_if_dst_bounded<Move>)
|
||||
(first, last, dst_traits::local(dst_first), dst_traits::end(sfirst), pred, dst_is_local_seg_t(), SrcCat());
|
||||
if(first == last)
|
||||
return dst_traits::compose(sfirst, dst_local);
|
||||
|
||||
for(++sfirst; sfirst != slast; ++sfirst) {
|
||||
dst_local = (segmented_remove_copy_if_dst_bounded<Move>)
|
||||
(first, last, dst_traits::begin(sfirst), dst_traits::end(sfirst), pred, dst_is_local_seg_t(), SrcCat());
|
||||
if(first == last)
|
||||
return dst_traits::compose(sfirst, dst_local);
|
||||
}
|
||||
|
||||
dst_local = (segmented_remove_copy_if_dst_bounded<Move>)
|
||||
(first, last, dst_traits::begin(slast), dst_traits::local(dst_last), pred, dst_is_local_seg_t(), SrcCat());
|
||||
return dst_traits::compose(sfirst, dst_local);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Destination dispatch: routes to bounded helper.
|
||||
// Non-segmented destination: single unbounded call (unreachable_sentinel_t).
|
||||
// Segmented destination: loop over destination segments, bounded per segment.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <bool Move, class SrcIter, class Sent, class DstIter, class Pred, class Cat>
|
||||
BOOST_CONTAINER_FORCEINLINE DstIter segmented_remove_copy_if_dst_dispatch
|
||||
(SrcIter first, Sent last, DstIter result, Pred pred,
|
||||
const non_segmented_iterator_tag &, Cat)
|
||||
{
|
||||
return (segmented_remove_copy_if_dst_bounded<Move>)
|
||||
(first, last, result, unreachable_sentinel_t(), pred, non_segmented_iterator_tag(), Cat());
|
||||
}
|
||||
|
||||
template <bool Move, class SrcIter, class Sent, class SegDstIter, class Pred, class Cat>
|
||||
SegDstIter segmented_remove_copy_if_dst_dispatch
|
||||
(SrcIter first, Sent last, SegDstIter result, Pred pred,
|
||||
const segmented_iterator_tag &, Cat)
|
||||
{
|
||||
typedef segmented_iterator_traits<SegDstIter> dst_traits;
|
||||
typedef typename dst_traits::local_iterator dst_local_iterator;
|
||||
typedef typename dst_traits::segment_iterator dst_segment_iterator;
|
||||
typedef typename segmented_iterator_traits<dst_local_iterator>::is_segmented_iterator dst_is_local_seg_t;
|
||||
|
||||
if(first == last)
|
||||
return result;
|
||||
|
||||
dst_segment_iterator dst_seg = dst_traits::segment(result);
|
||||
dst_local_iterator dst_local = dst_traits::local(result);
|
||||
|
||||
while(first != last) {
|
||||
dst_local_iterator dst_end = dst_traits::end(dst_seg);
|
||||
dst_local = (segmented_remove_copy_if_dst_bounded<Move>)
|
||||
(first, last, dst_local, dst_end, pred, dst_is_local_seg_t(), Cat());
|
||||
if(first != last) {
|
||||
++dst_seg;
|
||||
dst_local = dst_traits::begin(dst_seg);
|
||||
}
|
||||
}
|
||||
return dst_traits::compose(dst_seg, dst_local);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Source dispatch: walks the source (read pointer) segments
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <bool Move, class SrcIter, class Sent, class OutIter, class Pred, class Tag, class Cat>
|
||||
typename algo_enable_if_c<
|
||||
!Tag::value || is_sentinel<Sent, SrcIter>::value, OutIter>::type
|
||||
segmented_remove_copy_if_dispatch
|
||||
(SrcIter first, Sent last, OutIter result, Pred pred, Tag, Cat)
|
||||
{
|
||||
typedef segmented_iterator_traits<OutIter> dst_traits;
|
||||
return (segmented_remove_copy_if_dst_dispatch<Move>)
|
||||
(first, last, result, pred, typename dst_traits::is_segmented_iterator(), Cat());
|
||||
}
|
||||
|
||||
template <bool Move, class SegIter, class OutIter, class Pred, class Cat>
|
||||
OutIter segmented_remove_copy_if_dispatch
|
||||
(SegIter first, SegIter last, OutIter result, Pred pred, segmented_iterator_tag, Cat)
|
||||
{
|
||||
typedef segmented_iterator_traits<SegIter> traits;
|
||||
typedef typename traits::local_iterator local_iterator;
|
||||
typedef typename traits::segment_iterator segment_iterator;
|
||||
typedef typename segmented_iterator_traits<local_iterator>::is_segmented_iterator is_local_seg_t;
|
||||
typedef typename iterator_traits<local_iterator>::iterator_category local_cat_t;
|
||||
typedef segmented_iterator_traits<SegIter> src_traits;
|
||||
typedef typename src_traits::local_iterator src_local_iterator;
|
||||
typedef typename src_traits::segment_iterator src_segment_iterator;
|
||||
typedef typename segmented_iterator_traits<src_local_iterator>::is_segmented_iterator src_is_local_seg_t;
|
||||
typedef typename iterator_traits<src_local_iterator>::iterator_category src_local_cat_t;
|
||||
|
||||
segment_iterator sfirst = traits::segment(first);
|
||||
segment_iterator slast = traits::segment(last);
|
||||
src_segment_iterator sfirst = src_traits::segment(first);
|
||||
const src_segment_iterator slast = src_traits::segment(last);
|
||||
|
||||
if(sfirst == slast) {
|
||||
return (segmented_remove_copy_if_dispatch)(traits::local(first), traits::local(last), result, pred, is_local_seg_t(), local_cat_t());
|
||||
return (segmented_remove_copy_if_dispatch<Move>)
|
||||
(src_traits::local(first), src_traits::local(last), result, pred, src_is_local_seg_t(), src_local_cat_t());
|
||||
}
|
||||
else {
|
||||
result = (segmented_remove_copy_if_dispatch)(traits::local(first), traits::end(sfirst), result, pred, is_local_seg_t(), local_cat_t());
|
||||
result = (segmented_remove_copy_if_dispatch<Move>)
|
||||
(src_traits::local(first), src_traits::end(sfirst), result, pred, src_is_local_seg_t(), src_local_cat_t());
|
||||
|
||||
for(++sfirst; sfirst != slast; ++sfirst)
|
||||
result = (segmented_remove_copy_if_dispatch)(traits::begin(sfirst), traits::end(sfirst), result, pred, is_local_seg_t(), local_cat_t());
|
||||
result = (segmented_remove_copy_if_dispatch<Move>)
|
||||
(src_traits::begin(sfirst), src_traits::end(sfirst), result, pred, src_is_local_seg_t(), src_local_cat_t());
|
||||
|
||||
return (segmented_remove_copy_if_dispatch)(traits::begin(sfirst), traits::local(last), result, pred, is_local_seg_t(), local_cat_t());
|
||||
return (segmented_remove_copy_if_dispatch<Move>)
|
||||
(src_traits::begin(slast), src_traits::local(last), result, pred, src_is_local_seg_t(), src_local_cat_t());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +240,7 @@ BOOST_CONTAINER_FORCEINLINE
|
||||
OutIter segmented_remove_copy_if(InIter first, Sent last, OutIter result, Pred pred)
|
||||
{
|
||||
typedef segmented_iterator_traits<InIter> traits;
|
||||
return detail_algo::segmented_remove_copy_if_dispatch
|
||||
return detail_algo::segmented_remove_copy_if_dispatch<false>
|
||||
(first, last, result, pred, typename traits::is_segmented_iterator(), typename iterator_traits<InIter>::iterator_category());
|
||||
}
|
||||
|
||||
|
||||
@@ -20,224 +20,12 @@
|
||||
|
||||
#include <boost/container/detail/config_begin.hpp>
|
||||
#include <boost/container/detail/workaround.hpp>
|
||||
#include <boost/container/experimental/segmented_iterator_traits.hpp>
|
||||
#include <boost/container/experimental/segmented_remove_copy_if.hpp>
|
||||
#include <boost/container/experimental/segmented_find_if.hpp>
|
||||
|
||||
#include <boost/move/utility_core.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
template <class FwdIt, class Sent, class Predicate>
|
||||
FwdIt segmented_remove_if(FwdIt first, Sent last, Predicate pred);
|
||||
|
||||
namespace detail_algo {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Bounded result helper: fills destination range [dst_first, dst_last)
|
||||
// from source elements not matching pred. Advances next (by reference)
|
||||
// until source is exhausted or destination is full.
|
||||
// Recursively walks destination segments when dst is segmented.
|
||||
// SrcCat is threaded through so the RA-optimized leaf is selected.
|
||||
//
|
||||
// When dst_last is unreachable_sentinel_t the destination-full check
|
||||
// is optimised away, giving the same code as an unbounded loop.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING)
|
||||
|
||||
template <class RASrcIter, class DstIter, class DstSent, class Pred>
|
||||
DstIter segmented_remove_if_dst_bounded
|
||||
(RASrcIter& next_out, RASrcIter last, DstIter dst_first, DstSent dst_last, Pred pred,
|
||||
const non_segmented_iterator_tag &, const std::random_access_iterator_tag &)
|
||||
{
|
||||
typedef typename iterator_traits<RASrcIter>::difference_type difference_type;
|
||||
RASrcIter next = next_out;
|
||||
|
||||
difference_type n = last - next;
|
||||
|
||||
while(n >= difference_type(4)) {
|
||||
if(!pred(*next)) { if(dst_first == dst_last) goto out_path; *dst_first = boost::move(*next); ++dst_first; } ++next;
|
||||
if(!pred(*next)) { if(dst_first == dst_last) goto out_path; *dst_first = boost::move(*next); ++dst_first; } ++next;
|
||||
if(!pred(*next)) { if(dst_first == dst_last) goto out_path; *dst_first = boost::move(*next); ++dst_first; } ++next;
|
||||
if(!pred(*next)) { if(dst_first == dst_last) goto out_path; *dst_first = boost::move(*next); ++dst_first; } ++next;
|
||||
n -= 4;
|
||||
}
|
||||
|
||||
switch(n) {
|
||||
case 3:
|
||||
if(!pred(*next)) { if(dst_first == dst_last) goto out_path; *dst_first = boost::move(*next); ++dst_first; } ++next;
|
||||
BOOST_FALLTHROUGH;
|
||||
case 2:
|
||||
if(!pred(*next)) { if(dst_first == dst_last) goto out_path; *dst_first = boost::move(*next); ++dst_first; } ++next;
|
||||
BOOST_FALLTHROUGH;
|
||||
case 1:
|
||||
if(!pred(*next)) { if(dst_first == dst_last) goto out_path; *dst_first = boost::move(*next); ++dst_first; } ++next;
|
||||
BOOST_FALLTHROUGH;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
out_path:
|
||||
next_out = next;
|
||||
return dst_first;
|
||||
}
|
||||
|
||||
#endif //BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING
|
||||
|
||||
template <class SrcIter, class Sent, class DstIter, class DstSent, class Pred, class DstTag, class SrcCat>
|
||||
typename algo_enable_if_c<!DstTag::value, DstIter>::type
|
||||
segmented_remove_if_dst_bounded
|
||||
(SrcIter& next_out, Sent last, DstIter dst_first, DstSent dst_last, Pred pred, DstTag, SrcCat)
|
||||
{
|
||||
SrcIter next = next_out;
|
||||
|
||||
for(; next != last; ++next) {
|
||||
if(!pred(*next)) {
|
||||
if(dst_first == dst_last)
|
||||
goto out_path;
|
||||
*dst_first = boost::move(*next);
|
||||
++dst_first;
|
||||
}
|
||||
}
|
||||
out_path:
|
||||
next_out = next;
|
||||
return dst_first;
|
||||
}
|
||||
|
||||
template <class SrcIter, class Sent, class SegDstIter, class Pred, class SrcCat>
|
||||
SegDstIter segmented_remove_if_dst_bounded
|
||||
(SrcIter& next, Sent last, SegDstIter dst_first, SegDstIter dst_last, Pred pred,
|
||||
segmented_iterator_tag, SrcCat)
|
||||
{
|
||||
typedef segmented_iterator_traits<SegDstIter> dst_traits;
|
||||
typedef typename dst_traits::local_iterator dst_local_iterator;
|
||||
typedef typename dst_traits::segment_iterator dst_segment_iterator;
|
||||
typedef typename segmented_iterator_traits<dst_local_iterator>::is_segmented_iterator dst_is_local_seg_t;
|
||||
|
||||
dst_segment_iterator sfirst = dst_traits::segment(dst_first);
|
||||
const dst_segment_iterator slast = dst_traits::segment(dst_last);
|
||||
|
||||
if(sfirst == slast) {
|
||||
dst_local_iterator r = (segmented_remove_if_dst_bounded)
|
||||
(next, last, dst_traits::local(dst_first), dst_traits::local(dst_last), pred, dst_is_local_seg_t(), SrcCat());
|
||||
return dst_traits::compose(sfirst, r);
|
||||
}
|
||||
else {
|
||||
dst_local_iterator dst_local = (segmented_remove_if_dst_bounded)
|
||||
(next, last, dst_traits::local(dst_first), dst_traits::end(sfirst), pred, dst_is_local_seg_t(), SrcCat());
|
||||
if(next == last)
|
||||
return dst_traits::compose(sfirst, dst_local);
|
||||
|
||||
for(++sfirst; sfirst != slast; ++sfirst) {
|
||||
dst_local = (segmented_remove_if_dst_bounded)
|
||||
(next, last, dst_traits::begin(sfirst), dst_traits::end(sfirst), pred, dst_is_local_seg_t(), SrcCat());
|
||||
if(next == last)
|
||||
return dst_traits::compose(sfirst, dst_local);
|
||||
}
|
||||
|
||||
dst_local = (segmented_remove_if_dst_bounded)
|
||||
(next, last, dst_traits::begin(slast), dst_traits::local(dst_last), pred, dst_is_local_seg_t(), SrcCat());
|
||||
return dst_traits::compose(sfirst, dst_local);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Result dispatch: routes to bounded helper.
|
||||
// Non-segmented destination: single unbounded call (unreachable_sentinel_t).
|
||||
// Segmented destination: loop over destination segments, bounded per segment.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class SrcIter, class Sent, class DstIter, class Pred, class Cat>
|
||||
BOOST_CONTAINER_FORCEINLINE DstIter segmented_remove_if_dst_dispatch
|
||||
(SrcIter next, Sent last, DstIter first, Pred pred,
|
||||
const non_segmented_iterator_tag &, Cat)
|
||||
{
|
||||
return (segmented_remove_if_dst_bounded)
|
||||
(next, last, first, unreachable_sentinel_t(), pred, non_segmented_iterator_tag(), Cat());
|
||||
}
|
||||
|
||||
template <class SrcIter, class Sent, class SegDstIter, class Pred, class Cat>
|
||||
SegDstIter segmented_remove_if_dst_dispatch
|
||||
(SrcIter next, Sent last, SegDstIter first, Pred pred,
|
||||
const segmented_iterator_tag &, Cat)
|
||||
{
|
||||
typedef segmented_iterator_traits<SegDstIter> dst_traits;
|
||||
typedef typename dst_traits::local_iterator dst_local_iterator;
|
||||
typedef typename dst_traits::segment_iterator dst_segment_iterator;
|
||||
typedef typename segmented_iterator_traits<dst_local_iterator>::is_segmented_iterator dst_is_local_seg_t;
|
||||
|
||||
if(next == last)
|
||||
return first;
|
||||
|
||||
dst_segment_iterator dst_seg = dst_traits::segment(first);
|
||||
dst_local_iterator dst_local = dst_traits::local(first);
|
||||
|
||||
while(next != last) {
|
||||
dst_local_iterator dst_end = dst_traits::end(dst_seg);
|
||||
dst_local = (segmented_remove_if_dst_bounded)
|
||||
(next, last, dst_local, dst_end, pred, dst_is_local_seg_t(), Cat());
|
||||
if(next != last) {
|
||||
++dst_seg;
|
||||
dst_local = dst_traits::begin(dst_seg);
|
||||
}
|
||||
}
|
||||
return dst_traits::compose(dst_seg, dst_local);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Source dispatch: walks the source (read pointer) segments
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class SrcIter, class Sent, class DstIter, class Pred, class Tag, class Cat>
|
||||
typename algo_enable_if_c<
|
||||
!Tag::value || is_sentinel<Sent, SrcIter>::value, DstIter>::type
|
||||
segmented_remove_if_dispatch
|
||||
(SrcIter next, Sent last, DstIter first, Pred pred, Tag, Cat)
|
||||
{
|
||||
// No longer segmented source, now dispatch on destination segmentation.
|
||||
typedef segmented_iterator_traits<DstIter> dst_traits;
|
||||
return (segmented_remove_if_dst_dispatch)
|
||||
(next, last, first, pred,
|
||||
typename dst_traits::is_segmented_iterator(), Cat());
|
||||
}
|
||||
|
||||
template <class SegSrcIter, class DstIter, class Pred, class Cat>
|
||||
DstIter segmented_remove_if_dispatch
|
||||
(SegSrcIter next, SegSrcIter last, DstIter first, Pred pred,
|
||||
segmented_iterator_tag, Cat)
|
||||
{
|
||||
typedef segmented_iterator_traits<SegSrcIter> src_traits;
|
||||
typedef typename src_traits::local_iterator src_local_iterator;
|
||||
typedef typename src_traits::segment_iterator src_segment_iterator;
|
||||
typedef typename segmented_iterator_traits<src_local_iterator>::is_segmented_iterator src_is_local_seg_t;
|
||||
typedef typename iterator_traits<src_local_iterator>::iterator_category src_local_cat_t;
|
||||
|
||||
src_segment_iterator sfirst = src_traits::segment(next);
|
||||
const src_segment_iterator slast = src_traits::segment(last);
|
||||
|
||||
if(sfirst == slast) {
|
||||
return (segmented_remove_if_dispatch)
|
||||
(src_traits::local(next), src_traits::local(last), first, pred,
|
||||
src_is_local_seg_t(), src_local_cat_t());
|
||||
}
|
||||
else {
|
||||
first = (segmented_remove_if_dispatch)
|
||||
(src_traits::local(next), src_traits::end(sfirst), first, pred,
|
||||
src_is_local_seg_t(), src_local_cat_t());
|
||||
|
||||
for(++sfirst; sfirst != slast; ++sfirst)
|
||||
first = (segmented_remove_if_dispatch)
|
||||
(src_traits::begin(sfirst), src_traits::end(sfirst), first, pred,
|
||||
src_is_local_seg_t(), src_local_cat_t());
|
||||
|
||||
return (segmented_remove_if_dispatch)
|
||||
(src_traits::begin(slast), src_traits::local(last), first, pred,
|
||||
src_is_local_seg_t(), src_local_cat_t());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail_algo
|
||||
|
||||
//! Removes all elements for which \c pred returns true from [first, last),
|
||||
//! moving retained elements forward. Returns iterator to new end.
|
||||
template <class FwdIt, class Sent, class Predicate>
|
||||
@@ -252,7 +40,7 @@ FwdIt segmented_remove_if(FwdIt first, Sent last, Predicate pred)
|
||||
FwdIt next = first;
|
||||
++next;
|
||||
|
||||
return detail_algo::segmented_remove_if_dispatch
|
||||
return detail_algo::segmented_remove_copy_if_dispatch<true>
|
||||
(next, last, first, pred,
|
||||
typename traits::is_segmented_iterator(),
|
||||
typename iterator_traits<FwdIt>::iterator_category());
|
||||
|
||||
Reference in New Issue
Block a user