考虑以下代码:
struct T
{
bool status;
UsefulData data;
};
std::forward_list<T> lst;
lst.remove_if([](T &x) -> bool { return x.status= !x.status; });
比如一次性切换状态并删除不活跃元素。
根据cppreference的说法,上述代码似乎是未定义行为(强调我的):
template< class UnaryPredicate > void remove_if( UnaryPredicate p );
p
- unary predicate which returns true if the element should be removed. The signature of the predicate function should be equivalent to the following:
bool pred(const Type &a);
The signature does not need to have
const &
, but the function must not modify the objects passed to it. The typeType
must be such that an object of typeforward_list<T,Allocator>::const_iterator
can be dereferenced and then implicitly converted toType
.
然而,当前的工作草案似乎不那么严格(N4659 [forwardlist.ops]):
void remove(const T& value) template <class Predicate> void remove_if(Predicate pred);
Effects:
Erases all the elements in the list referred by a list iterator
i
for which the following conditions hold:*i == value
(forremove()
),pred(*i)
istrue
(forremove_if()
). Invalidates only the iterators and references to the erased elements.Throws:
Nothing unless an exception is thrown by the equality comparison or the predicate.
Remarks:
Stable (20.5.5.7).
Complexity:
Exactly
distance(begin(), end())
applications of the corresponding predicate.
标准的其他部分是否对谓词有额外限制?
我已在多个编译器上测试了上面的代码,它可以编译并似乎按预期工作。我真的需要两次遍历列表吗?
remove_if
并不特别棘手,但允许Compare
修改list::sort
元素肯定是一个非常糟糕的想法,而且这种非修改要求仅在[alg.sorting]中找到。 - T.C.