我从 std::set 得到 const_iterator 而不是迭代器
I get const_iterator instead of iterator from std::set
我有以下代码根本无法编译。
它说我不能将 const Node
转换为 Node&
但 Node
不是 const
也不是 A
的方法引用 const this
也不是 std::set
是常量。
我哪里错了?
#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; }
std::set
不仅仅是一组元素,它是一组经过排序的唯一元素。 std::set
的元素在设计上是不可变的,因此您不能通过修改其元素来破坏 std::set
不变性。这就是为什么 std::set::iterator
和 std::set::const_iterator
都是常量迭代器的原因。
std::set
上的 Cppreference reads:
Member type Definition
iterator Constant LegacyBidirectionalIterator
const_iterator Constant LegacyBidirectionalIterator
另见 this LWG issue:
Keys in an associative container are immutable. ... For associative containers where the value type is the same as the key type, both iterator
and const_iterator
are constant iterators.
Rationale: ... if elements were mutable, there would be no compile-time way to detect of a simple user oversight which caused ordering to be modified. There was a report that this had actually happened in practice, and had been painful to diagnose. If users need to modify elements, it is possible to use mutable members or const_cast
.
我有以下代码根本无法编译。
它说我不能将 const Node
转换为 Node&
但 Node
不是 const
也不是 A
的方法引用 const this
也不是 std::set
是常量。
我哪里错了?
#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; }
std::set
不仅仅是一组元素,它是一组经过排序的唯一元素。 std::set
的元素在设计上是不可变的,因此您不能通过修改其元素来破坏 std::set
不变性。这就是为什么 std::set::iterator
和 std::set::const_iterator
都是常量迭代器的原因。
std::set
上的 Cppreference reads:
Member type Definition
iterator Constant LegacyBidirectionalIterator
const_iterator Constant LegacyBidirectionalIterator
另见 this LWG issue:
Keys in an associative container are immutable. ... For associative containers where the value type is the same as the key type, both
iterator
andconst_iterator
are constant iterators.Rationale: ... if elements were mutable, there would be no compile-time way to detect of a simple user oversight which caused ordering to be modified. There was a report that this had actually happened in practice, and had been painful to diagnose. If users need to modify elements, it is possible to use mutable members or
const_cast
.