假设我有一张地图,其中键是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
有没有办法检查我的构造函数中迭代器是否指向地图的末尾?如果是这样的话?
答案 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);
}