假设我们想从一个向量int
s中删除重复的值。通常的解决方案是对矢量进行排序并使用擦除删除方式擦除重复项。但是我们需要维护不会被删除的元素的顺序,所以我们无法排序。所以有人会想出这样的断言,并使用与remove_if
算法:标准库算法是否允许复制谓词参数?
struct comp {
std::set<int> s;
comp() : s() {}
bool operator()(int i)
{
return !(s.insert(i)).second;
}
};
但是,这将打破,如果谓词对象将被复制出于某种原因,因为我们将得到set
成员的两个副本。事实上,海湾合作委员会的执行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;
但问题依然存在:
难道我们需要确保谓词仿函数的可能副本不会破坏我们的逻辑? 标准中是否有任何规定(或禁止)关于此问题的某些行为?或者它是实施中的错误?
+1关于纯功能和良好参考的好处。 – juanchopanza
有标准指定顺序的算法。像'std :: copy',不是?标准中的“备注:稳定”是什么意思,是不是要求订单得到保留? – jrok
@jrok:只有在保留元素的相对顺序不会改变的意义上,它才是稳定的,而不是OP所希望的。 (并且'copy'不带谓词,'copy_if'不带谓词,'copy_if'只带一个,但没有指定它的应用顺序。) –