Fix destination exhaustion logic as the source must be always consumed

This commit is contained in:
Ion Gaztañaga
2026-07-26 14:22:22 +02:00
parent 1ca8484469
commit c857e95625
4 changed files with 125 additions and 109 deletions
@@ -55,8 +55,15 @@ set_difference_dst_bounded
(Iter1 first1, Sent1 last1, Iter2 first2, Sent2 last2,
DstIter dst_first, DstSent dst_last, Comp comp, DstTag, SrcCat)
{
while(first1 != last1 && first2 != last2 && dst_first != dst_last) {
// The destination-full test guards the write, not the whole iteration: an
// element that produces no output still has to be consumed, so stopping
// with room left in the sources but none in the destination would leave
// the segmented walker unable to tell a full segment from an exhausted
// destination. With unreachable_sentinel_t the test folds away as before.
while(first1 != last1 && first2 != last2) {
if (comp(*first1, *first2)) {
if(BOOST_CONTAINER_SEG_UNLIKELY(dst_first == dst_last))
break;
*dst_first = *first1;
++first1;
++dst_first;
@@ -139,7 +146,6 @@ segtrio<Iter1, Iter2, DstIter> set_difference_until_exhausts
template <class Iter1, class Sent1, class Iter2, class Sent2, class SegDstIter,
class Comp, class Cat>
BOOST_CONTAINER_FORCEINLINE
segtrio<Iter1, Iter2, SegDstIter> set_difference_until_exhausts
(Iter1 first1, Sent1 last1, Iter2 first2, Sent2 last2, SegDstIter result, Comp comp,
const segmented_iterator_tag &, const Cat &src1_cat)
@@ -166,9 +172,15 @@ segtrio<Iter1, Iter2, SegDstIter> set_difference_until_exhausts
first2 = r.second;
dst_local = r.third;
if(BOOST_CONTAINER_SEG_UNLIKELY(dst_local != dst_end)) {
// Stop on source exhaustion, not on "the segment did not fill": when
// the output ends exactly on a segment boundary both hold at once, and
// stepping dst_seg then walks off the end of the destination. compose()
// normalises a local iterator sitting on the segment end, the same way
// segmented_copy_dst_dispatch relies on.
if(BOOST_CONTAINER_SEG_UNLIKELY(first1 == last1 || first2 == last2)) {
return result_t(first1, first2, dst_traits::compose(dst_seg, dst_local));
}
// dst segment full and both sources still live; advance to the next.
++dst_seg;
dst_local = dst_traits::begin(dst_seg);
}
@@ -193,7 +205,6 @@ BOOST_CONTAINER_FORCEINLINE segtrio<Iter1, Iter2, OutIter> set_difference_seg2_d
}
template <class Iter1, class Sent1, class SegIter2, class OutIter, class Comp, class Cat>
BOOST_CONTAINER_FORCEINLINE
segtrio<Iter1, SegIter2, OutIter> set_difference_seg2_dispatch
(Iter1 first1, Sent1 last1, SegIter2 first2, SegIter2 last2, OutIter result, Comp comp,
segmented_iterator_tag, const Cat & cat)
@@ -213,33 +224,29 @@ segtrio<Iter1, SegIter2, OutIter> set_difference_seg2_dispatch
const src2_segment_iterator sl2 = src2_traits::segment(last2);
src2_local_iterator lf2 = src2_traits::local(first2);
if(sf2 == sl2) {
local_result_t r = (set_difference_seg2_dispatch)
(first1, last1, lf2, src2_traits::local(last2), result, comp,
src2_is_local_seg_t(), cat);
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
}
else {
if(BOOST_CONTAINER_SEG_LIKELY(sf2 != sl2)) {
local_result_t r = (set_difference_seg2_dispatch)
(first1, last1, lf2, src2_traits::end(sf2), result, comp,
src2_is_local_seg_t(), cat);
if (BOOST_CONTAINER_SEG_UNLIKELY(r.first == last1))
goto exit;
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
for(++sf2; sf2 != sl2; ++sf2) {
r = (set_difference_seg2_dispatch)
(r.first, last1, src2_traits::begin(sf2), src2_traits::end(sf2),
r.third, comp, src2_is_local_seg_t(), cat);
if(BOOST_CONTAINER_SEG_UNLIKELY(r.first == last1))
goto exit;
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
}
r = (set_difference_seg2_dispatch)
(r.first, last1, src2_traits::begin(sf2), src2_traits::local(last2),
r.third, comp, src2_is_local_seg_t(), cat);
exit:
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
lf2 = src2_traits::begin(sl2);
first1 = r.first;
result = r.third;
}
const local_result_t r = (set_difference_seg2_dispatch)
(first1, last1, lf2, src2_traits::local(last2), result, comp,
src2_is_local_seg_t(), cat);
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
}
//////////////////////////////////////////////////////////////////////////////
@@ -264,7 +271,6 @@ BOOST_CONTAINER_FORCEINLINE segtrio<FwdIt, InIter2, OutIter> set_difference_scan
}
template <class SegIt, class InIter2, class Sent2, class OutIter, class Comp>
BOOST_CONTAINER_FORCEINLINE
segtrio<SegIt, InIter2, OutIter> set_difference_scan
(SegIt first, SegIt last, InIter2 first2, Sent2 last2, OutIter result, Comp comp,
segmented_iterator_tag)
@@ -284,12 +290,7 @@ segtrio<SegIt, InIter2, OutIter> set_difference_scan
segment_iterator const slast = traits::segment(last);
local_iterator lcur = traits::local(first);
if(scur == slast) {
local_result_t r = set_difference_scan
(lcur, traits::local(last), first2, last2, result, comp, is_local_seg_t());
return result_t(traits::compose(scur, r.first), r.second, r.third);
}
else {
if(BOOST_CONTAINER_SEG_LIKELY(scur != slast)) {
local_result_t r = set_difference_scan
(lcur, traits::end(scur), first2, last2, result, comp, is_local_seg_t());
if(BOOST_CONTAINER_SEG_UNLIKELY(r.second == last2))
@@ -302,10 +303,13 @@ segtrio<SegIt, InIter2, OutIter> set_difference_scan
return result_t(traits::compose(scur, r.first), r.second, r.third);
}
r = set_difference_scan
(traits::begin(scur), traits::local(last), r.second, last2, r.third, comp, is_local_seg_t());
return result_t(traits::compose(scur, r.first), r.second, r.third);
lcur = traits::begin(slast);
first2 = r.second;
result = r.third;
}
const local_result_t r = set_difference_scan
(lcur, traits::local(last), first2, last2, result, comp, is_local_seg_t());
return result_t(traits::compose(scur, r.first), r.second, r.third);
}
} // namespace detail_algo
@@ -52,10 +52,19 @@ set_intersection_dst_bounded
(Iter1 first1, Sent1 last1, Iter2 first2, Sent2 last2,
DstIter dst_first, DstSent dst_last, Comp comp, DstTag, SrcCat)
{
while(first1 != last1 && first2 != last2 && dst_first != dst_last) {
// The destination-full test guards the write, not the whole iteration: an
// element that produces no output still has to be consumed, so stopping
// with room left in the sources but none in the destination would leave
// the segmented walker unable to tell a full segment from an exhausted
// destination. With unreachable_sentinel_t the test folds away as before.
while(first1 != last1 && first2 != last2) {
if (comp(*first1, *first2)) { ++first1; }
else if (comp(*first2, *first1)) { ++first2; }
else { *dst_first = *first1; ++first1; ++first2; ++dst_first; }
else {
if(BOOST_CONTAINER_SEG_UNLIKELY(dst_first == dst_last))
break;
*dst_first = *first1; ++first1; ++first2; ++dst_first;
}
}
return segtrio<Iter1, Iter2, DstIter>(first1, first2, dst_first);
}
@@ -150,9 +159,15 @@ segtrio<Iter1, Iter2, SegDstIter> set_intersection_until_exhausts
first2 = r.second;
dst_local = r.third;
if(BOOST_CONTAINER_SEG_UNLIKELY(dst_local != dst_end)) {
// Stop on source exhaustion, not on "the segment did not fill": when
// the output ends exactly on a segment boundary both hold at once, and
// stepping dst_seg then walks off the end of the destination. compose()
// normalises a local iterator sitting on the segment end, the same way
// segmented_copy_dst_dispatch relies on.
if(BOOST_CONTAINER_SEG_UNLIKELY(first1 == last1 || first2 == last2)) {
return result_t(first1, first2, dst_traits::compose(dst_seg, dst_local));
}
// dst segment full and both sources still live; advance to the next.
++dst_seg;
dst_local = dst_traits::begin(dst_seg);
}
@@ -196,33 +211,29 @@ segtrio<Iter1, SegIter2, OutIter> set_intersection_seg2_dispatch
const src2_segment_iterator sl2 = src2_traits::segment(last2);
src2_local_iterator lf2 = src2_traits::local(first2);
if(sf2 == sl2) {
local_result_t r = (set_intersection_seg2_dispatch)
(first1, last1, lf2, src2_traits::local(last2), result, comp,
src2_is_local_seg_t(), cat);
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
}
else {
if(BOOST_CONTAINER_SEG_LIKELY(sf2 != sl2)) {
local_result_t r = (set_intersection_seg2_dispatch)
(first1, last1, lf2, src2_traits::end(sf2), result, comp,
src2_is_local_seg_t(), cat);
if (BOOST_CONTAINER_SEG_UNLIKELY(r.first == last1))
goto exit;
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
for(++sf2; sf2 != sl2; ++sf2) {
r = (set_intersection_seg2_dispatch)
(r.first, last1, src2_traits::begin(sf2), src2_traits::end(sf2),
r.third, comp, src2_is_local_seg_t(), cat);
if(BOOST_CONTAINER_SEG_UNLIKELY(r.first == last1))
goto exit;
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
}
r = (set_intersection_seg2_dispatch)
(r.first, last1, src2_traits::begin(sf2), src2_traits::local(last2),
r.third, comp, src2_is_local_seg_t(), cat);
exit:
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
lf2 = src2_traits::begin(sl2);
first1 = r.first;
result = r.third;
}
const local_result_t r = (set_intersection_seg2_dispatch)
(first1, last1, lf2, src2_traits::local(last2), result, comp,
src2_is_local_seg_t(), cat);
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
}
//////////////////////////////////////////////////////////////////////////////
@@ -266,12 +277,7 @@ segtrio<SegIt, InIter2, OutIter> set_intersection_scan
segment_iterator const slast = traits::segment(last);
local_iterator lcur = traits::local(first);
if(scur == slast) {
local_result_t r = set_intersection_scan
(lcur, traits::local(last), first2, last2, result, comp, is_local_seg_t());
return result_t(traits::compose(scur, r.first), r.second, r.third);
}
else {
if(BOOST_CONTAINER_SEG_LIKELY(scur != slast)) {
local_result_t r = set_intersection_scan
(lcur, traits::end(scur), first2, last2, result, comp, is_local_seg_t());
if(BOOST_CONTAINER_SEG_UNLIKELY(r.second == last2))
@@ -284,10 +290,13 @@ segtrio<SegIt, InIter2, OutIter> set_intersection_scan
return result_t(traits::compose(scur, r.first), r.second, r.third);
}
r = set_intersection_scan
(traits::begin(scur), traits::local(last), r.second, last2, r.third, comp, is_local_seg_t());
return result_t(traits::compose(scur, r.first), r.second, r.third);
lcur = traits::begin(slast);
first2 = r.second;
result = r.third;
}
const local_result_t r = set_intersection_scan
(lcur, traits::local(last), first2, last2, result, comp, is_local_seg_t());
return result_t(traits::compose(scur, r.first), r.second, r.third);
}
} // namespace detail_algo
@@ -55,14 +55,23 @@ set_symmetric_difference_dst_bounded
(Iter1 first1, Sent1 last1, Iter2 first2, Sent2 last2,
DstIter dst_first, DstSent dst_last, Comp comp, DstTag, SrcCat)
{
while(first1 != last1 && first2 != last2 && dst_first != dst_last) {
// The destination-full test guards the write, not the whole iteration: an
// element that produces no output still has to be consumed, so stopping
// with room left in the sources but none in the destination would leave
// the segmented walker unable to tell a full segment from an exhausted
// destination. With unreachable_sentinel_t the test folds away as before.
while(first1 != last1 && first2 != last2) {
if (comp(*first1, *first2)) {
if(BOOST_CONTAINER_SEG_UNLIKELY(dst_first == dst_last))
break;
*dst_first = *first1;
++first1;
++dst_first;
}
else {
if (comp(*first2, *first1)) {
if(BOOST_CONTAINER_SEG_UNLIKELY(dst_first == dst_last))
break;
*dst_first = *first2;
++dst_first;
}
@@ -153,7 +162,6 @@ segtrio<Iter1, Iter2, DstIter> set_symmetric_difference_until_exhausts
template <class Iter1, class Sent1, class Iter2, class Sent2, class SegDstIter,
class Comp, class Cat>
BOOST_CONTAINER_FORCEINLINE
segtrio<Iter1, Iter2, SegDstIter> set_symmetric_difference_until_exhausts
(Iter1 first1, Sent1 last1, Iter2 first2, Sent2 last2, SegDstIter result, Comp comp,
const segmented_iterator_tag &, const Cat &src1_cat)
@@ -180,9 +188,15 @@ segtrio<Iter1, Iter2, SegDstIter> set_symmetric_difference_until_exhausts
first2 = r.second;
dst_local = r.third;
if(BOOST_CONTAINER_SEG_UNLIKELY(dst_local != dst_end)) {
// Stop on source exhaustion, not on "the segment did not fill": when
// the output ends exactly on a segment boundary both hold at once, and
// stepping dst_seg then walks off the end of the destination. compose()
// normalises a local iterator sitting on the segment end, the same way
// segmented_copy_dst_dispatch relies on.
if(BOOST_CONTAINER_SEG_UNLIKELY(first1 == last1 || first2 == last2)) {
return result_t(first1, first2, dst_traits::compose(dst_seg, dst_local));
}
// dst segment full and both sources still live; advance to the next.
++dst_seg;
dst_local = dst_traits::begin(dst_seg);
}
@@ -207,7 +221,6 @@ BOOST_CONTAINER_FORCEINLINE segtrio<Iter1, Iter2, OutIter> set_symmetric_differe
}
template <class Iter1, class Sent1, class SegIter2, class OutIter, class Comp, class Cat>
BOOST_CONTAINER_FORCEINLINE
segtrio<Iter1, SegIter2, OutIter> set_symmetric_difference_seg2_dispatch
(Iter1 first1, Sent1 last1, SegIter2 first2, SegIter2 last2, OutIter result, Comp comp,
segmented_iterator_tag, const Cat & cat)
@@ -227,33 +240,29 @@ segtrio<Iter1, SegIter2, OutIter> set_symmetric_difference_seg2_dispatch
const src2_segment_iterator sl2 = src2_traits::segment(last2);
src2_local_iterator lf2 = src2_traits::local(first2);
if(sf2 == sl2) {
local_result_t r = (set_symmetric_difference_seg2_dispatch)
(first1, last1, lf2, src2_traits::local(last2), result, comp,
src2_is_local_seg_t(), cat);
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
}
else {
if(BOOST_CONTAINER_SEG_LIKELY(sf2 != sl2)) {
local_result_t r = (set_symmetric_difference_seg2_dispatch)
(first1, last1, lf2, src2_traits::end(sf2), result, comp,
src2_is_local_seg_t(), cat);
if (BOOST_CONTAINER_SEG_UNLIKELY(r.first == last1))
goto exit;
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
for(++sf2; sf2 != sl2; ++sf2) {
r = (set_symmetric_difference_seg2_dispatch)
(r.first, last1, src2_traits::begin(sf2), src2_traits::end(sf2),
r.third, comp, src2_is_local_seg_t(), cat);
if(BOOST_CONTAINER_SEG_UNLIKELY(r.first == last1))
goto exit;
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
}
r = (set_symmetric_difference_seg2_dispatch)
(r.first, last1, src2_traits::begin(sf2), src2_traits::local(last2),
r.third, comp, src2_is_local_seg_t(), cat);
exit:
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
lf2 = src2_traits::begin(sl2);
first1 = r.first;
result = r.third;
}
const local_result_t r = (set_symmetric_difference_seg2_dispatch)
(first1, last1, lf2, src2_traits::local(last2), result, comp,
src2_is_local_seg_t(), cat);
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
}
//////////////////////////////////////////////////////////////////////////////
@@ -278,7 +287,6 @@ BOOST_CONTAINER_FORCEINLINE segtrio<FwdIt, InIter2, OutIter> set_symmetric_diffe
}
template <class SegIt, class InIter2, class Sent2, class OutIter, class Comp>
BOOST_CONTAINER_FORCEINLINE
segtrio<SegIt, InIter2, OutIter> set_symmetric_difference_scan
(SegIt first, SegIt last, InIter2 first2, Sent2 last2, OutIter result, Comp comp,
segmented_iterator_tag)
@@ -298,12 +306,7 @@ segtrio<SegIt, InIter2, OutIter> set_symmetric_difference_scan
segment_iterator const slast = traits::segment(last);
local_iterator lcur = traits::local(first);
if(scur == slast) {
local_result_t r = set_symmetric_difference_scan
(lcur, traits::local(last), first2, last2, result, comp, is_local_seg_t());
return result_t(traits::compose(scur, r.first), r.second, r.third);
}
else {
if(BOOST_CONTAINER_SEG_LIKELY(scur != slast)) {
local_result_t r = set_symmetric_difference_scan
(lcur, traits::end(scur), first2, last2, result, comp, is_local_seg_t());
if(BOOST_CONTAINER_SEG_UNLIKELY(r.second == last2))
@@ -316,10 +319,13 @@ segtrio<SegIt, InIter2, OutIter> set_symmetric_difference_scan
return result_t(traits::compose(scur, r.first), r.second, r.third);
}
r = set_symmetric_difference_scan
(traits::begin(scur), traits::local(last), r.second, last2, r.third, comp, is_local_seg_t());
return result_t(traits::compose(scur, r.first), r.second, r.third);
lcur = traits::begin(slast);
first2 = r.second;
result = r.third;
}
const local_result_t r = set_symmetric_difference_scan
(lcur, traits::local(last), first2, last2, result, comp, is_local_seg_t());
return result_t(traits::compose(scur, r.first), r.second, r.third);
}
} // namespace detail_algo
@@ -126,7 +126,6 @@ segtrio<Iter1, Iter2, DstIter> set_union_until_exhausts
template <class Iter1, class Sent1, class Iter2, class Sent2, class SegDstIter,
class Comp, class Cat>
BOOST_CONTAINER_FORCEINLINE
segtrio<Iter1, Iter2, SegDstIter> set_union_until_exhausts
(Iter1 first1, Sent1 last1, Iter2 first2, Sent2 last2, SegDstIter result, Comp comp,
const segmented_iterator_tag &, const Cat &src1_cat)
@@ -153,9 +152,15 @@ segtrio<Iter1, Iter2, SegDstIter> set_union_until_exhausts
first2 = r.second;
dst_local = r.third;
if(BOOST_CONTAINER_SEG_UNLIKELY(dst_local != dst_end)) {
// Stop on source exhaustion, not on "the segment did not fill": when
// the output ends exactly on a segment boundary both hold at once, and
// stepping dst_seg then walks off the end of the destination. compose()
// normalises a local iterator sitting on the segment end, the same way
// segmented_copy_dst_dispatch relies on.
if(BOOST_CONTAINER_SEG_UNLIKELY(first1 == last1 || first2 == last2)) {
return result_t(first1, first2, dst_traits::compose(dst_seg, dst_local));
}
// dst segment full and both sources still live; advance to the next.
++dst_seg;
dst_local = dst_traits::begin(dst_seg);
}
@@ -180,7 +185,6 @@ BOOST_CONTAINER_FORCEINLINE segtrio<Iter1, Iter2, OutIter> set_union_seg2_dispat
}
template <class Iter1, class Sent1, class SegIter2, class OutIter, class Comp, class Cat>
BOOST_CONTAINER_FORCEINLINE
segtrio<Iter1, SegIter2, OutIter> set_union_seg2_dispatch
(Iter1 first1, Sent1 last1, SegIter2 first2, SegIter2 last2, OutIter result, Comp comp,
segmented_iterator_tag, const Cat & cat)
@@ -200,33 +204,29 @@ segtrio<Iter1, SegIter2, OutIter> set_union_seg2_dispatch
const src2_segment_iterator sl2 = src2_traits::segment(last2);
src2_local_iterator lf2 = src2_traits::local(first2);
if(sf2 == sl2) {
local_result_t r = (set_union_seg2_dispatch)
(first1, last1, lf2, src2_traits::local(last2), result, comp,
src2_is_local_seg_t(), cat);
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
}
else {
if(BOOST_CONTAINER_SEG_LIKELY(sf2 != sl2)) {
local_result_t r = (set_union_seg2_dispatch)
(first1, last1, lf2, src2_traits::end(sf2), result, comp,
src2_is_local_seg_t(), cat);
if (BOOST_CONTAINER_SEG_UNLIKELY(r.first == last1))
goto exit;
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
for(++sf2; sf2 != sl2; ++sf2) {
r = (set_union_seg2_dispatch)
(r.first, last1, src2_traits::begin(sf2), src2_traits::end(sf2),
r.third, comp, src2_is_local_seg_t(), cat);
if(BOOST_CONTAINER_SEG_UNLIKELY(r.first == last1))
goto exit;
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
}
r = (set_union_seg2_dispatch)
(r.first, last1, src2_traits::begin(sf2), src2_traits::local(last2),
r.third, comp, src2_is_local_seg_t(), cat);
exit:
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
lf2 = src2_traits::begin(sl2);
first1 = r.first;
result = r.third;
}
const local_result_t r = (set_union_seg2_dispatch)
(first1, last1, lf2, src2_traits::local(last2), result, comp,
src2_is_local_seg_t(), cat);
return result_t(r.first, src2_traits::compose(sf2, r.second), r.third);
}
//////////////////////////////////////////////////////////////////////////////
@@ -251,7 +251,6 @@ BOOST_CONTAINER_FORCEINLINE segtrio<FwdIt, InIter2, OutIter> set_union_scan
}
template <class SegIt, class InIter2, class Sent2, class OutIter, class Comp>
BOOST_CONTAINER_FORCEINLINE
segtrio<SegIt, InIter2, OutIter> set_union_scan
(SegIt first, SegIt last, InIter2 first2, Sent2 last2, OutIter result, Comp comp,
segmented_iterator_tag)
@@ -271,12 +270,7 @@ segtrio<SegIt, InIter2, OutIter> set_union_scan
segment_iterator const slast = traits::segment(last);
local_iterator lcur = traits::local(first);
if(scur == slast) {
local_result_t r = set_union_scan
(lcur, traits::local(last), first2, last2, result, comp, is_local_seg_t());
return result_t(traits::compose(scur, r.first), r.second, r.third);
}
else {
if(BOOST_CONTAINER_SEG_LIKELY(scur != slast)) {
local_result_t r = set_union_scan
(lcur, traits::end(scur), first2, last2, result, comp, is_local_seg_t());
if(BOOST_CONTAINER_SEG_UNLIKELY(r.second == last2))
@@ -289,10 +283,13 @@ segtrio<SegIt, InIter2, OutIter> set_union_scan
return result_t(traits::compose(scur, r.first), r.second, r.third);
}
r = set_union_scan
(traits::begin(scur), traits::local(last), r.second, last2, r.third, comp, is_local_seg_t());
return result_t(traits::compose(scur, r.first), r.second, r.third);
lcur = traits::begin(slast);
first2 = r.second;
result = r.third;
}
const local_result_t r = set_union_scan
(lcur, traits::local(last), first2, last2, result, comp, is_local_seg_t());
return result_t(traits::compose(scur, r.first), r.second, r.third);
}
} // namespace detail_algo