考虑以下代码:
#include <vector>
#include <set>
using Iterator = std::vector<int>::iterator;
using ConstIterator = std::vector<int>::const_iterator;
std::set<ConstIterator> s;
int main() {
bool equal = Iterator{} == ConstIterator{};
s.count(Iterator{});
s.count(ConstIterator{});
s.contains(Iterator{});
s.contains(ConstIterator{});
}
这段代码是正确的,因为
ConstIterator
可以从Iterator
创建,但反之则不然。如果我们将 s
类型更改为 std::set<Iterator>
,使用 ConstIterator
的函数调用将导致构建失败。
如您所知,函数
count
和 contains
都不会修改集合,并且在内部它们只是将传递的值与存储的值进行比较。这种比较是绝对正确的(参见代码示例中的 equal
部分),我们可以比较 Iterator
和 ConstIterator
是否相等。一种可能的解决方法是将 find_if
与 lambda 一起使用,例如:
std::ranges::find_if(s, [](auto v) { return v == ConstIterator{}; });
因此,问题是:当我们有
count
并且想要查看存储 contains
的容器时,我们如何以标准且美观的方式处理 ConstIterator
/Iterator
?
使用
std::set<Iterator, std::less<>>
,或者 std::set<Iterator, std::ranges::less>
(如果可以的话)。
这些比较器类型包括一个
is_transparent
成员,它向 std::set
发出信号,表明它应该支持与任何键可比较类型进行比较,而不是转换为键类型。 (需要选择加入的原因是向后兼容性)。
这些类型本身在比较运算符中也接受不同的类型,而不是像
std::less<int>
(std::set<int>
的默认值)这样的类型,后者专门有 operator<(const int&, const int&)
。