@@ -43,6 +43,24 @@ struct __set_intersection_result {
43
43
: __in1_(std::move(__in_iter1)), __in2_(std::move(__in_iter2)), __out_(std::move(__out_iter)) {}
44
44
};
45
45
46
+ // Helper for __set_intersection() with one-sided binary search: populate result and advance input iterators if they
47
+ // haven't advanced in the last 2 calls. This function is very intimately related to the way it is used and doesn't
48
+ // attempt to abstract that, it's not appropriate for general usage outside of its context. It would be a lambda of
49
+ // __set_intersection() if that hadn't stumped the compiler in c++03 mode in some platforms.
50
+ template <class _InForwardIter1 , class _InForwardIter2 , class _OutIter >
51
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __set_intersection_add_output_unless (
52
+ bool __advanced, _InForwardIter1& __first1, _InForwardIter2& __first2, _OutIter& __result, bool & __prev_advanced) {
53
+ if (__advanced | __prev_advanced) {
54
+ __prev_advanced = __advanced;
55
+ } else {
56
+ *__result = *__first1;
57
+ ++__result;
58
+ ++__first1;
59
+ ++__first2;
60
+ __prev_advanced = true ;
61
+ }
62
+ }
63
+
46
64
// With forward iterators we can make multiple passes over the data, allowing the use of one-sided binary search to
47
65
// reduce best-case complexity to log(N). Understanding how we can use binary search and still respect complexity
48
66
// guarantees is _not_ straightforward: the guarantee is "at most 2*(N+M)-1 comparisons", and one-sided binary search
@@ -76,30 +94,18 @@ __set_intersection(
76
94
_LIBCPP_CONSTEXPR std::__identity __proj;
77
95
bool __prev_advanced = true ;
78
96
79
- auto __add_output_unless = [&](bool __advanced) {
80
- if (__advanced | __prev_advanced) {
81
- __prev_advanced = __advanced;
82
- } else {
83
- *__result = *__first1;
84
- ++__result;
85
- ++__first1;
86
- ++__first2;
87
- __prev_advanced = true ;
88
- }
89
- };
90
-
91
97
while (__first2 != __last2) {
92
98
_InForwardIter1 __first1_next =
93
99
std::__lower_bound_onesided<_AlgPolicy>(__first1, __last1, *__first2, __comp, __proj);
94
100
std::swap (__first1_next, __first1);
95
- __add_output_unless (__first1 != __first1_next);
101
+ std::__set_intersection_add_output_unless (__first1 != __first1_next, __first1, __first2, __result, __prev_advanced );
96
102
if (__first1 == __last1)
97
103
break ;
98
104
99
105
_InForwardIter2 __first2_next =
100
106
std::__lower_bound_onesided<_AlgPolicy>(__first2, __last2, *__first1, __comp, __proj);
101
107
std::swap (__first2_next, __first2);
102
- __add_output_unless (__first2 != __first2_next);
108
+ std::__set_intersection_add_output_unless (__first2 != __first2_next, __first1, __first2, __result, __prev_advanced );
103
109
}
104
110
return __set_intersection_result<_InForwardIter1, _InForwardIter2, _OutIter>(
105
111
_IterOps<_AlgPolicy>::next (std::move (__first1), std::move (__last1)),
0 commit comments