我有一个这样的班级:
class C {
private:
std::unordered_map<char, int> m = {{'a', 1}, {'b', 2}, {'c', 3}};
public:
int operator[](const char& key) const {
return m.find(key)->second;
}
};
是否可以在不修改类的情况下迭代地图的元素?
我想要类似的东西
for (auto x: c) {
// x -> a map element
}
答案 0 :(得分:12)
否,ranged-for循环不使用operator[]
的定义
for ( range_declaration : range_expression ) loop_statement
是否按原样对待(不引入__names
)
{
auto && __range = range_expression ;
auto __begin = begin_expr ;
auto __end = end_expr ;
for ( ; __begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
对于begin_expr
和end_expr
具有以下规则:
- 如果
range_expression
是数组类型的表达式,则begin_expr
是__range
,而end_expr
是(__range + __bound)
, 其中__bound
是数组中元素的数量(如果数组 大小未知或类型不完整,程序为 格式不正确)- 如果range_expression是类类型
C
的表达式,它既具有名为begin
的成员又具有名为end
的成员(无论 该成员的类型或可访问性),则begin_expr
为__range.begin()
和end_expr
是__range.end()
;- 否则,
begin_expr
是begin(__range)
,而end_expr
是end(__range)
,这是通过与参数相关的查找(非ADL 查找未执行。)
对您的班级进行一次简单的更改就足够了,只需添加begin
和end
,委托给m.begin()
和m.end()
class C {
private:
std::unordered_map<char, int> m = {{'a', 1}, {'b', 2}, {'c', 3}};
public:
int operator[](const char& key) const {
return m.find(key)->second;
// return m.at(key); or return m[key]; are both safer than this
}
std::unordered_map<char, int>::iterator begin() {
return m.begin();
}
// overloaded on the constness of "this"
std::unordered_map<char, int>::const_iterator begin() const {
return m.begin();
}
std::unordered_map<char, int>::iterator end() {
return m.end();
}
// overloaded on the constness of "this"
std::unordered_map<char, int>::const_iterator end() const {
return m.end();
}
};
答案 1 :(得分:4)
否。
除了其他人已涵盖的范围外特定施加的约束之外,您的类也不提供任何方法来知道映射中的哪些元素,甚至没有第一个或最后一个元素键。它不公开任何迭代器。它只是没有提供足够的信息来执行迭代。
答案 2 :(得分:2)
如果一个类提供了迭代器,即begin(c)
和end(c)
返回迭代器(或c.begin()
和c.end()
),则可以对其进行迭代。您的类不提供迭代器,并且由于内部映射是私有的,因此无法在类外部实现迭代器。
因此,答案是否定的,该类确实需要修改。