这是C++标准库remove
代码中的代码.为什么不平等测试if (!(*first == val))
而不是if (*first != val)
?
template <class ForwardIterator, class T>
ForwardIterator remove (ForwardIterator first, ForwardIterator last, const T& val)
{
ForwardIterator result = first;
while (first!=last) {
if (!(*first == val)) {
*result = *first;
++result;
}
++first;
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
Tom*_*ner 144
因为这意味着对T的唯一要求是实现一个operator==
.你可以要求T有一个,operator!=
但这里的一般想法是你应该尽可能减轻模板用户的负担,而其他模板确实需要operator==
.
Luk*_*řík 36
STL中的大多数功能仅适用于operator<
或operator==
.这要求用户仅实现这两个操作符(或者有时至少其中一个).例如std::set
使用operator<
(更确切地说std::less
,operator<
默认情况下调用)而不operator>
管理排序.remove
您的示例中的模板是类似的情况 - 它仅使用operator==
而不是operator!=
因此operator!=
不需要定义.
Chr*_*ckl 28
这是来自C++标准库的代码删除代码.
错误.这不是在 C++标准库remove
的代码.它是C++标准库函数的一种可能的内部实现remove
.C++标准没有规定实际代码; 它预示着功能原型和所需行为.
换句话说:从严格的语言角度来看,您看到的代码不存在.它可能来自编译器标准库实现附带的一些头文件.请注意,C++标准甚至不需要存在这些头文件.文件只是编译器实现者满足类似行的要求#include <algorithm>
(即制作std::remove
和其他可用功能)的便捷方式.
为什么不平等测试
if (!(*first == val))
而不是if (*first != val)
?
因为只有operator==
功能需要.
当涉及到自定义类型的运算符重载时,该语言允许您执行各种奇怪的事情.您可以很好地创建一个具有重载operator==
但没有重载的类operator!=
.或者更糟糕的是:你可能会超载,operator!=
但却完全没有相关的东西.
考虑这个例子:
#include <algorithm>
#include <vector>
struct Example
{
int i;
Example() : i(0) {}
bool operator==(Example const& other) const
{
return i == other.i;
}
bool operator!=(Example const& other) const
{
return i == 5; // weird, but nothing stops you
// from doing so
}
};
int main()
{
std::vector<Example> v(10);
// ...
auto it = std::remove(v.begin(), v.end(), Example());
// ...
}
Run Code Online (Sandbox Code Playgroud)
如果std::remove
使用operator!=
,那么结果将完全不同.
Ric*_*ges 15
这里有一些好的答案.我只想添加一点注释.
像所有好的库一样,标准库的设计考虑了(至少)两个非常重要的原则:
将最少的责任放在您可以逃脱的图书馆用户身上.部分原因是在使用界面时给予他们最少的工作量.(就像定义尽可能少的操作员一样).它的另一部分与它们并不奇怪或要求它们检查错误代码(因此保持接口一致并<stdexcept>
在出现问题时抛出异常).
消除所有逻辑冗余.所有的比较都可以仅仅从中推断出来operator<
,那么为什么要求用户定义其他的?例如:
(a> b)相当于(b <a)
(a> = b)相当于!(a <b)
(a == b)相当于!((a <b)||(b <a))
等等.
当然,在本文中,人们可能会问为什么unordered_map
要求operator==
(至少在默认情况下)而不是operator<
.答案是在哈希表中,我们需要的唯一比较是一个相等的.因此,它要求它们定义相等运算符在逻辑上更一致(即对库用户更有意义).要求一个operator<
会让人感到困惑,因为它并不是很明显你为什么需要它.
小智 8
这个EqualityComparable
概念只需要operator==
定义.
因此,任何声称使用满足类型的函数EqualityComparable
都不能依赖于该operator!=
类型对象的存在.(除非有其他要求暗示存在operator!=
).