如何迭代一个重载operator []的类?

时间:2018-10-18 09:06:01

标签: c++

我有一个这样的班级:

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
}

3 个答案:

答案 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_exprend_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_exprbegin(__range),而end_exprend(__range),这是通过与参数相关的查找(非ADL   查找未执行。)
  •   

对您的班级进行一次简单的更改就足够了,只需添加beginend,委托给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()),则可以对其进行迭代。您的类不提供迭代器,并且由于内部映射是私有的,因此无法在类外部实现迭代器。

因此,答案是否定的,该类确实需要修改。