假设我们想从向量中删除重复值int
s。通常的解决方案是对向量进行排序并使用擦除删除惯用语删除重复项。但我们需要保持不会被移除的元素的顺序,所以我们无法排序。所以人们可能会想出这样的谓词并使用 with withremove_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;
但问题仍然存在:
我们是否需要确保谓词函子的可能副本不会破坏我们的逻辑?标准中是否有任何内容强制(或禁止)与此问题相关的某些行为?或者是实施中的一个错误?
Yes, the standard does not specify how many times the predicate will be copied, nor does it say in what order the predicate will be applied to elements of the container. Essentially, predicates must act like pure functions http://en.wikipedia.org/wiki/Pure_function; they must have no observable state.1
So remove_if
这里听起来不像是合适的算法。诸如存储之类的黑客行为set
函子外部无法解决问题;您仍然会调用未定义的行为。
1. For a more in-depth discussion, see Item 39 ("Make predicates pure functions") of Scott Meyers' .
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)