为什么C ++标准库中的集合(std::set
和std::multiset
)提供非const_iterator
方法(set::begin
和multiset::begin
)?
通过迭代器访问密钥总是const
。如果集合本身是const也无关紧要。 为什么要引入那些额外的重载?
答案 0 :(得分:1)
请注意,在[member.functions]中,它表示:
对于C ++标准库中描述的非虚拟成员函数,实现可以声明一组不同的成员函数签名,前提是对成员函数的任何调用都将从此处描述的声明集中选择一个重载。文档的行为就像选择了重载一样。
标准定义了[container.requirements.general]中每个容器的行为,这些容器需要:
a.begin()
产生iterator
(const_iterator
代表a
} a.end()
产生iterator
(const_iterator
代表a
} 实现的要求是存在那些类型(C::iterator
和C::const_iterator
),并且这些函数会产生这些类型。要求不特别是必须存在这四个重载(两个迭代器类型必须不同)。要求只是行为。
以下是set
的完全一致的实现:
template <class Key, class Compare = std::less<Key>, class Allocator = std::allocator<Key>>
class set {
public:
struct iterator { ... };
using const_iterator = iterator;
iterator begin() const { ... };
iterator end() const { ... };
// other stuff
};
通过此实现,满足所有要求。所以这就足够了。实际上,这就是libstdc ++实现它的方式 - 两个迭代器是same type,只有一个begin()
而只有一个end()
。
为什么要引入那些额外的重载?
没有额外的重载。或者至少,没有必要。这取决于实施者。
答案 1 :(得分:-1)
虽然我不能肯定地说,一致性(见@yurikilochek的评论)对我来说似乎是合理的。 “如果那些非常量迭代器方法不存在,你能给出一个通用代码失败的例子吗?”以下代码不使用libstdc ++编译(但在Visual Studio下编译)因为set没有非const方法。我承认这不是某人在一天中写得很好的代码。
#include <iostream>
#include <vector>
#include <set>
template <class C> //C is some container
void f(C& c)
{
typedef typename C::iterator iter;
typedef iter (C::*fn)(); // note non-const method
fn begin = &C::begin; // will fail with set if begin() is const only
fn end = &C::end;
for (iter i = (c.*begin)(), e = (c.*end)(); i != e; ++i)
std::cout << *i << ' ';
std::cout << '\n';
}
int
main()
{
std::vector<int> v;
std::set<int> s;
f(v);
f(s);
return 0;
}