假设我们想从int
s 的向量中删除重复值。通常的解决方案是使用erase-remove idiom对向量进行排序并擦除重复项。但是我们需要维护不会被删除的元素的顺序,所以我们不能排序。所以有人可能会想出一个这样的谓词并使用 withremove_if
算法:
struct comp {
std::set<int> s;
comp() : s() {}
bool operator()(int i)
{
return !(s.insert(i)).second;
}
};
但是如果谓词对象由于某种原因被复制,这将中断,因为我们将获得set
成员的两个副本。事实上,gcc 的实现remove_if
正是这样做的:
template<typename _ForwardIterator, typename _Predicate>
_ForwardIterator
remove_if(_ForwardIterator __first, _ForwardIterator __last,
_Predicate __pred)
{
__first = _GLIBCXX_STD_A::find_if(__first, __last, __pred);
if(__first == __last) // ^^^^^ here a copy is made
return __first;
_ForwardIterator __result = __first;
++__first;
for(; __first != __last; ++__first)
if(!bool(__pred(*__first)))
{
*__result = _GLIBCXX_MOVE(*__first);
++__result;
}
return __result;
}
解决方法是使set
我们的仿函数成员静态:
struct comp {
static set<int> s;
comp() { s. clear(); }
bool operator()(int i)
{
return !(s.insert(i)).second;
}
};
set<int> comp::s;
但问题仍然存在:
我们是否需要确保谓词函子的可能副本不会破坏我们的逻辑? 标准中是否有任何规定(或禁止)与此问题相关的某些行为?或者它是实现中的错误?