首页 > 解决方案 > 我从 std::set 得到 const_iterator 而不是迭代器

问题描述

我有以下根本无法编译的代码。它说我不能转换const NodeNode&Node不是const也不是A指方法const this也不std::set是 const。

我哪里错了?

#include <set>
#include <string>

struct Node
{
    std::string name;
};

struct NodeNameComparator
{
    using is_transparent = void;
    bool operator()(const Node &a, const std::string &b) const { return a.name < b; }
    bool operator()(const std::string &a, const Node &b) const { return a < b.name; }
    bool operator()(const Node &a, const Node &b) const { return a.name < b.name; }
};


struct A
{
    std::set<Node, NodeNameComparator> nodeset;
    Node &add_or_get_node(const std::string &name)
    {
        std::set<Node, NodeNameComparator>::iterator it = nodeset.template find(name);
        // IT WORKS BUT IT IS A WORKAROUND.
        //return it == nodeset.end() ? const_cast<Node&>(*(nodeset.insert(*new Node{name}).first)) : const_cast<Node&>(*it);
        //ERROR!!!
        return it == nodeset.end() ? *(nodeset.insert(*new Node{name}).first) : *it;
    };
};

int main() { return 0; }

标签: c++containersconst-iterator

解决方案


std::set不仅仅是一组元素,它是一组有序的独特元素。的元素在std::set设计上是不可变的,因此您不能通过std::set修改其元素来破坏不变性。这就是为什么std::set::iteratorstd::set::const_iterator都是常量迭代器的原因。

Cppreferencestd::set 读取

Member type       Definition 

iterator          Constant LegacyBidirectionalIterator
const_iterator    Constant LegacyBidirectionalIterator

另请参阅此 LWG 问题

关联容器中的键是不可变的。...对于值类型与键类型相同的关联容器,两者iterator都是const_iterator常量迭代器。

基本原理: ...如果元素是可变的,则没有编译时方法来检测导致修改排序的简单用户疏忽。有报道说这实际上发生在实践中,诊断起来很痛苦。如果用户需要修改元素,可以使用可变成员或const_cast.


推荐阅读