为什么std::(multi)set提供非const迭代器方法

4

为什么C++标准库中的集合(std::setstd::multiset)提供非const_iterator方法(set::beginmultiset::begin)?

通过迭代器访问键始终是const。无论集合本身是否为const都没有关系。为什么要引入这些额外的重载呢?


3
这个问题如何与那个问题重复? - Curious
为了完整性和通用性,遵守容器概念。 - yuri kilochek
@yurikilochek,仅为返回包含值的const引用提供const方法不够通用,您能否举出一个如果这些非const迭代器方法不存在将失败的通用代码示例?我唯一能想到的是一些部分特化检测非const begin()和end()方法的情况。 - Curious
我相信但不完全确定,早期版本的set允许您在迭代器上修改对象。当然,在以重新排序方式修改对象时会导致未定义行为,但有很多情况下,对象的一部分是键,其余部分可以安全地修改。老实说,我不知道为什么不允许这样做。 - Mark Ransom
std::set::erase 在它们上进行了重载。我们可以在这里应用原样规则吗? - yuri kilochek
显示剩余9条评论
2个回答

2
请注意,在[member.functions]中,它表达了以下内容:
对于在C++标准库中描述的非虚拟成员函数,实现可以声明一组不同的成员函数签名,只要任何调用该成员函数的操作都像选择了这个文档中描述的重载那样运行。
标准为[container.requirements.general]中的每个容器定义了行为,其中要求:
- a.begin() 产生一个迭代器(或常量aconst_iterator) - a.end() 产生一个迭代器(或常量aconst_iterator) - ...
要求实现中必须存在这些类型 (C::iteratorC::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++的实现方式——两个迭代器是相同类型,只有一个begin()和一个end()

为什么要引入这些额外的重载函数?

并没有额外的重载函数。或者至少,在实现者的手中决定是否需要。

-1
虽然我不能确定,但对我来说一致性(请参见@yurikilochek的评论)似乎是合理的。 “您能给出一个常规代码失败的示例,如果这些非const迭代器方法不存在?”以下代码在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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接