You are relying on the fact that the exact closure you pass into the algorithm is the one used as the predicate, but the standard allows it to be copied:
[algorithms.general]/10 (N4140)
: [Note: Unless otherwise specified, algorithms that take function objects as arguments are permitted to copy
those function objects freely. Programmers for whom object identity is important should consider using a
wrapper class that points to a noncopied implementation object such as reference_wrapper (20.9.3),
or some equivalent solution. —end note ]
This is exactly what libstdc++ does. From v6.2.1:
template<typename _ForwardIterator, typename _Predicate>
_ForwardIterator
__remove_if(_ForwardIterator __first, _ForwardIterator __last,
_Predicate __pred)
{
__first = std::__find_if(__first, __last, __pred);
if (__first == __last)
return __first;
_ForwardIterator __result = __first;
++__first;
for (; __first != __last; ++__first)
if (!__pred(__first))
{
*__result = _GLIBCXX_MOVE(*__first);
++__result;
}
return __result;
}
That call to std::__find_if
at the start of the function copies __pred
, which means that the value of i
is incremented a bit within std::__find_if
, but this doesn't change what's going on at the call site.
To fix this problem, you could use std::ref
:
auto clos = [i = 0U, it = cbegin(intervals), end = cend(intervals)](const auto&) mutable {
return it != end && ++i > it->first && (i <= it->second || (++it, true));
};
values.resize(distance(begin(values), std::remove_if(begin(values), end(values), std::ref(clos))));
Live demo
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…