我有这个代码,适用于GCC:
#include <map>
class Foo;
class Bar;
typedef std::map<Foo,Bar> MyMap;
MyMap::iterator i;
class Foo
{
MyMap::iterator some_data;
};
目前设计的代码(这是令人不快的循环是的,我坚持使用它)需要map<Foo,Bar>::iterator
可用于Foo
和Bar
。
它的工作原理是因为GCC库实现不需要实例化映射的键类型以实例化迭代器。
这有保证吗?在定义map迭代器类型时,标准似乎有点不干涉。这段代码有多便携?
这导致未定义的行为。
在声明MyMap::iterator i;
中,MyMap
必须是一个完整的类型,因此它是隐式实例化的。但是,Foo
和Bar
在实例化的这一点上并不完整,所以根据[res.on.functions]/2的行为是不确定的:
特别是,在以下情况下,效果未定义:
- ...
- 如果在实例化模板组件或评估概念时将不完整类型([basic.types])用作模板参数,除非特别允许该组件。
您可以通过考虑std::map
是基于节点的容器这一事实来支持整个问题,以便其包含元素的节点具有稳定的地址。即您可以使用普通指针而不是迭代器(当然,只要您不需要迭代器传递到std::map
的成员函数):
class Foo
{
std::pair<Foo const, Bar>* some_data;
};
请注意,此处仅需要声明Foo
,Bar
和std::pair<>
来定义成员some_data
。
如果你使用boost::multi_index
(它在很多方面优于std
关联容器)那么它有非常有用的函数to_iterator
,它接受对元素的引用并返回一个迭代器。