迭代者是否有自己的立场?

时间:2017-06-16 09:21:23

标签: c++

假设我有一张地图,其中键是int,为了简单起见,并且能够使用最少的编译示例重现该问题。在我自己的情况下,关键是一个更复杂的野兽。

我想重复使用此地图,以便使用不同的密钥创建另一个地图:例如enum而不是int。为此,我有两个函数可以将int转换为enum,反之亦然。

我没有重写整个班级,而是使用构图,然后将我的地图(在这种情况下为map<int,int>放入我的新班级myMap中。

我从以下实现开始,但是我在类A中遇到了自定义迭代器的问题。我没有选择继承std::iterator,也没有选择map<int,int>::iterator,而是再次使用合成:

class myMap
{
private:
    std::map<int, int> m;

public:

    typedef std::map<int, int> map_type;
    typedef enum { X1=0, X2, X3, INVALID } key_type;
    typedef int mapped_type;
    typedef pair<key_type, mapped_type> value_type;

    /* conversions from int to key_type and vice versa */
    friend key_type int2K(int k);
    friend int K2int(key_type k);

    class Iterator
    {
    private:
        map_type::iterator it;
        key_type K;
    public:

        Iterator(map_type::iterator & i) : 
                 it(i), K(int2K(i->first)) {} //<= Error if i is not valid (points to the end)
    };

    typedef Iterator iterator;

    iterator end() { return iterator(m.end()); }
    // other parts of the class skipped for concisness  
};

myMap::key_type int2K(int k) {
    return (k == 0 ? myMap::X1 : 
           (k == 1 ? myMap::X2 : 
           (k == 3 ? myMap::X3 : 
                  myMap::INVALID))); }

int K2int(myMap::key_type k) { return k; }

当我将myMap的迭代器初始化到地图的末尾时,它会失败:

myMap m;
myMap::iterator i = m.end(); //<= fails here

有没有办法检查我的构造函数中迭代器是否指向地图的末尾?如果是这样的话?

1 个答案:

答案 0 :(得分:1)

简短的回答是否定的。正如zett42在问题的评论中所说的那样,迭代器的位置已知的唯一位置是在迭代器调用端。

要解决这个问题,正如Jarod42建议的那样,只有在解除引用迭代器时才能通过计算等效键K来找到解决方案:

Iterator(map_type::iterator & i): it(i) {};

value_type operator*() {
    return { int2K(it->first), it->second};
} 

注意:在之前的回答中,我试图通过复制迭代器来测试迭代器是否在其容器的末尾,将副本递增1,并检查副本是否仍然等于原始版本指针(指向末尾)。

但正如zett42指出的那样,这不起作用: - 递增指向容器末尾的迭代器应该是未定义的行为 - 即使是简单的指针也可以作为迭代器。在这种情况下,看到此解决方案不起作用是微不足道的。

/* DISCLAIMER: Not working ! */
Iterator(map_type::iterator & i) : it(i), K(INVALID) 
{
    map_type::iterator j = i;
    j++;
    if(i!=j) K = int2K(i->first);
}